/// Link support adds the helper functions to a lifeted module // // This file is distributed under the MIT License. See LICENSE.md for details. // #include #include "llvm/ADT/ArrayRef.h" #include "llvm/IRReader/IRReader.h" #include "llvm/Linker/Linker.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/SourceMgr.h" #include "revng/Lift/LinkSupportPipe.h" #include "revng/Model/Architecture.h" #include "revng/Model/Binary.h" #include "revng/Pipeline/AllRegistries.h" #include "revng/Pipes/Kinds.h" #include "revng/Pipes/ModelGlobal.h" #include "revng/Pipes/RootKind.h" #include "revng/Support/Assert.h" #include "revng/Support/CommandLine.h" #include "revng/Support/ResourceFinder.h" using namespace llvm::cl; using namespace pipeline; using namespace revng::pipes; using namespace revng; static opt Tracing("link-trace", cat(MainCategory), init(false), desc("enable tracing when linking support")); static llvm::StringRef getSupportName(model::Architecture::Values V) { using namespace model::Architecture; switch (V) { case Invalid: case Count: revng_abort(); return "Invalid"; case x86: return "i386"; case x86_64: return "x86_64"; case arm: return "arm"; case aarch64: return "aarch64"; case mips: return "mips"; case mipsel: return "mipsel"; case systemz: return "s390x"; } revng_abort(); return "Invalid"; } static std::string getSupportPath(const model::Binary &Model) { const char *SupportConfig = Tracing ? "trace" : "normal"; auto ArchName = getSupportName(Model.Architecture()).str(); std::string SupportSearchPath = ("/share/revng/support-" + ArchName + "-" + SupportConfig + ".ll"); auto OptionalSupportPath = ResourceFinder.findFile(SupportSearchPath); revng_assert(OptionalSupportPath.has_value(), "Cannot find the support module"); std::string SupportPath = OptionalSupportPath.value(); return SupportPath; } void revng::pipes::LinkSupport::run(ExecutionContext &EC, LLVMContainer &ModuleContainer) { if (ModuleContainer.enumerate().empty()) return; std::string SupportPath = getSupportPath(*getModelFromContext(EC)); llvm::SMDiagnostic Err; auto Module = llvm::parseIRFile(SupportPath, Err, ModuleContainer.getModule().getContext()); revng_assert(Module != nullptr); auto Failed = llvm::Linker::linkModules(ModuleContainer.getModule(), std::move(Module)); EC.commitAllFor(ModuleContainer); revng_assert(not Failed); } static pipeline::RegisterPipe E4; namespace revng::pypeline::piperuns { LinkSupport::LinkSupport(const class Model &Model, llvm::StringRef Config, llvm::StringRef DynamicConfig, LLVMRootContainer &ModuleContainer) : Binary(*Model.get().get()), ModuleContainer(ModuleContainer) { } void LinkSupport::run() { std::string SupportPath = getSupportPath(Binary); llvm::SMDiagnostic Err; llvm::LLVMContext &Context = ModuleContainer.getModule().getContext(); auto Module = llvm::parseIRFile(SupportPath, Err, Context); revng_assert(Module != nullptr); bool Failed = llvm::Linker::linkModules(ModuleContainer.getModule(), std::move(Module)); revng_assert(not Failed); } } // namespace revng::pypeline::piperuns