diff --git a/include/revng/ADT/Hierarchy.h b/include/revng/ADT/Hierarchy.h index 7385748b6..8b3d410a9 100644 --- a/include/revng/ADT/Hierarchy.h +++ b/include/revng/ADT/Hierarchy.h @@ -27,7 +27,6 @@ public: HierarchyNode &operator=(HierarchyNode &&) = delete; HierarchyNode &operator=(const HierarchyNode &) = delete; ~HierarchyNode() = default; - bool operator==(const HierarchyNode &Other) const { return this == &Other; } bool isa(entry_t ID) const { return id() == ID; } diff --git a/include/revng/AutoEnforcer/AutoEnforcer.h b/include/revng/AutoEnforcer/AutoEnforcer.h index 7880e7da5..62325158e 100644 --- a/include/revng/AutoEnforcer/AutoEnforcer.h +++ b/include/revng/AutoEnforcer/AutoEnforcer.h @@ -73,23 +73,23 @@ public: } template - void addContainerFactory(llvm::StringRef Name, Args &&... Arguments) { + void registerContainerFactory(llvm::StringRef Name, Args &&... Arguments) { revng_assert(not CommittedRegistry); - Registry.addContainerFactory(Name, - std::forward(Arguments)...); + using BCT = BackingContainerType; + Registry.registerContainerFactory(Name, + std::forward(Arguments)...); } void - addContainerFactory(llvm::StringRef Name, - std::unique_ptr Entry) { - Registry.addContainerFactory(Name, std::move(Entry)); + registerContainerFactory(llvm::StringRef Name, + std::unique_ptr Entry) { + Registry.registerContainerFactory(Name, std::move(Entry)); } template - void addDefaultConstruibleFactory(llvm::StringRef Name) { + void registerDefaultConstructibleFactory(llvm::StringRef Name) { revng_assert(not CommittedRegistry); - Registry.addDefaultConstruibleFactory(Name); + Registry.registerDefaultConstructibleFactory(Name); } iterator begin() { return Pipeline.begin(); } diff --git a/include/revng/AutoEnforcer/AutoEnforcerTarget.h b/include/revng/AutoEnforcer/AutoEnforcerTarget.h index 18885838f..2fc870c5f 100644 --- a/include/revng/AutoEnforcer/AutoEnforcerTarget.h +++ b/include/revng/AutoEnforcer/AutoEnforcerTarget.h @@ -51,14 +51,14 @@ public: } template - void dump(OStream &OS) const { + void dump(OStream &OS) const debug_function { if (Name.has_value()) OS << *Name; else OS << "*"; } - void dump() const { dump(dbg); } + void dump() const debug_function { dump(dbg); } private: std::optional Name; @@ -119,7 +119,7 @@ public: void dropGranularity() { Entries.pop_back(); } template - void dump(OStream &OS, size_t Indents = 0) const { + void dump(OStream &OS, size_t Indents = 0) const debug_function { indent(OS, Indents); OS << (Exact == KindExactness::DerivedFrom ? "derived from " : "exactly ") @@ -132,7 +132,7 @@ public: } template - static void dumpQuantifiers(OStream &OS, Range R) { + static void dumpQuantifiers(OStream &OS, Range R) debug_function { for (const auto &Entry : R) { Entry.dump(OS); OS << "/"; @@ -240,7 +240,7 @@ public: return ContainersStatus.find(ContainerName); } - void dump() const { dump(dbg); } + void dump() const debug_function { dump(dbg); } void merge(const BackingContainersStatus &Other); @@ -253,7 +253,7 @@ llvm::Error parseAutoEnforcerTarget(BackingContainersStatus &CurrentStatus, llvm::StringRef AsString, const KindDictionary &Dict) { llvm::SmallVector Parts; - AsString.split(Parts, ':', 2); + AsString.split(Parts, ':', 1); if (Parts.size() != 2) return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -261,12 +261,6 @@ llvm::Error parseAutoEnforcerTarget(BackingContainersStatus &CurrentStatus, "", AsString.str().c_str()); - auto MaybeContainer = CurrentStatus.find(Parts[0]); - if (MaybeContainer == CurrentStatus.end()) - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "No known container named %s", - Parts[0].str().c_str()); - auto MaybeTarget = parseAutoEnforcerTarget(Parts[1], Dict); if (not MaybeTarget) return MaybeTarget.takeError(); diff --git a/include/revng/AutoEnforcer/BackingContainerRegistry.h b/include/revng/AutoEnforcer/BackingContainerRegistry.h index 153f7fbc5..001142593 100644 --- a/include/revng/AutoEnforcer/BackingContainerRegistry.h +++ b/include/revng/AutoEnforcer/BackingContainerRegistry.h @@ -14,14 +14,13 @@ #include "revng/AutoEnforcer/BackingContainers.h" namespace AutoEnforcer { -class BackingContainerRegistryEntry { +class BackingContainerFactory { public: virtual std::unique_ptr createEmpty() const = 0; - virtual ~BackingContainerRegistryEntry() = default; + virtual ~BackingContainerFactory() = default; }; -class BackingContainerFunctionFactoryWrapper - : public BackingContainerRegistryEntry { +class BackingContainerFunctionFactoryWrapper : public BackingContainerFactory { public: using CreatorFunctionType = std::unique_ptr (*)(void); BackingContainerFunctionFactoryWrapper(CreatorFunctionType CreatorFunction) : @@ -38,7 +37,7 @@ private: template class DefaultConstructibleBackingContainerFactory - : public BackingContainerRegistryEntry { + : public BackingContainerFactory { public: std::unique_ptr createEmpty() const override { return std::make_unique(); @@ -49,21 +48,21 @@ public: class BackingContainerRegistry { public: template - void addContainerFactory(llvm::StringRef Name, Arguments &&... Args) { + void registerContainerFactory(llvm::StringRef Name, Arguments &&... Args) { auto BC = std::make_unique(std::forward(Args)...); Entries.insert_or_assign(Name, std::move(BC)); } void - addContainerFactory(llvm::StringRef Name, - std::unique_ptr Entry) { + registerContainerFactory(llvm::StringRef Name, + std::unique_ptr Entry) { Entries.insert_or_assign(Name, std::move(Entry)); } template - void addDefaultConstruibleFactory(llvm::StringRef Name) { + void registerDefaultConstructibleFactory(llvm::StringRef Name) { using FactoryT = DefaultConstructibleBackingContainerFactory; - addContainerFactory(Name); + registerContainerFactory(Name); } BackingContainers createEmpty() const { @@ -75,6 +74,6 @@ public: } private: - llvm::StringMap> Entries; + llvm::StringMap> Entries; }; } // namespace AutoEnforcer diff --git a/include/revng/AutoEnforcer/BackingContainers.h b/include/revng/AutoEnforcer/BackingContainers.h index 10e5741e6..2efa74dcf 100644 --- a/include/revng/AutoEnforcer/BackingContainers.h +++ b/include/revng/AutoEnforcer/BackingContainers.h @@ -15,6 +15,7 @@ #include "llvm/IR/Module.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Error.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "revng/AutoEnforcer/AutoEnforcerTarget.h" @@ -28,7 +29,7 @@ public: BackingContainerBase(char const *const ID) : ID(ID) {} virtual std::unique_ptr cloneFiltered(const TargetContainer &Targets) const = 0; - virtual void mergeBack(BackingContainerBase &) = 0; + virtual void mergeBack(BackingContainerBase &&) = 0; virtual bool contains(const AutoEnforcerTarget &Target) const = 0; virtual bool remove(const AutoEnforcerTarget &Target) = 0; virtual llvm::Error storeToDisk(llvm::StringRef Path) const = 0; @@ -51,7 +52,7 @@ public: } protected: - char const *const ID; + char const *ID; }; template @@ -59,11 +60,11 @@ class BackingContainer : public BackingContainerBase { public: BackingContainer() : BackingContainerBase(&Derived::ID) {} - void mergeBack(BackingContainerBase &Container) final { + void mergeBack(BackingContainerBase &&Container) final { revng_assert(llvm::isa(Container)); - mergeBackDerived(llvm::cast(Container)); + mergeBackDerived(std::move(llvm::cast(Container))); } - virtual void mergeBackDerived(Derived &Container) = 0; + virtual void mergeBackDerived(Derived &&Container) = 0; ~BackingContainer() override = default; static bool classof(const BackingContainerBase *Base) { @@ -71,81 +72,6 @@ public: } }; -class StringContainer : public BackingContainer { -public: - using TargertContainer = BackingContainersStatus::TargetContainer; - ~StringContainer() override = default; - - static char ID; - - std::unique_ptr - cloneFiltered(const TargertContainer &Container) const final { - auto ToReturn = std::make_unique(); - for (const auto &Target : Container) - ToReturn->insert(Target); - return ToReturn; - } - - void insert(const AutoEnforcerTarget &Target) { - ContainedStrings.insert(toString(Target)); - } - - bool contains(const AutoEnforcerTarget &Target) const final { - return ContainedStrings.count(toString(Target)) != 0; - } - - void mergeBackDerived(StringContainer &Container) override { - for (auto &S : Container.ContainedStrings) - ContainedStrings.insert(S); - } - - bool remove(const AutoEnforcerTarget &Target) override { - if (contains(Target)) - return false; - - ContainedStrings.erase(toString(Target)); - return true; - } - - llvm::Error storeToDisk(llvm::StringRef Path) const override { - std::error_code EC; - llvm::raw_fd_ostream OS(Path, EC, llvm::sys::fs::CD_CreateNew); - if (EC) - return llvm::createStringError(EC, - "Could not store to file %s", - Path.str().c_str()); - - for (const auto &S : ContainedStrings) - OS << S << "\n"; - return llvm::Error::success(); - } - - llvm::Error loadFromDisk(llvm::StringRef Path) override { - std::ifstream OS; - OS.open(Path, std::ios::in | std::ios::trunc); - if (not OS.is_open()) - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "Could not load file to file %s", - Path.str().c_str()); - - std::string S; - while (getline(OS, S)) - ContainedStrings.insert(S); - return llvm::Error::success(); - } - -private: - static std::string toString(const AutoEnforcerTarget &Target) { - std::string ToInsert; - std::stringstream S(ToInsert); - AutoEnforcerTarget::dumpQuantifiers(S, Target.getQuantifiers()); - S.flush(); - return ToInsert; - } - - std::set ContainedStrings; -}; - class BackingContainers { public: using Map = llvm::StringMap>; @@ -163,7 +89,7 @@ public: void mergeBackingContainers(BackingContainers &&Other) { for (auto &Entry : Other.Containers) { revng_assert(Containers.count(Entry.first()) != 0); - Containers[Entry.first()]->mergeBack(*Entry.second); + Containers[Entry.first()]->mergeBack(std::move(*Entry.second)); } } diff --git a/include/revng/AutoEnforcer/CopyEnforcer.h b/include/revng/AutoEnforcer/CopyEnforcer.h new file mode 100644 index 000000000..db44b8630 --- /dev/null +++ b/include/revng/AutoEnforcer/CopyEnforcer.h @@ -0,0 +1,24 @@ +#pragma once + +#include "revng/AutoEnforcer/AutoEnforcerTarget.h" +#include "revng/AutoEnforcer/InputOutputContract.h" + +namespace AutoEnforcer { + +template +class CopyEnforcer { +public: + CopyEnforcer(Kind &K) : K(&K) {} + + static constexpr auto Name = "Copy Enforcer"; + std::array getContract() const { + return { InputOutputContract(*K, KindExactness::Exact, 0, *K, 1) }; + } + + void run(const Source &S, Destination &T) { T = S; } + +private: + Kind *K; +}; + +} // namespace AutoEnforcer diff --git a/include/revng/AutoEnforcer/LLVMEnforcer.h b/include/revng/AutoEnforcer/LLVMEnforcer.h index 3e76093b4..4d7c400d0 100644 --- a/include/revng/AutoEnforcer/LLVMEnforcer.h +++ b/include/revng/AutoEnforcer/LLVMEnforcer.h @@ -89,7 +89,7 @@ public: return Container.getModule().getFunction(LastName) != nullptr; } - void mergeBackDerived(DefaultLLVMContainer &ToMerge) override { + void mergeBackDerived(DefaultLLVMContainer &&ToMerge) override { Container.mergeBackDerived(ToMerge.Container); } @@ -125,7 +125,7 @@ private: }; template -class LLVMContainerFactory : public BackingContainerRegistryEntry { +class LLVMContainerFactory : public BackingContainerFactory { public: LLVMContainerFactory(llvm::LLVMContext &Context) : Context(Context) {} @@ -198,14 +198,14 @@ public: void run(DefaultLLVMContainer &Container); template - void dump(OStream &OS, size_t Indents = 0) const { + void dump(OStream &OS, size_t Indents = 0) const debug_function { for (const auto &Pass : Passess) { indent(OS, Indents); OS << Pass->getName().str() << "\n"; } } - void dump() const { dump(dbg); } + void dump() const debug_function { dump(dbg); } template void addPass(LLVMEnforcerPass Pass) { diff --git a/include/revng/AutoEnforcer/PipelineLoader.h b/include/revng/AutoEnforcer/PipelineLoader.h index 20a1352e8..15b6c40af 100644 --- a/include/revng/AutoEnforcer/PipelineLoader.h +++ b/include/revng/AutoEnforcer/PipelineLoader.h @@ -1,4 +1,7 @@ #pragma once +// +// This file is distributed under the MIT License. See LICENSE.md for details. +// #include #include @@ -40,36 +43,43 @@ public: llvm::Expected load(llvm::StringRef Pipeline) const; template - void addDefaultConstructibleContainer(llvm::StringRef Name) { + void registerDefaultConstructibleContainer(llvm::StringRef Name) { KnownContainerTypes.try_emplace(Name, []() { - return std::make_unique< - DefaultConstructibleBackingContainerFactory>(); + using Type = DefaultConstructibleBackingContainerFactory; + return std::make_unique(); }); } template - void addContainerFactory(llvm::StringRef Name, Args &&... A) { + void registerContainerFactory(llvm::StringRef Name, Args &&... A) { KnownContainerTypes.try_emplace(Name, [&A...]() { return std::make_unique(A...); }); } template - void addLLVMEnforcerPass(llvm::StringRef Name) { + void registerLLVMEnforcerPass(llvm::StringRef Name) { KnownLLVMEnforcerTypes.try_emplace(Name, []() { using Type = LLVMEnforcerImpl; - return std::make_unique( - std::forward(LLVMEnforcerPass())); + return std::make_unique(LLVMEnforcerPass()); }); } template - void addEnforcer(llvm::StringRef Name) { - KnownEnforcersTypes - .try_emplace(Name, [](std::vector ContainerNames) { - return EnforcerWrapper::makeWrapper( - std::move(ContainerNames)); - }); + void registerEnforcer(llvm::StringRef Name) { + const auto LambdaToEmplace = [](std::vector CName) { + return EnforcerWrapper::makeWrapper(std::move(CName)); + }; + KnownEnforcersTypes.try_emplace(Name, LambdaToEmplace); + } + + template + void registerEnforcer(llvm::StringRef Name, const EnforcerType &Enforcer) { + const auto LambdaToEmplace = + [Enforcer](std::vector ContainerNames) { + return EnforcerWrapper(Enforcer, std::move(ContainerNames)); + }; + KnownEnforcersTypes.try_emplace(Name, LambdaToEmplace); } private: @@ -84,9 +94,8 @@ private: llvm::Error parseLLVMPass(Step &Step, const EnforcerInvocation &Invocation) const; - llvm::StringMap< - std::function()>> - KnownContainerTypes; + using FType = std::function()>; + llvm::StringMap KnownContainerTypes; llvm::StringMap)>> KnownEnforcersTypes; llvm::StringMap()>> diff --git a/include/revng/AutoEnforcer/Step.h b/include/revng/AutoEnforcer/Step.h index cbdd15cd6..cf41bd740 100644 --- a/include/revng/AutoEnforcer/Step.h +++ b/include/revng/AutoEnforcer/Step.h @@ -189,6 +189,12 @@ EnforcerWrapper bindEnforcer(ContainerNames &&... Names) { return EnforcerWrapper::makeWrapper(std::move(NamesList)); } +template +EnforcerWrapper bindEnforcer(Enforcer &&E, ContainerNames &&... Names) { + auto NamesList = { std::forward(Names)... }; + return EnforcerWrapper(std::forward(E), std::move(NamesList)); +} + class Step { public: BackingContainers cloneAndRun(const BackingContainersStatus &Targets); diff --git a/include/revng/Enforcers/BinaryContainer.h b/include/revng/Enforcers/BinaryContainer.h index 0759c160b..9c34f9970 100644 --- a/include/revng/Enforcers/BinaryContainer.h +++ b/include/revng/Enforcers/BinaryContainer.h @@ -28,7 +28,7 @@ public: return false; } - void mergeBackDerived(BinaryContainer &Container) override { + void mergeBackDerived(BinaryContainer &&Container) override { revng_abort("You have to tell me how to merge back the a binary " "container into this one, probably a binary can only be " "used as a source and this should never be used?"); diff --git a/include/revng/Support/Debug.h b/include/revng/Support/Debug.h index db2bbc70d..b215b2e1a 100644 --- a/include/revng/Support/Debug.h +++ b/include/revng/Support/Debug.h @@ -27,7 +27,7 @@ extern size_t MaxLoggerNameLength; template void indent(OStream &OS, size_t Indents) { for (size_t I = 0; I < Indents; I++) - OS << "\t"; + OS << " "; } /// \brief Stream an instance of this class to call Logger::emit() diff --git a/lib/AutoEnforcer/BackingContainers.cpp b/lib/AutoEnforcer/BackingContainers.cpp index 2dfa20554..37a06219d 100644 --- a/lib/AutoEnforcer/BackingContainers.cpp +++ b/lib/AutoEnforcer/BackingContainers.cpp @@ -73,7 +73,6 @@ llvm::Error BackingContainers::load(StringRef Directory) { for (const auto &Pair : Containers) { const auto &Name = Directory.str() + "/" + Pair.first().str(); const auto &Container = Pair.second; - if (auto Error = Container->loadFromDisk(Name); !!Error) return Error; } @@ -103,5 +102,3 @@ BackingContainers::safeGetContainer(llvm::StringRef ContainerName) { return &*It->second; } - -char StringContainer::ID; diff --git a/lib/AutoEnforcer/CMakeLists.txt b/lib/AutoEnforcer/CMakeLists.txt index f6ab78525..a2f80dab8 100644 --- a/lib/AutoEnforcer/CMakeLists.txt +++ b/lib/AutoEnforcer/CMakeLists.txt @@ -2,7 +2,7 @@ # This file is distributed under the MIT License. See LICENSE.md for details. # -revng_add_library_internal(revngAutoEnforcer +revng_add_library_internal(revngAutoEnforcer SHARED LLVMEnforcer.cpp AutoEnforcerErrors.cpp AutoEnforcerTarget.cpp diff --git a/lib/AutoEnforcer/InputOutputContract.cpp b/lib/AutoEnforcer/InputOutputContract.cpp index 3becf1fc5..6406a23f7 100644 --- a/lib/AutoEnforcer/InputOutputContract.cpp +++ b/lib/AutoEnforcer/InputOutputContract.cpp @@ -73,7 +73,7 @@ bool InputOutputContract::forwardMatches(const AutoEnforcerTarget &In) const { case KindExactness::DerivedFrom: return Source->ancestorOf(In.getKind()); case KindExactness::Exact: - return In.getKind() == *Source; + return &In.getKind() == Source; } return false; } @@ -180,7 +180,7 @@ InputOutputContract::backwardInputKind(const AutoEnforcerTarget &Output) const { bool InputOutputContract::backwardMatches(const AutoEnforcerTarget &Out) const { if (Target != nullptr) - return Out.getKind() == *Target; + return &Out.getKind() == Target; switch (InputContract) { case KindExactness::DerivedFrom: diff --git a/lib/AutoEnforcer/PipelineLoader.cpp b/lib/AutoEnforcer/PipelineLoader.cpp index 62fb77775..24c2b3181 100644 --- a/lib/AutoEnforcer/PipelineLoader.cpp +++ b/lib/AutoEnforcer/PipelineLoader.cpp @@ -34,8 +34,8 @@ PipelineLoader::parseLLVMPass(Step &Step, auto &Entry = It->second; ToInsert.addPass(Entry()); } - Step.addEnforcer( - EnforcerWrapper(std::move(ToInsert), Invocation.UsedContainers)); + auto Wrapper = EnforcerWrapper(move(ToInsert), Invocation.UsedContainers); + Step.addEnforcer(move(Wrapper)); return Error::success(); } @@ -49,21 +49,25 @@ PipelineLoader::parseInvocation(Step &Step, auto It = KnownEnforcersTypes.find(Invocation.Name); if (It == KnownEnforcersTypes.end()) return createStringError(inconvertibleErrorCode(), - "No known enforcer with provided name"); + "while parsing inforcer invocation: No known " + "enforcer with name %s ", + Invocation.Name.c_str()); auto &Entry = It->second; Step.addEnforcer(Entry(Invocation.UsedContainers)); return Error::success(); } -llvm::Error PipelineLoader::parseContainerDeclaration( - PipelineRunner &Runner, - const BackingContainerDeclaration &Declaration) const { - auto It = KnownContainerTypes.find(Declaration.Type); +using BCDecl = BackingContainerDeclaration; +Error PipelineLoader::parseContainerDeclaration(PipelineRunner &AE, + const BCDecl &Dec) const { + auto It = KnownContainerTypes.find(Dec.Type); if (It == KnownContainerTypes.end()) return createStringError(inconvertibleErrorCode(), - "No known container with provided name"); + "while parsing contaienr declaration: No known " + "container with name %s", + Dec.Type.c_str()); auto &Entry = It->second; - Runner.addContainerFactory(Declaration.Name, Entry()); + AE.registerContainerFactory(Dec.Name, Entry()); return Error::success(); } diff --git a/lib/AutoEnforcer/Step.cpp b/lib/AutoEnforcer/Step.cpp index a2cb02618..45fb549f9 100644 --- a/lib/AutoEnforcer/Step.cpp +++ b/lib/AutoEnforcer/Step.cpp @@ -93,10 +93,10 @@ Error Step::invalidate(const BackingContainersStatus &ToRemove) { Error Step::store(llvm::StringRef DirPath) const { auto Path = DirPath.str() + "/" + Name; - if (auto ErrorCode = llvm::sys::fs::create_directories(DirPath); ErrorCode) + if (auto ErrorCode = llvm::sys::fs::create_directories(Path); ErrorCode) return createStringError(ErrorCode, "Could not create dir %s", - DirPath.str().c_str()); + Path.c_str()); return BackingContainer.store(Path); } Error Step::load(llvm::StringRef DirPath) { diff --git a/tests/Tests.cmake b/tests/Tests.cmake index 85acc74b5..b4ee00cda 100644 --- a/tests/Tests.cmake +++ b/tests/Tests.cmake @@ -8,5 +8,6 @@ enable_testing() include(${CMAKE_SOURCE_DIR}/tests/unit/UnitTests.cmake) include(${CMAKE_SOURCE_DIR}/tests/analysis/AnalysisTests.cmake) include(${CMAKE_SOURCE_DIR}/tests/runtime/RuntimeTests.cmake) +add_subdirectory(${CMAKE_SOURCE_DIR}/tests/tools) set(TEST_CFLAGS_${ARCH} "${TEST_CFLAGS_${ARCH}} -mthumb") diff --git a/tests/tools/AutoEnforcer/CMakeLists.txt b/tests/tools/AutoEnforcer/CMakeLists.txt new file mode 100644 index 000000000..249c6d404 --- /dev/null +++ b/tests/tools/AutoEnforcer/CMakeLists.txt @@ -0,0 +1,15 @@ +# +# This file is distributed under the MIT License. See LICENSE.md for details. +# + +add_library(StringContainerLibrary SHARED StringContainerLibrary.cpp) +target_link_libraries(StringContainerLibrary revngAutoEnforcer) + +macro(add_auto_enforcer_test TestName PipelineFile Targets InputsList OutputList) + add_test(NAME ${TEST_NAME} COMMAND revng-autoenforcer ${CMAKE_CURRENT_SOURCE_DIR}/${PipelineFile} ${Targets} -i ${InputsList} -o ${OutputList} -l $ -p ${CMAKE_CURRENT_BINARY_DIR}/${TestName}) +endmacro() + +set(CopyEnforcerTestInputs "FirstStep:Strings1:${CMAKE_CURRENT_SOURCE_DIR}/CopyEnforcerTestInput.txt") +set(CopyEnforcerTestOutputs "End:Strings2:${CMAKE_CURRENT_BINARY_DIR}/CopyEnforcerTestOutput.txt") +add_auto_enforcer_test(copy-enforcer-run-test CopyEnforcerTestPipeline.yaml Strings2:Root:Root ${CopyEnforcerTestInputs} ${CopyEnforcerTestOutputs}) +add_test(NAME copy-enforcer-check-equal-test COMMAND diff ${CMAKE_CURRENT_BINARY_DIR}/CopyEnforcerTestOutput.txt ${CMAKE_CURRENT_SOURCE_DIR}/CopyEnforcerTestExpected.txt) diff --git a/tests/tools/AutoEnforcer/CopyEnforcerTestExpected.txt b/tests/tools/AutoEnforcer/CopyEnforcerTestExpected.txt new file mode 100644 index 000000000..d529ceb24 --- /dev/null +++ b/tests/tools/AutoEnforcer/CopyEnforcerTestExpected.txt @@ -0,0 +1 @@ +Root/ diff --git a/tests/tools/AutoEnforcer/CopyEnforcerTestInput.txt b/tests/tools/AutoEnforcer/CopyEnforcerTestInput.txt new file mode 100644 index 000000000..01d67307d --- /dev/null +++ b/tests/tools/AutoEnforcer/CopyEnforcerTestInput.txt @@ -0,0 +1,2 @@ +Root/ +SomethingNotToBeCopied/ diff --git a/tests/tools/AutoEnforcer/CopyEnforcerTestPipeline.yaml b/tests/tools/AutoEnforcer/CopyEnforcerTestPipeline.yaml new file mode 100644 index 000000000..f19deba49 --- /dev/null +++ b/tests/tools/AutoEnforcer/CopyEnforcerTestPipeline.yaml @@ -0,0 +1,10 @@ +Containers: + - Name: Strings1 + Type: StringContainer + - Name: Strings2 + Type: StringContainer +Steps: + - Name: FirstStep + Enforcers: + - Name: CopyEnforcer + UsedContainers: [Strings1, Strings2] diff --git a/tests/tools/AutoEnforcer/StringContainerLibrary.cpp b/tests/tools/AutoEnforcer/StringContainerLibrary.cpp new file mode 100644 index 000000000..cbbc607c4 --- /dev/null +++ b/tests/tools/AutoEnforcer/StringContainerLibrary.cpp @@ -0,0 +1,108 @@ +#include "revng/AutoEnforcer/AutoEnforcerLibraryRegistry.h" +#include "revng/AutoEnforcer/CopyEnforcer.h" +#include "revng/AutoEnforcer/RevngEnforcers.h" + +using std::string; +using namespace llvm; +using namespace llvm::cl; +using namespace AutoEnforcer; + +class StringContainer : public BackingContainer { +public: + using TargertContainer = BackingContainersStatus::TargetContainer; + ~StringContainer() override = default; + + static char ID; + + std::unique_ptr + cloneFiltered(const TargertContainer &Container) const final { + auto ToReturn = std::make_unique(); + for (const auto &Target : Container) + ToReturn->insert(Target); + return ToReturn; + } + + void insert(const AutoEnforcerTarget &Target) { + ContainedStrings.insert(toString(Target)); + } + + bool contains(const AutoEnforcerTarget &Target) const final { + return ContainedStrings.count(toString(Target)) != 0; + } + + void mergeBackDerived(StringContainer &&Container) override { + for (auto &S : Container.ContainedStrings) + ContainedStrings.insert(S); + } + + bool remove(const AutoEnforcerTarget &Target) override { + if (contains(Target)) + return false; + + ContainedStrings.erase(toString(Target)); + return true; + } + + llvm::Error storeToDisk(llvm::StringRef Path) const override { + std::error_code EC; + llvm::raw_fd_ostream OS(Path, EC, llvm::sys::fs::CD_CreateAlways); + if (EC) + return llvm::createStringError(EC, + "Could not store to file %s", + Path.str().c_str()); + + for (const auto &S : ContainedStrings) + OS << S << "\n"; + return llvm::Error::success(); + } + + llvm::Error loadFromDisk(llvm::StringRef Path) override { + if (not llvm::sys::fs::exists(Path)) { + ContainedStrings.clear(); + return llvm::Error::success(); + } + + std::ifstream OS; + OS.open(Path, std::ios::in); + if (not OS.is_open()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Could not load file to file %s", + Path.str().c_str()); + + std::string S; + while (getline(OS, S)) + ContainedStrings.insert(S); + return llvm::Error::success(); + } + + const std::set &getStrings() const { return ContainedStrings; } + +private: + static std::string toString(const AutoEnforcerTarget &Target) { + std::stringstream S; + AutoEnforcerTarget::dumpQuantifiers(S, Target.getQuantifiers()); + std::string ToInsert = S.str(); + return ToInsert; + } + + std::set ContainedStrings; +}; + +char StringContainer::ID; + +class ExampleRegistryLibrary : public AutoEnforcerLibraryRegistry { + +public: + void registerContainersAndEnforcers(PipelineLoader &Loader) override { + Loader.registerDefaultConstructibleContainer("StringContai" + "ner"); + Loader.registerEnforcer("CopyEnforcer", + CopyEnforcer(Root)); + } + + void registerKinds(llvm::StringMap &KindDictionary) override {} + + ~ExampleRegistryLibrary() override = default; +}; + +static ExampleRegistryLibrary Registry; diff --git a/tests/tools/CMakeLists.txt b/tests/tools/CMakeLists.txt new file mode 100644 index 000000000..42567e61d --- /dev/null +++ b/tests/tools/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(AutoEnforcer) diff --git a/tests/unit/AutoEnforcer.cpp b/tests/unit/AutoEnforcer.cpp index 2ec7bf460..37bd6d822 100644 --- a/tests/unit/AutoEnforcer.cpp +++ b/tests/unit/AutoEnforcer.cpp @@ -5,9 +5,9 @@ // This file is distributed under the MIT License. See LICENSE.md for details. // -#include #include +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" @@ -63,7 +63,7 @@ public: return map.count(Target); } - void mergeBackDerived(MapContainer &Container) override { + void mergeBackDerived(MapContainer &&Container) override { for (auto &Pair : Container.map) map.insert(std::move(Pair)); } @@ -146,7 +146,7 @@ public: void run(const MapContainer &Source, MapContainer &Target) { for (const auto &Element : Source.getMap()) - if (Element.first.getKind() == RootKind) { + if (&Element.first.getKind() == &RootKind) { AutoEnforcerTarget NewTar = { Element.first.getQuantifiers(), RootKind2 }; Target.get(NewTar) = Element.second; @@ -168,7 +168,7 @@ BOOST_AUTO_TEST_CASE(InputOutputContractExactPassForward) { InputOutputContract Contract1(RootKind, KindExactness::Exact); Contract1.deduceResults(Targets, { CName }); - BOOST_TEST((Targets[CName][0].getKind() == RootKind)); + BOOST_TEST((&Targets[CName][0].getKind() == &RootKind)); BOOST_TEST((Targets[CName][0].kindExactness() == KindExactness::Exact)); } @@ -182,7 +182,7 @@ BOOST_AUTO_TEST_CASE(InputOutputContractExactExactForward) { RootKind2, 0); Contract1.deduceResults(Targets, { CName }); - BOOST_TEST((Targets[CName][0].getKind() == RootKind2)); + BOOST_TEST((&Targets[CName][0].getKind() == &RootKind2)); BOOST_TEST((Targets[CName][0].kindExactness() == KindExactness::Exact)); } @@ -192,7 +192,7 @@ BOOST_AUTO_TEST_CASE(InputOutputContractDerivedPassForward) { InputOutputContract Contract1(RootKind, KindExactness::DerivedFrom); Contract1.deduceResults(Targets, { CName }); - BOOST_TEST((Targets[CName][0].getKind() == RootKind2)); + BOOST_TEST((&Targets[CName][0].getKind() == &RootKind2)); BOOST_TEST((Targets[CName][0].kindExactness() == KindExactness::Exact)); } @@ -206,7 +206,7 @@ BOOST_AUTO_TEST_CASE(InputOutputContractDerivedExactForward) { RootKind, 0); Contract1.deduceResults(Targets, { CName }); - BOOST_TEST((Targets[CName][0].getKind() == RootKind)); + BOOST_TEST((&Targets[CName][0].getKind() == &RootKind)); BOOST_TEST((Targets[CName][0].kindExactness() == KindExactness::Exact)); } @@ -216,7 +216,7 @@ BOOST_AUTO_TEST_CASE(InputOutputContractExactPassBackward) { InputOutputContract Contract1(RootKind, KindExactness::Exact); Contract1.deduceRequirements(Targets, { CName }); - BOOST_TEST((Targets[CName][0].getKind() == RootKind)); + BOOST_TEST((&Targets[CName][0].getKind() == &RootKind)); BOOST_TEST((Targets[CName][0].kindExactness() == KindExactness::Exact)); } @@ -230,7 +230,7 @@ BOOST_AUTO_TEST_CASE(InputOutputContractExactExactBackward) { RootKind2, 0); Contract1.deduceRequirements(Targets, { CName }); - BOOST_TEST((Targets[CName][0].getKind() == RootKind)); + BOOST_TEST((&Targets[CName][0].getKind() == &RootKind)); BOOST_TEST((Targets[CName][0].kindExactness() == KindExactness::Exact)); } @@ -240,7 +240,7 @@ BOOST_AUTO_TEST_CASE(InputOutputContractDerivedPassBackward) { InputOutputContract Contract1(RootKind, KindExactness::DerivedFrom); Contract1.deduceRequirements(Targets, { CName }); - BOOST_TEST((Targets[CName][0].getKind() == RootKind2)); + BOOST_TEST((&Targets[CName][0].getKind() == &RootKind2)); BOOST_TEST((Targets[CName][0].kindExactness() == KindExactness::Exact)); } @@ -254,7 +254,7 @@ BOOST_AUTO_TEST_CASE(InputOutputContractDerivedExactBackward) { RootKind2, 0); Contract1.deduceRequirements(Targets, { CName }); - BOOST_TEST((Targets[CName][0].getKind() == RootKind)); + BOOST_TEST((&Targets[CName][0].getKind() == &RootKind)); BOOST_TEST((Targets[CName][0].kindExactness() == KindExactness::DerivedFrom)); } @@ -268,7 +268,7 @@ BOOST_AUTO_TEST_CASE(InputOutputContractExactExactFineGrainedBackward) { FunctionKind, 0); Contract1.deduceRequirements(Targets, { CName }); - BOOST_TEST((Targets[CName][0].getKind() == RootKind)); + BOOST_TEST((&Targets[CName][0].getKind() == &RootKind)); BOOST_TEST((Targets[CName][0].kindExactness() == KindExactness::Exact)); BOOST_TEST((Targets[CName][0].getQuantifiers().size() == 1)); BOOST_TEST((Targets[CName][0].getQuantifiers()[0].getName() == "root")); @@ -284,7 +284,7 @@ BOOST_AUTO_TEST_CASE(InputOutputContractExactExactFineGrainedForward) { FunctionKind, 0); Contract1.deduceResults(Targets, { CName }); - BOOST_TEST((Targets[CName][0].getKind() == FunctionKind)); + BOOST_TEST((&Targets[CName][0].getKind() == &FunctionKind)); BOOST_TEST((Targets[CName][0].kindExactness() == KindExactness::Exact)); BOOST_TEST((Targets[CName][0].getQuantifiers().size() == 2)); BOOST_TEST((Targets[CName][0].getQuantifiers()[0].getName() == "root")); @@ -302,9 +302,9 @@ BOOST_AUTO_TEST_CASE(InputOutputContractMupltipleInputTest) { RootKind2, 0); Contract1.deduceRequirements(Targets, { CName }); - BOOST_TEST((Targets[CName][1].getKind() == RootKind)); + BOOST_TEST((&Targets[CName][1].getKind() == &RootKind)); BOOST_TEST((Targets[CName][1].kindExactness() == KindExactness::DerivedFrom)); - BOOST_TEST((Targets[CName][0].getKind() == RootKind)); + BOOST_TEST((&Targets[CName][0].getKind() == &RootKind)); BOOST_TEST((Targets[CName][0].kindExactness() == KindExactness::Exact)); } @@ -320,13 +320,13 @@ BOOST_AUTO_TEST_CASE(InputOutputContractPreserved) { 0, true); Contract1.deduceResults(Targets, { CName }); - BOOST_TEST((Targets[CName][2].getKind() == RootKind2)); + BOOST_TEST((&Targets[CName][2].getKind() == &RootKind2)); BOOST_TEST((Targets[CName][2].kindExactness() == KindExactness::Exact)); - BOOST_TEST((Targets[CName][1].getKind() == RootKind)); + BOOST_TEST((&Targets[CName][1].getKind() == &RootKind)); BOOST_TEST((Targets[CName][1].kindExactness() == KindExactness::Exact)); - BOOST_TEST((Targets[CName][0].getKind() == RootKind2)); + BOOST_TEST((&Targets[CName][0].getKind() == &RootKind2)); BOOST_TEST((Targets[CName][0].kindExactness() == KindExactness::Exact)); } @@ -341,7 +341,7 @@ BOOST_AUTO_TEST_CASE(InputOutputContractPreservedBackwardMain) { 0, true); Contract1.deduceRequirements(Targets, { CName }); - BOOST_TEST((Targets[CName][0].getKind() == RootKind)); + BOOST_TEST((&Targets[CName][0].getKind() == &RootKind)); BOOST_TEST((Targets[CName][0].kindExactness() == KindExactness::DerivedFrom)); } @@ -356,7 +356,7 @@ BOOST_AUTO_TEST_CASE(InputOutputContractPreservedBackwardSecondary) { 0, true); Contract1.deduceRequirements(Targets, { CName }); - BOOST_TEST((Targets[CName][0].getKind() == RootKind)); + BOOST_TEST((&Targets[CName][0].getKind() == &RootKind)); BOOST_TEST((Targets[CName][0].kindExactness() == KindExactness::Exact)); } @@ -379,7 +379,7 @@ BOOST_AUTO_TEST_CASE(StepCanCloneAndRun) { BOOST_AUTO_TEST_CASE(PipelineCanBeManuallyExectued) { BackingContainerRegistry Registry; - Registry.addDefaultConstruibleFactory(CName); + Registry.registerDefaultConstructibleFactory(CName); Pipeline Pip; Pip.add(Step("first_step", @@ -439,7 +439,7 @@ public: void run(const MapContainer &Source, MapContainer &Target) { for (const auto &Element : Source.getMap()) { - if (Element.first.getKind() != RootKind) + if (&Element.first.getKind() != &RootKind) continue; auto Quantifiers = Element.first.getQuantifiers(); @@ -455,7 +455,7 @@ public: BOOST_AUTO_TEST_CASE(SingleElementPipelineBackwardFinedGrained) { PipelineRunner AE; - AE.addDefaultConstruibleFactory(CName); + AE.registerDefaultConstructibleFactory(CName); AE.addStep("first_step", bindEnforcer(CName, CName)); AE.addStep("End"); @@ -476,7 +476,7 @@ BOOST_AUTO_TEST_CASE(SingleElementPipelineBackwardFinedGrained) { BOOST_AUTO_TEST_CASE(SingleElementPipelineFailure) { PipelineRunner AE; - AE.addDefaultConstruibleFactory(CName); + AE.registerDefaultConstructibleFactory(CName); AE.addStep("first_step", bindEnforcer(CName, CName)); AE.addStep("End"); @@ -554,7 +554,7 @@ BOOST_AUTO_TEST_CASE(SingleElementLLVMPipelineBackwardFinedGrained) { llvm::LLVMContext C; PipelineRunner AE; - AE.addContainerFactory(CName, C); + AE.registerContainerFactory(CName, C); AE.addStep("first_step", wrapLLVMPassess(CName, @@ -582,7 +582,7 @@ BOOST_AUTO_TEST_CASE(SingleElementLLVMPipelineBackwardFinedGrained) { BOOST_AUTO_TEST_CASE(SingleElementPipelineForwardFinedGrained) { PipelineRunner AE; - AE.addDefaultConstruibleFactory(CName); + AE.registerDefaultConstructibleFactory(CName); AE.addStep("first_step", bindEnforcer(CName, CName)); AE.addStep("End"); @@ -605,7 +605,7 @@ BOOST_AUTO_TEST_CASE(SingleElementPipelineForwardFinedGrained) { BOOST_AUTO_TEST_CASE(SingleElementPipelineInvalidation) { PipelineRunner AE; - AE.addDefaultConstruibleFactory(CName); + AE.registerDefaultConstructibleFactory(CName); AE.addStep("first_step", bindEnforcer(CName, CName)); AE.addStep("End"); @@ -626,7 +626,7 @@ BOOST_AUTO_TEST_CASE(SingleElementPipelineInvalidation) { BOOST_AUTO_TEST_CASE(SingleElementPipelineWithRemove) { PipelineRunner AE; - AE.addDefaultConstruibleFactory(CName); + AE.registerDefaultConstructibleFactory(CName); AE.addStep("first_step", bindEnforcer(CName, CName)); AE.addStep("End"); @@ -648,8 +648,8 @@ BOOST_AUTO_TEST_CASE(PipelineLoaderTest) { { move(SDeclaration) } }; PipelineLoader Loader; - Loader.addDefaultConstructibleContainer("MapContainer"); - Loader.addEnforcer("FineGranerEnforcer"); + Loader.registerDefaultConstructibleContainer("MapContainer"); + Loader.registerEnforcer("FineGranerEnforcer"); auto MaybeAE = Loader.load(PDeclaration); BOOST_TEST(!!MaybeAE); @@ -685,8 +685,8 @@ static const std::string Pipeline(R"(--- BOOST_AUTO_TEST_CASE(PipelineLoaderTestFromYaml) { PipelineLoader Loader; - Loader.addDefaultConstructibleContainer("MapContainer"); - Loader.addEnforcer("FineGranerEnforcer"); + Loader.registerDefaultConstructibleContainer("MapContainer"); + Loader.registerEnforcer("FineGranerEnforcer"); auto MaybeAutoEnforcer = Loader.load(Pipeline); BOOST_TEST(!!MaybeAutoEnforcer); } @@ -694,10 +694,13 @@ BOOST_AUTO_TEST_CASE(PipelineLoaderTestFromYaml) { BOOST_AUTO_TEST_CASE(PipelineLoaderTestFromYamlLLVM) { llvm::LLVMContext C; PipelineLoader Loader; - Loader.addContainerFactory("LLVMContainer", C); - Loader.addLLVMEnforcerPass("CreateFunctionPa" - "ss"); - Loader.addLLVMEnforcerPass("IdentityPass"); + Loader.registerContainerFactory("LLVMContainer", + C); + Loader.registerLLVMEnforcerPass("CreateFunct" + "ionPa" + "ss"); + Loader.registerLLVMEnforcerPass("IdentityPa" + "ss"); std::string Pipeline(R"(--- Containers: @@ -731,7 +734,7 @@ static std::string getCurrentPath() { BOOST_AUTO_TEST_CASE(SingleElementPipelineStoreToDisk) { PipelineRunner AE; - AE.addDefaultConstruibleFactory(CName); + AE.registerDefaultConstructibleFactory(CName); AE.addStep("first_step", bindEnforcer(CName, CName)); AE.addStep("End"); @@ -751,8 +754,8 @@ BOOST_AUTO_TEST_CASE(SingleElementPipelineStoreToDisk) { BOOST_AUTO_TEST_CASE(SingleElementPipelineStoreToDiskWithOverrides) { PipelineLoader Loader; - Loader.addDefaultConstructibleContainer("MapContainer"); - Loader.addEnforcer("FineGranerEnforcer"); + Loader.registerDefaultConstructibleContainer("MapContainer"); + Loader.registerEnforcer("FineGranerEnforcer"); auto MaybeAutoEnforcer = Loader.load(Pipeline); BOOST_TEST(!!MaybeAutoEnforcer); auto &AE = *MaybeAutoEnforcer; diff --git a/tools/revng-autoenforcer/.Main.cpp.swp b/tools/revng-autoenforcer/.Main.cpp.swp deleted file mode 100644 index aaec7b5d5..000000000 Binary files a/tools/revng-autoenforcer/.Main.cpp.swp and /dev/null differ diff --git a/tools/revng-autoenforcer/Main.cpp b/tools/revng-autoenforcer/Main.cpp index 7331ac80b..e41763466 100644 --- a/tools/revng-autoenforcer/Main.cpp +++ b/tools/revng-autoenforcer/Main.cpp @@ -15,6 +15,7 @@ #include "revng/AutoEnforcer/AutoEnforcerLibraryRegistry.h" #include "revng/AutoEnforcer/AutoEnforcerTarget.h" #include "revng/AutoEnforcer/BackingContainers.h" +#include "revng/AutoEnforcer/CopyEnforcer.h" #include "revng/AutoEnforcer/PipelineLoader.h" #include "revng/Enforcers/RevngEnforcers.h" @@ -46,6 +47,13 @@ static list StoresOverrides("o", "target step in the target file"), cat(AutoEnforcerCategory)); +static opt ExecutionFolder("p", + desc("Folder from which all containers will " + "be loaded before everything else and " + "to which it will be store after " + "everything else"), + cat(AutoEnforcerCategory)); + static list loadLibraries("load", desc("libraries to open"), cat(AutoEnforcerCategory)); @@ -59,9 +67,7 @@ static ExitOnError exitOnError; class LLVMAutoEnforcerLibraryRegistry : public AutoEnforcerLibraryRegistry { public: - void registerContainersAndEnforcers(PipelineLoader &Loader) override { - Loader.addDefaultConstructibleContainer("StringContainer"); - } + void registerContainersAndEnforcers(PipelineLoader &Loader) override {} void registerKinds(llvm::StringMap &KindDictionary) override { KindDictionary["Root"] = &Root; @@ -73,13 +79,20 @@ public: static LLVMAutoEnforcerLibraryRegistry Registry; +static auto getBuffer(StringRef Path) { + return exitOnError(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Path))); +} + static PipelineRunner setUpAutoEnforcer() { PipelineLoader Loader; + AutoEnforcerLibraryRegistry::registerAllContainersAndEnforcers(Loader); - auto Pipeline = exitOnError( - errorOrToExpected(MemoryBuffer::getFileOrSTDIN(InputPipeline))); + auto Pipeline = getBuffer(InputPipeline); auto AutoEnforcer = exitOnError(Loader.load(Pipeline->getBuffer())); + if (not ExecutionFolder.empty()) + exitOnError(AutoEnforcer.load(ExecutionFolder)); + for (const auto &Override : ContainerOverrides) { auto Mapping = exitOnError(PipelineFileMapping::parse(Override)); exitOnError(Mapping.load(AutoEnforcer)); @@ -105,6 +118,8 @@ static void tearDownAutoEnforcer(PipelineRunner &AutoEnforcer) { exitOnError(Mapping.store(AutoEnforcer)); } + if (not ExecutionFolder.empty()) + exitOnError(AutoEnforcer.store(ExecutionFolder)); } int main(int argc, const char *argv[]) { @@ -113,8 +128,7 @@ int main(int argc, const char *argv[]) { string Msg; for (const auto &Library : loadLibraries) { - if (not sys::DynamicLibrary::LoadLibraryPermanently(Library.c_str(), - &Msg)) { + if (sys::DynamicLibrary::LoadLibraryPermanently(Library.c_str(), &Msg)) { dbg << Msg; return EXIT_FAILURE; }