#include #include "llvm/ADT/StringRef.h" #include "revng/AutoEnforcer/AutoEnforcer.h" #include "revng/AutoEnforcer/PipelineLoader.h" using namespace AutoEnforcer; using namespace std; using namespace llvm; llvm::Error PipelineLoader::parseStepDeclaration(PipelineRunner &Runner, const StepDeclaration &Declaration) const { Runner.addStep(Declaration.Name); for (const auto &Invocation : Declaration.Enforcers) if (auto error = parseInvocation(Runner.back(), Invocation); !!error) return error; return Error::success(); } llvm::Error PipelineLoader::parseLLVMPass(Step &Step, const EnforcerInvocation &Invocation) const { LLVMEnforcer ToInsert; for (const auto &PassName : Invocation.Passess) { auto It = KnownLLVMEnforcerTypes.find(PassName); if (It == KnownLLVMEnforcerTypes.end()) return createStringError(inconvertibleErrorCode(), "No known LLVM pass with provided name"); auto &Entry = It->second; ToInsert.addPass(Entry()); } auto Wrapper = EnforcerWrapper(move(ToInsert), Invocation.UsedContainers); Step.addEnforcer(move(Wrapper)); return Error::success(); } llvm::Error PipelineLoader::parseInvocation(Step &Step, const EnforcerInvocation &Invocation) const { if (Invocation.Name == "LLVMEnforcer") return parseLLVMPass(Step, Invocation); auto It = KnownEnforcersTypes.find(Invocation.Name); if (It == KnownEnforcersTypes.end()) return createStringError(inconvertibleErrorCode(), "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(); } 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(), "while parsing contaienr declaration: No known " "container with name %s", Dec.Type.c_str()); auto &Entry = It->second; AE.registerContainerFactory(Dec.Name, Entry()); return Error::success(); } llvm::Expected PipelineLoader::load(const PipelineDeclaration &Declaration) const { PipelineRunner ToReturn; for (const auto &Container : Declaration.Containers) if (auto error = parseContainerDeclaration(ToReturn, Container); !!error) return move(error); for (const auto &Step : Declaration.Steps) if (auto error = parseStepDeclaration(ToReturn, Step); !!error) return move(error); ToReturn.addStep("End"); return ToReturn; } llvm::Expected PipelineLoader::load(llvm::StringRef Pipeline) const { yaml::Input Input(Pipeline); PipelineDeclaration Declaration; Input >> Declaration; if (Input.error()) return createStringError(inconvertibleErrorCode(), "Could not parse pipeline"); return load(Declaration); }