mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
103 lines
3.3 KiB
C++
103 lines
3.3 KiB
C++
#include <optional>
|
|
|
|
#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<PipelineRunner>
|
|
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<PipelineRunner>
|
|
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);
|
|
}
|