<div dir="ltr">Thanks Erik!<div><br></div><div>-- Lang.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Feb 26, 2020 at 2:57 PM Erik Pilkington <<a href="mailto:erik.pilkington@gmail.com">erik.pilkington@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space">I can’t seem to easily reproduce it either, I committed your suggested workaround in 30f4362040f, I’ll keep an eye on the bot to verify that it fixes the issue.<div><br></div><div>Thanks,</div><div>Erik<br><div><br><blockquote type="cite"><div>On Feb 25, 2020, at 9:15 AM, Lang Hames <<a href="mailto:lhames@gmail.com" target="_blank">lhames@gmail.com</a>> wrote:</div><br><div><div dir="auto">Hi Eric,<div><br></div><div>I think this leak is expected (i.e. that cache might not be cleared until process termination), but I will need to talk to the ObjC runtime folks to confirm.</div><div><br></div><div>Any chance you could test a workaround for me in the mean time? I think if we replace the current run line,</div><div><br></div><div>RUN: lli -jit-kind=orc-lazy %s</div><div><br></div><div>with</div><div><br></div><div>RUN: ASAN_OPTIONS=detect_leaks=0 lli -jit-kind=orc-lazy %s</div><div><br></div><div>That should allow us to at least keep running asan on the test. If that doesn’t work we can just disable the test entirely when asan is enabled by adding</div><div><br></div><div>; UNSUPPORTED: asan</div><div><br></div><div>at the top.</div><div><br></div><div>I’d test these myself but my asan build doesn’t seem to have leak checking enabled, so I wasn’t able to reproduce this failure locally.</div><div><br></div><div>Regards,</div><div>Lang.</div><div><br></div><div><div dir="ltr"><blockquote type="cite">On Feb 24, 2020, at 1:44 PM, Lang Hames <<a href="mailto:lhames@gmail.com" target="_blank">lhames@gmail.com</a>> wrote:<br><br></blockquote></div><blockquote type="cite"><div dir="ltr">Hi Eric,<div><br></div><div>Thanks for letting me know! I’ll take a look and see if I can figure this out.</div><div><br></div><div>Regards,</div><div>Lang.<br><br><div dir="ltr">Sent from my iPad</div><div dir="ltr"><br><blockquote type="cite">On Feb 24, 2020, at 10:29 AM, Erik Pilkington <<a href="mailto:erik.pilkington@gmail.com" target="_blank">erik.pilkington@gmail.com</a>> wrote:<br><br></blockquote></div><blockquote type="cite"><div dir="ltr">Hi Lang,<div><br></div><div>It looks like a test you added in this commit is failing on macOS: <a href="http://lab.llvm.org:8080/green/job/clang-stage2-cmake-RgSan/6977" target="_blank">http://lab.llvm.org:8080/green/job/clang-stage2-cmake-RgSan/6977</a></div><div><br></div><div><div>Can you please take a look?</div><div><br></div><div>Thanks!</div><div>Erik<div><blockquote type="cite"></blockquote></div></div></div><div><br></div><div><pre style="word-wrap:break-word;white-space:pre-wrap">******************** TEST 'LLVM :: ExecutionEngine/OrcLazy/objc-minimal.ll' FAILED ********************
Script:
--
: 'RUN: at line 2'; /Users/buildslave/jenkins/workspace/clang-stage2-cmake-RgSan/clang-build/bin/lli -jit-kind=orc-lazy /Users/buildslave/jenkins/workspace/clang-stage2-cmake-RgSan/llvm-project/llvm/test/ExecutionEngine/OrcLazy/objc-minimal.ll
--
Exit Code: 1
Command Output (stderr):
--
=================================================================
==96779==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 80 byte(s) in 1 object(s) allocated from:
#0 0x1127fbef2 in wrap_calloc+0xa2 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x45ef2)
#1 0x7fff5addac5d in allocateBuckets(unsigned int)+0x1d (libobjc.A.dylib:x86_64h+0x9c5d)
#2 0x7fff5addabec in cache_t::reallocate(unsigned int, unsigned int)+0x2a (libobjc.A.dylib:x86_64h+0x9bec)
#3 0x7fff5adda3a8 in cache_fill+0xc2 (libobjc.A.dylib:x86_64h+0x93a8)
#4 0x7fff5add9b94 in lookUpImpOrForward+0x269 (libobjc.A.dylib:x86_64h+0x8b94)
#5 0x7fff5add9493 in _objc_msgSend_uncached+0x43 (libobjc.A.dylib:x86_64h+0x8493)
#6 0x1166f702a (<unknown module>)
#7 0x10a89cd22 in runOrcLazyJIT(char const*) lli.cpp:991
#8 0x10a890b79 in main lli.cpp:409
#9 0x7fff5beb5084 in start+0x0 (libdyld.dylib:x86_64+0x17084)
Direct leak of 80 byte(s) in 1 object(s) allocated from:
#0 0x1127fbef2 in wrap_calloc+0xa2 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x45ef2)
#1 0x7fff5addac5d in allocateBuckets(unsigned int)+0x1d (libobjc.A.dylib:x86_64h+0x9c5d)
#2 0x7fff5addabec in cache_t::reallocate(unsigned int, unsigned int)+0x2a (libobjc.A.dylib:x86_64h+0x9bec)
#3 0x7fff5adda3a8 in cache_fill+0xc2 (libobjc.A.dylib:x86_64h+0x93a8)
#4 0x7fff5add9b94 in lookUpImpOrForward+0x269 (libobjc.A.dylib:x86_64h+0x8b94)
#5 0x7fff5add9493 in _objc_msgSend_uncached+0x43 (libobjc.A.dylib:x86_64h+0x8493)
#6 0x1166f701b (<unknown module>)
#7 0x10a89cd22 in runOrcLazyJIT(char const*) lli.cpp:991
#8 0x10a890b79 in main lli.cpp:409
#9 0x7fff5beb5084 in start+0x0 (libdyld.dylib:x86_64+0x17084)
Direct leak of 64 byte(s) in 1 object(s) allocated from:
#0 0x1127fbef2 in wrap_calloc+0xa2 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x45ef2)
#1 0x7fff5add6510 in realizeClass(objc_class*)+0x4c (libobjc.A.dylib:x86_64h+0x5510)
#2 0x7fff5add65e2 in realizeClass(objc_class*)+0x11e (libobjc.A.dylib:x86_64h+0x55e2)
#3 0x7fff5adee3f5 in objc_readClassPair+0x76 (libobjc.A.dylib:x86_64h+0x1d3f5)
#4 0x10be4620c in llvm::orc::MachOJITDylibInitializers::registerObjCClasses() const MachOPlatform.cpp:133
#5 0x10be246a7 in (anonymous namespace)::MachOPlatformSupport::initialize(llvm::orc::JITDylib&) LLJIT.cpp:525
#6 0x10a8a73f7 in llvm::orc::LLJIT::initialize(llvm::orc::JITDylib&) LLJIT.h:141
#7 0x10a89c514 in runOrcLazyJIT(char const*) lli.cpp:975
#8 0x10a890b79 in main lli.cpp:409
#9 0x7fff5beb5084 in start+0x0 (libdyld.dylib:x86_64+0x17084)
Direct leak of 64 byte(s) in 1 object(s) allocated from:
#0 0x1127fbef2 in wrap_calloc+0xa2 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x45ef2)
#1 0x7fff5add6510 in realizeClass(objc_class*)+0x4c (libobjc.A.dylib:x86_64h+0x5510)
#2 0x7fff5adee3f5 in objc_readClassPair+0x76 (libobjc.A.dylib:x86_64h+0x1d3f5)
#3 0x10be4620c in llvm::orc::MachOJITDylibInitializers::registerObjCClasses() const MachOPlatform.cpp:133
#4 0x10be246a7 in (anonymous namespace)::MachOPlatformSupport::initialize(llvm::orc::JITDylib&) LLJIT.cpp:525
#5 0x10a8a73f7 in llvm::orc::LLJIT::initialize(llvm::orc::JITDylib&) LLJIT.h:141
#6 0x10a89c514 in runOrcLazyJIT(char const*) lli.cpp:975
#7 0x10a890b79 in main lli.cpp:409
#8 0x7fff5beb5084 in start+0x0 (libdyld.dylib:x86_64+0x17084)
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x1127fbef2 in wrap_calloc+0xa2 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x45ef2)
#1 0x7fff5add883d in class_createInstance+0x52 (libobjc.A.dylib:x86_64h+0x783d)
#2 0x7fff5addc595 in _objc_rootAlloc+0x2c (libobjc.A.dylib:x86_64h+0xb595)
#3 0x1166f701b (<unknown module>)
#4 0x10a89cd22 in runOrcLazyJIT(char const*) lli.cpp:991
#5 0x10a890b79 in main lli.cpp:409
#6 0x7fff5beb5084 in start+0x0 (libdyld.dylib:x86_64+0x17084)
SUMMARY: AddressSanitizer: 304 byte(s) leaked in 5 allocation(s)
</pre></div><div><div><blockquote type="cite"><div>On Feb 19, 2020, at 2:03 PM, Lang Hames via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:</div><br><div><div><br>Author: Lang Hames<br>Date: 2020-02-19T13:59:32-08:00<br>New Revision: 85fb997659b55101b58e3545733e581bf4ed9cf2<br><br>URL: <a href="https://github.com/llvm/llvm-project/commit/85fb997659b55101b58e3545733e581bf4ed9cf2" target="_blank">https://github.com/llvm/llvm-project/commit/85fb997659b55101b58e3545733e581bf4ed9cf2</a><br>DIFF: <a href="https://github.com/llvm/llvm-project/commit/85fb997659b55101b58e3545733e581bf4ed9cf2.diff" target="_blank">https://github.com/llvm/llvm-project/commit/85fb997659b55101b58e3545733e581bf4ed9cf2.diff</a><br><br>LOG: [ORC] Add generic initializer/deinitializer support.<br><br>Initializers and deinitializers are used to implement C++ static constructors<br>and destructors, runtime registration for some languages (e.g. with the<br>Objective-C runtime for Objective-C/C++ code) and other tasks that would<br>typically be performed when a shared-object/dylib is loaded or unloaded by a<br>statically compiled program.<br><br>MCJIT and ORC have historically provided limited support for discovering and<br>running initializers/deinitializers by scanning the llvm.global_ctors and<br>llvm.global_dtors variables and recording the functions to be run. This approach<br>suffers from several drawbacks: (1) It only works for IR inputs, not for object<br>files (including cached JIT'd objects). (2) It only works for initializers<br>described by llvm.global_ctors and llvm.global_dtors, however not all<br>initializers are described in this way (Objective-C, for example, describes<br>initializers via specially named metadata sections). (3) To make the<br>initializer/deinitializer functions described by llvm.global_ctors and<br>llvm.global_dtors searchable they must be promoted to extern linkage, polluting<br>the JIT symbol table (extra care must be taken to ensure this promotion does<br>not result in symbol name clashes).<br><br>This patch introduces several interdependent changes to ORCv2 to support the<br>construction of new initialization schemes, and includes an implementation of a<br>backwards-compatible llvm.global_ctor/llvm.global_dtor scanning scheme, and a<br>MachO specific scheme that handles Objective-C runtime registration (if the<br>Objective-C runtime is available) enabling execution of LLVM IR compiled from<br>Objective-C and Swift.<br><br>The major changes included in this patch are:<br><br>(1) The MaterializationUnit and MaterializationResponsibility classes are<br>extended to describe an optional "initializer" symbol for the module (see the<br>getInitializerSymbol method on each class). The presence or absence of this<br>symbol indicates whether the module contains any initializers or<br>deinitializers. The initializer symbol otherwise behaves like any other:<br>searching for it triggers materialization.<br><br>(2) A new Platform interface is introduced in llvm/ExecutionEngine/Orc/Core.h<br>which provides the following callback interface:<br><br> - Error setupJITDylib(JITDylib &JD): Can be used to install standard symbols<br> in JITDylibs upon creation. E.g. __dso_handle.<br><br> - Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU): Generally<br> used to record initializer symbols.<br><br> - Error notifyRemoving(JITDylib &JD, VModuleKey K): Used to notify a platform<br> that a module is being removed.<br><br> Platform implementations can use these callbacks to track outstanding<br>initializers and implement a platform-specific approach for executing them. For<br>example, the MachOPlatform installs a plugin in the JIT linker to scan for both<br>__mod_inits sections (for C++ static constructors) and ObjC metadata sections.<br>If discovered, these are processed in the usual platform order: Objective-C<br>registration is carried out first, then static initializers are executed,<br>ensuring that calls to Objective-C from static initializers will be safe.<br><br>This patch updates LLJIT to use the new scheme for initialization. Two<br>LLJIT::PlatformSupport classes are implemented: A GenericIR platform and a MachO<br>platform. The GenericIR platform implements a modified version of the previous<br>llvm.global-ctor scraping scheme to provide support for Windows and<br>Linux. LLJIT's MachO platform uses the MachOPlatform class to provide MachO<br>specific initialization as described above.<br><br>Reviewers: sgraenitz, dblaikie<br><br>Subscribers: mgorny, hiraditya, mgrang, ributzka, llvm-commits<br><br>Tags: #llvm<br><br>Differential Revision: <a href="https://reviews.llvm.org/D74300" target="_blank">https://reviews.llvm.org/D74300</a><br><br>Added: <br> llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h<br> llvm/include/llvm/ExecutionEngine/Orc/Mangling.h<br> llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp<br> llvm/lib/ExecutionEngine/Orc/Mangling.cpp<br> llvm/test/ExecutionEngine/OrcLazy/objc-minimal.ll<br><br>Modified: <br> llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h<br> llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h<br> llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h<br> llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h<br> llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h<br> llvm/include/llvm/ExecutionEngine/Orc/Core.h<br> llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h<br> llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h<br> llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h<br> llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h<br> llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h<br> llvm/include/llvm/ExecutionEngine/Orc/Layer.h<br> llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h<br> llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h<br> llvm/lib/ExecutionEngine/Orc/CMakeLists.txt<br> llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp<br> llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp<br> llvm/lib/ExecutionEngine/Orc/Core.cpp<br> llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp<br> llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp<br> llvm/lib/ExecutionEngine/Orc/LLJIT.cpp<br> llvm/lib/ExecutionEngine/Orc/Layer.cpp<br> llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp<br> llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp<br> llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp<br> llvm/tools/lli/lli.cpp<br> llvm/tools/llvm-jitlink/llvm-jitlink.cpp<br> llvm/tools/llvm-jitlink/llvm-jitlink.h<br> llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp<br> llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h<br> llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp<br><br>Removed: <br><br><br><br>################################################################################<br>diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h<br>index b7404baf1ff0..adb6be436660 100644<br>--- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h<br>+++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h<br>@@ -49,7 +49,7 @@ class KaleidoscopeJIT {<br> std::make_unique<ConcurrentIRCompiler>(std::move(JTMB))),<br> DL(std::move(DL)), Mangle(ES, this->DL),<br> Ctx(std::make_unique<LLVMContext>()),<br>- MainJD(ES.createJITDylib("<main>")) {<br>+ MainJD(ES.createBareJITDylib("<main>")) {<br> MainJD.addGenerator(<br> cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess(<br> DL.getGlobalPrefix())));<br><br>diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h<br>index efb19349e3e1..28649ffe4910 100644<br>--- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h<br>+++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h<br>@@ -55,7 +55,7 @@ class KaleidoscopeJIT {<br> std::make_unique<ConcurrentIRCompiler>(std::move(JTMB))),<br> OptimizeLayer(ES, CompileLayer, optimizeModule), DL(std::move(DL)),<br> Mangle(ES, this->DL), Ctx(std::make_unique<LLVMContext>()),<br>- MainJD(ES.createJITDylib("<main>")) {<br>+ MainJD(ES.createBareJITDylib("<main>")) {<br> MainJD.addGenerator(<br> cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess(<br> DL.getGlobalPrefix())));<br><br>diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h<br>index 1a8f5cacbcd4..d673a89386da 100644<br>--- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h<br>+++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h<br>@@ -488,6 +488,8 @@ class Symbol {<br><br> /// Set the visibility for this Symbol.<br> void setScope(Scope S) {<br>+ assert((!Name.empty() || S == Scope::Local) &&<br>+ "Can not set anonymous symbol to non-local scope");<br> assert((S == Scope::Default || Base->isDefined() || Base->isAbsolute()) &&<br> "Invalid visibility for symbol type");<br> this->S = static_cast<uint8_t>(S);<br><br>diff --git a/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h<br>index 65295f97e2c6..ef251ac302df 100644<br>--- a/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h<br>+++ b/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h<br>@@ -94,6 +94,7 @@ class CompileOnDemandLayer : public IRLayer {<br><br> /// Sets the ImplSymbolMap<br> void setImplMap(ImplSymbolMap *Imp);<br>+<br> /// Emits the given module. This should not be called by clients: it will be<br> /// called by the JIT when a definition added via the add method is requested.<br> void emit(MaterializationResponsibility R, ThreadSafeModule TSM) override;<br><br>diff --git a/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h<br>index 218afda1b546..8376d163d57a 100644<br>--- a/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h<br>+++ b/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h<br>@@ -30,7 +30,7 @@ namespace orc {<br><br> class JITTargetMachineBuilder;<br><br>-IRMaterializationUnit::ManglingOptions<br>+IRSymbolMapper::ManglingOptions<br> irManglingOptionsFromTargetOptions(const TargetOptions &Opts);<br><br> /// Simple compile functor: Takes a single IR module and returns an ObjectFile.<br>@@ -52,7 +52,7 @@ class SimpleCompiler : public IRCompileLayer::IRCompiler {<br> Expected<CompileResult> operator()(Module &M) override;<br><br> private:<br>- IRMaterializationUnit::ManglingOptions<br>+ IRSymbolMapper::ManglingOptions<br> manglingOptionsForTargetMachine(const TargetMachine &TM);<br><br> CompileResult tryToLoadFromObjectCache(const Module &M);<br><br>diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h<br>index 1a55801b9d87..94600f2286b8 100644<br>--- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h<br>+++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h<br>@@ -14,11 +14,11 @@<br> #define LLVM_EXECUTIONENGINE_ORC_CORE_H<br><br> #include "llvm/ADT/BitmaskEnum.h"<br>+#include "llvm/ADT/DenseSet.h"<br> #include "llvm/ADT/FunctionExtras.h"<br> #include "llvm/ExecutionEngine/JITSymbol.h"<br> #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"<br> #include "llvm/ExecutionEngine/OrcV1Deprecation.h"<br>-#include "llvm/IR/Module.h"<br> #include "llvm/Support/Debug.h"<br><br> #include <memory><br>@@ -456,6 +456,11 @@ class MaterializationResponsibility {<br> /// before using.<br> const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }<br><br>+ /// Returns the initialization pseudo-symbol, if any. This symbol will also<br>+ /// be present in the SymbolFlagsMap for this MaterializationResponsibility<br>+ /// object.<br>+ const SymbolStringPtr &getInitializerSymbol() const { return InitSymbol; }<br>+<br> /// Returns the names of any symbols covered by this<br> /// MaterializationResponsibility object that have queries pending. This<br> /// information can be used to return responsibility for unrequested symbols<br>@@ -532,10 +537,15 @@ class MaterializationResponsibility {<br> /// Create a MaterializationResponsibility for the given JITDylib and<br> /// initial symbols.<br> MaterializationResponsibility(JITDylib &JD, SymbolFlagsMap SymbolFlags,<br>- VModuleKey K);<br>+ SymbolStringPtr InitSymbol, VModuleKey K)<br>+ : JD(JD), SymbolFlags(std::move(SymbolFlags)),<br>+ InitSymbol(std::move(InitSymbol)), K(std::move(K)) {<br>+ assert(!this->SymbolFlags.empty() && "Materializing nothing?");<br>+ }<br><br> JITDylib &JD;<br> SymbolFlagsMap SymbolFlags;<br>+ SymbolStringPtr InitSymbol;<br> VModuleKey K;<br> };<br><br>@@ -549,8 +559,13 @@ class MaterializationResponsibility {<br> /// stronger definition is added or already present.<br> class MaterializationUnit {<br> public:<br>- MaterializationUnit(SymbolFlagsMap InitalSymbolFlags, VModuleKey K)<br>- : SymbolFlags(std::move(InitalSymbolFlags)), K(std::move(K)) {}<br>+ MaterializationUnit(SymbolFlagsMap InitalSymbolFlags,<br>+ SymbolStringPtr InitSymbol, VModuleKey K)<br>+ : SymbolFlags(std::move(InitalSymbolFlags)),<br>+ InitSymbol(std::move(InitSymbol)), K(std::move(K)) {<br>+ assert((!this->InitSymbol || this->SymbolFlags.count(this->InitSymbol)) &&<br>+ "If set, InitSymbol should appear in InitialSymbolFlags map");<br>+ }<br><br> virtual ~MaterializationUnit() {}<br><br>@@ -561,12 +576,15 @@ class MaterializationUnit {<br> /// Return the set of symbols that this source provides.<br> const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }<br><br>+ /// Returns the initialization symbol for this MaterializationUnit (if any).<br>+ const SymbolStringPtr &getInitializerSymbol() const { return InitSymbol; }<br>+<br> /// Called by materialization dispatchers (see<br> /// ExecutionSession::DispatchMaterializationFunction) to trigger<br> /// materialization of this MaterializationUnit.<br> void doMaterialize(JITDylib &JD) {<br>- materialize(MaterializationResponsibility(JD, std::move(SymbolFlags),<br>- std::move(K)));<br>+ materialize(MaterializationResponsibility(<br>+ JD, std::move(SymbolFlags), std::move(InitSymbol), std::move(K)));<br> }<br><br> /// Called by JITDylibs to notify MaterializationUnits that the given symbol<br>@@ -578,6 +596,7 @@ class MaterializationUnit {<br><br> protected:<br> SymbolFlagsMap SymbolFlags;<br>+ SymbolStringPtr InitSymbol;<br> VModuleKey K;<br><br> private:<br>@@ -774,6 +793,7 @@ class AsynchronousSymbolQuery {<br> class JITDylib {<br> friend class AsynchronousSymbolQuery;<br> friend class ExecutionSession;<br>+ friend class Platform;<br> friend class MaterializationResponsibility;<br> public:<br> /// Definition generators can be attached to JITDylibs to generate new<br>@@ -1054,6 +1074,35 @@ class JITDylib {<br> JITDylibSearchOrder SearchOrder;<br> };<br><br>+/// Platforms set up standard symbols and mediate interactions between dynamic<br>+/// initializers (e.g. C++ static constructors) and ExecutionSession state.<br>+/// Note that Platforms do not automatically run initializers: clients are still<br>+/// responsible for doing this.<br>+class Platform {<br>+public:<br>+ virtual ~Platform();<br>+<br>+ /// This method will be called outside the session lock each time a JITDylib<br>+ /// is created (unless it is created with EmptyJITDylib set) to allow the<br>+ /// Platform to install any JITDylib specific standard symbols (e.g<br>+ /// __dso_handle).<br>+ virtual Error setupJITDylib(JITDylib &JD) = 0;<br>+<br>+ /// This method will be called under the ExecutionSession lock each time a<br>+ /// MaterializationUnit is added to a JITDylib.<br>+ virtual Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) = 0;<br>+<br>+ /// This method will be called under the ExecutionSession lock when a<br>+ /// VModuleKey is removed.<br>+ virtual Error notifyRemoving(JITDylib &JD, VModuleKey K) = 0;<br>+<br>+ /// A utility function for looking up initializer symbols. Performs a blocking<br>+ /// lookup for the given symbols in each of the given JITDylibs.<br>+ static Expected<DenseMap<JITDylib *, SymbolMap>><br>+ lookupInitSymbols(ExecutionSession &ES,<br>+ const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms);<br>+};<br>+<br> /// An ExecutionSession represents a running JIT program.<br> class ExecutionSession {<br> // FIXME: Remove this when we remove the old ORC layers.<br>@@ -1078,6 +1127,13 @@ class ExecutionSession {<br> /// Returns a shared_ptr to the SymbolStringPool for this ExecutionSession.<br> std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return SSP; }<br><br>+ /// Set the Platform for this ExecutionSession.<br>+ void setPlatform(std::unique_ptr<Platform> P) { this->P = std::move(P); }<br>+<br>+ /// Get the Platform for this session.<br>+ /// Will return null if no Platform has been set for this ExecutionSession.<br>+ Platform *getPlatform() { return P.get(); }<br>+<br> /// Run the given lambda with the session mutex locked.<br> template <typename Func> decltype(auto) runSessionLocked(Func &&F) {<br> std::lock_guard<std::recursive_mutex> Lock(SessionMutex);<br>@@ -1088,12 +1144,26 @@ class ExecutionSession {<br> /// Ownership of JITDylib remains within Execution Session<br> JITDylib *getJITDylibByName(StringRef Name);<br><br>+ /// Add a new bare JITDylib to this ExecutionSession.<br>+ ///<br>+ /// The JITDylib Name is required to be unique. Clients should verify that<br>+ /// names are not being re-used (E.g. by calling getJITDylibByName) if names<br>+ /// are based on user input.<br>+ ///<br>+ /// This call does not install any library code or symbols into the newly<br>+ /// created JITDylib. The client is responsible for all configuration.<br>+ JITDylib &createBareJITDylib(std::string Name);<br>+<br> /// Add a new JITDylib to this ExecutionSession.<br> ///<br> /// The JITDylib Name is required to be unique. Clients should verify that<br> /// names are not being re-used (e.g. by calling getJITDylibByName) if names<br> /// are based on user input.<br>- JITDylib &createJITDylib(std::string Name);<br>+ ///<br>+ /// If a Platform is attached then Platform::setupJITDylib will be called to<br>+ /// install standard platform symbols (e.g. standard library interposes).<br>+ /// If no Platform is attached this call is equivalent to createBareJITDylib.<br>+ Expected<JITDylib &> createJITDylib(std::string Name);<br><br> /// Allocate a module key for a new module to add to the JIT.<br> VModuleKey allocateVModule() {<br>@@ -1177,20 +1247,23 @@ class ExecutionSession {<br> /// Convenience version of blocking lookup.<br> /// Searches each of the JITDylibs in the search order in turn for the given<br> /// symbol.<br>- Expected<JITEvaluatedSymbol> lookup(const JITDylibSearchOrder &SearchOrder,<br>- SymbolStringPtr Symbol);<br>+ Expected<JITEvaluatedSymbol><br>+ lookup(const JITDylibSearchOrder &SearchOrder, SymbolStringPtr Symbol,<br>+ SymbolState RequiredState = SymbolState::Ready);<br><br> /// Convenience version of blocking lookup.<br> /// Searches each of the JITDylibs in the search order in turn for the given<br> /// symbol. The search will not find non-exported symbols.<br>- Expected<JITEvaluatedSymbol> lookup(ArrayRef<JITDylib *> SearchOrder,<br>- SymbolStringPtr Symbol);<br>+ Expected<JITEvaluatedSymbol><br>+ lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Symbol,<br>+ SymbolState RequiredState = SymbolState::Ready);<br><br> /// Convenience version of blocking lookup.<br> /// Searches each of the JITDylibs in the search order in turn for the given<br> /// symbol. The search will not find non-exported symbols.<br>- Expected<JITEvaluatedSymbol> lookup(ArrayRef<JITDylib *> SearchOrder,<br>- StringRef Symbol);<br>+ Expected<JITEvaluatedSymbol><br>+ lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Symbol,<br>+ SymbolState RequiredState = SymbolState::Ready);<br><br> /// Materialize the given unit.<br> void dispatchMaterialization(JITDylib &JD,<br>@@ -1221,6 +1294,7 @@ class ExecutionSession {<br><br> mutable std::recursive_mutex SessionMutex;<br> std::shared_ptr<SymbolStringPool> SSP;<br>+ std::unique_ptr<Platform> P;<br> VModuleKey LastKey = 0;<br> ErrorReporter ReportError = logErrorsToStdErr;<br> DispatchMaterializationFunction DispatchMaterialization =<br>@@ -1256,6 +1330,11 @@ Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU) {<br> if (auto Err = defineImpl(*MU))<br> return Err;<br><br>+ if (auto *P = ES.getPlatform()) {<br>+ if (auto Err = P->notifyAdding(*this, *MU))<br>+ return Err;<br>+ }<br>+<br> /// defineImpl succeeded.<br> auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));<br> for (auto &KV : UMI->MU->getSymbols())<br>@@ -1273,6 +1352,11 @@ Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU) {<br> if (auto Err = defineImpl(*MU))<br> return Err;<br><br>+ if (auto *P = ES.getPlatform()) {<br>+ if (auto Err = P->notifyAdding(*this, *MU))<br>+ return Err;<br>+ }<br>+<br> /// defineImpl succeeded.<br> auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));<br> for (auto &KV : UMI->MU->getSymbols())<br>@@ -1305,18 +1389,6 @@ class ReexportsGenerator : public JITDylib::DefinitionGenerator {<br> SymbolPredicate Allow;<br> };<br><br>-/// Mangles symbol names then uniques them in the context of an<br>-/// ExecutionSession.<br>-class MangleAndInterner {<br>-public:<br>- MangleAndInterner(ExecutionSession &ES, const DataLayout &DL);<br>- SymbolStringPtr operator()(StringRef Name);<br>-<br>-private:<br>- ExecutionSession &ES;<br>- const DataLayout &DL;<br>-};<br>-<br> } // End namespace orc<br> } // End namespace llvm<br><br><br>diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h<br>index f7255c5af845..49ab0d628b0b 100644<br>--- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h<br>+++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h<br>@@ -17,6 +17,7 @@<br> #include "llvm/ADT/iterator_range.h"<br> #include "llvm/ExecutionEngine/JITSymbol.h"<br> #include "llvm/ExecutionEngine/Orc/Core.h"<br>+#include "llvm/ExecutionEngine/Orc/Mangling.h"<br> #include "llvm/ExecutionEngine/Orc/OrcError.h"<br> #include "llvm/ExecutionEngine/RuntimeDyld.h"<br> #include "llvm/Object/Archive.h"<br>@@ -104,6 +105,53 @@ iterator_range<CtorDtorIterator> getConstructors(const Module &M);<br> /// array.<br> iterator_range<CtorDtorIterator> getDestructors(const Module &M);<br><br>+/// This iterator provides a convenient way to iterate over GlobalValues that<br>+/// have initialization effects.<br>+class StaticInitGVIterator {<br>+public:<br>+ StaticInitGVIterator() = default;<br>+<br>+ StaticInitGVIterator(Module &M)<br>+ : I(M.global_values().begin()), E(M.global_values().end()),<br>+ ObjFmt(Triple(M.getTargetTriple()).getObjectFormat()) {<br>+ if (I != E) {<br>+ if (!isStaticInitGlobal(*I))<br>+ moveToNextStaticInitGlobal();<br>+ } else<br>+ I = E = Module::global_value_iterator();<br>+ }<br>+<br>+ bool operator==(const StaticInitGVIterator &O) const { return I == O.I; }<br>+ bool operator!=(const StaticInitGVIterator &O) const { return I != O.I; }<br>+<br>+ StaticInitGVIterator &operator++() {<br>+ assert(I != E && "Increment past end of range");<br>+ moveToNextStaticInitGlobal();<br>+ return *this;<br>+ }<br>+<br>+ GlobalValue &operator*() { return *I; }<br>+<br>+private:<br>+ bool isStaticInitGlobal(GlobalValue &GV);<br>+ void moveToNextStaticInitGlobal() {<br>+ ++I;<br>+ while (I != E && !isStaticInitGlobal(*I))<br>+ ++I;<br>+ if (I == E)<br>+ I = E = Module::global_value_iterator();<br>+ }<br>+<br>+ Module::global_value_iterator I, E;<br>+ Triple::ObjectFormatType ObjFmt;<br>+};<br>+<br>+/// Create an iterator range over the GlobalValues that contribute to static<br>+/// initialization.<br>+inline iterator_range<StaticInitGVIterator> getStaticInitGVs(Module &M) {<br>+ return make_range(StaticInitGVIterator(M), StaticInitGVIterator());<br>+}<br>+<br> /// Convenience class for recording constructor/destructor names for<br> /// later execution.<br> template <typename JITLayerT><br>@@ -246,6 +294,22 @@ class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase {<br> Error enable(JITDylib &JD, MangleAndInterner &Mangler);<br> };<br><br>+/// An interface for Itanium __cxa_atexit interposer implementations.<br>+class ItaniumCXAAtExitSupport {<br>+public:<br>+ struct AtExitRecord {<br>+ void (*F)(void *);<br>+ void *Ctx;<br>+ };<br>+<br>+ void registerAtExit(void (*F)(void *), void *Ctx, void *DSOHandle);<br>+ void runAtExits(void *DSOHandle);<br>+<br>+private:<br>+ std::mutex AtExitsMutex;<br>+ DenseMap<void *, std::vector<AtExitRecord>> AtExitRecords;<br>+};<br>+<br> /// A utility class to expose symbols found via dlsym to the JIT.<br> ///<br> /// If an instance of this class is attached to a JITDylib as a fallback<br><br>diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h<br>index bb8270fe80a3..eb74d283f043 100644<br>--- a/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h<br>+++ b/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h<br>@@ -31,18 +31,18 @@ class IRCompileLayer : public IRLayer {<br> public:<br> class IRCompiler {<br> public:<br>- IRCompiler(IRMaterializationUnit::ManglingOptions MO) : MO(std::move(MO)) {}<br>+ IRCompiler(IRSymbolMapper::ManglingOptions MO) : MO(std::move(MO)) {}<br> virtual ~IRCompiler();<br>- const IRMaterializationUnit::ManglingOptions &getManglingOptions() const {<br>+ const IRSymbolMapper::ManglingOptions &getManglingOptions() const {<br> return MO;<br> }<br> virtual Expected<std::unique_ptr<MemoryBuffer>> operator()(Module &M) = 0;<br><br> protected:<br>- IRMaterializationUnit::ManglingOptions &manglingOptions() { return MO; }<br>+ IRSymbolMapper::ManglingOptions &manglingOptions() { return MO; }<br><br> private:<br>- IRMaterializationUnit::ManglingOptions MO;<br>+ IRSymbolMapper::ManglingOptions MO;<br> };<br><br> using NotifyCompiledFunction =<br>@@ -61,7 +61,7 @@ class IRCompileLayer : public IRLayer {<br> mutable std::mutex IRLayerMutex;<br> ObjectLayer &BaseLayer;<br> std::unique_ptr<IRCompiler> Compile;<br>- const IRMaterializationUnit::ManglingOptions *ManglingOpts;<br>+ const IRSymbolMapper::ManglingOptions *ManglingOpts;<br> NotifyCompiledFunction NotifyCompiled = NotifyCompiledFunction();<br> };<br><br><br>diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h<br>index b71e5b339711..296d74ae6b86 100644<br>--- a/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h<br>+++ b/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h<br>@@ -28,7 +28,7 @@ namespace orc {<br> class IRTransformLayer : public IRLayer {<br> public:<br> using TransformFunction = std::function<Expected<ThreadSafeModule>(<br>- ThreadSafeModule, const MaterializationResponsibility &R)>;<br>+ ThreadSafeModule, MaterializationResponsibility &R)>;<br><br> IRTransformLayer(ExecutionSession &ES, IRLayer &BaseLayer,<br> TransformFunction Transform = identityTransform);<br>@@ -39,9 +39,8 @@ class IRTransformLayer : public IRLayer {<br><br> void emit(MaterializationResponsibility R, ThreadSafeModule TSM) override;<br><br>- static ThreadSafeModule<br>- identityTransform(ThreadSafeModule TSM,<br>- const MaterializationResponsibility &R) {<br>+ static ThreadSafeModule identityTransform(ThreadSafeModule TSM,<br>+ MaterializationResponsibility &R) {<br> return TSM;<br> }<br><br><br>diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h<br>index a9ab3a630a64..880c8ff44c5f 100644<br>--- a/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h<br>+++ b/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h<br>@@ -201,7 +201,7 @@ class JITCompileCallbackManager {<br> ExecutionSession &ES,<br> JITTargetAddress ErrorHandlerAddress)<br> : TP(std::move(TP)), ES(ES),<br>- CallbacksJD(ES.createJITDylib("<Callbacks>")),<br>+ CallbacksJD(ES.createBareJITDylib("<Callbacks>")),<br> ErrorHandlerAddress(ErrorHandlerAddress) {}<br><br> void setTrampolinePool(std::unique_ptr<TrampolinePool> TP) {<br><br>diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h<br>index 3374a29f04df..c0b5012f801f 100644<br>--- a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h<br>+++ b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h<br>@@ -35,7 +35,23 @@ class LLLazyJITBuilderState;<br> class LLJIT {<br> template <typename, typename, typename> friend class LLJITBuilderSetters;<br><br>+ friend void setUpGenericLLVMIRPlatform(LLJIT &J);<br>+<br> public:<br>+ /// Initializer support for LLJIT.<br>+ class PlatformSupport {<br>+ public:<br>+ virtual ~PlatformSupport();<br>+<br>+ virtual Error initialize(JITDylib &JD) = 0;<br>+<br>+ virtual Error deinitialize(JITDylib &JD) = 0;<br>+<br>+ protected:<br>+ static void setInitTransform(LLJIT &J,<br>+ IRTransformLayer::TransformFunction T);<br>+ };<br>+<br> static Expected<std::unique_ptr<LLJIT>> Create(LLJITBuilderState &S);<br><br> /// Destruct this instance. If a multi-threaded instance, waits for all<br>@@ -52,7 +68,7 @@ class LLJIT {<br> const DataLayout &getDataLayout() const { return DL; }<br><br> /// Returns a reference to the JITDylib representing the JIT'd main program.<br>- JITDylib &getMainJITDylib() { return Main; }<br>+ JITDylib &getMainJITDylib() { return *Main; }<br><br> /// Returns the JITDylib with the given name, or nullptr if no JITDylib with<br> /// that name exists.<br>@@ -66,7 +82,7 @@ class LLJIT {<br> /// input or elsewhere in the environment then the client should check<br> /// (e.g. by calling getJITDylibByName) that the given name is not already in<br> /// use.<br>- JITDylib &createJITDylib(std::string Name) {<br>+ Expected<JITDylib &> createJITDylib(std::string Name) {<br> return ES->createJITDylib(std::move(Name));<br> }<br><br>@@ -78,7 +94,7 @@ class LLJIT {<br><br> /// Adds an IR module to the Main JITDylib.<br> Error addIRModule(ThreadSafeModule TSM) {<br>- return addIRModule(Main, std::move(TSM));<br>+ return addIRModule(*Main, std::move(TSM));<br> }<br><br> /// Adds an object file to the given JITDylib.<br>@@ -86,7 +102,7 @@ class LLJIT {<br><br> /// Adds an object file to the given JITDylib.<br> Error addObjectFile(std::unique_ptr<MemoryBuffer> Obj) {<br>- return addObjectFile(Main, std::move(Obj));<br>+ return addObjectFile(*Main, std::move(Obj));<br> }<br><br> /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to<br>@@ -98,7 +114,7 @@ class LLJIT {<br> /// (to look up symbols based on their IR name use the lookup function<br> /// instead).<br> Expected<JITEvaluatedSymbol> lookupLinkerMangled(StringRef Name) {<br>- return lookupLinkerMangled(Main, Name);<br>+ return lookupLinkerMangled(*Main, Name);<br> }<br><br> /// Look up a symbol in JITDylib JD based on its IR symbol name.<br>@@ -108,14 +124,28 @@ class LLJIT {<br><br> /// Look up a symbol in the main JITDylib based on its IR symbol name.<br> Expected<JITEvaluatedSymbol> lookup(StringRef UnmangledName) {<br>- return lookup(Main, UnmangledName);<br>+ return lookup(*Main, UnmangledName);<br> }<br><br>- /// Runs all not-yet-run static constructors.<br>- Error runConstructors() { return CtorRunner.run(); }<br>+ /// Set the PlatformSupport instance.<br>+ void setPlatformSupport(std::unique_ptr<PlatformSupport> PS) {<br>+ this->PS = std::move(PS);<br>+ }<br><br>- /// Runs all not-yet-run static destructors.<br>- Error runDestructors() { return DtorRunner.run(); }<br>+ /// Get the PlatformSupport instance.<br>+ PlatformSupport *getPlatformSupport() { return PS.get(); }<br>+<br>+ /// Run the initializers for the given JITDylib.<br>+ Error initialize(JITDylib &JD) {<br>+ assert(PS && "PlatformSupport must be set to run initializers.");<br>+ return PS->initialize(JD);<br>+ }<br>+<br>+ /// Run the deinitializers for the given JITDylib.<br>+ Error deinitialize(JITDylib &JD) {<br>+ assert(PS && "PlatformSupport must be set to run initializers.");<br>+ return PS->deinitialize(JD);<br>+ }<br><br> /// Returns a reference to the ObjLinkingLayer<br> ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; }<br>@@ -126,6 +156,9 @@ class LLJIT {<br> /// Returns a reference to the IR transform layer.<br> IRTransformLayer &getIRTransformLayer() { return *TransformLayer; }<br><br>+ /// Returns a reference to the IR compile layer.<br>+ IRCompileLayer &getIRCompileLayer() { return *CompileLayer; }<br>+<br> protected:<br> static std::unique_ptr<ObjectLayer><br> createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES);<br>@@ -143,7 +176,9 @@ class LLJIT {<br> void recordCtorDtors(Module &M);<br><br> std::unique_ptr<ExecutionSession> ES;<br>- JITDylib &Main;<br>+ std::unique_ptr<PlatformSupport> PS;<br>+<br>+ JITDylib *Main = nullptr;<br><br> DataLayout DL;<br> Triple TT;<br>@@ -153,8 +188,7 @@ class LLJIT {<br> ObjectTransformLayer ObjTransformLayer;<br> std::unique_ptr<IRCompileLayer> CompileLayer;<br> std::unique_ptr<IRTransformLayer> TransformLayer;<br>-<br>- CtorDtorRunner CtorRunner, DtorRunner;<br>+ std::unique_ptr<IRTransformLayer> InitHelperTransformLayer;<br> };<br><br> /// An extended version of LLJIT that supports lazy function-at-a-time<br>@@ -175,7 +209,7 @@ class LLLazyJIT : public LLJIT {<br><br> /// Add a module to be lazily compiled to the main JITDylib.<br> Error addLazyIRModule(ThreadSafeModule M) {<br>- return addLazyIRModule(Main, std::move(M));<br>+ return addLazyIRModule(*Main, std::move(M));<br> }<br><br> private:<br>@@ -196,10 +230,14 @@ class LLJITBuilderState {<br> std::function<Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>(<br> JITTargetMachineBuilder JTMB)>;<br><br>+ using PlatformSetupFunction = std::function<Error(LLJIT &J)>;<br>+<br> std::unique_ptr<ExecutionSession> ES;<br> Optional<JITTargetMachineBuilder> JTMB;<br>+ Optional<DataLayout> DL;<br> ObjectLinkingLayerCreator CreateObjectLinkingLayer;<br> CompileFunctionCreator CreateCompileFunction;<br>+ PlatformSetupFunction SetUpPlatform;<br> unsigned NumCompileThreads = 0;<br><br> /// Called prior to JIT class construcion to fix up defaults.<br>@@ -224,6 +262,13 @@ class LLJITBuilderSetters {<br> return impl().JTMB;<br> }<br><br>+ /// Set a DataLayout for this instance. If no data layout is specified then<br>+ /// the target's default data layout will be used.<br>+ SetterImpl &setDataLayout(Optional<DataLayout> DL) {<br>+ impl().DL = std::move(DL);<br>+ return impl();<br>+ }<br>+<br> /// Set an ObjectLinkingLayer creation function.<br> ///<br> /// If this method is not called, a default creation function will be used<br>@@ -246,6 +291,16 @@ class LLJITBuilderSetters {<br> return impl();<br> }<br><br>+ /// Set up an PlatformSetupFunction.<br>+ ///<br>+ /// If this method is not called then setUpGenericLLVMIRPlatform<br>+ /// will be used to configure the JIT's platform support.<br>+ SetterImpl &<br>+ setPlatformSetUp(LLJITBuilderState::PlatformSetupFunction SetUpPlatform) {<br>+ impl().SetUpPlatform = std::move(SetUpPlatform);<br>+ return impl();<br>+ }<br>+<br> /// Set the number of compile threads to use.<br> ///<br> /// If set to zero, compilation will be performed on the execution thread when<br>@@ -334,6 +389,26 @@ class LLLazyJITBuilder<br> public LLLazyJITBuilderSetters<LLLazyJIT, LLLazyJITBuilder,<br> LLLazyJITBuilderState> {};<br><br>+/// Configure the LLJIT instance to scrape modules for llvm.global_ctors and<br>+/// llvm.global_dtors variables and (if present) build initialization and<br>+/// deinitialization functions. Platform specific initialization configurations<br>+/// should be preferred where available.<br>+void setUpGenericLLVMIRPlatform(LLJIT &J);<br>+<br>+/// Configure the LLJIT instance to use MachOPlatform support.<br>+///<br>+/// Warning: MachOPlatform *requires* that LLJIT be configured to use<br>+/// ObjectLinkingLayer (default on platforms supported by JITLink). If<br>+/// MachOPlatform is used with RTDyldObjectLinkingLayer it will result in<br>+/// undefined behavior).<br>+///<br>+/// MachOPlatform installs an ObjectLinkingLayer plugin to scrape initializers<br>+/// from the __mod_inits section. It also provides interposes for the dlfcn<br>+/// functions (dlopen, dlclose, dlsym, dlerror) that work for JITDylibs as<br>+/// well as regular libraries (JITDylibs will be preferenced, so make sure<br>+/// your JITDylib names do not shadow any real library paths).<br>+Error setUpMachOPlatform(LLJIT &J);<br>+<br> } // End namespace orc<br> } // End namespace llvm<br><br><br>diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Layer.h b/llvm/include/llvm/ExecutionEngine/Orc/Layer.h<br>index 95e32b2431a0..e843d0f56245 100644<br>--- a/llvm/include/llvm/ExecutionEngine/Orc/Layer.h<br>+++ b/llvm/include/llvm/ExecutionEngine/Orc/Layer.h<br>@@ -14,6 +14,7 @@<br> #define LLVM_EXECUTIONENGINE_ORC_LAYER_H<br><br> #include "llvm/ExecutionEngine/Orc/Core.h"<br>+#include "llvm/ExecutionEngine/Orc/Mangling.h"<br> #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"<br> #include "llvm/IR/Module.h"<br> #include "llvm/Support/MemoryBuffer.h"<br>@@ -27,15 +28,12 @@ namespace orc {<br> /// their linkage is changed to available-externally.<br> class IRMaterializationUnit : public MaterializationUnit {<br> public:<br>- struct ManglingOptions {<br>- bool EmulatedTLS = false;<br>- };<br>-<br> using SymbolNameToDefinitionMap = std::map<SymbolStringPtr, GlobalValue *>;<br><br> /// Create an IRMaterializationLayer. Scans the module to build the<br> /// SymbolFlags and SymbolToDefinition maps.<br>- IRMaterializationUnit(ExecutionSession &ES, const ManglingOptions &MO,<br>+ IRMaterializationUnit(ExecutionSession &ES,<br>+ const IRSymbolMapper::ManglingOptions &MO,<br> ThreadSafeModule TSM, VModuleKey K);<br><br> /// Create an IRMaterializationLayer from a module, and pre-existing<br>@@ -44,12 +42,13 @@ class IRMaterializationUnit : public MaterializationUnit {<br> /// This constructor is useful for delegating work from one<br> /// IRMaterializationUnit to another.<br> IRMaterializationUnit(ThreadSafeModule TSM, VModuleKey K,<br>- SymbolFlagsMap SymbolFlags,<br>+ SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol,<br> SymbolNameToDefinitionMap SymbolToDefinition);<br><br> /// Return the ModuleIdentifier as the name for this MaterializationUnit.<br> StringRef getName() const override;<br><br>+ /// Return a reference to the contained ThreadSafeModule.<br> const ThreadSafeModule &getModule() const { return TSM; }<br><br> protected:<br>@@ -57,14 +56,16 @@ class IRMaterializationUnit : public MaterializationUnit {<br> SymbolNameToDefinitionMap SymbolToDefinition;<br><br> private:<br>+ static SymbolStringPtr getInitSymbol(ExecutionSession &ES,<br>+ const ThreadSafeModule &TSM);<br>+<br> void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;<br> };<br><br> /// Interface for layers that accept LLVM IR.<br> class IRLayer {<br> public:<br>- IRLayer(ExecutionSession &ES,<br>- const IRMaterializationUnit::ManglingOptions *&MO)<br>+ IRLayer(ExecutionSession &ES, const IRSymbolMapper::ManglingOptions *&MO)<br> : ES(ES), MO(MO) {}<br><br> virtual ~IRLayer();<br>@@ -73,7 +74,7 @@ class IRLayer {<br> ExecutionSession &getExecutionSession() { return ES; }<br><br> /// Get the mangling options for this layer.<br>- const IRMaterializationUnit::ManglingOptions *&getManglingOptions() const {<br>+ const IRSymbolMapper::ManglingOptions *&getManglingOptions() const {<br> return MO;<br> }<br><br>@@ -104,14 +105,15 @@ class IRLayer {<br> private:<br> bool CloneToNewContextOnEmit = false;<br> ExecutionSession &ES;<br>- const IRMaterializationUnit::ManglingOptions *&MO;<br>+ const IRSymbolMapper::ManglingOptions *&MO;<br> };<br><br> /// MaterializationUnit that materializes modules by calling the 'emit' method<br> /// on the given IRLayer.<br> class BasicIRLayerMaterializationUnit : public IRMaterializationUnit {<br> public:<br>- BasicIRLayerMaterializationUnit(IRLayer &L, const ManglingOptions &MO,<br>+ BasicIRLayerMaterializationUnit(IRLayer &L,<br>+ const IRSymbolMapper::ManglingOptions &MO,<br> ThreadSafeModule TSM, VModuleKey K);<br><br> private:<br>@@ -153,7 +155,8 @@ class BasicObjectLayerMaterializationUnit : public MaterializationUnit {<br><br> BasicObjectLayerMaterializationUnit(ObjectLayer &L, VModuleKey K,<br> std::unique_ptr<MemoryBuffer> O,<br>- SymbolFlagsMap SymbolFlags);<br>+ SymbolFlagsMap SymbolFlags,<br>+ SymbolStringPtr InitSymbol);<br><br> /// Return the buffer's identifier as the name for this MaterializationUnit.<br> StringRef getName() const override;<br>@@ -167,12 +170,6 @@ class BasicObjectLayerMaterializationUnit : public MaterializationUnit {<br> std::unique_ptr<MemoryBuffer> O;<br> };<br><br>-/// Returns a SymbolFlagsMap for the object file represented by the given<br>-/// buffer, or an error if the buffer does not contain a valid object file.<br>-// FIXME: Maybe move to Core.h?<br>-Expected<SymbolFlagsMap> getObjectSymbolFlags(ExecutionSession &ES,<br>- MemoryBufferRef ObjBuffer);<br>-<br> } // End namespace orc<br> } // End namespace llvm<br><br><br>diff --git a/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h b/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h<br>new file mode 100644<br>index 000000000000..92c1a04921b8<br>--- /dev/null<br>+++ b/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h<br>@@ -0,0 +1,147 @@<br>+//===-- MachOPlatform.h - Utilities for executing MachO in Orc --*- C++ -*-===//<br>+//<br>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.<br>+// See <a href="https://llvm.org/LICENSE.txt" target="_blank">https://llvm.org/LICENSE.txt</a> for license information.<br>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception<br>+//<br>+//===----------------------------------------------------------------------===//<br>+//<br>+// Utilities for executing JIT'd MachO in Orc.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H<br>+#define LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H<br>+<br>+#include "llvm/ADT/StringRef.h"<br>+#include "llvm/ExecutionEngine/Orc/Core.h"<br>+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"<br>+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"<br>+<br>+#include <future><br>+#include <thread><br>+#include <vector><br>+<br>+namespace llvm {<br>+namespace orc {<br>+<br>+/// Enable registration of JIT'd ObjC classes and selectors.<br>+Error enableObjCRegistration(const char *PathToLibObjC);<br>+bool objCRegistrationEnabled();<br>+<br>+class MachOJITDylibInitializers {<br>+public:<br>+ struct SectionExtent {<br>+ SectionExtent() = default;<br>+ SectionExtent(JITTargetAddress Address, uint64_t NumPtrs)<br>+ : Address(Address), NumPtrs(NumPtrs) {}<br>+ JITTargetAddress Address = 0;<br>+ uint64_t NumPtrs = 0;<br>+ };<br>+<br>+ void setObjCImageInfoAddr(JITTargetAddress ObjCImageInfoAddr) {<br>+ this->ObjCImageInfoAddr = ObjCImageInfoAddr;<br>+ }<br>+<br>+ void addModInitsSection(SectionExtent ModInit) {<br>+ ModInitSections.push_back(std::move(ModInit));<br>+ }<br>+<br>+ void addObjCSelRefsSection(SectionExtent ObjCSelRefs) {<br>+ ObjCSelRefsSections.push_back(std::move(ObjCSelRefs));<br>+ }<br>+<br>+ void addObjCClassListSection(SectionExtent ObjCClassList) {<br>+ ObjCClassListSections.push_back(std::move(ObjCClassList));<br>+ }<br>+<br>+ void runModInits() const;<br>+ void registerObjCSelectors() const;<br>+ Error registerObjCClasses() const;<br>+<br>+ void dump() const;<br>+<br>+private:<br>+ using RawPointerSectionList = std::vector<SectionExtent>;<br>+<br>+ JITTargetAddress ObjCImageInfoAddr;<br>+ RawPointerSectionList ModInitSections;<br>+ RawPointerSectionList ObjCSelRefsSections;<br>+ RawPointerSectionList ObjCClassListSections;<br>+};<br>+<br>+class MachOJITDylibDeinitializers {};<br>+<br>+/// Mediates between MachO initialization and ExecutionSession state.<br>+class MachOPlatform : public Platform {<br>+public:<br>+ using InitializerSequence =<br>+ std::vector<std::pair<JITDylib *, MachOJITDylibInitializers>>;<br>+<br>+ using DeinitializerSequence =<br>+ std::vector<std::pair<JITDylib *, MachOJITDylibDeinitializers>>;<br>+<br>+ MachOPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,<br>+ std::unique_ptr<MemoryBuffer> StandardSymbolsObject);<br>+<br>+ ExecutionSession &getExecutionSession() const { return ES; }<br>+<br>+ Error setupJITDylib(JITDylib &JD) override;<br>+ Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) override;<br>+ Error notifyRemoving(JITDylib &JD, VModuleKey K) override;<br>+<br>+ Expected<InitializerSequence> getInitializerSequence(JITDylib &JD);<br>+<br>+ Expected<DeinitializerSequence> getDeinitializerSequence(JITDylib &JD);<br>+<br>+private:<br>+ // This ObjectLinkingLayer plugin scans JITLink graphs for __mod_init_func,<br>+ // __objc_classlist and __sel_ref sections and records their extents so that<br>+ // they can be run in the target process.<br>+ class InitScraperPlugin : public ObjectLinkingLayer::Plugin {<br>+ public:<br>+ InitScraperPlugin(MachOPlatform &MP) : MP(MP) {}<br>+<br>+ void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,<br>+ jitlink::PassConfiguration &Config) override;<br>+<br>+ LocalDependenciesMap getSyntheticSymbolLocalDependencies(<br>+ MaterializationResponsibility &MR) override;<br>+<br>+ private:<br>+ using InitSymbolDepMap =<br>+ DenseMap<MaterializationResponsibility *, JITLinkSymbolVector>;<br>+<br>+ void preserveInitSectionIfPresent(JITLinkSymbolVector &Syms,<br>+ jitlink::LinkGraph &G,<br>+ StringRef SectionName);<br>+<br>+ Error processObjCImageInfo(jitlink::LinkGraph &G,<br>+ MaterializationResponsibility &MR);<br>+<br>+ std::mutex InitScraperMutex;<br>+ MachOPlatform &MP;<br>+ DenseMap<JITDylib *, std::pair<uint32_t, uint32_t>> ObjCImageInfos;<br>+ InitSymbolDepMap InitSymbolDeps;<br>+ };<br>+<br>+ static std::vector<JITDylib *> getDFSLinkOrder(JITDylib &JD);<br>+<br>+ void registerInitInfo(JITDylib &JD, JITTargetAddress ObjCImageInfoAddr,<br>+ MachOJITDylibInitializers::SectionExtent ModInits,<br>+ MachOJITDylibInitializers::SectionExtent ObjCSelRefs,<br>+ MachOJITDylibInitializers::SectionExtent ObjCClassList);<br>+<br>+ std::mutex PlatformMutex;<br>+ ExecutionSession &ES;<br>+ ObjectLinkingLayer &ObjLinkingLayer;<br>+ std::unique_ptr<MemoryBuffer> StandardSymbolsObject;<br>+<br>+ DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;<br>+ DenseMap<JITDylib *, MachOJITDylibInitializers> InitSeqs;<br>+};<br>+<br>+} // end namespace orc<br>+} // end namespace llvm<br>+<br>+#endif // LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H<br><br>diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h b/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h<br>new file mode 100644<br>index 000000000000..e0f770a601fb<br>--- /dev/null<br>+++ b/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h<br>@@ -0,0 +1,66 @@<br>+//===------ Mangling.h -- Name Mangling Utilities for ORC -------*- C++ -*-===//<br>+//<br>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.<br>+// See <a href="https://llvm.org/LICENSE.txt" target="_blank">https://llvm.org/LICENSE.txt</a> for license information.<br>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception<br>+//<br>+//===----------------------------------------------------------------------===//<br>+//<br>+// Name mangling utilities for ORC.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef LLVM_EXECUTIONENGINE_ORC_MANGLING_H<br>+#define LLVM_EXECUTIONENGINE_ORC_MANGLING_H<br>+<br>+#include "llvm/ExecutionEngine/Orc/Core.h"<br>+#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"<br>+#include "llvm/IR/Module.h"<br>+#include "llvm/Support/MemoryBuffer.h"<br>+<br>+namespace llvm {<br>+namespace orc {<br>+<br>+/// Mangles symbol names then uniques them in the context of an<br>+/// ExecutionSession.<br>+class MangleAndInterner {<br>+public:<br>+ MangleAndInterner(ExecutionSession &ES, const DataLayout &DL);<br>+ SymbolStringPtr operator()(StringRef Name);<br>+<br>+private:<br>+ ExecutionSession &ES;<br>+ const DataLayout &DL;<br>+};<br>+<br>+/// Maps IR global values to their linker symbol names / flags.<br>+///<br>+/// This utility can be used when adding new IR globals in the JIT.<br>+class IRSymbolMapper {<br>+public:<br>+ struct ManglingOptions {<br>+ bool EmulatedTLS = false;<br>+ };<br>+<br>+ using SymbolNameToDefinitionMap = std::map<SymbolStringPtr, GlobalValue *>;<br>+<br>+ /// Add mangled symbols for the given GlobalValues to SymbolFlags.<br>+ /// If a SymbolToDefinitionMap pointer is supplied then it will be populated<br>+ /// with Name-to-GlobalValue* mappings. Note that this mapping is not<br>+ /// necessarily one-to-one: thread-local GlobalValues, for example, may<br>+ /// produce more than one symbol, in which case the map will contain duplicate<br>+ /// values.<br>+ static void add(ExecutionSession &ES, const ManglingOptions &MO,<br>+ ArrayRef<GlobalValue *> GVs, SymbolFlagsMap &SymbolFlags,<br>+ SymbolNameToDefinitionMap *SymbolToDefinition = nullptr);<br>+};<br>+<br>+/// Returns a SymbolFlagsMap for the object file represented by the given<br>+/// buffer, or an error if the buffer does not contain a valid object file.<br>+Expected<std::pair<SymbolFlagsMap, SymbolStringPtr>><br>+getObjectSymbolInfo(ExecutionSession &ES, MemoryBufferRef ObjBuffer);<br>+<br>+} // End namespace orc<br>+} // End namespace llvm<br>+<br>+#endif // LLVM_EXECUTIONENGINE_ORC_MANGLING_H<br><br>diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h<br>index 50d25f18891e..1b4c03bd2cfd 100644<br>--- a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h<br>+++ b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h<br>@@ -35,6 +35,7 @@ namespace llvm {<br><br> namespace jitlink {<br> class EHFrameRegistrar;<br>+class Symbol;<br> } // namespace jitlink<br><br> namespace object {<br>@@ -59,10 +60,14 @@ class ObjectLinkingLayer : public ObjectLayer {<br> /// configured.<br> class Plugin {<br> public:<br>+ using JITLinkSymbolVector = std::vector<const jitlink::Symbol *>;<br>+ using LocalDependenciesMap = DenseMap<SymbolStringPtr, JITLinkSymbolVector>;<br>+<br> virtual ~Plugin();<br> virtual void modifyPassConfig(MaterializationResponsibility &MR,<br> const Triple &TT,<br> jitlink::PassConfiguration &Config) {}<br>+<br> virtual void notifyLoaded(MaterializationResponsibility &MR) {}<br> virtual Error notifyEmitted(MaterializationResponsibility &MR) {<br> return Error::success();<br>@@ -71,6 +76,15 @@ class ObjectLinkingLayer : public ObjectLayer {<br> return Error::success();<br> }<br> virtual Error notifyRemovingAllModules() { return Error::success(); }<br>+<br>+ /// Return any dependencies that synthetic symbols (e.g. init symbols)<br>+ /// have on locally scoped jitlink::Symbols. This is used by the<br>+ /// ObjectLinkingLayer to update the dependencies for the synthetic<br>+ /// symbols.<br>+ virtual LocalDependenciesMap<br>+ getSyntheticSymbolLocalDependencies(MaterializationResponsibility &MR) {<br>+ return LocalDependenciesMap();<br>+ }<br> };<br><br> using ReturnObjectBufferFunction =<br><br>diff --git a/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h b/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h<br>index c354f6c3559c..c8462dc3d2c8 100644<br>--- a/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h<br>+++ b/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h<br>@@ -53,6 +53,7 @@ class SymbolStringPtr {<br><br> public:<br> SymbolStringPtr() = default;<br>+ SymbolStringPtr(nullptr_t) {}<br> SymbolStringPtr(const SymbolStringPtr &Other)<br> : S(Other.S) {<br> if (isRealPoolEntry(S))<br>@@ -85,6 +86,8 @@ class SymbolStringPtr {<br> --S->getValue();<br> }<br><br>+ explicit operator bool() const { return S; }<br>+<br> StringRef operator*() const { return S->first(); }<br><br> friend bool operator==(const SymbolStringPtr &LHS,<br><br>diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt<br>index e3a7a67c8a0e..7eb2742d7b53 100644<br>--- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt<br>+++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt<br>@@ -12,6 +12,8 @@ add_llvm_component_library(LLVMOrcJIT<br> Legacy.cpp<br> Layer.cpp<br> LLJIT.cpp<br>+ MachOPlatform.cpp<br>+ Mangling.cpp<br> NullResolver.cpp<br> ObjectLinkingLayer.cpp<br> ObjectTransformLayer.cpp<br><br>diff --git a/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp b/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp<br>index 29d18b6e4d7b..f22ae01a2080 100644<br>--- a/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp<br>+++ b/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp<br>@@ -7,6 +7,7 @@<br> //===----------------------------------------------------------------------===//<br><br> #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"<br>+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"<br> #include "llvm/IR/Mangler.h"<br> #include "llvm/IR/Module.h"<br><br>@@ -68,18 +69,18 @@ namespace orc {<br> class PartitioningIRMaterializationUnit : public IRMaterializationUnit {<br> public:<br> PartitioningIRMaterializationUnit(ExecutionSession &ES,<br>- const ManglingOptions &MO,<br>+ const IRSymbolMapper::ManglingOptions &MO,<br> ThreadSafeModule TSM, VModuleKey K,<br> CompileOnDemandLayer &Parent)<br> : IRMaterializationUnit(ES, MO, std::move(TSM), std::move(K)),<br> Parent(Parent) {}<br><br> PartitioningIRMaterializationUnit(<br>- ThreadSafeModule TSM, SymbolFlagsMap SymbolFlags,<br>- SymbolNameToDefinitionMap SymbolToDefinition,<br>+ ThreadSafeModule TSM, VModuleKey K, SymbolFlagsMap SymbolFlags,<br>+ SymbolStringPtr InitSymbol, SymbolNameToDefinitionMap SymbolToDefinition,<br> CompileOnDemandLayer &Parent)<br> : IRMaterializationUnit(std::move(TSM), std::move(K),<br>- std::move(SymbolFlags),<br>+ std::move(SymbolFlags), std::move(InitSymbol),<br> std::move(SymbolToDefinition)),<br> Parent(Parent) {}<br><br>@@ -172,21 +173,23 @@ CompileOnDemandLayer::getPerDylibResources(JITDylib &TargetD) {<br> auto I = DylibResources.find(&TargetD);<br> if (I == DylibResources.end()) {<br> auto &ImplD =<br>- getExecutionSession().createJITDylib(TargetD.getName() + ".impl");<br>+ getExecutionSession().createBareJITDylib(TargetD.getName() + ".impl");<br>+ JITDylibSearchOrder NewSearchOrder;<br> TargetD.withSearchOrderDo(<br> [&](const JITDylibSearchOrder &TargetSearchOrder) {<br>- auto NewSearchOrder = TargetSearchOrder;<br>- assert(<br>- !NewSearchOrder.empty() &&<br>- NewSearchOrder.front().first == &TargetD &&<br>- NewSearchOrder.front().second ==<br>- JITDylibLookupFlags::MatchAllSymbols &&<br>- "TargetD must be at the front of its own search order and match "<br>- "non-exported symbol");<br>- NewSearchOrder.insert(std::next(NewSearchOrder.begin()),<br>- {&ImplD, JITDylibLookupFlags::MatchAllSymbols});<br>- ImplD.setSearchOrder(std::move(NewSearchOrder), false);<br>+ NewSearchOrder = TargetSearchOrder;<br> });<br>+<br>+ assert(<br>+ !NewSearchOrder.empty() && NewSearchOrder.front().first == &TargetD &&<br>+ NewSearchOrder.front().second == JITDylibLookupFlags::MatchAllSymbols &&<br>+ "TargetD must be at the front of its own search order and match "<br>+ "non-exported symbol");<br>+ NewSearchOrder.insert(std::next(NewSearchOrder.begin()),<br>+ {&ImplD, JITDylibLookupFlags::MatchAllSymbols});<br>+ ImplD.setSearchOrder(NewSearchOrder, false);<br>+ TargetD.setSearchOrder(std::move(NewSearchOrder), false);<br>+<br> PerDylibResources PDR(ImplD, BuildIndirectStubsManager());<br> I = DylibResources.insert(std::make_pair(&TargetD, std::move(PDR))).first;<br> }<br>@@ -251,8 +254,15 @@ void CompileOnDemandLayer::emitPartition(<br> auto &ES = getExecutionSession();<br> GlobalValueSet RequestedGVs;<br> for (auto &Name : R.getRequestedSymbols()) {<br>- assert(Defs.count(Name) && "No definition for symbol");<br>- RequestedGVs.insert(Defs[Name]);<br>+ if (Name == R.getInitializerSymbol())<br>+ TSM.withModuleDo([&](Module &M) {<br>+ for (auto &GV : getStaticInitGVs(M))<br>+ RequestedGVs.insert(&GV);<br>+ });<br>+ else {<br>+ assert(Defs.count(Name) && "No definition for symbol");<br>+ RequestedGVs.insert(Defs[Name]);<br>+ }<br> }<br><br> /// Perform partitioning with the context lock held, since the partition<br>@@ -272,7 +282,8 @@ void CompileOnDemandLayer::emitPartition(<br> // If the partition is empty, return the whole module to the symbol table.<br> if (GVsToExtract->empty()) {<br> R.replace(std::make_unique<PartitioningIRMaterializationUnit>(<br>- std::move(TSM), R.getSymbols(), std::move(Defs), *this));<br>+ std::move(TSM), R.getVModuleKey(), R.getSymbols(),<br>+ R.getInitializerSymbol(), std::move(Defs), *this));<br> return;<br> }<br><br><br>diff --git a/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp b/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp<br>index 160e5ba50311..f8efed15edea 100644<br>--- a/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp<br>+++ b/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp<br>@@ -24,9 +24,9 @@<br> namespace llvm {<br> namespace orc {<br><br>-IRMaterializationUnit::ManglingOptions<br>+IRSymbolMapper::ManglingOptions<br> irManglingOptionsFromTargetOptions(const TargetOptions &Opts) {<br>- IRMaterializationUnit::ManglingOptions MO;<br>+ IRSymbolMapper::ManglingOptions MO;<br><br> MO.EmulatedTLS = Opts.EmulatedTLS;<br><br><br>diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp<br>index a7af34a21926..6a0df10f7c3f 100644<br>--- a/llvm/lib/ExecutionEngine/Orc/Core.cpp<br>+++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp<br>@@ -11,7 +11,6 @@<br> #include "llvm/ADT/STLExtras.h"<br> #include "llvm/Config/llvm-config.h"<br> #include "llvm/ExecutionEngine/Orc/OrcError.h"<br>-#include "llvm/IR/Mangler.h"<br> #include "llvm/Support/CommandLine.h"<br> #include "llvm/Support/Debug.h"<br> #include "llvm/Support/Format.h"<br>@@ -421,12 +420,6 @@ void AsynchronousSymbolQuery::detach() {<br> QueryRegistrations.clear();<br> }<br><br>-MaterializationResponsibility::MaterializationResponsibility(<br>- JITDylib &JD, SymbolFlagsMap SymbolFlags, VModuleKey K)<br>- : JD(JD), SymbolFlags(std::move(SymbolFlags)), K(std::move(K)) {<br>- assert(!this->SymbolFlags.empty() && "Materializing nothing?");<br>-}<br>-<br> MaterializationResponsibility::~MaterializationResponsibility() {<br> assert(SymbolFlags.empty() &&<br> "All symbols should have been explicitly materialized or failed");<br>@@ -501,9 +494,13 @@ void MaterializationResponsibility::failMaterialization() {<br><br> void MaterializationResponsibility::replace(<br> std::unique_ptr<MaterializationUnit> MU) {<br>+<br> for (auto &KV : MU->getSymbols())<br> SymbolFlags.erase(KV.first);<br><br>+ if (MU->getInitializerSymbol() == InitSymbol)<br>+ InitSymbol = nullptr;<br>+<br> LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() {<br> dbgs() << "In " << JD.getName() << " replacing symbols with " << *MU<br> << "\n";<br>@@ -519,6 +516,7 @@ MaterializationResponsibility::delegate(const SymbolNameSet &Symbols,<br> if (NewKey == VModuleKey())<br> NewKey = K;<br><br>+ SymbolStringPtr DelegatedInitSymbol;<br> SymbolFlagsMap DelegatedFlags;<br><br> for (auto &Name : Symbols) {<br>@@ -528,10 +526,14 @@ MaterializationResponsibility::delegate(const SymbolNameSet &Symbols,<br> "instance");<br><br> DelegatedFlags[Name] = std::move(I->second);<br>+ if (Name == InitSymbol)<br>+ std::swap(InitSymbol, DelegatedInitSymbol);<br>+<br> SymbolFlags.erase(I);<br> }<br><br> return MaterializationResponsibility(JD, std::move(DelegatedFlags),<br>+ std::move(DelegatedInitSymbol),<br> std::move(NewKey));<br> }<br><br>@@ -550,7 +552,7 @@ void MaterializationResponsibility::addDependenciesForAll(<br><br> AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit(<br> SymbolMap Symbols, VModuleKey K)<br>- : MaterializationUnit(extractFlags(Symbols), std::move(K)),<br>+ : MaterializationUnit(extractFlags(Symbols), nullptr, std::move(K)),<br> Symbols(std::move(Symbols)) {}<br><br> StringRef AbsoluteSymbolsMaterializationUnit::getName() const {<br>@@ -581,7 +583,7 @@ AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) {<br> ReExportsMaterializationUnit::ReExportsMaterializationUnit(<br> JITDylib *SourceJD, JITDylibLookupFlags SourceJDLookupFlags,<br> SymbolAliasMap Aliases, VModuleKey K)<br>- : MaterializationUnit(extractFlags(Aliases), std::move(K)),<br>+ : MaterializationUnit(extractFlags(Aliases), nullptr, std::move(K)),<br> SourceJD(SourceJD), SourceJDLookupFlags(SourceJDLookupFlags),<br> Aliases(std::move(Aliases)) {}<br><br>@@ -972,7 +974,7 @@ void JITDylib::addDependencies(const SymbolStringPtr &Name,<br> // Assert that this symbol exists and has not reached the ready state<br> // already.<br> assert(OtherSymI != OtherJITDylib.Symbols.end() &&<br>- (OtherSymI->second.getState() != SymbolState::Ready &&<br>+ (OtherSymI->second.getState() < SymbolState::Ready &&<br> "Dependency on emitted/ready symbol"));<br> #endif<br><br>@@ -1101,6 +1103,7 @@ Error JITDylib::resolve(const SymbolMap &Resolved) {<br> Error JITDylib::emit(const SymbolFlagsMap &Emitted) {<br> AsynchronousSymbolQuerySet CompletedQueries;<br> SymbolNameSet SymbolsInErrorState;<br>+ DenseMap<JITDylib *, SymbolNameVector> ReadySymbols;<br><br> ES.runSessionLocked([&, this]() {<br> std::vector<SymbolTable::iterator> Worklist;<br>@@ -1145,6 +1148,7 @@ Error JITDylib::emit(const SymbolFlagsMap &Emitted) {<br> // dependencies) then notify any pending queries.<br> for (auto &KV : MI.Dependants) {<br> auto &DependantJD = *KV.first;<br>+ auto &DependantJDReadySymbols = ReadySymbols[&DependantJD];<br> for (auto &DependantName : KV.second) {<br> auto DependantMII =<br> DependantJD.MaterializingInfos.find(DependantName);<br>@@ -1184,6 +1188,7 @@ Error JITDylib::emit(const SymbolFlagsMap &Emitted) {<br> // Since this dependant is now ready, we erase its MaterializingInfo<br> // and update its materializing state.<br> DependantSymEntry.setState(SymbolState::Ready);<br>+ DependantJDReadySymbols.push_back(DependantName);<br><br> for (auto &Q : DependantMI.takeQueriesMeeting(SymbolState::Ready)) {<br> Q->notifySymbolMetRequiredState(<br>@@ -1192,22 +1197,21 @@ Error JITDylib::emit(const SymbolFlagsMap &Emitted) {<br> CompletedQueries.insert(Q);<br> Q->removeQueryDependence(DependantJD, DependantName);<br> }<br>-<br>- DependantJD.MaterializingInfos.erase(DependantMII);<br> }<br> }<br> }<br><br>+ auto &ThisJDReadySymbols = ReadySymbols[this];<br> MI.Dependants.clear();<br> if (MI.UnemittedDependencies.empty()) {<br> SymI->second.setState(SymbolState::Ready);<br>+ ThisJDReadySymbols.push_back(Name);<br> for (auto &Q : MI.takeQueriesMeeting(SymbolState::Ready)) {<br> Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());<br> if (Q->isComplete())<br> CompletedQueries.insert(Q);<br> Q->removeQueryDependence(*this, Name);<br> }<br>- MaterializingInfos.erase(MII);<br> }<br> }<br> });<br>@@ -1882,6 +1886,57 @@ void JITDylib::transferEmittedNodeDependencies(<br> }<br> }<br><br>+Platform::~Platform() {}<br>+<br>+Expected<DenseMap<JITDylib *, SymbolMap>> Platform::lookupInitSymbols(<br>+ ExecutionSession &ES,<br>+ const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms) {<br>+<br>+ DenseMap<JITDylib *, SymbolMap> CompoundResult;<br>+ Error CompoundErr = Error::success();<br>+ std::mutex LookupMutex;<br>+ std::condition_variable CV;<br>+ uint64_t Count = InitSyms.size();<br>+<br>+ LLVM_DEBUG({<br>+ dbgs() << "Issuing init-symbol lookup:\n";<br>+ for (auto &KV : InitSyms)<br>+ dbgs() << " " << KV.first->getName() << ": " << KV.second << "\n";<br>+ });<br>+<br>+ for (auto &KV : InitSyms) {<br>+ auto *JD = KV.first;<br>+ auto Names = std::move(KV.second);<br>+ ES.lookup(<br>+ LookupKind::Static,<br>+ JITDylibSearchOrder({{JD, JITDylibLookupFlags::MatchAllSymbols}}),<br>+ std::move(Names), SymbolState::Ready,<br>+ [&, JD](Expected<SymbolMap> Result) {<br>+ {<br>+ std::lock_guard<std::mutex> Lock(LookupMutex);<br>+ --Count;<br>+ if (Result) {<br>+ assert(!CompoundResult.count(JD) &&<br>+ "Duplicate JITDylib in lookup?");<br>+ CompoundResult[JD] = std::move(*Result);<br>+ } else<br>+ CompoundErr =<br>+ joinErrors(std::move(CompoundErr), Result.takeError());<br>+ }<br>+ CV.notify_one();<br>+ },<br>+ NoDependenciesToRegister);<br>+ }<br>+<br>+ std::unique_lock<std::mutex> Lock(LookupMutex);<br>+ CV.wait(Lock, [&] { return Count == 0 || CompoundErr; });<br>+<br>+ if (CompoundErr)<br>+ return std::move(CompoundErr);<br>+<br>+ return std::move(CompoundResult);<br>+}<br>+<br> ExecutionSession::ExecutionSession(std::shared_ptr<SymbolStringPool> SSP)<br> : SSP(SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>()) {<br> }<br>@@ -1895,7 +1950,7 @@ JITDylib *ExecutionSession::getJITDylibByName(StringRef Name) {<br> });<br> }<br><br>-JITDylib &ExecutionSession::createJITDylib(std::string Name) {<br>+JITDylib &ExecutionSession::createBareJITDylib(std::string Name) {<br> assert(!getJITDylibByName(Name) && "JITDylib with that name already exists");<br> return runSessionLocked([&, this]() -> JITDylib & {<br> JDs.push_back(<br>@@ -1904,6 +1959,14 @@ JITDylib &ExecutionSession::createJITDylib(std::string Name) {<br> });<br> }<br><br>+Expected<JITDylib &> ExecutionSession::createJITDylib(std::string Name) {<br>+ auto &JD = createBareJITDylib(Name);<br>+ if (P)<br>+ if (auto Err = P->setupJITDylib(JD))<br>+ return std::move(Err);<br>+ return JD;<br>+}<br>+<br> void ExecutionSession::legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err) {<br> assert(!!Err && "Error should be in failure state");<br><br>@@ -2144,11 +2207,11 @@ ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,<br><br> Expected<JITEvaluatedSymbol><br> ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,<br>- SymbolStringPtr Name) {<br>+ SymbolStringPtr Name, SymbolState RequiredState) {<br> SymbolLookupSet Names({Name});<br><br> if (auto ResultMap = lookup(SearchOrder, std::move(Names), LookupKind::Static,<br>- SymbolState::Ready, NoDependenciesToRegister)) {<br>+ RequiredState, NoDependenciesToRegister)) {<br> assert(ResultMap->size() == 1 && "Unexpected number of results");<br> assert(ResultMap->count(Name) && "Missing result for symbol");<br> return std::move(ResultMap->begin()->second);<br>@@ -2157,14 +2220,15 @@ ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,<br> }<br><br> Expected<JITEvaluatedSymbol><br>-ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder,<br>- SymbolStringPtr Name) {<br>- return lookup(makeJITDylibSearchOrder(SearchOrder), Name);<br>+ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Name,<br>+ SymbolState RequiredState) {<br>+ return lookup(makeJITDylibSearchOrder(SearchOrder), Name, RequiredState);<br> }<br><br> Expected<JITEvaluatedSymbol><br>-ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Name) {<br>- return lookup(SearchOrder, intern(Name));<br>+ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Name,<br>+ SymbolState RequiredState) {<br>+ return lookup(SearchOrder, intern(Name), RequiredState);<br> }<br><br> void ExecutionSession::dump(raw_ostream &OS) {<br>@@ -2195,17 +2259,5 @@ void ExecutionSession::runOutstandingMUs() {<br> }<br> }<br><br>-MangleAndInterner::MangleAndInterner(ExecutionSession &ES, const DataLayout &DL)<br>- : ES(ES), DL(DL) {}<br>-<br>-SymbolStringPtr MangleAndInterner::operator()(StringRef Name) {<br>- std::string MangledName;<br>- {<br>- raw_string_ostream MangledNameStream(MangledName);<br>- Mangler::getNameWithPrefix(MangledNameStream, Name, DL);<br>- }<br>- return ES.intern(MangledName);<br>-}<br>-<br> } // End namespace orc.<br> } // End namespace llvm.<br><br>diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp<br>index 3d97fe9eeab1..a98445a2295e 100644<br>--- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp<br>+++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp<br>@@ -113,6 +113,26 @@ iterator_range<CtorDtorIterator> getDestructors(const Module &M) {<br> CtorDtorIterator(DtorsList, true));<br> }<br><br>+bool StaticInitGVIterator::isStaticInitGlobal(GlobalValue &GV) {<br>+ if (GV.isDeclaration())<br>+ return false;<br>+<br>+ if (GV.hasName() && (GV.getName() == "llvm.global_ctors" ||<br>+ GV.getName() == "llvm.global_dtors"))<br>+ return true;<br>+<br>+ if (ObjFmt == Triple::MachO) {<br>+ // FIXME: These section checks are too strict: We should match first and<br>+ // second word split by comma.<br>+ if (GV.hasSection() &&<br>+ (GV.getSection().startswith("__DATA,__objc_classlist") ||<br>+ GV.getSection().startswith("__DATA,__objc_selrefs")))<br>+ return true;<br>+ }<br>+<br>+ return false;<br>+}<br>+<br> void CtorDtorRunner::add(iterator_range<CtorDtorIterator> CtorDtors) {<br> if (CtorDtors.empty())<br> return;<br>@@ -198,6 +218,30 @@ Error LocalCXXRuntimeOverrides::enable(JITDylib &JD,<br> return JD.define(absoluteSymbols(std::move(RuntimeInterposes)));<br> }<br><br>+void ItaniumCXAAtExitSupport::registerAtExit(void (*F)(void *), void *Ctx,<br>+ void *DSOHandle) {<br>+ std::lock_guard<std::mutex> Lock(AtExitsMutex);<br>+ AtExitRecords[DSOHandle].push_back({F, Ctx});<br>+}<br>+<br>+void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle) {<br>+ std::vector<AtExitRecord> AtExitsToRun;<br>+<br>+ {<br>+ std::lock_guard<std::mutex> Lock(AtExitsMutex);<br>+ auto I = AtExitRecords.find(DSOHandle);<br>+ if (I != AtExitRecords.end()) {<br>+ AtExitsToRun = std::move(I->second);<br>+ AtExitRecords.erase(I);<br>+ }<br>+ }<br>+<br>+ while (!AtExitsToRun.empty()) {<br>+ AtExitsToRun.back().F(AtExitsToRun.back().Ctx);<br>+ AtExitsToRun.pop_back();<br>+ }<br>+}<br>+<br> DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator(<br> sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow)<br> : Dylib(std::move(Dylib)), Allow(std::move(Allow)),<br><br>diff --git a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp<br>index 1ac9a58aeaef..1e991d8f58f2 100644<br>--- a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp<br>+++ b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp<br>@@ -28,7 +28,7 @@ class CompileCallbackMaterializationUnit : public orc::MaterializationUnit {<br> CompileCallbackMaterializationUnit(SymbolStringPtr Name,<br> CompileFunction Compile, VModuleKey K)<br> : MaterializationUnit(SymbolFlagsMap({{Name, JITSymbolFlags::Exported}}),<br>- std::move(K)),<br>+ nullptr, std::move(K)),<br> Name(std::move(Name)), Compile(std::move(Compile)) {}<br><br> StringRef getName() const override { return "<Compile Callbacks>"; }<br><br>diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp<br>index 4218ca4e481f..5b2f86823355 100644<br>--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp<br>+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp<br>@@ -8,15 +8,827 @@<br><br> #include "llvm/ExecutionEngine/Orc/LLJIT.h"<br> #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"<br>+#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"<br> #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"<br> #include "llvm/ExecutionEngine/Orc/OrcError.h"<br> #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"<br> #include "llvm/ExecutionEngine/SectionMemoryManager.h"<br>+#include "llvm/IR/GlobalVariable.h"<br>+#include "llvm/IR/IRBuilder.h"<br> #include "llvm/IR/Mangler.h"<br>+#include "llvm/IR/Module.h"<br>+#include "llvm/Support/DynamicLibrary.h"<br>+<br>+#include <map><br>+<br>+using namespace llvm;<br>+using namespace llvm::orc;<br>+<br>+namespace {<br>+<br>+/// Add a reference to the __dso_handle global to the given module.<br>+/// Returns a reference to the __dso_handle IR decl.<br>+GlobalVariable *addDSOHandleDecl(Module &M) {<br>+ auto DSOHandleTy = StructType::create(M.getContext(), "lljit.dso_handle");<br>+ return new GlobalVariable(M, DSOHandleTy, true, GlobalValue::ExternalLinkage,<br>+ nullptr, "__dso_handle");<br>+}<br>+<br>+/// Adds helper function decls and wrapper functions that call the helper with<br>+/// some additional prefix arguments.<br>+///<br>+/// E.g. For wrapper "foo" with type i8(i8, i64), helper "bar", and prefix<br>+/// args i32 4 and i16 12345, this function will add:<br>+///<br>+/// declare i8 @bar(i32, i16, i8, i64)<br>+///<br>+/// define i8 @foo(i8, i64) {<br>+/// entry:<br>+/// %2 = call i8 @bar(i32 4, i16 12345, i8 %0, i64 %1)<br>+/// ret i8 %2<br>+/// }<br>+///<br>+Function *addHelperAndWrapper(Module &M, StringRef WrapperName,<br>+ FunctionType *WrapperFnType,<br>+ GlobalValue::VisibilityTypes WrapperVisibility,<br>+ StringRef HelperName,<br>+ ArrayRef<Value *> HelperPrefixArgs) {<br>+ std::vector<Type *> HelperArgTypes;<br>+ for (auto *Arg : HelperPrefixArgs)<br>+ HelperArgTypes.push_back(Arg->getType());<br>+ for (auto *T : WrapperFnType->params())<br>+ HelperArgTypes.push_back(T);<br>+ auto *HelperFnType =<br>+ FunctionType::get(WrapperFnType->getReturnType(), HelperArgTypes, false);<br>+ auto *HelperFn = Function::Create(HelperFnType, GlobalValue::ExternalLinkage,<br>+ HelperName, M);<br>+<br>+ auto *WrapperFn = Function::Create(<br>+ WrapperFnType, GlobalValue::ExternalLinkage, WrapperName, M);<br>+ WrapperFn->setVisibility(WrapperVisibility);<br>+<br>+ auto *EntryBlock = BasicBlock::Create(M.getContext(), "entry", WrapperFn);<br>+ IRBuilder<> IB(EntryBlock);<br>+<br>+ std::vector<Value *> HelperArgs;<br>+ for (auto *Arg : HelperPrefixArgs)<br>+ HelperArgs.push_back(Arg);<br>+ for (auto &Arg : WrapperFn->args())<br>+ HelperArgs.push_back(&Arg);<br>+ auto *HelperResult = IB.CreateCall(HelperFn, HelperArgs);<br>+ if (HelperFn->getReturnType()->isVoidTy())<br>+ IB.CreateRetVoid();<br>+ else<br>+ IB.CreateRet(HelperResult);<br>+<br>+ return WrapperFn;<br>+}<br>+<br>+class GenericLLVMIRPlatformSupport;<br>+<br>+/// orc::Platform component of Generic LLVM IR Platform support.<br>+/// Just forwards calls to the GenericLLVMIRPlatformSupport class below.<br>+class GenericLLVMIRPlatform : public Platform {<br>+public:<br>+ GenericLLVMIRPlatform(GenericLLVMIRPlatformSupport &S) : S(S) {}<br>+ Error setupJITDylib(JITDylib &JD) override;<br>+ Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) override;<br>+ Error notifyRemoving(JITDylib &JD, VModuleKey K) override {<br>+ // Noop -- Nothing to do (yet).<br>+ return Error::success();<br>+ }<br>+<br>+private:<br>+ GenericLLVMIRPlatformSupport &S;<br>+};<br>+<br>+/// This transform parses llvm.global_ctors to produce a single initialization<br>+/// function for the module, records the function, then deletes<br>+/// llvm.global_ctors.<br>+class GlobalCtorDtorScraper {<br>+public:<br>+ GlobalCtorDtorScraper(GenericLLVMIRPlatformSupport &PS) : PS(PS) {}<br>+ Expected<ThreadSafeModule> operator()(ThreadSafeModule TSM,<br>+ MaterializationResponsibility &R);<br>+<br>+private:<br>+ GenericLLVMIRPlatformSupport &PS;<br>+};<br>+<br>+/// Generic IR Platform Support<br>+///<br>+/// Scrapes llvm.global_ctors and llvm.global_dtors and replaces them with<br>+/// specially named 'init' and 'deinit'. Injects definitions / interposes for<br>+/// some runtime API, including __cxa_atexit, dlopen, and dlclose.<br>+class GenericLLVMIRPlatformSupport : public LLJIT::PlatformSupport {<br>+public:<br>+ // GenericLLVMIRPlatform &P) : P(P) {<br>+ GenericLLVMIRPlatformSupport(LLJIT &J) : J(J) {<br>+<br>+ getExecutionSession().setPlatform(<br>+ std::make_unique<GenericLLVMIRPlatform>(*this));<br>+<br>+ setInitTransform(J, GlobalCtorDtorScraper(*this));<br>+<br>+ MangleAndInterner Mangle(getExecutionSession(), J.getDataLayout());<br>+ SymbolMap StdInterposes;<br>+<br>+ StdInterposes[Mangle("__lljit.platform_support_instance")] =<br>+ JITEvaluatedSymbol(pointerToJITTargetAddress(this), JITSymbolFlags());<br>+ StdInterposes[Mangle("__lljit.cxa_atexit_helper")] = JITEvaluatedSymbol(<br>+ pointerToJITTargetAddress(registerAtExitHelper), JITSymbolFlags());<br>+ StdInterposes[Mangle("__lljit.run_atexits_helper")] = JITEvaluatedSymbol(<br>+ pointerToJITTargetAddress(runAtExitsHelper), JITSymbolFlags());<br>+<br>+ cantFail(<br>+ J.getMainJITDylib().define(absoluteSymbols(std::move(StdInterposes))));<br>+ cantFail(setupJITDylib(J.getMainJITDylib()));<br>+ cantFail(J.addIRModule(J.getMainJITDylib(), createPlatformRuntimeModule()));<br>+ }<br>+<br>+ ExecutionSession &getExecutionSession() { return J.getExecutionSession(); }<br>+<br>+ /// Adds a module that defines the __dso_handle global.<br>+ Error setupJITDylib(JITDylib &JD) {<br>+ auto Ctx = std::make_unique<LLVMContext>();<br>+ auto M = std::make_unique<Module>("__standard_lib", *Ctx);<br>+ M->setDataLayout(J.getDataLayout());<br>+<br>+ auto *Int64Ty = Type::getInt64Ty(*Ctx);<br>+ auto *DSOHandle = new GlobalVariable(<br>+ *M, Int64Ty, true, GlobalValue::ExternalLinkage,<br>+ ConstantInt::get(Int64Ty, reinterpret_cast<uintptr_t>(&JD)),<br>+ "__dso_handle");<br>+ DSOHandle->setVisibility(GlobalValue::HiddenVisibility);<br>+ DSOHandle->setInitializer(<br>+ ConstantInt::get(Int64Ty, pointerToJITTargetAddress(&JD)));<br>+ return J.addIRModule(JD, ThreadSafeModule(std::move(M), std::move(Ctx)));<br>+ }<br>+<br>+ Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) {<br>+ std::lock_guard<std::mutex> Lock(PlatformSupportMutex);<br>+ if (auto &InitSym = MU.getInitializerSymbol())<br>+ InitSymbols[&JD].add(InitSym);<br>+ return Error::success();<br>+ }<br>+<br>+ Error initialize(JITDylib &JD) override {<br>+ if (auto Initializers = getInitializers(JD)) {<br>+ for (auto InitFnAddr : *Initializers) {<br>+ auto *InitFn = jitTargetAddressToFunction<void (*)()>(InitFnAddr);<br>+ InitFn();<br>+ }<br>+ } else<br>+ return Initializers.takeError();<br>+ return Error::success();<br>+ }<br>+<br>+ Error deinitialize(JITDylib &JD) override {<br>+ if (auto Deinitializers = getDeinitializers(JD)) {<br>+ for (auto DeinitFnAddr : *Deinitializers) {<br>+ auto *DeinitFn = jitTargetAddressToFunction<void (*)()>(DeinitFnAddr);<br>+ DeinitFn();<br>+ }<br>+ } else<br>+ return Deinitializers.takeError();<br>+<br>+ return Error::success();<br>+ }<br>+<br>+ void registerInitFunc(JITDylib &JD, SymbolStringPtr InitName) {<br>+ std::lock_guard<std::mutex> Lock(PlatformSupportMutex);<br>+ InitFunctions[&JD].add(InitName);<br>+ }<br>+<br>+private:<br>+ Expected<std::vector<JITTargetAddress>> getInitializers(JITDylib &JD) {<br>+ if (auto Err = issueInitLookups(JD))<br>+ return std::move(Err);<br>+<br>+ DenseMap<JITDylib *, SymbolLookupSet> LookupSymbols;<br>+ std::vector<JITDylib *> DFSLinkOrder;<br>+<br>+ {<br>+ std::lock_guard<std::mutex> Lock(PlatformSupportMutex);<br>+ DFSLinkOrder = getDFSLinkOrder(JD);<br>+<br>+ for (auto *NextJD : DFSLinkOrder) {<br>+ auto IFItr = InitFunctions.find(NextJD);<br>+ if (IFItr != InitFunctions.end()) {<br>+ LookupSymbols[NextJD] = std::move(IFItr->second);<br>+ InitFunctions.erase(IFItr);<br>+ }<br>+ }<br>+ }<br>+<br>+ auto &ES = getExecutionSession();<br>+ auto LookupResult = Platform::lookupInitSymbols(ES, LookupSymbols);<br>+<br>+ if (!LookupResult)<br>+ return LookupResult.takeError();<br>+<br>+ std::vector<JITTargetAddress> Initializers;<br>+ while (!DFSLinkOrder.empty()) {<br>+ auto &NextJD = *DFSLinkOrder.back();<br>+ DFSLinkOrder.pop_back();<br>+ auto InitsItr = LookupResult->find(&NextJD);<br>+ if (InitsItr == LookupResult->end())<br>+ continue;<br>+ for (auto &KV : InitsItr->second)<br>+ Initializers.push_back(KV.second.getAddress());<br>+ }<br>+<br>+ return Initializers;<br>+ }<br>+<br>+ Expected<std::vector<JITTargetAddress>> getDeinitializers(JITDylib &JD) {<br>+ auto &ES = getExecutionSession();<br>+<br>+ MangleAndInterner Mangle(getExecutionSession(), J.getDataLayout());<br>+ auto LLJITRunAtExits = Mangle("__lljit_run_atexits");<br>+<br>+ DenseMap<JITDylib *, SymbolLookupSet> LookupSymbols;<br>+ std::vector<JITDylib *> DFSLinkOrder;<br>+<br>+ {<br>+ std::lock_guard<std::mutex> Lock(PlatformSupportMutex);<br>+ DFSLinkOrder = getDFSLinkOrder(JD);<br>+<br>+ for (auto *NextJD : DFSLinkOrder) {<br>+ auto &JDLookupSymbols = LookupSymbols[NextJD];<br>+ auto DIFItr = DeInitFunctions.find(NextJD);<br>+ if (DIFItr != DeInitFunctions.end()) {<br>+ LookupSymbols[NextJD] = std::move(DIFItr->second);<br>+ DeInitFunctions.erase(DIFItr);<br>+ }<br>+ JDLookupSymbols.add(LLJITRunAtExits,<br>+ SymbolLookupFlags::WeaklyReferencedSymbol);<br>+ }<br>+ }<br>+<br>+ auto LookupResult = Platform::lookupInitSymbols(ES, LookupSymbols);<br>+<br>+ if (!LookupResult)<br>+ return LookupResult.takeError();<br>+<br>+ std::vector<JITTargetAddress> DeInitializers;<br>+ for (auto *NextJD : DFSLinkOrder) {<br>+ auto DeInitsItr = LookupResult->find(NextJD);<br>+ assert(DeInitsItr != LookupResult->end() &&<br>+ "Every JD should have at least __lljit_run_atexits");<br>+<br>+ auto RunAtExitsItr = DeInitsItr->second.find(LLJITRunAtExits);<br>+ if (RunAtExitsItr != DeInitsItr->second.end())<br>+ DeInitializers.push_back(RunAtExitsItr->second.getAddress());<br>+<br>+ for (auto &KV : DeInitsItr->second)<br>+ if (KV.first != LLJITRunAtExits)<br>+ DeInitializers.push_back(KV.second.getAddress());<br>+ }<br>+<br>+ return DeInitializers;<br>+ }<br>+<br>+ // Returns a DFS traversal order of the JITDylibs reachable (via<br>+ // links-against edges) from JD, starting with JD itself.<br>+ static std::vector<JITDylib *> getDFSLinkOrder(JITDylib &JD) {<br>+ std::vector<JITDylib *> DFSLinkOrder;<br>+ std::vector<JITDylib *> WorkStack({&JD});<br>+ DenseSet<JITDylib *> Visited;<br>+<br>+ while (!WorkStack.empty()) {<br>+ auto &NextJD = *WorkStack.back();<br>+ WorkStack.pop_back();<br>+ if (Visited.count(&NextJD))<br>+ continue;<br>+ Visited.insert(&NextJD);<br>+ DFSLinkOrder.push_back(&NextJD);<br>+ NextJD.withSearchOrderDo([&](const JITDylibSearchOrder &SearchOrder) {<br>+ for (auto &KV : SearchOrder)<br>+ WorkStack.push_back(KV.first);<br>+ });<br>+ }<br>+<br>+ return DFSLinkOrder;<br>+ }<br>+<br>+ /// Issue lookups for all init symbols required to initialize JD (and any<br>+ /// JITDylibs that it depends on).<br>+ Error issueInitLookups(JITDylib &JD) {<br>+ DenseMap<JITDylib *, SymbolLookupSet> RequiredInitSymbols;<br>+<br>+ {<br>+ std::lock_guard<std::mutex> Lock(PlatformSupportMutex);<br>+<br>+ auto DFSLinkOrder = getDFSLinkOrder(JD);<br>+<br>+ for (auto *NextJD : DFSLinkOrder) {<br>+ auto ISItr = InitSymbols.find(NextJD);<br>+ if (ISItr != InitSymbols.end()) {<br>+ RequiredInitSymbols[NextJD] = std::move(ISItr->second);<br>+ InitSymbols.erase(ISItr);<br>+ }<br>+ }<br>+ }<br>+<br>+ return Platform::lookupInitSymbols(getExecutionSession(),<br>+ RequiredInitSymbols)<br>+ .takeError();<br>+ }<br>+<br>+ static void registerAtExitHelper(void *Self, void (*F)(void *), void *Ctx,<br>+ void *DSOHandle) {<br>+ static_cast<GenericLLVMIRPlatformSupport *>(Self)->AtExitMgr.registerAtExit(<br>+ F, Ctx, DSOHandle);<br>+ }<br>+<br>+ static void runAtExitsHelper(void *Self, void *DSOHandle) {<br>+ static_cast<GenericLLVMIRPlatformSupport *>(Self)->AtExitMgr.runAtExits(<br>+ DSOHandle);<br>+ }<br>+<br>+ // Constructs an LLVM IR module containing platform runtime globals,<br>+ // functions, and interposes.<br>+ ThreadSafeModule createPlatformRuntimeModule() {<br>+ auto Ctx = std::make_unique<LLVMContext>();<br>+ auto M = std::make_unique<Module>("__standard_lib", *Ctx);<br>+ M->setDataLayout(J.getDataLayout());<br>+<br>+ auto *GenericIRPlatformSupportTy =<br>+ StructType::create(*Ctx, "lljit.GenericLLJITIRPlatformSupport");<br>+<br>+ auto *PlatformInstanceDecl = new GlobalVariable(<br>+ *M, GenericIRPlatformSupportTy, true, GlobalValue::ExternalLinkage,<br>+ nullptr, "__lljit.platform_support_instance");<br>+<br>+ auto *DSOHandleDecl = addDSOHandleDecl(*M);<br>+<br>+ auto *Int8Ty = Type::getInt8Ty(*Ctx);<br>+ auto *IntTy = Type::getIntNTy(*Ctx, sizeof(int) * CHAR_BIT);<br>+ auto *VoidTy = Type::getVoidTy(*Ctx);<br>+ auto *BytePtrTy = PointerType::getUnqual(Int8Ty);<br>+ auto *AtExitCallbackTy = FunctionType::get(VoidTy, {BytePtrTy}, false);<br>+ auto *AtExitCallbackPtrTy = PointerType::getUnqual(AtExitCallbackTy);<br>+<br>+ addHelperAndWrapper(<br>+ *M, "__cxa_atexit",<br>+ FunctionType::get(IntTy, {AtExitCallbackPtrTy, BytePtrTy, BytePtrTy},<br>+ false),<br>+ GlobalValue::HiddenVisibility, "__lljit.cxa_atexit_helper",<br>+ {PlatformInstanceDecl});<br>+<br>+ addHelperAndWrapper(<br>+ *M, "__lljit_run_atexits", FunctionType::get(VoidTy, {}, false),<br>+ GlobalValue::HiddenVisibility, "__lljit.run_atexits_helper",<br>+ {PlatformInstanceDecl, DSOHandleDecl});<br>+<br>+ return ThreadSafeModule(std::move(M), std::move(Ctx));<br>+ }<br>+<br>+ std::mutex PlatformSupportMutex;<br>+ LLJIT &J;<br>+ DenseMap<JITDylib *, SymbolLookupSet> InitSymbols;<br>+ DenseMap<JITDylib *, SymbolLookupSet> InitFunctions;<br>+ DenseMap<JITDylib *, SymbolLookupSet> DeInitFunctions;<br>+ ItaniumCXAAtExitSupport AtExitMgr;<br>+};<br>+<br>+Error GenericLLVMIRPlatform::setupJITDylib(JITDylib &JD) {<br>+ return S.setupJITDylib(JD);<br>+}<br>+<br>+Error GenericLLVMIRPlatform::notifyAdding(JITDylib &JD,<br>+ const MaterializationUnit &MU) {<br>+ return S.notifyAdding(JD, MU);<br>+}<br>+<br>+Expected<ThreadSafeModule><br>+GlobalCtorDtorScraper::operator()(ThreadSafeModule TSM,<br>+ MaterializationResponsibility &R) {<br>+ auto Err = TSM.withModuleDo([&](Module &M) -> Error {<br>+ auto &Ctx = M.getContext();<br>+ auto *GlobalCtors = M.getNamedGlobal("llvm.global_ctors");<br>+<br>+ // If there's no llvm.global_ctors or it's just a decl then skip.<br>+ if (!GlobalCtors || GlobalCtors->isDeclaration())<br>+ return Error::success();<br>+<br>+ std::string InitFunctionName;<br>+ raw_string_ostream(InitFunctionName)<br>+ << "__orc_init." << M.getModuleIdentifier();<br>+<br>+ MangleAndInterner Mangle(PS.getExecutionSession(), M.getDataLayout());<br>+ auto InternedName = Mangle(InitFunctionName);<br>+ if (auto Err =<br>+ R.defineMaterializing({{InternedName, JITSymbolFlags::Callable}}))<br>+ return Err;<br>+<br>+ auto *InitFunc =<br>+ Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {}, false),<br>+ GlobalValue::ExternalLinkage, InitFunctionName, &M);<br>+ InitFunc->setVisibility(GlobalValue::HiddenVisibility);<br>+ std::vector<std::pair<Function *, unsigned>> Inits;<br>+ for (auto E : getConstructors(M))<br>+ Inits.push_back(std::make_pair(E.Func, E.Priority));<br>+ llvm::sort(Inits, [](const std::pair<Function *, unsigned> &LHS,<br>+ const std::pair<Function *, unsigned> &RHS) {<br>+ return LHS.first < RHS.first;<br>+ });<br>+ auto *EntryBlock = BasicBlock::Create(Ctx, "entry", InitFunc);<br>+ IRBuilder<> IB(EntryBlock);<br>+ for (auto &KV : Inits)<br>+ IB.CreateCall(KV.first);<br>+ IB.CreateRetVoid();<br>+<br>+ PS.registerInitFunc(R.getTargetJITDylib(), InternedName);<br>+ GlobalCtors->eraseFromParent();<br>+ return Error::success();<br>+ });<br>+<br>+ if (Err)<br>+ return std::move(Err);<br>+<br>+ return TSM;<br>+}<br>+<br>+class MachOPlatformSupport : public LLJIT::PlatformSupport {<br>+public:<br>+ using DLOpenType = void *(*)(const char *Name, int Mode);<br>+ using DLCloseType = int (*)(void *Handle);<br>+ using DLSymType = void *(*)(void *Handle, const char *Name);<br>+ using DLErrorType = const char *(*)();<br>+<br>+ struct DlFcnValues {<br>+ Optional<void *> RTLDDefault;<br>+ DLOpenType dlopen = nullptr;<br>+ DLCloseType dlclose = nullptr;<br>+ DLSymType dlsym = nullptr;<br>+ DLErrorType dlerror = nullptr;<br>+ };<br>+<br>+ static Expected<std::unique_ptr<MachOPlatformSupport>><br>+ Create(LLJIT &J, JITDylib &PlatformJITDylib) {<br>+<br>+ // Make process symbols visible.<br>+ {<br>+ std::string ErrMsg;<br>+ auto Lib = sys::DynamicLibrary::getPermanentLibrary(nullptr, &ErrMsg);<br>+ if (!Lib.isValid())<br>+ return make_error<StringError>(std::move(ErrMsg),<br>+ inconvertibleErrorCode());<br>+ }<br>+<br>+ DlFcnValues DlFcn;<br>+<br>+ // Add support for RTLDDefault on known platforms.<br>+#ifdef __APPLE__<br>+ DlFcn.RTLDDefault = reinterpret_cast<void *>(-2);<br>+#endif // __APPLE__<br>+<br>+ if (auto Err = hookUpFunction(DlFcn.dlopen, "dlopen"))<br>+ return std::move(Err);<br>+ if (auto Err = hookUpFunction(DlFcn.dlclose, "dlclose"))<br>+ return std::move(Err);<br>+ if (auto Err = hookUpFunction(DlFcn.dlsym, "dlsym"))<br>+ return std::move(Err);<br>+ if (auto Err = hookUpFunction(DlFcn.dlerror, "dlerror"))<br>+ return std::move(Err);<br>+<br>+ std::unique_ptr<MachOPlatformSupport> MP(<br>+ new MachOPlatformSupport(J, PlatformJITDylib, DlFcn));<br>+ return std::move(MP);<br>+ }<br>+<br>+ Error initialize(JITDylib &JD) override {<br>+ if (auto InitSeq = MP.getInitializerSequence(JD)) {<br>+ for (auto &KV : *InitSeq) {<br>+ KV.second.registerObjCSelectors();<br>+ if (auto Err = KV.second.registerObjCClasses()) {<br>+ // FIXME: Roll back registrations on error?<br>+ return Err;<br>+ }<br>+ }<br>+ for (auto &KV : *InitSeq)<br>+ KV.second.runModInits();<br>+ } else<br>+ return InitSeq.takeError();<br>+ return Error::success();<br>+ }<br>+<br>+ Error deinitialize(JITDylib &JD) override {<br>+ auto &ES = J.getExecutionSession();<br>+ if (auto DeinitSeq = MP.getDeinitializerSequence(JD)) {<br>+ for (auto &KV : *DeinitSeq) {<br>+ auto DSOHandleName = ES.intern("___dso_handle");<br>+<br>+ // FIXME: Run DeInits here.<br>+ auto Result = ES.lookup(<br>+ {{KV.first, JITDylibLookupFlags::MatchAllSymbols}},<br>+ SymbolLookupSet(DSOHandleName,<br>+ SymbolLookupFlags::WeaklyReferencedSymbol));<br>+ if (!Result)<br>+ return Result.takeError();<br>+ if (Result->empty())<br>+ continue;<br>+ assert(Result->count(DSOHandleName) &&<br>+ "Result does not contain __dso_handle");<br>+ auto *DSOHandle = jitTargetAddressToPointer<void *>(<br>+ Result->begin()->second.getAddress());<br>+ AtExitMgr.runAtExits(DSOHandle);<br>+ }<br>+ } else<br>+ return DeinitSeq.takeError();<br>+ return Error::success();<br>+ }<br>+<br>+private:<br>+ template <typename FunctionPtrTy><br>+ static Error hookUpFunction(FunctionPtrTy &Fn, const char *Name) {<br>+ if (auto *FnAddr = sys::DynamicLibrary::SearchForAddressOfSymbol(Name)) {<br>+ Fn = reinterpret_cast<FunctionPtrTy>(Fn);<br>+ return Error::success();<br>+ }<br>+<br>+ return make_error<StringError>((Twine("Can not enable MachO JIT Platform: "<br>+ "missing function: ") +<br>+ Name)<br>+ .str(),<br>+ inconvertibleErrorCode());<br>+ }<br>+<br>+ MachOPlatformSupport(LLJIT &J, JITDylib &PlatformJITDylib, DlFcnValues DlFcn)<br>+ : J(J), MP(setupPlatform(J)), DlFcn(std::move(DlFcn)) {<br>+<br>+ MangleAndInterner Mangle(J.getExecutionSession(), J.getDataLayout());<br>+ SymbolMap HelperSymbols;<br>+<br>+ // platform and atexit helpers.<br>+ HelperSymbols[Mangle("__lljit.platform_support_instance")] =<br>+ JITEvaluatedSymbol(pointerToJITTargetAddress(this), JITSymbolFlags());<br>+ HelperSymbols[Mangle("__lljit.cxa_atexit_helper")] = JITEvaluatedSymbol(<br>+ pointerToJITTargetAddress(registerAtExitHelper), JITSymbolFlags());<br>+ HelperSymbols[Mangle("__lljit.run_atexits_helper")] = JITEvaluatedSymbol(<br>+ pointerToJITTargetAddress(runAtExitsHelper), JITSymbolFlags());<br>+<br>+ // dlfcn helpers.<br>+ HelperSymbols[Mangle("__lljit.dlopen_helper")] = JITEvaluatedSymbol(<br>+ pointerToJITTargetAddress(dlopenHelper), JITSymbolFlags());<br>+ HelperSymbols[Mangle("__lljit.dlclose_helper")] = JITEvaluatedSymbol(<br>+ pointerToJITTargetAddress(dlcloseHelper), JITSymbolFlags());<br>+ HelperSymbols[Mangle("__lljit.dlsym_helper")] = JITEvaluatedSymbol(<br>+ pointerToJITTargetAddress(dlsymHelper), JITSymbolFlags());<br>+ HelperSymbols[Mangle("__lljit.dlerror_helper")] = JITEvaluatedSymbol(<br>+ pointerToJITTargetAddress(dlerrorHelper), JITSymbolFlags());<br>+<br>+ cantFail(<br>+ PlatformJITDylib.define(absoluteSymbols(std::move(HelperSymbols))));<br>+ cantFail(MP.setupJITDylib(J.getMainJITDylib()));<br>+ cantFail(J.addIRModule(PlatformJITDylib, createPlatformRuntimeModule()));<br>+ }<br>+<br>+ static MachOPlatform &setupPlatform(LLJIT &J) {<br>+ auto Tmp = std::make_unique<MachOPlatform>(<br>+ J.getExecutionSession(),<br>+ static_cast<ObjectLinkingLayer &>(J.getObjLinkingLayer()),<br>+ createStandardSymbolsObject(J));<br>+ auto &MP = *Tmp;<br>+ J.getExecutionSession().setPlatform(std::move(Tmp));<br>+ return MP;<br>+ }<br>+<br>+ static std::unique_ptr<MemoryBuffer> createStandardSymbolsObject(LLJIT &J) {<br>+ LLVMContext Ctx;<br>+ Module M("__standard_symbols", Ctx);<br>+ M.setDataLayout(J.getDataLayout());<br>+<br>+ auto *Int64Ty = Type::getInt64Ty(Ctx);<br>+<br>+ auto *DSOHandle =<br>+ new GlobalVariable(M, Int64Ty, true, GlobalValue::ExternalLinkage,<br>+ ConstantInt::get(Int64Ty, 0), "__dso_handle");<br>+ DSOHandle->setVisibility(GlobalValue::HiddenVisibility);<br>+<br>+ return cantFail(J.getIRCompileLayer().getCompiler()(M));<br>+ }<br>+<br>+ ThreadSafeModule createPlatformRuntimeModule() {<br>+ auto Ctx = std::make_unique<LLVMContext>();<br>+ auto M = std::make_unique<Module>("__standard_lib", *Ctx);<br>+ M->setDataLayout(J.getDataLayout());<br>+<br>+ auto *MachOPlatformSupportTy =<br>+ StructType::create(*Ctx, "lljit.MachOPlatformSupport");<br>+<br>+ auto *PlatformInstanceDecl = new GlobalVariable(<br>+ *M, MachOPlatformSupportTy, true, GlobalValue::ExternalLinkage, nullptr,<br>+ "__lljit.platform_support_instance");<br>+<br>+ auto *Int8Ty = Type::getInt8Ty(*Ctx);<br>+ auto *IntTy = Type::getIntNTy(*Ctx, sizeof(int) * CHAR_BIT);<br>+ auto *VoidTy = Type::getVoidTy(*Ctx);<br>+ auto *BytePtrTy = PointerType::getUnqual(Int8Ty);<br>+ auto *AtExitCallbackTy = FunctionType::get(VoidTy, {BytePtrTy}, false);<br>+ auto *AtExitCallbackPtrTy = PointerType::getUnqual(AtExitCallbackTy);<br>+<br>+ addHelperAndWrapper(<br>+ *M, "__cxa_atexit",<br>+ FunctionType::get(IntTy, {AtExitCallbackPtrTy, BytePtrTy, BytePtrTy},<br>+ false),<br>+ GlobalValue::DefaultVisibility, "__lljit.cxa_atexit_helper",<br>+ {PlatformInstanceDecl});<br>+<br>+ addHelperAndWrapper(*M, "dlopen",<br>+ FunctionType::get(BytePtrTy, {BytePtrTy, IntTy}, false),<br>+ GlobalValue::DefaultVisibility, "__lljit.dlopen_helper",<br>+ {PlatformInstanceDecl});<br>+<br>+ addHelperAndWrapper(*M, "dlclose",<br>+ FunctionType::get(IntTy, {BytePtrTy}, false),<br>+ GlobalValue::DefaultVisibility,<br>+ "__lljit.dlclose_helper", {PlatformInstanceDecl});<br>+<br>+ addHelperAndWrapper(<br>+ *M, "dlsym",<br>+ FunctionType::get(BytePtrTy, {BytePtrTy, BytePtrTy}, false),<br>+ GlobalValue::DefaultVisibility, "__lljit.dlsym_helper",<br>+ {PlatformInstanceDecl});<br>+<br>+ addHelperAndWrapper(*M, "dlerror", FunctionType::get(BytePtrTy, {}, false),<br>+ GlobalValue::DefaultVisibility,<br>+ "__lljit.dlerror_helper", {PlatformInstanceDecl});<br>+<br>+ return ThreadSafeModule(std::move(M), std::move(Ctx));<br>+ }<br>+<br>+ static void registerAtExitHelper(void *Self, void (*F)(void *), void *Ctx,<br>+ void *DSOHandle) {<br>+ static_cast<MachOPlatformSupport *>(Self)->AtExitMgr.registerAtExit(<br>+ F, Ctx, DSOHandle);<br>+ }<br>+<br>+ static void runAtExitsHelper(void *Self, void *DSOHandle) {<br>+ static_cast<MachOPlatformSupport *>(Self)->AtExitMgr.runAtExits(DSOHandle);<br>+ }<br>+<br>+ void *jit_dlopen(const char *Path, int Mode) {<br>+ JITDylib *JDToOpen = nullptr;<br>+ // FIXME: Do the right thing with Mode flags.<br>+ {<br>+ std::lock_guard<std::mutex> Lock(PlatformSupportMutex);<br>+<br>+ // Clear any existing error messages.<br>+ dlErrorMsgs.erase(std::this_thread::get_id());<br>+<br>+ if (auto *JD = J.getExecutionSession().getJITDylibByName(Path)) {<br>+ auto I = JDRefCounts.find(JD);<br>+ if (I != JDRefCounts.end()) {<br>+ ++I->second;<br>+ return JD;<br>+ }<br>+<br>+ JDRefCounts[JD] = 1;<br>+ JDToOpen = JD;<br>+ }<br>+ }<br>+<br>+ if (JDToOpen) {<br>+ if (auto Err = initialize(*JDToOpen)) {<br>+ recordError(std::move(Err));<br>+ return 0;<br>+ }<br>+ }<br>+<br>+ // Fall through to dlopen if no JITDylib found for Path.<br>+ return DlFcn.dlopen(Path, Mode);<br>+ }<br>+<br>+ static void *dlopenHelper(void *Self, const char *Path, int Mode) {<br>+ return static_cast<MachOPlatformSupport *>(Self)->jit_dlopen(Path, Mode);<br>+ }<br>+<br>+ int jit_dlclose(void *Handle) {<br>+ JITDylib *JDToClose = nullptr;<br>+<br>+ {<br>+ std::lock_guard<std::mutex> Lock(PlatformSupportMutex);<br>+<br>+ // Clear any existing error messages.<br>+ dlErrorMsgs.erase(std::this_thread::get_id());<br>+<br>+ auto I = JDRefCounts.find(Handle);<br>+ if (I != JDRefCounts.end()) {<br>+ --I->second;<br>+ if (I->second == 0) {<br>+ JDRefCounts.erase(I);<br>+ JDToClose = static_cast<JITDylib *>(Handle);<br>+ } else<br>+ return 0;<br>+ }<br>+ }<br>+<br>+ if (JDToClose) {<br>+ if (auto Err = deinitialize(*JDToClose)) {<br>+ recordError(std::move(Err));<br>+ return -1;<br>+ }<br>+ return 0;<br>+ }<br>+<br>+ // Fall through to dlclose if no JITDylib found for Path.<br>+ return DlFcn.dlclose(Handle);<br>+ }<br>+<br>+ static int dlcloseHelper(void *Self, void *Handle) {<br>+ return static_cast<MachOPlatformSupport *>(Self)->jit_dlclose(Handle);<br>+ }<br>+<br>+ void *jit_dlsym(void *Handle, const char *Name) {<br>+ JITDylibSearchOrder JITSymSearchOrder;<br>+<br>+ // FIXME: RTLD_NEXT, RTLD_SELF not supported.<br>+ {<br>+ std::lock_guard<std::mutex> Lock(PlatformSupportMutex);<br>+<br>+ // Clear any existing error messages.<br>+ dlErrorMsgs.erase(std::this_thread::get_id());<br>+<br>+ if (JDRefCounts.count(Handle)) {<br>+ JITSymSearchOrder.push_back(<br>+ {static_cast<JITDylib *>(Handle),<br>+ JITDylibLookupFlags::MatchExportedSymbolsOnly});<br>+ } else if (Handle == DlFcn.RTLDDefault) {<br>+ for (auto &KV : JDRefCounts)<br>+ JITSymSearchOrder.push_back(<br>+ {static_cast<JITDylib *>(KV.first),<br>+ JITDylibLookupFlags::MatchExportedSymbolsOnly});<br>+ }<br>+ }<br>+<br>+ if (!JITSymSearchOrder.empty()) {<br>+ MangleAndInterner Mangle(J.getExecutionSession(), J.getDataLayout());<br>+ auto MangledName = Mangle(Name);<br>+ SymbolLookupSet Syms(MangledName,<br>+ SymbolLookupFlags::WeaklyReferencedSymbol);<br>+ if (auto Result = J.getExecutionSession().lookup(JITSymSearchOrder, Syms,<br>+ LookupKind::DLSym)) {<br>+ auto I = Result->find(MangledName);<br>+ if (I != Result->end())<br>+ return jitTargetAddressToPointer<void *>(I->second.getAddress());<br>+ } else {<br>+ recordError(Result.takeError());<br>+ return 0;<br>+ }<br>+ }<br>+<br>+ // Fall through to dlsym.<br>+ return DlFcn.dlsym(Handle, Name);<br>+ }<br>+<br>+ static void *dlsymHelper(void *Self, void *Handle, const char *Name) {<br>+ return static_cast<MachOPlatformSupport *>(Self)->jit_dlsym(Handle, Name);<br>+ }<br>+<br>+ const char *jit_dlerror() {<br>+ {<br>+ std::lock_guard<std::mutex> Lock(PlatformSupportMutex);<br>+ auto I = dlErrorMsgs.find(std::this_thread::get_id());<br>+ if (I != dlErrorMsgs.end())<br>+ return I->second->c_str();<br>+ }<br>+ return DlFcn.dlerror();<br>+ }<br>+<br>+ static const char *dlerrorHelper(void *Self) {<br>+ return static_cast<MachOPlatformSupport *>(Self)->jit_dlerror();<br>+ }<br>+<br>+ void recordError(Error Err) {<br>+ std::lock_guard<std::mutex> Lock(PlatformSupportMutex);<br>+ dlErrorMsgs[std::this_thread::get_id()] =<br>+ std::make_unique<std::string>(toString(std::move(Err)));<br>+ }<br>+<br>+ std::mutex PlatformSupportMutex;<br>+ LLJIT &J;<br>+ MachOPlatform &MP;<br>+ DlFcnValues DlFcn;<br>+ ItaniumCXAAtExitSupport AtExitMgr;<br>+ DenseMap<void *, unsigned> JDRefCounts;<br>+ std::map<std::thread::id, std::unique_ptr<std::string>> dlErrorMsgs;<br>+};<br>+<br>+} // end anonymous namespace<br><br> namespace llvm {<br> namespace orc {<br><br>+void LLJIT::PlatformSupport::setInitTransform(<br>+ LLJIT &J, IRTransformLayer::TransformFunction T) {<br>+ J.InitHelperTransformLayer->setTransform(std::move(T));<br>+}<br>+<br>+LLJIT::PlatformSupport::~PlatformSupport() {}<br>+<br> Error LLJITBuilderState::prepareForConstruction() {<br><br> if (!JTMB) {<br>@@ -57,7 +869,7 @@ LLJIT::~LLJIT() {<br> Error LLJIT::defineAbsolute(StringRef Name, JITEvaluatedSymbol Sym) {<br> auto InternedName = ES->intern(Name);<br> SymbolMap Symbols({{InternedName, Sym}});<br>- return Main.define(absoluteSymbols(std::move(Symbols)));<br>+ return Main->define(absoluteSymbols(std::move(Symbols)));<br> }<br><br> Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) {<br>@@ -67,7 +879,8 @@ Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) {<br> TSM.withModuleDo([&](Module &M) { return applyDataLayout(M); }))<br> return Err;<br><br>- return TransformLayer->add(JD, std::move(TSM), ES->allocateVModule());<br>+ return InitHelperTransformLayer->add(JD, std::move(TSM),<br>+ ES->allocateVModule());<br> }<br><br> Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) {<br>@@ -128,16 +941,23 @@ LLJIT::createCompileFunction(LLJITBuilderState &S,<br> }<br><br> LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)<br>- : ES(<a href="http://S.ES" target="_blank">S.ES</a> ? std::move(<a href="http://S.ES" target="_blank">S.ES</a>) : std::make_unique<ExecutionSession>()),<br>- Main(this->ES->createJITDylib("<main>")), DL(""),<br>- TT(S.JTMB->getTargetTriple()),<br>+ : ES(<a href="http://S.ES" target="_blank">S.ES</a> ? std::move(<a href="http://S.ES" target="_blank">S.ES</a>) : std::make_unique<ExecutionSession>()), Main(),<br>+ DL(""), TT(S.JTMB->getTargetTriple()),<br> ObjLinkingLayer(createObjectLinkingLayer(S, *ES)),<br>- ObjTransformLayer(*this->ES, *ObjLinkingLayer), CtorRunner(Main),<br>- DtorRunner(Main) {<br>+ ObjTransformLayer(*this->ES, *ObjLinkingLayer) {<br><br> ErrorAsOutParameter _(&Err);<br><br>- if (auto DLOrErr = S.JTMB->getDefaultDataLayoutForTarget())<br>+ if (auto MainOrErr = this->ES->createJITDylib("main"))<br>+ Main = &*MainOrErr;<br>+ else {<br>+ Err = MainOrErr.takeError();<br>+ return;<br>+ }<br>+<br>+ if (S.DL)<br>+ DL = std::move(*S.DL);<br>+ else if (auto DLOrErr = S.JTMB->getDefaultDataLayoutForTarget())<br> DL = std::move(*DLOrErr);<br> else {<br> Err = DLOrErr.takeError();<br>@@ -153,10 +973,12 @@ LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)<br> CompileLayer = std::make_unique<IRCompileLayer>(<br> *ES, ObjTransformLayer, std::move(*CompileFunction));<br> TransformLayer = std::make_unique<IRTransformLayer>(*ES, *CompileLayer);<br>+ InitHelperTransformLayer =<br>+ std::make_unique<IRTransformLayer>(*ES, *TransformLayer);<br> }<br><br> if (S.NumCompileThreads > 0) {<br>- TransformLayer->setCloneToNewContextOnEmit(true);<br>+ InitHelperTransformLayer->setCloneToNewContextOnEmit(true);<br> CompileThreads =<br> std::make_unique<ThreadPool>(hardware_concurrency(S.NumCompileThreads));<br> ES->setDispatchMaterialization(<br>@@ -167,6 +989,11 @@ LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)<br> CompileThreads->async(std::move(Work));<br> });<br> }<br>+<br>+ if (S.SetUpPlatform)<br>+ Err = S.SetUpPlatform(*this);<br>+ else<br>+ setUpGenericLLVMIRPlatform(*this);<br> }<br><br> std::string LLJIT::mangle(StringRef UnmangledName) {<br>@@ -184,15 +1011,24 @@ Error LLJIT::applyDataLayout(Module &M) {<br><br> if (M.getDataLayout() != DL)<br> return make_error<StringError>(<br>- "Added modules have incompatible data layouts",<br>+ "Added modules have incompatible data layouts: " +<br>+ M.getDataLayout().getStringRepresentation() + " (module) vs " +<br>+ DL.getStringRepresentation() + " (jit)",<br> inconvertibleErrorCode());<br><br> return Error::success();<br> }<br><br>-void LLJIT::recordCtorDtors(Module &M) {<br>- CtorRunner.add(getConstructors(M));<br>- DtorRunner.add(getDestructors(M));<br>+void setUpGenericLLVMIRPlatform(LLJIT &J) {<br>+ J.setPlatformSupport(std::make_unique<GenericLLVMIRPlatformSupport>(J));<br>+}<br>+<br>+Error setUpMachOPlatform(LLJIT &J) {<br>+ auto MP = MachOPlatformSupport::Create(J, J.getMainJITDylib());<br>+ if (!MP)<br>+ return MP.takeError();<br>+ J.setPlatformSupport(std::move(*MP));<br>+ return Error::success();<br> }<br><br> Error LLLazyJITBuilderState::prepareForConstruction() {<br>@@ -205,13 +1041,8 @@ Error LLLazyJITBuilderState::prepareForConstruction() {<br> Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) {<br> assert(TSM && "Can not add null module");<br><br>- if (auto Err = TSM.withModuleDo([&](Module &M) -> Error {<br>- if (auto Err = applyDataLayout(M))<br>- return Err;<br>-<br>- recordCtorDtors(M);<br>- return Error::success();<br>- }))<br>+ if (auto Err = TSM.withModuleDo(<br>+ [&](Module &M) -> Error { return applyDataLayout(M); }))<br> return Err;<br><br> return CODLayer->add(JD, std::move(TSM), ES->allocateVModule());<br>@@ -256,7 +1087,7 @@ LLLazyJIT::LLLazyJIT(LLLazyJITBuilderState &S, Error &Err) : LLJIT(S, Err) {<br><br> // Create the COD layer.<br> CODLayer = std::make_unique<CompileOnDemandLayer>(<br>- *ES, *TransformLayer, *LCTMgr, std::move(ISMBuilder));<br>+ *ES, *InitHelperTransformLayer, *LCTMgr, std::move(ISMBuilder));<br><br> if (S.NumCompileThreads > 0)<br> CODLayer->setCloneToNewContextOnEmit(true);<br><br>diff --git a/llvm/lib/ExecutionEngine/Orc/Layer.cpp b/llvm/lib/ExecutionEngine/Orc/Layer.cpp<br>index ebc7801f11ff..63b04a0562bd 100644<br>--- a/llvm/lib/ExecutionEngine/Orc/Layer.cpp<br>+++ b/llvm/lib/ExecutionEngine/Orc/Layer.cpp<br>@@ -7,7 +7,10 @@<br> //===----------------------------------------------------------------------===//<br><br> #include "llvm/ExecutionEngine/Orc/Layer.h"<br>+<br>+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"<br> #include "llvm/IR/Constants.h"<br>+#include "llvm/Object/MachO.h"<br> #include "llvm/Object/ObjectFile.h"<br> #include "llvm/Support/Debug.h"<br><br>@@ -23,10 +26,11 @@ Error IRLayer::add(JITDylib &JD, ThreadSafeModule TSM, VModuleKey K) {<br> *this, *getManglingOptions(), std::move(TSM), std::move(K)));<br> }<br><br>-IRMaterializationUnit::IRMaterializationUnit(ExecutionSession &ES,<br>- const ManglingOptions &MO,<br>- ThreadSafeModule TSM, VModuleKey K)<br>- : MaterializationUnit(SymbolFlagsMap(), std::move(K)), TSM(std::move(TSM)) {<br>+IRMaterializationUnit::IRMaterializationUnit(<br>+ ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO,<br>+ ThreadSafeModule TSM, VModuleKey K)<br>+ : MaterializationUnit(SymbolFlagsMap(), nullptr, std::move(K)),<br>+ TSM(std::move(TSM)) {<br><br> assert(this->TSM && "Module must not be null");<br><br>@@ -34,6 +38,7 @@ IRMaterializationUnit::IRMaterializationUnit(ExecutionSession &ES,<br> this->TSM.withModuleDo([&](Module &M) {<br> for (auto &G : M.global_values()) {<br> // Skip globals that don't generate symbols.<br>+<br> if (!G.hasName() || G.isDeclaration() || G.hasLocalLinkage() ||<br> G.hasAvailableExternallyLinkage() || G.hasAppendingLinkage())<br> continue;<br>@@ -72,13 +77,23 @@ IRMaterializationUnit::IRMaterializationUnit(ExecutionSession &ES,<br> SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G);<br> SymbolToDefinition[MangledName] = &G;<br> }<br>+<br>+ // If we need an init symbol for this module then create one.<br>+ if (!llvm::empty(getStaticInitGVs(M))) {<br>+ std::string InitSymbolName;<br>+ raw_string_ostream(InitSymbolName)<br>+ << "$." << M.getModuleIdentifier() << ".__inits";<br>+ InitSymbol = ES.intern(InitSymbolName);<br>+ SymbolFlags[InitSymbol] = JITSymbolFlags();<br>+ }<br> });<br> }<br><br> IRMaterializationUnit::IRMaterializationUnit(<br> ThreadSafeModule TSM, VModuleKey K, SymbolFlagsMap SymbolFlags,<br>- SymbolNameToDefinitionMap SymbolToDefinition)<br>- : MaterializationUnit(std::move(SymbolFlags), std::move(K)),<br>+ SymbolStringPtr InitSymbol, SymbolNameToDefinitionMap SymbolToDefinition)<br>+ : MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol),<br>+ std::move(K)),<br> TSM(std::move(TSM)), SymbolToDefinition(std::move(SymbolToDefinition)) {}<br><br> StringRef IRMaterializationUnit::getName() const {<br>@@ -105,7 +120,8 @@ void IRMaterializationUnit::discard(const JITDylib &JD,<br> }<br><br> BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit(<br>- IRLayer &L, const ManglingOptions &MO, ThreadSafeModule TSM, VModuleKey K)<br>+ IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, ThreadSafeModule TSM,<br>+ VModuleKey K)<br> : IRMaterializationUnit(L.getExecutionSession(), MO, std::move(TSM),<br> std::move(K)),<br> L(L), K(std::move(K)) {}<br>@@ -150,22 +166,26 @@ Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O,<br> Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>><br> BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L, VModuleKey K,<br> std::unique_ptr<MemoryBuffer> O) {<br>- auto SymbolFlags =<br>- getObjectSymbolFlags(L.getExecutionSession(), O->getMemBufferRef());<br>+ auto ObjSymInfo =<br>+ getObjectSymbolInfo(L.getExecutionSession(), O->getMemBufferRef());<br>+<br>+ if (!ObjSymInfo)<br>+ return ObjSymInfo.takeError();<br><br>- if (!SymbolFlags)<br>- return SymbolFlags.takeError();<br>+ auto &SymbolFlags = ObjSymInfo->first;<br>+ auto &InitSymbol = ObjSymInfo->second;<br><br> return std::unique_ptr<BasicObjectLayerMaterializationUnit>(<br>- new BasicObjectLayerMaterializationUnit(L, K, std::move(O),<br>- std::move(*SymbolFlags)));<br>+ new BasicObjectLayerMaterializationUnit(<br>+ L, K, std::move(O), std::move(SymbolFlags), std::move(InitSymbol)));<br> }<br><br> BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit(<br> ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O,<br>- SymbolFlagsMap SymbolFlags)<br>- : MaterializationUnit(std::move(SymbolFlags), std::move(K)), L(L),<br>- O(std::move(O)) {}<br>+ SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol)<br>+ : MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol),<br>+ std::move(K)),<br>+ L(L), O(std::move(O)) {}<br><br> StringRef BasicObjectLayerMaterializationUnit::getName() const {<br> if (O)<br>@@ -184,35 +204,5 @@ void BasicObjectLayerMaterializationUnit::discard(const JITDylib &JD,<br> // filter to pass to the object layer along with the object itself.<br> }<br><br>-Expected<SymbolFlagsMap> getObjectSymbolFlags(ExecutionSession &ES,<br>- MemoryBufferRef ObjBuffer) {<br>- auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);<br>-<br>- if (!Obj)<br>- return Obj.takeError();<br>-<br>- SymbolFlagsMap SymbolFlags;<br>- for (auto &Sym : (*Obj)->symbols()) {<br>- // Skip symbols not defined in this object file.<br>- if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined)<br>- continue;<br>-<br>- // Skip symbols that are not global.<br>- if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global))<br>- continue;<br>-<br>- auto Name = Sym.getName();<br>- if (!Name)<br>- return Name.takeError();<br>- auto InternedName = ES.intern(*Name);<br>- auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);<br>- if (!SymFlags)<br>- return SymFlags.takeError();<br>- SymbolFlags[InternedName] = std::move(*SymFlags);<br>- }<br>-<br>- return SymbolFlags;<br>-}<br>-<br> } // End namespace orc.<br> } // End namespace llvm.<br><br>diff --git a/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp b/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp<br>index 97f36ede713f..27d08e18270f 100644<br>--- a/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp<br>+++ b/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp<br>@@ -51,7 +51,7 @@ LazyCallThroughManager::callThroughToSymbol(JITTargetAddress TrampolineAddr) {<br><br> auto LookupResult = ES.lookup(<br> makeJITDylibSearchOrder(SourceJD, JITDylibLookupFlags::MatchAllSymbols),<br>- SymbolName);<br>+ SymbolName, SymbolState::Ready);<br><br> if (!LookupResult) {<br> ES.reportError(LookupResult.takeError());<br>@@ -123,10 +123,9 @@ LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(<br> LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,<br> JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc,<br> VModuleKey K)<br>- : MaterializationUnit(extractFlags(CallableAliases), std::move(K)),<br>+ : MaterializationUnit(extractFlags(CallableAliases), nullptr, std::move(K)),<br> LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),<br>- CallableAliases(std::move(CallableAliases)),<br>- AliaseeTable(SrcJDLoc) {}<br>+ CallableAliases(std::move(CallableAliases)), AliaseeTable(SrcJDLoc) {}<br><br> StringRef LazyReexportsMaterializationUnit::getName() const {<br> return "<Lazy Reexports>";<br><br>diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp<br>new file mode 100644<br>index 000000000000..4618d53315ef<br>--- /dev/null<br>+++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp<br>@@ -0,0 +1,459 @@<br>+//===------ MachOPlatform.cpp - Utilities for executing MachO in Orc ------===//<br>+//<br>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.<br>+// See <a href="https://llvm.org/LICENSE.txt" target="_blank">https://llvm.org/LICENSE.txt</a> for license information.<br>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"<br>+<br>+#include "llvm/BinaryFormat/MachO.h"<br>+#include "llvm/Support/BinaryByteStream.h"<br>+<br>+namespace {<br>+<br>+struct objc_class;<br>+struct objc_image_info;<br>+struct objc_object;<br>+struct objc_selector;<br>+<br>+using Class = objc_class *;<br>+using id = objc_object *;<br>+using SEL = objc_selector *;<br>+<br>+using ObjCMsgSendTy = id (*)(id, SEL, ...);<br>+using ObjCReadClassPairTy = Class (*)(Class, const objc_image_info *);<br>+using SelRegisterNameTy = SEL (*)(const char *);<br>+<br>+enum class ObjCRegistrationAPI { Uninitialized, Unavailable, Initialized };<br>+<br>+ObjCRegistrationAPI ObjCRegistrationAPIState =<br>+ ObjCRegistrationAPI::Uninitialized;<br>+ObjCMsgSendTy objc_msgSend = nullptr;<br>+ObjCReadClassPairTy objc_readClassPair = nullptr;<br>+SelRegisterNameTy sel_registerName = nullptr;<br>+<br>+} // end anonymous namespace<br>+<br>+namespace llvm {<br>+namespace orc {<br>+<br>+template <typename FnTy><br>+static Error setUpObjCRegAPIFunc(FnTy &Target, sys::DynamicLibrary &LibObjC,<br>+ const char *Name) {<br>+ if (void *Addr = LibObjC.getAddressOfSymbol(Name))<br>+ Target = reinterpret_cast<FnTy>(Addr);<br>+ else<br>+ return make_error<StringError>(<br>+ (Twine("Could not find address for ") + Name).str(),<br>+ inconvertibleErrorCode());<br>+ return Error::success();<br>+}<br>+<br>+Error enableObjCRegistration(const char *PathToLibObjC) {<br>+ // If we've already tried to initialize then just bail out.<br>+ if (ObjCRegistrationAPIState != ObjCRegistrationAPI::Uninitialized)<br>+ return Error::success();<br>+<br>+ ObjCRegistrationAPIState = ObjCRegistrationAPI::Unavailable;<br>+<br>+ std::string ErrMsg;<br>+ auto LibObjC =<br>+ sys::DynamicLibrary::getPermanentLibrary(PathToLibObjC, &ErrMsg);<br>+<br>+ if (!LibObjC.isValid())<br>+ return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());<br>+<br>+ if (auto Err = setUpObjCRegAPIFunc(objc_msgSend, LibObjC, "objc_msgSend"))<br>+ return Err;<br>+ if (auto Err = setUpObjCRegAPIFunc(objc_readClassPair, LibObjC,<br>+ "objc_readClassPair"))<br>+ return Err;<br>+ if (auto Err =<br>+ setUpObjCRegAPIFunc(sel_registerName, LibObjC, "sel_registerName"))<br>+ return Err;<br>+<br>+ ObjCRegistrationAPIState = ObjCRegistrationAPI::Initialized;<br>+ return Error::success();<br>+}<br>+<br>+bool objcRegistrationEnabled() {<br>+ return ObjCRegistrationAPIState == ObjCRegistrationAPI::Initialized;<br>+}<br>+<br>+void MachOJITDylibInitializers::runModInits() const {<br>+ for (const auto &ModInit : ModInitSections) {<br>+ for (uint64_t I = 0; I != ModInit.NumPtrs; ++I) {<br>+ auto *InitializerAddr = jitTargetAddressToPointer<uintptr_t *>(<br>+ ModInit.Address + (I * sizeof(uintptr_t)));<br>+ auto *Initializer =<br>+ jitTargetAddressToFunction<void (*)()>(*InitializerAddr);<br>+ Initializer();<br>+ }<br>+ }<br>+}<br>+<br>+void MachOJITDylibInitializers::registerObjCSelectors() const {<br>+ assert(objcRegistrationEnabled() && "ObjC registration not enabled.");<br>+<br>+ for (const auto &ObjCSelRefs : ObjCSelRefsSections) {<br>+ for (uint64_t I = 0; I != ObjCSelRefs.NumPtrs; ++I) {<br>+ auto SelEntryAddr = ObjCSelRefs.Address + (I * sizeof(uintptr_t));<br>+ const auto *SelName =<br>+ *jitTargetAddressToPointer<const char **>(SelEntryAddr);<br>+ auto Sel = sel_registerName(SelName);<br>+ *jitTargetAddressToPointer<SEL *>(SelEntryAddr) = Sel;<br>+ }<br>+ }<br>+}<br>+<br>+Error MachOJITDylibInitializers::registerObjCClasses() const {<br>+ assert(objcRegistrationEnabled() && "ObjC registration not enabled.");<br>+<br>+ struct ObjCClassCompiled {<br>+ void *Metaclass;<br>+ void *Parent;<br>+ void *Cache1;<br>+ void *Cache2;<br>+ void *Data;<br>+ };<br>+<br>+ auto *ImageInfo =<br>+ jitTargetAddressToPointer<const objc_image_info *>(ObjCImageInfoAddr);<br>+ auto ClassSelector = sel_registerName("class");<br>+<br>+ for (const auto &ObjCClassList : ObjCClassListSections) {<br>+ for (uint64_t I = 0; I != ObjCClassList.NumPtrs; ++I) {<br>+ auto ClassPtrAddr = ObjCClassList.Address + (I * sizeof(uintptr_t));<br>+ auto Cls = *jitTargetAddressToPointer<Class *>(ClassPtrAddr);<br>+ auto *ClassCompiled =<br>+ *jitTargetAddressToPointer<ObjCClassCompiled **>(ClassPtrAddr);<br>+ objc_msgSend(reinterpret_cast<id>(ClassCompiled->Parent), ClassSelector);<br>+ auto Registered = objc_readClassPair(Cls, ImageInfo);<br>+<br>+ // FIXME: Improve diagnostic by reporting the failed class's name.<br>+ if (Registered != Cls)<br>+ return make_error<StringError>("Unable to register Objective-C class",<br>+ inconvertibleErrorCode());<br>+ }<br>+ }<br>+ return Error::success();<br>+}<br>+<br>+void MachOJITDylibInitializers::dump() const {<br>+ for (auto &Extent : ModInitSections)<br>+ dbgs() << formatv("{0:x16}", Extent.Address) << " -- "<br>+ << formatv("{0:x16}", Extent.Address + 8 * Extent.NumPtrs) << "\n";<br>+}<br>+<br>+MachOPlatform::MachOPlatform(<br>+ ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,<br>+ std::unique_ptr<MemoryBuffer> StandardSymbolsObject)<br>+ : ES(ES), ObjLinkingLayer(ObjLinkingLayer),<br>+ StandardSymbolsObject(std::move(StandardSymbolsObject)) {<br>+ ObjLinkingLayer.addPlugin(std::make_unique<InitScraperPlugin>(*this));<br>+}<br>+<br>+Error MachOPlatform::setupJITDylib(JITDylib &JD) {<br>+ auto ObjBuffer = MemoryBuffer::getMemBuffer(<br>+ StandardSymbolsObject->getMemBufferRef(), false);<br>+ return ObjLinkingLayer.add(JD, std::move(ObjBuffer));<br>+}<br>+<br>+Error MachOPlatform::notifyAdding(JITDylib &JD, const MaterializationUnit &MU) {<br>+ const auto &InitSym = MU.getInitializerSymbol();<br>+ if (!InitSym)<br>+ return Error::success();<br>+<br>+ std::lock_guard<std::mutex> Lock(PlatformMutex);<br>+ RegisteredInitSymbols[&JD].add(InitSym);<br>+ return Error::success();<br>+}<br>+<br>+Error MachOPlatform::notifyRemoving(JITDylib &JD, VModuleKey K) {<br>+ llvm_unreachable("Not supported yet");<br>+}<br>+<br>+Expected<MachOPlatform::InitializerSequence><br>+MachOPlatform::getInitializerSequence(JITDylib &JD) {<br>+<br>+ std::vector<JITDylib *> DFSLinkOrder;<br>+<br>+ while (true) {<br>+ // Lock the platform while we search for any initializer symbols to<br>+ // look up.<br>+ DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;<br>+ {<br>+ std::lock_guard<std::mutex> Lock(PlatformMutex);<br>+ DFSLinkOrder = getDFSLinkOrder(JD);<br>+<br>+ for (auto *InitJD : DFSLinkOrder) {<br>+ auto RISItr = RegisteredInitSymbols.find(InitJD);<br>+ if (RISItr != RegisteredInitSymbols.end()) {<br>+ NewInitSymbols[InitJD] = std::move(RISItr->second);<br>+ RegisteredInitSymbols.erase(RISItr);<br>+ }<br>+ }<br>+ }<br>+<br>+ if (NewInitSymbols.empty())<br>+ break;<br>+<br>+ // Outside the lock, issue the lookup.<br>+ if (auto R = lookupInitSymbols(JD.getExecutionSession(), NewInitSymbols))<br>+ ; // Nothing to do in the success case.<br>+ else<br>+ return R.takeError();<br>+ }<br>+<br>+ // Lock again to collect the initializers.<br>+ InitializerSequence FullInitSeq;<br>+ {<br>+ std::lock_guard<std::mutex> Lock(PlatformMutex);<br>+ for (auto *InitJD : reverse(DFSLinkOrder)) {<br>+ auto ISItr = InitSeqs.find(InitJD);<br>+ if (ISItr != InitSeqs.end()) {<br>+ FullInitSeq.emplace_back(InitJD, std::move(ISItr->second));<br>+ InitSeqs.erase(ISItr);<br>+ }<br>+ }<br>+ }<br>+<br>+ return FullInitSeq;<br>+}<br>+<br>+Expected<MachOPlatform::DeinitializerSequence><br>+MachOPlatform::getDeinitializerSequence(JITDylib &JD) {<br>+ std::vector<JITDylib *> DFSLinkOrder = getDFSLinkOrder(JD);<br>+<br>+ DeinitializerSequence FullDeinitSeq;<br>+ {<br>+ std::lock_guard<std::mutex> Lock(PlatformMutex);<br>+ for (auto *DeinitJD : DFSLinkOrder) {<br>+ FullDeinitSeq.emplace_back(DeinitJD, MachOJITDylibDeinitializers());<br>+ }<br>+ }<br>+<br>+ return FullDeinitSeq;<br>+}<br>+<br>+std::vector<JITDylib *> MachOPlatform::getDFSLinkOrder(JITDylib &JD) {<br>+ std::vector<JITDylib *> Result, WorkStack({&JD});<br>+ DenseSet<JITDylib *> Visited;<br>+<br>+ while (!WorkStack.empty()) {<br>+ auto *NextJD = WorkStack.back();<br>+ WorkStack.pop_back();<br>+ if (Visited.count(NextJD))<br>+ continue;<br>+ Visited.insert(NextJD);<br>+ Result.push_back(NextJD);<br>+ NextJD->withSearchOrderDo([&](const JITDylibSearchOrder &SO) {<br>+ for (auto &KV : SO)<br>+ WorkStack.push_back(KV.first);<br>+ });<br>+ }<br>+<br>+ return Result;<br>+}<br>+<br>+void MachOPlatform::registerInitInfo(<br>+ JITDylib &JD, JITTargetAddress ObjCImageInfoAddr,<br>+ MachOJITDylibInitializers::SectionExtent ModInits,<br>+ MachOJITDylibInitializers::SectionExtent ObjCSelRefs,<br>+ MachOJITDylibInitializers::SectionExtent ObjCClassList) {<br>+ std::lock_guard<std::mutex> Lock(PlatformMutex);<br>+<br>+ auto &InitSeq = InitSeqs[&JD];<br>+<br>+ InitSeq.setObjCImageInfoAddr(ObjCImageInfoAddr);<br>+<br>+ if (ModInits.Address)<br>+ InitSeq.addModInitsSection(std::move(ModInits));<br>+<br>+ if (ObjCSelRefs.Address)<br>+ InitSeq.addObjCSelRefsSection(std::move(ObjCSelRefs));<br>+<br>+ if (ObjCClassList.Address)<br>+ InitSeq.addObjCClassListSection(std::move(ObjCClassList));<br>+}<br>+<br>+static Expected<MachOJITDylibInitializers::SectionExtent><br>+getSectionExtent(jitlink::LinkGraph &G, StringRef SectionName) {<br>+ auto *Sec = G.findSectionByName(SectionName);<br>+ if (!Sec)<br>+ return MachOJITDylibInitializers::SectionExtent();<br>+ jitlink::SectionRange R(*Sec);<br>+ if (R.getSize() % G.getPointerSize() != 0)<br>+ return make_error<StringError>(SectionName + " section size is not a "<br>+ "multiple of the pointer size",<br>+ inconvertibleErrorCode());<br>+ return MachOJITDylibInitializers::SectionExtent(<br>+ R.getStart(), R.getSize() / G.getPointerSize());<br>+}<br>+<br>+void MachOPlatform::InitScraperPlugin::modifyPassConfig(<br>+ MaterializationResponsibility &MR, const Triple &TT,<br>+ jitlink::PassConfiguration &Config) {<br>+<br>+ Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) -> Error {<br>+ JITLinkSymbolVector InitSectionSymbols;<br>+ preserveInitSectionIfPresent(InitSectionSymbols, G, "__mod_init_func");<br>+ preserveInitSectionIfPresent(InitSectionSymbols, G, "__objc_selrefs");<br>+ preserveInitSectionIfPresent(InitSectionSymbols, G, "__objc_classlist");<br>+<br>+ if (!InitSymbolDeps.empty()) {<br>+ std::lock_guard<std::mutex> Lock(InitScraperMutex);<br>+ InitSymbolDeps[&MR] = std::move(InitSectionSymbols);<br>+ }<br>+<br>+ if (auto Err = processObjCImageInfo(G, MR))<br>+ return Err;<br>+<br>+ return Error::success();<br>+ });<br>+<br>+ Config.PostFixupPasses.push_back([this, &JD = MR.getTargetJITDylib()](<br>+ jitlink::LinkGraph &G) -> Error {<br>+ MachOJITDylibInitializers::SectionExtent ModInits, ObjCSelRefs,<br>+ ObjCClassList;<br>+<br>+ JITTargetAddress ObjCImageInfoAddr = 0;<br>+ if (auto *ObjCImageInfoSec = G.findSectionByName("__objc_image_info")) {<br>+ if (auto Addr = jitlink::SectionRange(*ObjCImageInfoSec).getStart()) {<br>+ ObjCImageInfoAddr = Addr;<br>+ dbgs() << "Recorded __objc_imageinfo @ " << formatv("{0:x16}", Addr);<br>+ }<br>+ }<br>+<br>+ // Record __mod_init_func.<br>+ if (auto ModInitsOrErr = getSectionExtent(G, "__mod_init_func"))<br>+ ModInits = std::move(*ModInitsOrErr);<br>+ else<br>+ return ModInitsOrErr.takeError();<br>+<br>+ // Record __objc_selrefs.<br>+ if (auto ObjCSelRefsOrErr = getSectionExtent(G, "__objc_selrefs"))<br>+ ObjCSelRefs = std::move(*ObjCSelRefsOrErr);<br>+ else<br>+ return ObjCSelRefsOrErr.takeError();<br>+<br>+ // Record __objc_classlist.<br>+ if (auto ObjCClassListOrErr = getSectionExtent(G, "__objc_classlist"))<br>+ ObjCClassList = std::move(*ObjCClassListOrErr);<br>+ else<br>+ return ObjCClassListOrErr.takeError();<br>+<br>+ MP.registerInitInfo(JD, ObjCImageInfoAddr, std::move(ModInits),<br>+ std::move(ObjCSelRefs), std::move(ObjCClassList));<br>+<br>+ return Error::success();<br>+ });<br>+}<br>+<br>+ObjectLinkingLayer::Plugin::LocalDependenciesMap<br>+MachOPlatform::InitScraperPlugin::getSyntheticSymbolLocalDependencies(<br>+ MaterializationResponsibility &MR) {<br>+ std::lock_guard<std::mutex> Lock(InitScraperMutex);<br>+ auto I = InitSymbolDeps.find(&MR);<br>+ if (I != InitSymbolDeps.end()) {<br>+ LocalDependenciesMap Result;<br>+ Result[MR.getInitializerSymbol()] = std::move(I->second);<br>+ InitSymbolDeps.erase(&MR);<br>+ return Result;<br>+ }<br>+ return LocalDependenciesMap();<br>+}<br>+<br>+void MachOPlatform::InitScraperPlugin::preserveInitSectionIfPresent(<br>+ JITLinkSymbolVector &Symbols, jitlink::LinkGraph &G,<br>+ StringRef SectionName) {<br>+ if (auto *Sec = G.findSectionByName(SectionName)) {<br>+ auto SecBlocks = Sec->blocks();<br>+ if (!llvm::empty(SecBlocks))<br>+ Symbols.push_back(<br>+ &G.addAnonymousSymbol(**SecBlocks.begin(), 0, 0, false, true));<br>+ }<br>+}<br>+<br>+Error MachOPlatform::InitScraperPlugin::processObjCImageInfo(<br>+ jitlink::LinkGraph &G, MaterializationResponsibility &MR) {<br>+<br>+ // If there's an ObjC imagine info then either<br>+ // (1) It's the first __objc_imageinfo we've seen in this JITDylib. In<br>+ // this case we name and record it.<br>+ // OR<br>+ // (2) We already have a recorded __objc_imageinfo for this JITDylib,<br>+ // in which case we just verify it.<br>+ auto *ObjCImageInfo = G.findSectionByName("__objc_imageinfo");<br>+ if (!ObjCImageInfo)<br>+ return Error::success();<br>+<br>+ auto ObjCImageInfoBlocks = ObjCImageInfo->blocks();<br>+<br>+ // Check that the section is not empty if present.<br>+ if (llvm::empty(ObjCImageInfoBlocks))<br>+ return make_error<StringError>("Empty __objc_imageinfo section in " +<br>+ G.getName(),<br>+ inconvertibleErrorCode());<br>+<br>+ // Check that there's only one block in the section.<br>+ if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end())<br>+ return make_error<StringError>("Multiple blocks in __objc_imageinfo "<br>+ "section in " +<br>+ G.getName(),<br>+ inconvertibleErrorCode());<br>+<br>+ // Check that the __objc_imageinfo section is unreferenced.<br>+ // FIXME: We could optimize this check if Symbols had a ref-count.<br>+ for (auto &Sec : G.sections()) {<br>+ if (&Sec != ObjCImageInfo)<br>+ for (auto *B : Sec.blocks())<br>+ for (auto &E : B->edges())<br>+ if (E.getTarget().isDefined() &&<br>+ &E.getTarget().getBlock().getSection() == ObjCImageInfo)<br>+ return make_error<StringError>("__objc_imageinfo is referenced "<br>+ "within file " +<br>+ G.getName(),<br>+ inconvertibleErrorCode());<br>+ }<br>+<br>+ auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin();<br>+ auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data();<br>+ auto Version = support::endian::read32(ObjCImageInfoData, G.getEndianness());<br>+ auto Flags =<br>+ support::endian::read32(ObjCImageInfoData + 4, G.getEndianness());<br>+<br>+ // Lock the mutex while we verify / update the ObjCImageInfos map.<br>+ std::lock_guard<std::mutex> Lock(InitScraperMutex);<br>+<br>+ auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib());<br>+ if (ObjCImageInfoItr != ObjCImageInfos.end()) {<br>+ // We've already registered an __objc_imageinfo section. Verify the<br>+ // content of this new section matches, then delete it.<br>+ if (ObjCImageInfoItr->second.first != Version)<br>+ return make_error<StringError>(<br>+ "ObjC version in " + G.getName() +<br>+ " does not match first registered version",<br>+ inconvertibleErrorCode());<br>+ if (ObjCImageInfoItr->second.second != Flags)<br>+ return make_error<StringError>("ObjC flags in " + G.getName() +<br>+ " do not match first registered flags",<br>+ inconvertibleErrorCode());<br>+<br>+ // __objc_imageinfo is valid. Delete the block.<br>+ for (auto *S : ObjCImageInfo->symbols())<br>+ G.removeDefinedSymbol(*S);<br>+ G.removeBlock(ObjCImageInfoBlock);<br>+ } else {<br>+ // We haven't registered an __objc_imageinfo section yet. Register and<br>+ // move on. The section should already be marked no-dead-strip.<br>+ ObjCImageInfos[&MR.getTargetJITDylib()] = std::make_pair(Version, Flags);<br>+ }<br>+<br>+ return Error::success();<br>+}<br>+<br>+} // End namespace orc.<br>+} // End namespace llvm.<br><br>diff --git a/llvm/lib/ExecutionEngine/Orc/Mangling.cpp b/llvm/lib/ExecutionEngine/Orc/Mangling.cpp<br>new file mode 100644<br>index 000000000000..7ec7869d00b5<br>--- /dev/null<br>+++ b/llvm/lib/ExecutionEngine/Orc/Mangling.cpp<br>@@ -0,0 +1,131 @@<br>+//===----------- Mangling.cpp -- Name Mangling Utilities for ORC ----------===//<br>+//<br>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.<br>+// See <a href="https://llvm.org/LICENSE.txt" target="_blank">https://llvm.org/LICENSE.txt</a> for license information.<br>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#include "llvm/ExecutionEngine/Orc/Mangling.h"<br>+#include "llvm/IR/Constants.h"<br>+#include "llvm/IR/Mangler.h"<br>+#include "llvm/Object/MachO.h"<br>+#include "llvm/Object/ObjectFile.h"<br>+#include "llvm/Support/Debug.h"<br>+<br>+#define DEBUG_TYPE "orc"<br>+<br>+namespace llvm {<br>+namespace orc {<br>+<br>+MangleAndInterner::MangleAndInterner(ExecutionSession &ES, const DataLayout &DL)<br>+ : ES(ES), DL(DL) {}<br>+<br>+SymbolStringPtr MangleAndInterner::operator()(StringRef Name) {<br>+ std::string MangledName;<br>+ {<br>+ raw_string_ostream MangledNameStream(MangledName);<br>+ Mangler::getNameWithPrefix(MangledNameStream, Name, DL);<br>+ }<br>+ return ES.intern(MangledName);<br>+}<br>+<br>+void IRSymbolMapper::add(ExecutionSession &ES, const ManglingOptions &MO,<br>+ ArrayRef<GlobalValue *> GVs,<br>+ SymbolFlagsMap &SymbolFlags,<br>+ SymbolNameToDefinitionMap *SymbolToDefinition) {<br>+ if (GVs.empty())<br>+ return;<br>+<br>+ MangleAndInterner Mangle(ES, GVs[0]->getParent()->getDataLayout());<br>+ for (auto *G : GVs) {<br>+ assert(G && "GVs cannot contain null elements");<br>+ if (!G->hasName() || G->isDeclaration() || G->hasLocalLinkage() ||<br>+ G->hasAvailableExternallyLinkage() || G->hasAppendingLinkage())<br>+ continue;<br>+<br>+ if (G->isThreadLocal() && MO.EmulatedTLS) {<br>+ auto *GV = cast<GlobalVariable>(G);<br>+<br>+ auto Flags = JITSymbolFlags::fromGlobalValue(*GV);<br>+<br>+ auto EmuTLSV = Mangle(("__emutls_v." + GV->getName()).str());<br>+ SymbolFlags[EmuTLSV] = Flags;<br>+ if (SymbolToDefinition)<br>+ (*SymbolToDefinition)[EmuTLSV] = GV;<br>+<br>+ // If this GV has a non-zero initializer we'll need to emit an<br>+ // __emutls.t symbol too.<br>+ if (GV->hasInitializer()) {<br>+ const auto *InitVal = GV->getInitializer();<br>+<br>+ // Skip zero-initializers.<br>+ if (isa<ConstantAggregateZero>(InitVal))<br>+ continue;<br>+ const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal);<br>+ if (InitIntValue && InitIntValue->isZero())<br>+ continue;<br>+<br>+ auto EmuTLST = Mangle(("__emutls_t." + GV->getName()).str());<br>+ SymbolFlags[EmuTLST] = Flags;<br>+ if (SymbolToDefinition)<br>+ (*SymbolToDefinition)[EmuTLST] = GV;<br>+ }<br>+ continue;<br>+ }<br>+<br>+ // Otherwise we just need a normal linker mangling.<br>+ auto MangledName = Mangle(G->getName());<br>+ SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(*G);<br>+ if (SymbolToDefinition)<br>+ (*SymbolToDefinition)[MangledName] = G;<br>+ }<br>+}<br>+<br>+Expected<std::pair<SymbolFlagsMap, SymbolStringPtr>><br>+getObjectSymbolInfo(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {<br>+ auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);<br>+<br>+ if (!Obj)<br>+ return Obj.takeError();<br>+<br>+ SymbolFlagsMap SymbolFlags;<br>+ for (auto &Sym : (*Obj)->symbols()) {<br>+ // Skip symbols not defined in this object file.<br>+ if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined)<br>+ continue;<br>+<br>+ // Skip symbols that are not global.<br>+ if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global))<br>+ continue;<br>+<br>+ auto Name = Sym.getName();<br>+ if (!Name)<br>+ return Name.takeError();<br>+ auto InternedName = ES.intern(*Name);<br>+ auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);<br>+ if (!SymFlags)<br>+ return SymFlags.takeError();<br>+ SymbolFlags[InternedName] = std::move(*SymFlags);<br>+ }<br>+<br>+ SymbolStringPtr InitSymbol;<br>+<br>+ if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get())) {<br>+ for (auto &Sec : MachOObj->sections()) {<br>+ auto SecType = MachOObj->getSectionType(Sec);<br>+ if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) {<br>+ std::string InitSymString;<br>+ raw_string_ostream(InitSymString)<br>+ << "$." << ObjBuffer.getBufferIdentifier() << ".__inits";<br>+ InitSymbol = ES.intern(InitSymString);<br>+ break;<br>+ }<br>+ }<br>+ }<br>+<br>+ return std::make_pair(std::move(SymbolFlags), std::move(InitSymbol));<br>+}<br>+<br>+} // End namespace orc.<br>+} // End namespace llvm.<br><br>diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp<br>index 6575b0a6ccb2..db88ec8517bf 100644<br>--- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp<br>+++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp<br>@@ -144,6 +144,10 @@ class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {<br> if (!ExtraSymbolsToClaim.empty())<br> if (auto Err = MR.defineMaterializing(ExtraSymbolsToClaim))<br> return notifyFailed(std::move(Err));<br>+<br>+ if (const auto &InitSym = MR.getInitializerSymbol())<br>+ InternedResult[InitSym] = JITEvaluatedSymbol();<br>+<br> if (auto Err = MR.notifyResolved(InternedResult)) {<br> Layer.getExecutionSession().reportError(std::move(Err));<br> MR.failMaterialization();<br>@@ -184,8 +188,12 @@ class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {<br> }<br><br> private:<br>- using JITLinkSymbolSet = DenseSet<const Symbol *>;<br>- using LocalToNamedDependenciesMap = DenseMap<const Symbol *, JITLinkSymbolSet>;<br>+ struct LocalSymbolNamedDependencies {<br>+ SymbolNameSet Internal, External;<br>+ };<br>+<br>+ using LocalSymbolNamedDependenciesMap =<br>+ DenseMap<const Symbol *, LocalSymbolNamedDependencies>;<br><br> Error externalizeWeakAndCommonSymbols(LinkGraph &G) {<br> auto &ES = Layer.getExecutionSession();<br>@@ -216,6 +224,7 @@ class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {<br> auto &ES = MR.getTargetJITDylib().getExecutionSession();<br> auto LocalDeps = computeLocalDeps(G);<br><br>+ // Compute dependencies for symbols defined in the JITLink graph.<br> for (auto *Sym : G.defined_symbols()) {<br><br> // Skip local symbols: we do not track dependencies for these.<br>@@ -239,15 +248,12 @@ class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {<br> assert(TargetSym.isDefined() &&<br> "local symbols must be defined");<br> auto I = LocalDeps.find(&TargetSym);<br>- if (I != LocalDeps.end())<br>- for (auto &S : I->second) {<br>- assert(S->hasName() &&<br>- "LocalDeps should only contain named values");<br>- if (S->isExternal())<br>- ExternalSymDeps.insert(ES.intern(S->getName()));<br>- else if (S != Sym)<br>- InternalSymDeps.insert(ES.intern(S->getName()));<br>- }<br>+ if (I != LocalDeps.end()) {<br>+ for (auto &S : I->second.External)<br>+ ExternalSymDeps.insert(S);<br>+ for (auto &S : I->second.Internal)<br>+ InternalSymDeps.insert(S);<br>+ }<br> }<br> }<br><br>@@ -261,11 +267,33 @@ class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {<br> InternalNamedSymbolDeps[SymName] = std::move(InternalSymDeps);<br> }<br><br>+ for (auto &P : Layer.Plugins) {<br>+ auto SyntheticLocalDeps = P->getSyntheticSymbolLocalDependencies(MR);<br>+ if (SyntheticLocalDeps.empty())<br>+ continue;<br>+<br>+ for (auto &KV : SyntheticLocalDeps) {<br>+ auto &Name = KV.first;<br>+ auto &LocalDepsForName = KV.second;<br>+ for (auto *Local : LocalDepsForName) {<br>+ assert(Local->getScope() == Scope::Local &&<br>+ "Dependence on non-local symbol");<br>+ auto LocalNamedDepsItr = LocalDeps.find(Local);<br>+ if (LocalNamedDepsItr == LocalDeps.end())<br>+ continue;<br>+ for (auto &S : LocalNamedDepsItr->second.Internal)<br>+ InternalNamedSymbolDeps[Name].insert(S);<br>+ for (auto &S : LocalNamedDepsItr->second.External)<br>+ ExternalNamedSymbolDeps[Name].insert(S);<br>+ }<br>+ }<br>+ }<br>+<br> return Error::success();<br> }<br><br>- LocalToNamedDependenciesMap computeLocalDeps(LinkGraph &G) {<br>- LocalToNamedDependenciesMap DepMap;<br>+ LocalSymbolNamedDependenciesMap computeLocalDeps(LinkGraph &G) {<br>+ DenseMap<jitlink::Symbol *, DenseSet<jitlink::Symbol *>> DepMap;<br><br> // For all local symbols:<br> // (1) Add their named dependencies.<br>@@ -319,7 +347,26 @@ class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {<br> }<br> } while (Changed);<br><br>- return DepMap;<br>+ // Intern the results to produce a mapping of jitlink::Symbol* to internal<br>+ // and external symbol names.<br>+ auto &ES = Layer.getExecutionSession();<br>+ LocalSymbolNamedDependenciesMap Result;<br>+ for (auto &KV : DepMap) {<br>+ auto *Local = KV.first;<br>+ assert(Local->getScope() == Scope::Local &&<br>+ "DepMap keys should all be local symbols");<br>+ auto &LocalNamedDeps = Result[Local];<br>+ for (auto *Named : KV.second) {<br>+ assert(Named->getScope() != Scope::Local &&<br>+ "DepMap values should all be non-local symbol sets");<br>+ if (Named->isExternal())<br>+ LocalNamedDeps.External.insert(ES.intern(Named->getName()));<br>+ else<br>+ LocalNamedDeps.Internal.insert(ES.intern(Named->getName()));<br>+ }<br>+ }<br>+<br>+ return Result;<br> }<br><br> void registerDependencies(const SymbolDependenceMap &QueryDeps) {<br><br>diff --git a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp<br>index ff8289a264c8..0eaf13c6e3c8 100644<br>--- a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp<br>+++ b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp<br>@@ -88,7 +88,8 @@ RTDyldObjectLinkingLayer::~RTDyldObjectLinkingLayer() {<br> void RTDyldObjectLinkingLayer::emit(MaterializationResponsibility R,<br> std::unique_ptr<MemoryBuffer> O) {<br> assert(O && "Object must not be null");<br>-<br>+ dbgs() << "Emitting via RTDyldObjectLinkingLayer:\n"<br>+ << R.getSymbols() << "\n";<br> // This method launches an asynchronous link step that will fulfill our<br> // materialization responsibility. We need to switch R to be heap<br> // allocated before that happens so it can live as long as the asynchronous<br>@@ -229,6 +230,9 @@ Error RTDyldObjectLinkingLayer::onObjLoad(<br> Symbols.erase(KV.first);<br> }<br><br>+ if (const auto &InitSym = R.getInitializerSymbol())<br>+ Symbols[InitSym] = JITEvaluatedSymbol();<br>+<br> if (auto Err = R.notifyResolved(Symbols)) {<br> R.failMaterialization();<br> return Err;<br><br>diff --git a/llvm/test/ExecutionEngine/OrcLazy/objc-minimal.ll b/llvm/test/ExecutionEngine/OrcLazy/objc-minimal.ll<br>new file mode 100644<br>index 000000000000..8a940573dcb9<br>--- /dev/null<br>+++ b/llvm/test/ExecutionEngine/OrcLazy/objc-minimal.ll<br>@@ -0,0 +1,73 @@<br>+; REQUIRES: system-darwin<br>+; RUN: lli -jit-kind=orc-lazy %s<br>+;<br>+; Sanity check MachO Platform support: Call a no-op method (returning int 0) on<br>+; an ObjC object. This test checks that we correctly auto-identify this as a<br>+; MachO target, configure MachOPlatform support, and correctly register the<br>+; class metadata and method selector with the Objective-C runtime.<br>+<br>+source_filename = "<a href="http://objc-minimal.mm" target="_blank">objc-minimal.mm</a>"<br>+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"<br>+target triple = "x86_64-apple-macosx10.14.0"<br>+<br>+%0 = type opaque<br>+%struct._objc_cache = type opaque<br>+%struct._class_t = type { %struct._class_t*, %struct._class_t*, %struct._objc_cache*, i8* (i8*, i8*)**, %struct._class_ro_t* }<br>+%struct._class_ro_t = type { i32, i32, i32, i8*, i8*, %struct.__method_list_t*, %struct._objc_protocol_list*, %struct._ivar_list_t*, i8*, %struct._prop_list_t* }<br>+%struct.__method_list_t = type { i32, i32, [0 x %struct._objc_method] }<br>+%struct._objc_method = type { i8*, i8*, i8* }<br>+%struct._objc_protocol_list = type { i64, [0 x %struct._protocol_t*] }<br>+%struct._protocol_t = type { i8*, i8*, %struct._objc_protocol_list*, %struct.__method_list_t*, %struct.__method_list_t*, %struct.__method_list_t*, %struct.__method_list_t*, %struct._prop_list_t*, i32, i32, i8**, i8*, %struct._prop_list_t* }<br>+%struct._ivar_list_t = type { i32, i32, [0 x %struct._ivar_t] }<br>+%struct._ivar_t = type { i64*, i8*, i8*, i32, i32 }<br>+%struct._prop_list_t = type { i32, i32, [0 x %struct._prop_t] }<br>+%struct._prop_t = type { i8*, i8* }<br>+<br>+@_objc_empty_cache = external global %struct._objc_cache<br>+@"OBJC_METACLASS_$_NSObject" = external global %struct._class_t<br>+@OBJC_CLASS_NAME_ = private unnamed_addr constant [4 x i8] c"Foo\00", section "__TEXT,__objc_classname,cstring_literals", align 1<br>+@"\01l_OBJC_METACLASS_RO_$_Foo" = private global %struct._class_ro_t { i32 1, i32 40, i32 40, i8* null, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), %struct.__method_list_t* null, %struct._objc_protocol_list* null, %struct._ivar_list_t* null, i8* null, %struct._prop_list_t* null }, section "__DATA, __objc_const", align 8<br>+@"OBJC_METACLASS_$_Foo" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_NSObject", %struct._class_t* @"OBJC_METACLASS_$_NSObject", %struct._objc_cache* @_objc_empty_cache, i8* (i8*, i8*)** null, %struct._class_ro_t* @"\01l_OBJC_METACLASS_RO_$_Foo" }, section "__DATA, __objc_data", align 8<br>+@"OBJC_CLASS_$_NSObject" = external global %struct._class_t<br>+@OBJC_METH_VAR_NAME_ = private unnamed_addr constant [4 x i8] c"foo\00", section "__TEXT,__objc_methname,cstring_literals", align 1<br>+@OBJC_METH_VAR_TYPE_ = private unnamed_addr constant [8 x i8] c"i16@0:8\00", section "__TEXT,__objc_methtype,cstring_literals", align 1<br>+@"\01l_OBJC_$_INSTANCE_METHODS_Foo" = private global { i32, i32, [1 x %struct._objc_method] } { i32 24, i32 1, [1 x %struct._objc_method] [%struct._objc_method { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @OBJC_METH_VAR_NAME_, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @OBJC_METH_VAR_TYPE_, i32 0, i32 0), i8* bitcast (i32 (%0*, i8*)* @"\01-[Foo foo]" to i8*) }] }, section "__DATA, __objc_const", align 8<br>+@"\01l_OBJC_CLASS_RO_$_Foo" = private global %struct._class_ro_t { i32 0, i32 8, i32 8, i8* null, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), %struct.__method_list_t* bitcast ({ i32, i32, [1 x %struct._objc_method] }* @"\01l_OBJC_$_INSTANCE_METHODS_Foo" to %struct.__method_list_t*), %struct._objc_protocol_list* null, %struct._ivar_list_t* null, i8* null, %struct._prop_list_t* null }, section "__DATA, __objc_const", align 8<br>+@"OBJC_CLASS_$_Foo" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_Foo", %struct._class_t* @"OBJC_CLASS_$_NSObject", %struct._objc_cache* @_objc_empty_cache, i8* (i8*, i8*)** null, %struct._class_ro_t* @"\01l_OBJC_CLASS_RO_$_Foo" }, section "__DATA, __objc_data", align 8<br>+@"OBJC_CLASSLIST_REFERENCES_$_" = private global %struct._class_t* @"OBJC_CLASS_$_Foo", section "__DATA,__objc_classrefs,regular,no_dead_strip", align 8<br>+@OBJC_METH_VAR_NAME_.1 = private unnamed_addr constant [5 x i8] c"init\00", section "__TEXT,__objc_methname,cstring_literals", align 1<br>+@OBJC_SELECTOR_REFERENCES_ = private externally_initialized global i8* getelementptr inbounds ([5 x i8], [5 x i8]* @OBJC_METH_VAR_NAME_.1, i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8<br>+@OBJC_SELECTOR_REFERENCES_.2 = private externally_initialized global i8* getelementptr inbounds ([4 x i8], [4 x i8]* @OBJC_METH_VAR_NAME_, i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8<br>+@"OBJC_LABEL_CLASS_$" = private global [1 x i8*] [i8* bitcast (%struct._class_t* @"OBJC_CLASS_$_Foo" to i8*)], section "__DATA,__objc_classlist,regular,no_dead_strip", align 8<br>+@llvm.compiler.used = appending global [9 x i8*] [i8* bitcast ({ i32, i32, [1 x %struct._objc_method] }* @"\01l_OBJC_$_INSTANCE_METHODS_Foo" to i8*), i8* bitcast (%struct._class_t** @"OBJC_CLASSLIST_REFERENCES_$_" to i8*), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), i8* bitcast ([1 x i8*]* @"OBJC_LABEL_CLASS_$" to i8*), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @OBJC_METH_VAR_NAME_, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @OBJC_METH_VAR_NAME_.1, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @OBJC_METH_VAR_TYPE_, i32 0, i32 0), i8* bitcast (i8** @OBJC_SELECTOR_REFERENCES_ to i8*), i8* bitcast (i8** @OBJC_SELECTOR_REFERENCES_.2 to i8*)], section "llvm.metadata"<br>+<br>+; Function Attrs: noinline norecurse nounwind readnone ssp uwtable<br>+define internal i32 @"\01-[Foo foo]"(%0* nocapture readnone, i8* nocapture readnone) {<br>+ ret i32 0<br>+}<br>+<br>+; Function Attrs: noinline norecurse ssp uwtable<br>+define i32 @main(i32, i8** nocapture readnone) local_unnamed_addr {<br>+ %3 = load i8*, i8** bitcast (%struct._class_t** @"OBJC_CLASSLIST_REFERENCES_$_" to i8**), align 8<br>+ %4 = tail call i8* @objc_alloc(i8* %3)<br>+ %5 = load i8*, i8** @OBJC_SELECTOR_REFERENCES_, align 8<br>+ %6 = tail call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* %4, i8* %5)<br>+ %7 = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.2, align 8<br>+ %8 = tail call i32 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i32 (i8*, i8*)*)(i8* %6, i8* %7)<br>+ ret i32 %8<br>+}<br>+<br>+declare i8* @objc_alloc(i8*) local_unnamed_addr<br>+<br>+; Function Attrs: nonlazybind<br>+declare i8* @objc_msgSend(i8*, i8*, ...) local_unnamed_addr<br>+<br>+!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6 }<br>+<br>+!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 10, i32 15]}<br>+!1 = !{i32 1, !"Objective-C Version", i32 2}<br>+!2 = !{i32 1, !"Objective-C Image Info Version", i32 0}<br>+!3 = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"}<br>+!4 = !{i32 4, !"Objective-C Garbage Collection", i32 0}<br>+!5 = !{i32 1, !"Objective-C Class Properties", i32 64}<br>+!6 = !{i32 1, !"wchar_size", i32 4}<br><br>diff --git a/llvm/tools/lli/lli.cpp b/llvm/tools/lli/lli.cpp<br>index e7251b12f7fc..55b9557bddfe 100644<br>--- a/llvm/tools/lli/lli.cpp<br>+++ b/llvm/tools/lli/lli.cpp<br>@@ -24,9 +24,11 @@<br> #include "llvm/ExecutionEngine/JITEventListener.h"<br> #include "llvm/ExecutionEngine/MCJIT.h"<br> #include "llvm/ExecutionEngine/ObjectCache.h"<br>+#include "llvm/ExecutionEngine/Orc/DebugUtils.h"<br> #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"<br> #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"<br> #include "llvm/ExecutionEngine/Orc/LLJIT.h"<br>+#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"<br> #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h"<br> #include "llvm/ExecutionEngine/OrcMCJITReplacement.h"<br> #include "llvm/ExecutionEngine/SectionMemoryManager.h"<br>@@ -206,6 +208,19 @@ namespace {<br> cl::desc("Do not resolve lli process symbols in JIT'd code"),<br> cl::init(false));<br><br>+ enum class LLJITPlatform { DetectHost, GenericIR, MachO };<br>+<br>+ cl::opt<LLJITPlatform><br>+ Platform("lljit-platform", cl::desc("Platform to use with LLJIT"),<br>+ cl::init(LLJITPlatform::DetectHost),<br>+ cl::values(clEnumValN(LLJITPlatform::DetectHost, "DetectHost",<br>+ "Select based on JIT target triple"),<br>+ clEnumValN(LLJITPlatform::GenericIR, "GenericIR",<br>+ "Use LLJITGenericIRPlatform"),<br>+ clEnumValN(LLJITPlatform::MachO, "MachO",<br>+ "Use LLJITMachOPlatform")),<br>+ cl::Hidden);<br>+<br> enum class DumpKind {<br> NoDump,<br> DumpFuncsToStdOut,<br>@@ -772,16 +787,20 @@ int runOrcLazyJIT(const char *ProgName) {<br> if (!MainModule)<br> reportError(Err, ProgName);<br><br>- const auto &TT = MainModule->getTargetTriple();<br>+ Triple TT(MainModule->getTargetTriple());<br> orc::LLLazyJITBuilder Builder;<br><br> Builder.setJITTargetMachineBuilder(<br>- TT.empty() ? ExitOnErr(orc::JITTargetMachineBuilder::detectHost())<br>- : orc::JITTargetMachineBuilder(Triple(TT)));<br>+ MainModule->getTargetTriple().empty()<br>+ ? ExitOnErr(orc::JITTargetMachineBuilder::detectHost())<br>+ : orc::JITTargetMachineBuilder(TT));<br><br> if (!MArch.empty())<br> Builder.getJITTargetMachineBuilder()->getTargetTriple().setArchName(MArch);<br><br>+ if (!MainModule->getDataLayout().isDefault())<br>+ Builder.setDataLayout(MainModule->getDataLayout());<br>+<br> Builder.getJITTargetMachineBuilder()<br> ->setCPU(getCPUStr())<br> .addFeatures(getFeatureList())<br>@@ -796,6 +815,29 @@ int runOrcLazyJIT(const char *ProgName) {<br> pointerToJITTargetAddress(exitOnLazyCallThroughFailure));<br> Builder.setNumCompileThreads(LazyJITCompileThreads);<br><br>+ // Set up LLJIT platform.<br>+ {<br>+ LLJITPlatform P = Platform;<br>+ if (P == LLJITPlatform::DetectHost) {<br>+ if (TT.isOSBinFormatMachO())<br>+ P = LLJITPlatform::MachO;<br>+ else<br>+ P = LLJITPlatform::GenericIR;<br>+ }<br>+<br>+ switch (P) {<br>+ case LLJITPlatform::GenericIR:<br>+ // Nothing to do: LLJITBuilder will use this by default.<br>+ break;<br>+ case LLJITPlatform::MachO:<br>+ Builder.setPlatformSetUp(orc::setUpMachOPlatform);<br>+ ExitOnErr(orc::enableObjCRegistration("libobjc.dylib"));<br>+ break;<br>+ default:<br>+ llvm_unreachable("Unrecognized platform value");<br>+ }<br>+ }<br>+<br> auto J = ExitOnErr(Builder.create());<br><br> if (PerModuleLazy)<br>@@ -828,9 +870,6 @@ int runOrcLazyJIT(const char *ProgName) {<br> return Name != MainName;<br> })));<br><br>- orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;<br>- ExitOnErr(CXXRuntimeOverrides.enable(J->getMainJITDylib(), Mangle));<br>-<br> // Add the main module.<br> ExitOnErr(<br> J->addLazyIRModule(orc::ThreadSafeModule(std::move(MainModule), TSCtx)));<br>@@ -845,8 +884,11 @@ int runOrcLazyJIT(const char *ProgName) {<br> for (auto JDItr = JITDylibs.begin(), JDEnd = JITDylibs.end();<br> JDItr != JDEnd; ++JDItr) {<br> orc::JITDylib *JD = J->getJITDylibByName(*JDItr);<br>- if (!JD)<br>- JD = &J->createJITDylib(*JDItr);<br>+ if (!JD) {<br>+ JD = &ExitOnErr(J->createJITDylib(*JDItr));<br>+ J->getMainJITDylib().addToSearchOrder(*JD);<br>+ JD->addToSearchOrder(J->getMainJITDylib());<br>+ }<br> IdxToDylib[JITDylibs.getPosition(JDItr - JITDylibs.begin())] = JD;<br> }<br><br>@@ -882,7 +924,7 @@ int runOrcLazyJIT(const char *ProgName) {<br> }<br><br> // Run any static constructors.<br>- ExitOnErr(J->runConstructors());<br>+ ExitOnErr(J->initialize(J->getMainJITDylib()));<br><br> // Run any -thread-entry points.<br> std::vector<std::thread> AltEntryThreads;<br>@@ -907,8 +949,7 @@ int runOrcLazyJIT(const char *ProgName) {<br> AltEntryThread.join();<br><br> // Run destructors.<br>- ExitOnErr(J->runDestructors());<br>- CXXRuntimeOverrides.runDestructors();<br>+ ExitOnErr(J->deinitialize(J->getMainJITDylib()));<br><br> return Result;<br> }<br><br>diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp<br>index 26bcf46d60a6..7765d53f402d 100644<br>--- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp<br>+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp<br>@@ -396,9 +396,18 @@ static std::unique_ptr<jitlink::JITLinkMemoryManager> createMemoryManager() {<br> return std::make_unique<jitlink::InProcessMemoryManager>();<br> }<br><br>-Session::Session(Triple TT)<br>- : MainJD(ES.createJITDylib("<main>")), ObjLayer(ES, createMemoryManager()),<br>- TT(std::move(TT)) {<br>+Expected<std::unique_ptr<Session>> Session::Create(Triple TT) {<br>+ Error Err = Error::success();<br>+ std::unique_ptr<Session> S(new Session(std::move(TT), Err));<br>+ if (Err)<br>+ return std::move(Err);<br>+ return std::move(S);<br>+}<br>+<br>+// FIXME: Move to createJITDylib if/when we start using Platform support in<br>+// llvm-jitlink.<br>+Session::Session(Triple TT, Error &Err)<br>+ : ObjLayer(ES, createMemoryManager()), TT(std::move(TT)) {<br><br> /// Local ObjectLinkingLayer::Plugin class to forward modifyPassConfig to the<br> /// Session.<br>@@ -414,6 +423,15 @@ Session::Session(Triple TT)<br> Session &S;<br> };<br><br>+ ErrorAsOutParameter _(&Err);<br>+<br>+ if (auto MainJDOrErr = ES.createJITDylib("main"))<br>+ MainJD = &*MainJDOrErr;<br>+ else {<br>+ Err = MainJDOrErr.takeError();<br>+ return;<br>+ }<br>+<br> if (!NoExec && !TT.isOSWindows())<br> ObjLayer.addPlugin(std::make_unique<EHFrameRegistrationPlugin>(<br> InProcessEHFrameRegistrar::getInstance()));<br>@@ -561,7 +579,7 @@ Error loadProcessSymbols(Session &S) {<br> auto FilterMainEntryPoint = [InternedEntryPointName](SymbolStringPtr Name) {<br> return Name != InternedEntryPointName;<br> };<br>- S.MainJD.addGenerator(<br>+ S.MainJD->addGenerator(<br> ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(<br> GlobalPrefix, FilterMainEntryPoint)));<br><br>@@ -590,20 +608,22 @@ Error loadObjects(Session &S) {<br> LLVM_DEBUG(dbgs() << "Creating JITDylibs...\n");<br> {<br> // Create a "main" JITLinkDylib.<br>- IdxToJLD[0] = &S.MainJD;<br>- S.JDSearchOrder.push_back(&S.MainJD);<br>- LLVM_DEBUG(dbgs() << " 0: " << S.MainJD.getName() << "\n");<br>+ IdxToJLD[0] = S.MainJD;<br>+ S.JDSearchOrder.push_back(S.MainJD);<br>+ LLVM_DEBUG(dbgs() << " 0: " << S.MainJD->getName() << "\n");<br><br> // Add any extra JITLinkDylibs from the command line.<br> std::string JDNamePrefix("lib");<br> for (auto JLDItr = JITLinkDylibs.begin(), JLDEnd = JITLinkDylibs.end();<br> JLDItr != JLDEnd; ++JLDItr) {<br>- auto &JD = S.ES.createJITDylib(JDNamePrefix + *JLDItr);<br>+ auto JD = S.ES.createJITDylib(JDNamePrefix + *JLDItr);<br>+ if (!JD)<br>+ return JD.takeError();<br> unsigned JDIdx =<br> JITLinkDylibs.getPosition(JLDItr - JITLinkDylibs.begin());<br>- IdxToJLD[JDIdx] = &JD;<br>- S.JDSearchOrder.push_back(&JD);<br>- LLVM_DEBUG(dbgs() << " " << JDIdx << ": " << JD.getName() << "\n");<br>+ IdxToJLD[JDIdx] = &*JD;<br>+ S.JDSearchOrder.push_back(&*JD);<br>+ LLVM_DEBUG(dbgs() << " " << JDIdx << ": " << JD->getName() << "\n");<br> }<br><br> // Set every dylib to link against every other, in command line order.<br>@@ -790,32 +810,32 @@ int main(int argc, char *argv[]) {<br> std::unique_ptr<JITLinkTimers> Timers =<br> ShowTimes ? std::make_unique<JITLinkTimers>() : nullptr;<br><br>- Session S(getFirstFileTriple());<br>+ auto S = ExitOnErr(Session::Create(getFirstFileTriple()));<br><br>- ExitOnErr(sanitizeArguments(S));<br>+ ExitOnErr(sanitizeArguments(*S));<br><br> if (!NoProcessSymbols)<br>- ExitOnErr(loadProcessSymbols(S));<br>+ ExitOnErr(loadProcessSymbols(*S));<br> ExitOnErr(loadDylibs());<br><br><br> {<br> TimeRegion TR(Timers ? &Timers->LoadObjectsTimer : nullptr);<br>- ExitOnErr(loadObjects(S));<br>+ ExitOnErr(loadObjects(*S));<br> }<br><br> JITEvaluatedSymbol EntryPoint = 0;<br> {<br> TimeRegion TR(Timers ? &Timers->LinkTimer : nullptr);<br>- EntryPoint = ExitOnErr(getMainEntryPoint(S));<br>+ EntryPoint = ExitOnErr(getMainEntryPoint(*S));<br> }<br><br> if (ShowAddrs)<br>- S.dumpSessionInfo(outs());<br>+ S->dumpSessionInfo(outs());<br><br>- ExitOnErr(runChecks(S));<br>+ ExitOnErr(runChecks(*S));<br><br>- dumpSessionStats(S);<br>+ dumpSessionStats(*S);<br><br> if (NoExec)<br> return 0;<br><br>diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.h b/llvm/tools/llvm-jitlink/llvm-jitlink.h<br>index 0f92d7605012..c888baec9adf 100644<br>--- a/llvm/tools/llvm-jitlink/llvm-jitlink.h<br>+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.h<br>@@ -26,12 +26,13 @@ namespace llvm {<br><br> struct Session {<br> orc::ExecutionSession ES;<br>- orc::JITDylib &MainJD;<br>+ orc::JITDylib *MainJD;<br> orc::ObjectLinkingLayer ObjLayer;<br> std::vector<orc::JITDylib *> JDSearchOrder;<br> Triple TT;<br><br> Session(Triple TT);<br>+ static Expected<std::unique_ptr<Session>> Create(Triple TT);<br> void dumpSessionInfo(raw_ostream &OS);<br> void modifyPassConfig(const Triple &FTT,<br> jitlink::PassConfiguration &PassConfig);<br>@@ -63,6 +64,9 @@ struct Session {<br> FileInfoMap FileInfos;<br> uint64_t SizeBeforePruning = 0;<br> uint64_t SizeAfterFixups = 0;<br>+<br>+private:<br>+ Session(Triple TT, Error &Err);<br> };<br><br> Error registerMachOStubsAndGOT(Session &S, jitlink::LinkGraph &G);<br><br>diff --git a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp<br>index 68a6d2ed2ca2..171ff37f0069 100644<br>--- a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp<br>+++ b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp<br>@@ -113,6 +113,7 @@ TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) {<br> cantFail(R.notifyResolved({{Bar, BarSym}}));<br> cantFail(R.notifyEmitted());<br> },<br>+ nullptr,<br> [&](const JITDylib &JD, const SymbolStringPtr &Name) {<br> EXPECT_EQ(Name, Bar) << "Expected \"Bar\" to be discarded";<br> if (Name == Bar)<br>@@ -126,6 +127,7 @@ TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) {<br> cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(<br> SymbolFlagsMap({{Baz, BazSym.getFlags()}}),<br> [&](MaterializationResponsibility R) { BazR.emplace(std::move(R)); },<br>+ nullptr,<br> [](const JITDylib &JD, const SymbolStringPtr &Name) {<br> ADD_FAILURE() << "\"Baz\" discarded unexpectedly";<br> })));<br>@@ -176,7 +178,7 @@ TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) {<br> TEST_F(CoreAPIsStandardTest, ChainedJITDylibLookup) {<br> cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));<br><br>- auto &JD2 = ES.createJITDylib("JD2");<br>+ auto &JD2 = ES.createBareJITDylib("JD2");<br><br> bool OnCompletionRun = false;<br><br>@@ -198,7 +200,7 @@ TEST_F(CoreAPIsStandardTest, LookupWithHiddenSymbols) {<br><br> cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarHiddenSym}})));<br><br>- auto &JD2 = ES.createJITDylib("JD2");<br>+ auto &JD2 = ES.createBareJITDylib("JD2");<br> cantFail(JD2.define(absoluteSymbols({{Bar, QuxSym}})));<br><br> /// Try a blocking lookup.<br>@@ -307,7 +309,7 @@ TEST_F(CoreAPIsStandardTest, TestBasicReExports) {<br> // JITDylib works.<br> cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));<br><br>- auto &JD2 = ES.createJITDylib("JD2");<br>+ auto &JD2 = ES.createBareJITDylib("JD2");<br><br> cantFail(JD2.define(reexports(JD, {{Bar, {Foo, BarSym.getFlags()}}})));<br><br>@@ -332,7 +334,7 @@ TEST_F(CoreAPIsStandardTest, TestThatReExportsDontUnnecessarilyMaterialize) {<br><br> cantFail(JD.define(BarMU));<br><br>- auto &JD2 = ES.createJITDylib("JD2");<br>+ auto &JD2 = ES.createBareJITDylib("JD2");<br><br> cantFail(JD2.define(reexports(<br> JD, {{Baz, {Foo, BazSym.getFlags()}}, {Qux, {Bar, QuxSym.getFlags()}}})));<br>@@ -347,7 +349,7 @@ TEST_F(CoreAPIsStandardTest, TestThatReExportsDontUnnecessarilyMaterialize) {<br> TEST_F(CoreAPIsStandardTest, TestReexportsGenerator) {<br> // Test that a re-exports generator can dynamically generate reexports.<br><br>- auto &JD2 = ES.createJITDylib("JD2");<br>+ auto &JD2 = ES.createBareJITDylib("JD2");<br> cantFail(JD2.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}})));<br><br> auto Filter = [this](SymbolStringPtr Name) { return Name != Bar; };<br>@@ -838,6 +840,7 @@ TEST_F(CoreAPIsStandardTest, DropMaterializerWhenEmpty) {<br> [](MaterializationResponsibility R) {<br> llvm_unreachable("Unexpected call to materialize");<br> },<br>+ nullptr,<br> [&](const JITDylib &JD, SymbolStringPtr Name) {<br> EXPECT_TRUE(Name == Foo || Name == Bar)<br> << "Discard of unexpected symbol?";<br>@@ -872,6 +875,7 @@ TEST_F(CoreAPIsStandardTest, AddAndMaterializeLazySymbol) {<br> cantFail(R.notifyEmitted());<br> FooMaterialized = true;<br> },<br>+ nullptr,<br> [&](const JITDylib &JD, SymbolStringPtr Name) {<br> EXPECT_EQ(Name, Bar) << "Expected Name to be Bar";<br> BarDiscarded = true;<br>@@ -920,6 +924,7 @@ TEST_F(CoreAPIsStandardTest, TestBasicWeakSymbolMaterialization) {<br> ADD_FAILURE() << "Attempt to materialize Bar from the wrong unit";<br> R.failMaterialization();<br> },<br>+ nullptr,<br> [&](const JITDylib &JD, SymbolStringPtr Name) {<br> EXPECT_EQ(Name, Bar) << "Expected \"Bar\" to be discarded";<br> DuplicateBarDiscarded = true;<br><br>diff --git a/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h<br>index d82012b5a853..b25851d8f796 100644<br>--- a/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h<br>+++ b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h<br>@@ -47,7 +47,7 @@ class CoreAPIsBasedStandardTest : public testing::Test {<br> protected:<br> std::shared_ptr<SymbolStringPool> SSP = std::make_shared<SymbolStringPool>();<br> ExecutionSession ES{SSP};<br>- JITDylib &JD = ES.createJITDylib("JD");<br>+ JITDylib &JD = ES.createBareJITDylib("JD");<br> SymbolStringPtr Foo = ES.intern("foo");<br> SymbolStringPtr Bar = ES.intern("bar");<br> SymbolStringPtr Baz = ES.intern("baz");<br>@@ -93,9 +93,11 @@ class SimpleMaterializationUnit : public orc::MaterializationUnit {<br><br> SimpleMaterializationUnit(<br> orc::SymbolFlagsMap SymbolFlags, MaterializeFunction Materialize,<br>+ orc::SymbolStringPtr InitSym = nullptr,<br> DiscardFunction Discard = DiscardFunction(),<br> DestructorFunction Destructor = DestructorFunction())<br>- : MaterializationUnit(std::move(SymbolFlags), orc::VModuleKey()),<br>+ : MaterializationUnit(std::move(SymbolFlags), std::move(InitSym),<br>+ orc::VModuleKey()),<br> Materialize(std::move(Materialize)), Discard(std::move(Discard)),<br> Destructor(std::move(Destructor)) {}<br><br><br>diff --git a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp<br>index 0c66841e9af0..9a50571b1969 100644<br>--- a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp<br>+++ b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp<br>@@ -50,7 +50,7 @@ static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,<br> bool DebugSectionSeen = false;<br><br> ExecutionSession ES;<br>- auto &JD = ES.createJITDylib("main");<br>+ auto &JD = ES.createBareJITDylib("main");<br> auto Foo = ES.intern("foo");<br><br> RTDyldObjectLinkingLayer ObjLayer(ES, [&DebugSectionSeen]() {<br>@@ -151,7 +151,7 @@ TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) {<br><br> // Create a simple stack and set the override flags option.<br> ExecutionSession ES;<br>- auto &JD = ES.createJITDylib("main");<br>+ auto &JD = ES.createBareJITDylib("main");<br> auto Foo = ES.intern("foo");<br> RTDyldObjectLinkingLayer ObjLayer(<br> ES, []() { return std::make_unique<SectionMemoryManager>(); });<br>@@ -218,7 +218,7 @@ TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) {<br><br> // Create a simple stack and set the override flags option.<br> ExecutionSession ES;<br>- auto &JD = ES.createJITDylib("main");<br>+ auto &JD = ES.createBareJITDylib("main");<br> auto Foo = ES.intern("foo");<br> RTDyldObjectLinkingLayer ObjLayer(<br> ES, []() { return std::make_unique<SectionMemoryManager>(); });<br><br><br><br>_______________________________________________<br>llvm-commits mailing list<br><a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br><a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br></div></div></blockquote></div><br></div></div></blockquote></div></div></blockquote></div></div></div></blockquote></div><br></div></div></blockquote></div>