diff --git a/llvm/lib/ExecutionEngine/CMakeLists.txt b/llvm/lib/ExecutionEngine/CMakeLists.txt --- a/llvm/lib/ExecutionEngine/CMakeLists.txt +++ b/llvm/lib/ExecutionEngine/CMakeLists.txt @@ -17,6 +17,7 @@ Core MC Object + OrcTargetProcess RuntimeDyld Support Target diff --git a/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp b/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp --- a/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp +++ b/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp @@ -47,21 +47,28 @@ // We put information about the JITed function in this global, which the // debugger reads. Make sure to specify the version statically, because the // debugger checks the version before we can set it during runtime. - struct jit_descriptor __jit_debug_descriptor = { 1, 0, nullptr, nullptr }; + extern struct jit_descriptor __jit_debug_descriptor; // Debuggers puts a breakpoint in this function. - LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() { - // The noinline and the asm prevent calls to this function from being - // optimized out. -#if !defined(_MSC_VER) - asm volatile("":::"memory"); -#endif - } - + extern "C" void __jit_debug_register_code(); } namespace { +// FIXME: lli aims to provide both, RuntimeDyld and JITLink, as the dynamic +// loaders for it's JIT implementations. And they both offer debugging via the +// GDB JIT interface, which builds on the two well-known symbol names below. +// As these symbols must be unique accross the linked executable, we can only +// define them in one of the libraries and make the other depend on it. +// OrcTargetProcess is a minimal stub for embedding a JIT client in remote +// executors. For the moment it seems reasonable to have the definition there +// and let ExecutionEngine depend on it, until we find a better solution. +// +LLVM_ATTRIBUTE_USED void requiredSymbolDefinitionsFromOrcTargetProcess() { + errs() << (void *)&__jit_debug_register_code + << (void *)&__jit_debug_descriptor; +} + struct RegisteredObjectInfo { RegisteredObjectInfo() {} diff --git a/llvm/tools/lli/lli.cpp b/llvm/tools/lli/lli.cpp --- a/llvm/tools/lli/lli.cpp +++ b/llvm/tools/lli/lli.cpp @@ -24,6 +24,7 @@ #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/ExecutionEngine/ObjectCache.h" +#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h" #include "llvm/ExecutionEngine/Orc/DebugUtils.h" #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" @@ -31,6 +32,11 @@ #include "llvm/ExecutionEngine/Orc/MachOPlatform.h" #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" +#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h" +#include "llvm/ExecutionEngine/Orc/TPCDebugObjectRegistrar.h" +#include "llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h" +#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h" +#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h" #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/IRBuilder.h" @@ -77,6 +83,7 @@ namespace { enum class JITKind { MCJIT, OrcLazy }; + enum class JITLinkerKind { Default, RuntimeDyld, JITLink }; cl::opt InputFile(cl::desc(""), cl::Positional, cl::init("-")); @@ -95,6 +102,16 @@ clEnumValN(JITKind::OrcLazy, "orc-lazy", "Orc-based lazy JIT."))); + cl::opt + JITLinker("jit-linker", cl::desc("Choose the dynamic linker/loader."), + cl::init(JITLinkerKind::Default), + cl::values(clEnumValN(JITLinkerKind::Default, "default", + "Default for platform and JIT-kind"), + clEnumValN(JITLinkerKind::RuntimeDyld, "rtdyld", + "RuntimeDyld"), + clEnumValN(JITLinkerKind::JITLink, "jitlink", + "Orc-specific linker"))); + cl::opt LazyJITCompileThreads("compile-threads", cl::desc("Choose the number of compile threads " @@ -246,6 +263,12 @@ ExitOnError ExitOnErr; } +LLVM_ATTRIBUTE_USED void linkComponents() { + errs() << (void *)&llvm_orc_registerEHFrameSectionWrapper + << (void *)&llvm_orc_deregisterEHFrameSectionWrapper + << (void *)&llvm_orc_registerJITLoaderGDBWrapper; +} + //===----------------------------------------------------------------------===// // Object cache // @@ -879,6 +902,23 @@ } } + std::unique_ptr TPC = nullptr; + if (JITLinker == JITLinkerKind::JITLink) { + TPC = ExitOnErr(orc::SelfTargetProcessControl::Create( + std::make_shared())); + + Builder.setTargetProcessControl(*TPC); + Builder.setObjectLinkingLayerCreator([&TPC](orc::ExecutionSession &ES, + const Triple &) { + auto L = std::make_unique(ES, TPC->getMemMgr()); + L->addPlugin(std::make_unique( + ES, ExitOnErr(orc::TPCEHFrameRegistrar::Create(*TPC)))); + L->addPlugin(std::make_unique( + ES, ExitOnErr(orc::createJITLoaderGDBRegistrar(*TPC)))); + return L; + }); + } + auto J = ExitOnErr(Builder.create()); if (TT->isOSBinFormatELF()) @@ -981,10 +1021,15 @@ // Run main. auto MainSym = ExitOnErr(J->lookup("main")); - typedef int (*MainFnPtr)(int, char *[]); - auto Result = orc::runAsMain( - jitTargetAddressToFunction(MainSym.getAddress()), InputArgv, - StringRef(InputFile)); + // Run main. + int Result; + if (TPC) { + Result = ExitOnErr(TPC->runAsMain(MainSym.getAddress(), InputArgv)); + } else { + using MainFnTy = int(int, char *[]); + auto MainFn = jitTargetAddressToFunction(MainSym.getAddress()); + Result = orc::runAsMain(MainFn, InputArgv, StringRef(InputFile)); + } // Wait for -entry-point threads. for (auto &AltEntryThread : AltEntryThreads)