/// \file Main.cpp // // This file is distributed under the MIT License. See LICENSE.md for details. // #include #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/raw_os_ostream.h" #include "revng/Model/LoadModelPass.h" #include "revng/Pipeline/AllRegistries.h" #include "revng/Pipeline/ContainerSet.h" #include "revng/Pipeline/CopyPipe.h" #include "revng/Pipeline/GenericLLVMPipe.h" #include "revng/Pipeline/LLVMContainerFactory.h" #include "revng/Pipeline/LLVMGlobalKindBase.h" #include "revng/Pipeline/Loader.h" #include "revng/Pipeline/Target.h" #include "revng/Pipes/ModelGlobal.h" #include "revng/Pipes/PipelineManager.h" using std::string; using namespace llvm; using namespace llvm::cl; using namespace pipeline; using namespace ::revng::pipes; static Logger<> PipelineLogger("pipeline"); cl::OptionCategory PipelineCategory("revng-pipeline options", ""); static cl::list InputPipeline("P", desc(""), cat(PipelineCategory)); static cl::list Targets(Positional, Required, desc("..."), cat(PipelineCategory)); static cl::list ContainerOverrides("i", desc("Load the target file in the " "target container at the " "target " "step"), cat(PipelineCategory)); static opt ModelOverride("m", desc("Load the model from a provided file"), cat(PipelineCategory), init("")); static opt SaveModel("save-model", desc("Save the model at the end of the run"), cat(PipelineCategory), init("")); static opt TargetStep("step", Required, desc("name the step in which to produce the " "elements"), cat(PipelineCategory)); static opt ProduceAllPossibleTargets("produce-all", desc("Try producing all possible " "targets"), cat(PipelineCategory), init(false)); static opt InvalidateAll("invalidate-all", desc("Try invalidating all possible " "targets after producing them. Used for " "debug porpuses"), cat(PipelineCategory), init(false)); static opt DumpPipeline("d", desc("Dump built pipeline and dont run"), cat(PipelineCategory)); static opt Verbose("verbose", desc("Print explanation while running"), cat(PipelineCategory), init(false)); static alias VerboseAlias1("v", desc("Alias for --verbose"), aliasopt(Verbose), cat(PipelineCategory)); static cl::list StoresOverrides("o", desc("Store the target container at " "the " "target step in the target file"), cat(PipelineCategory)); static cl::list EnablingFlags("f", desc("list of pipeline enabling flags"), cat(PipelineCategory)); static opt ExecutionDirectory("p", desc("Directory from which all " "containers will " "be loaded before everything else " "and " "to which it will be store after " "everything else"), cat(PipelineCategory)); static cl::list LoadLibraries("load", desc("libraries to open"), cat(PipelineCategory)); static alias A1("l", desc("Alias for --load"), aliasopt(LoadLibraries), cat(PipelineCategory)); static opt PrintBuildableTargets("targets", desc("Prints the target that can be " "produced from the current status " "and exit"), cat(PipelineCategory)); static alias A2("t", desc("Alias for --targets"), aliasopt(PrintBuildableTargets), cat(PipelineCategory)); static ExitOnError AbortOnError; static void runPipeline(Runner &Pipeline) { ContainerToTargetsMap ToProduce; const auto &Registry = Pipeline.getKindsRegistry(); for (const auto &Target : Targets) AbortOnError(parseTarget(ToProduce, Target, Registry)); auto *Stream = Verbose ? &dbgs() : nullptr; AbortOnError(Pipeline.run(TargetStep, ToProduce, Stream)); } static auto makeManager() { return PipelineManager::create(InputPipeline, EnablingFlags, ExecutionDirectory); } int main(int argc, const char *argv[]) { HideUnrelatedOptions(PipelineCategory); ParseCommandLineOptions(argc, argv); auto LoggerOS = PipelineLogger.getAsLLVMStream(); std::string Msg; for (const auto &Library : LoadLibraries) { if (sys::DynamicLibrary::LoadLibraryPermanently(Library.c_str(), &Msg)) AbortOnError(createStringError(inconvertibleErrorCode(), Msg)); } Registry::runAllInitializationRoutines(); auto Manager = AbortOnError(makeManager()); for (const auto &Override : ContainerOverrides) AbortOnError(Manager.overrideContainer(Override)); if (not ModelOverride.empty()) AbortOnError(Manager.overrideModel(ModelOverride)); if (DumpPipeline) { Manager.dump(); return EXIT_SUCCESS; } if (PrintBuildableTargets) { llvm::raw_os_ostream OS(dbg); Manager.writeAllPossibleTargets(OS); return EXIT_SUCCESS; } if (ProduceAllPossibleTargets) { PipelineLogger.enable(); AbortOnError(Manager.produceAllPossibleTargets(*LoggerOS)); } else { runPipeline(Manager.getRunner()); } if (InvalidateAll) { PipelineLogger.enable(); AbortOnError(Manager.invalidateAllPossibleTargets(*LoggerOS)); } AbortOnError(Manager.store(StoresOverrides)); AbortOnError(Manager.storeToDisk()); if (not SaveModel.empty()) { auto Context = Manager.context(); auto ModelName = ModelGlobal::Name; auto FinalModel = AbortOnError(Context.getGlobal(ModelName)); AbortOnError(FinalModel->storeToDisk(SaveModel)); } return EXIT_SUCCESS; }