// // This file is distributed under the MIT License. See LICENSE.md for details. // #include #include #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/ToolOutputFile.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/Global.h" #include "revng/Pipeline/LLVMContainerFactory.h" #include "revng/Pipeline/LLVMKind.h" #include "revng/Pipeline/Loader.h" #include "revng/Pipeline/Step.h" #include "revng/Pipeline/Target.h" #include "revng/Pipeline/Target/YAMLTraits.h" #include "revng/Pipes/ModelGlobal.h" #include "revng/Pipes/PipelineManager.h" #include "revng/Pipes/ToolCLOptions.h" #include "revng/Support/CommandLine.h" #include "revng/Support/InitRevng.h" #include "revng/TupleTree/TupleTree.h" namespace cl = llvm::cl; using namespace pipeline; using namespace ::revng::pipes; static cl::list Arguments(cl::Positional, cl::ZeroOrMore, cl::desc(" "), cl::cat(MainCategory)); static revng::OutputPathOpt Output("o", cl::desc("Output filepath of produced " "model"), cl::cat(MainCategory), cl::init(revng::PathInit::Dash)); static cl::opt NoApplyModel("no-apply", cl::desc("run the analysis but do not apply " "it (used to recreate consistent " "debug configurations)"), cl::cat(MainCategory), cl::init(false)); static cl::opt InvalidationsPath("save-invalidations", cl::desc("path where to save the " "list of invalidated " "targets"), cl::cat(MainCategory), cl::init("")); static ToolCLOptions BaseOptions(MainCategory); static llvm::ExitOnError AbortOnError; static TupleTreeGlobal &getModel(PipelineManager &Manager) { auto &Context = Manager.context(); const auto &ModelName = revng::ModelGlobalName; auto *Result = AbortOnError(Context.getGlobal(ModelName)); revng_assert(Result != nullptr); return *Result; } static llvm::Error overrideModel(PipelineManager &Manager, TupleTree NewModel) { const auto &Name = revng::ModelGlobalName; auto *Model(cantFail(Manager.context().getGlobal(Name))); Model->get() = std::move(NewModel); return llvm::Error::success(); } int main(int argc, char *argv[]) { using revng::FilePath; revng::InitRevng X(argc, argv, "", { &MainCategory }); Registry::runAllInitializationRoutines(); auto Manager = AbortOnError(BaseOptions.makeManager()); const auto &C = Manager.context(); using BR = TupleTreeGlobal; auto OriginalModel = *AbortOnError(C.getGlobal
(revng::ModelGlobalName)); if (Arguments.size() == 0) { std::cout << "USAGE: revng-analyze [options] \n\n"; std::vector> Pairs; std::cout << " can be one of the following analyses list:\n\n"; for (size_t I = 0; I < Manager.getRunner().getAnalysesListCount(); I++) { AnalysesList AL = Manager.getRunner().getAnalysesList(I); std::cout << " " << AL.getName().str() << "\n"; } std::cout << "\n can also be one of the following analyses:\n\n"; for (const auto &Step : Manager.getRunner()) for (const auto &Analysis : Step.analyses()) std::cout << " " << Analysis.getKey().str() << "\n"; return EXIT_SUCCESS; } if (Arguments.size() == 1) { AbortOnError(revng::createError("Expected any number of positional " "arguments different from 1")); } auto &InputContainer = Manager.getRunner().begin()->containers()["input"]; InputPath = Arguments[1]; FilePath InputFilePath = FilePath::fromLocalStorage(Arguments[1]); AbortOnError(InputFilePath.check()); AbortOnError(InputContainer.load(InputFilePath)); auto InvMap = revng::pipes::runAnalysisOrAnalysesList(Manager, Arguments[0], AbortOnError); if (NoApplyModel) AbortOnError(overrideModel(Manager, OriginalModel.get())); if (not InvalidationsPath.empty()) { std::error_code EC; llvm::ToolOutputFile InvalidationOutput(InvalidationsPath, EC, llvm::sys::fs::OpenFlags::OF_Text); if (EC) AbortOnError(llvm::createStringError(EC, EC.message())); serialize(InvalidationOutput.os(), InvMap); InvalidationOutput.keep(); } AbortOnError(Manager.store()); auto &FinalModel = getModel(Manager); auto MaybeOutput = AbortOnError(Output.get()); revng_assert(MaybeOutput.has_value()); AbortOnError(FinalModel.store(*MaybeOutput)); return EXIT_SUCCESS; }