Index: compiler-rt/lib/orc/CMakeLists.txt =================================================================== --- compiler-rt/lib/orc/CMakeLists.txt +++ compiler-rt/lib/orc/CMakeLists.txt @@ -13,6 +13,7 @@ set(ALL_ORC_SOURCES ${ORC_COMMON_SOURCES} coff_platform.cpp + coff_platform.per_jd.cpp elfnix_platform.cpp macho_ehframe_registration.cpp macho_platform.cpp @@ -128,7 +129,12 @@ set(ORC_SOURCES ${ORC_COMMON_SOURCES} coff_platform.cpp + coff_platform.per_jd.cpp ) + + if (MSVC) + set(ORC_CFLAGS "${ORC_CFLAGS} /MD") + endif() else() set(ORC_BUILD_TYPE STATIC) Index: compiler-rt/lib/orc/coff_platform.cpp =================================================================== --- compiler-rt/lib/orc/coff_platform.cpp +++ compiler-rt/lib/orc/coff_platform.cpp @@ -81,6 +81,7 @@ size_t LinkedAgainstRefCount = 0; size_t DlRefCount = 0; std::vector Deps; + std::vector AtExits; XtorSection CInitSection; // XIA~XIZ XtorSection CXXInitSection; // XCA~XCZ XtorSection CPreTermSection; // XPA~XPZ @@ -94,6 +95,7 @@ public: static void initialize(); static COFFPlatformRuntimeState &get(); + static bool isInitialized() { return CPS; } static void destroy(); COFFPlatformRuntimeState() = default; @@ -113,6 +115,8 @@ Error registerJITDylib(std::string Name, void *Header); Error deregisterJITDylib(void *Header); + Error registerAtExit(ExecutorAddr HeaderAddr, void (*AtExit)(void)); + Error registerObjectSections( ExecutorAddr HeaderAddr, std::vector> Secs, @@ -410,7 +414,10 @@ JDS.Name.c_str()); }); - // FIXME: call atexits. + // Run atexits + for (auto AtExit : JDS.AtExits) + AtExit(); + JDS.AtExits.clear(); // Run static terminators. JDS.CPreTermSection.RunAllNewAndFlush(); @@ -454,8 +461,7 @@ auto I = JDStates.find(HeaderAddr.toPtr()); if (I == JDStates.end()) { std::ostringstream ErrStream; - ErrStream << "Attempted to register unrecognized header " - << HeaderAddr.getValue(); + ErrStream << "Unrecognized header " << HeaderAddr.getValue(); return make_error(ErrStream.str()); } auto &JDState = I->second; @@ -499,7 +505,7 @@ auto I = JDStates.find(HeaderAddr.toPtr()); if (I == JDStates.end()) { std::ostringstream ErrStream; - ErrStream << "Attempted to register unrecognized header " + ErrStream << "Attempted to deregister unrecognized header " << HeaderAddr.getValue(); return make_error(ErrStream.str()); } @@ -549,6 +555,19 @@ return Error::success(); } +Error COFFPlatformRuntimeState::registerAtExit(ExecutorAddr HeaderAddr, + void (*AtExit)(void)) { + std::lock_guard Lock(JDStatesMutex); + auto I = JDStates.find(HeaderAddr.toPtr()); + if (I == JDStates.end()) { + std::ostringstream ErrStream; + ErrStream << "Unrecognized header " << HeaderAddr.getValue(); + return make_error(ErrStream.str()); + } + I->second.AtExits.push_back(AtExit); + return Error::success(); +} + void COFFPlatformRuntimeState::initialize() { assert(!CPS && "COFFPlatformRuntimeState should be null"); CPS = new COFFPlatformRuntimeState(); @@ -691,6 +710,32 @@ _countof(parameters), parameters); } +//------------------------------------------------------------------------------ +// COFF atexits +//------------------------------------------------------------------------------ + +typedef int (*OnExitFunction)(void); +typedef void (*AtExitFunction)(void); + +ORC_RT_INTERFACE OnExitFunction __orc_rt_coff_onexit(void *Header, + OnExitFunction Func) { + if (auto Err = COFFPlatformRuntimeState::get().registerAtExit( + ExecutorAddr::fromPtr(Header), (void (*)(void))Func)) { + consumeError(std::move(Err)); + return nullptr; + } + return Func; +} + +ORC_RT_INTERFACE int __orc_rt_coff_atexit(void *Header, AtExitFunction Func) { + if (auto Err = COFFPlatformRuntimeState::get().registerAtExit( + ExecutorAddr::fromPtr(Header), (void (*)(void))Func)) { + consumeError(std::move(Err)); + return -1; + } + return 0; +} + //------------------------------------------------------------------------------ // COFF Run Program //------------------------------------------------------------------------------ Index: compiler-rt/lib/orc/coff_platform.per_jd.cpp =================================================================== --- /dev/null +++ compiler-rt/lib/orc/coff_platform.per_jd.cpp @@ -0,0 +1,31 @@ +//===- coff_platform.per_jd.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains code that will be loaded per each JITDylib. +// +//===----------------------------------------------------------------------===// +#include "compiler.h" + +ORC_RT_INTERFACE void __orc_rt_coff_per_jd_marker() {} + +typedef int (*OnExitFunction)(void); +typedef void (*AtExitFunction)(void); + +extern "C" void *__ImageBase; +ORC_RT_INTERFACE OnExitFunction __orc_rt_coff_onexit(void *Header, + OnExitFunction Func); +ORC_RT_INTERFACE int __orc_rt_coff_atexit(void *Header, AtExitFunction Func); + +ORC_RT_INTERFACE OnExitFunction +__orc_rt_coff_onexit_per_jd(OnExitFunction Func) { + return __orc_rt_coff_onexit(&__ImageBase, Func); +} + +ORC_RT_INTERFACE int __orc_rt_coff_atexit_per_jd(AtExitFunction Func) { + return __orc_rt_coff_atexit(&__ImageBase, Func); +} \ No newline at end of file Index: compiler-rt/test/orc/TestCases/Windows/x86-64/Inputs/standalone-dylib.c =================================================================== --- compiler-rt/test/orc/TestCases/Windows/x86-64/Inputs/standalone-dylib.c +++ compiler-rt/test/orc/TestCases/Windows/x86-64/Inputs/standalone-dylib.c @@ -1,9 +1,13 @@ #include +#include + +void Dtor() { printf("destructor\n"); } int Ctor() { printf("constructor\n"); + atexit(Dtor); return 0; } #pragma section(".CRT$XIV", long, read) -__declspec(allocate(".CRT$XIV")) int (*i1)(void) = Ctor; +__declspec(allocate(".CRT$XIV")) int (*i1)(void) = Ctor; \ No newline at end of file Index: compiler-rt/test/orc/TestCases/Windows/x86-64/hello-world.c =================================================================== --- compiler-rt/test/orc/TestCases/Windows/x86-64/hello-world.c +++ compiler-rt/test/orc/TestCases/Windows/x86-64/hello-world.c @@ -1,4 +1,4 @@ -// RUN: %clang -c -o %t %s +// RUN: %clang_cl -MD -c -o %t %s // RUN: %llvm_jitlink %t 2>&1 | FileCheck %s // CHECK: Hello, world! Index: compiler-rt/test/orc/TestCases/Windows/x86-64/hello-world.cpp =================================================================== --- compiler-rt/test/orc/TestCases/Windows/x86-64/hello-world.cpp +++ compiler-rt/test/orc/TestCases/Windows/x86-64/hello-world.cpp @@ -1,4 +1,4 @@ -// RUN: %clangxx -c -o %t %s +// RUN: %clang_cl -MD -c -o %t %s // RUN: %llvm_jitlink %t 2>&1 | FileCheck %s // CHECK: Hello, world! Index: compiler-rt/test/orc/TestCases/Windows/x86-64/priority-static-initializer-three.c =================================================================== --- compiler-rt/test/orc/TestCases/Windows/x86-64/priority-static-initializer-three.c +++ compiler-rt/test/orc/TestCases/Windows/x86-64/priority-static-initializer-three.c @@ -1,4 +1,4 @@ -// RUN: %clang -c -o %t %s +// RUN: %clang_cl -MD -c -o %t %s // RUN: %llvm_jitlink %t 2>&1 | FileCheck %s // CHECK: init1 // CHECK-NEXT: init2 Index: compiler-rt/test/orc/TestCases/Windows/x86-64/priority-static-initializer.c =================================================================== --- compiler-rt/test/orc/TestCases/Windows/x86-64/priority-static-initializer.c +++ compiler-rt/test/orc/TestCases/Windows/x86-64/priority-static-initializer.c @@ -1,4 +1,4 @@ -// RUN: %clang -c -o %t %s +// RUN: %clang_cl -MD -c -o %t %s // RUN: %llvm_jitlink %t 2>&1 | FileCheck %s // CHECK: init1 // CHECK-NEXT: init2 Index: compiler-rt/test/orc/TestCases/Windows/x86-64/sehframe-handling.cpp =================================================================== --- compiler-rt/test/orc/TestCases/Windows/x86-64/sehframe-handling.cpp +++ compiler-rt/test/orc/TestCases/Windows/x86-64/sehframe-handling.cpp @@ -1,4 +1,4 @@ -// RUN: %clangxx -c -o %t %s +// RUN: %clang_cl -EHsc -MD -c -o %t %s // RUN: %llvm_jitlink %t extern "C" __declspec(dllimport) void llvm_jitlink_setTestResultOverride( Index: compiler-rt/test/orc/TestCases/Windows/x86-64/static-initializer.cpp =================================================================== --- compiler-rt/test/orc/TestCases/Windows/x86-64/static-initializer.cpp +++ compiler-rt/test/orc/TestCases/Windows/x86-64/static-initializer.cpp @@ -1,4 +1,4 @@ -// RUN: %clangxx -c -o %t %s +// RUN: %clang_cl -MD -c -o %t %s // RUN: %llvm_jitlink %t extern "C" __declspec(dllimport) void llvm_jitlink_setTestResultOverride( Index: compiler-rt/test/orc/TestCases/Windows/x86-64/trivial-atexit.c =================================================================== --- /dev/null +++ compiler-rt/test/orc/TestCases/Windows/x86-64/trivial-atexit.c @@ -0,0 +1,18 @@ +// RUN: %clang_cl -MD -c -o %t %s +// RUN: %llvm_jitlink %t 2>&1 | FileCheck %s +// CHECK: Entering main +// CHECK-NEXT: Meow + +#include +#include + +void meow() { + printf("Meow\n"); + fflush(stdout); +} + +int main(int argc, char *argv[]) { + atexit(meow); + printf("Entering main\n"); + return 0; +} Index: compiler-rt/test/orc/TestCases/Windows/x86-64/trivial-jit-dlopen.c =================================================================== --- compiler-rt/test/orc/TestCases/Windows/x86-64/trivial-jit-dlopen.c +++ compiler-rt/test/orc/TestCases/Windows/x86-64/trivial-jit-dlopen.c @@ -1,10 +1,9 @@ -// XFAIL: * // Test that __orc_rt_coff_jit_dlopen and __orc_rt_coff_jit_dlclose work as // expected for a straightforward dlopen; dlclose sequence: first the // constructors should be run. // -// RUN: %clang -c -o %t.inits.o %p/Inputs/standalone-dylib.c -// RUN: %clang -c -o %t.test.o %s +// RUN: %clang_cl -MD -c -o %t.inits.o %p/Inputs/standalone-dylib.c +// RUN: %clang_cl -MD -c -o %t.test.o %s // RUN: %llvm_jitlink \ // RUN: -alias dlopen=__orc_rt_coff_jit_dlopen \ // RUN: -alias dlclose=__orc_rt_coff_jit_dlclose \ @@ -12,11 +11,12 @@ // CHECK: entering main // CHECK-NEXT: constructor +// CHECK-NEXT: destructor // CHECK-NEXT: leaving main #include -__declspec(dllimport) void *dlopen(const char *path, int mode); -__declspec(dllimport) int dlclose(void *handle); +void *dlopen(const char *path, int mode); +int dlclose(void *handle); int main(int argc, char *argv[]) { printf("entering main\n"); Index: compiler-rt/test/orc/lit.cfg.py =================================================================== --- compiler-rt/test/orc/lit.cfg.py +++ compiler-rt/test/orc/lit.cfg.py @@ -29,6 +29,9 @@ config.substitutions.append( ('%clangxx ', build_invocation(config.cxx_mode_flags + [config.target_cflags]))) +config.substitutions.append( + ('%clang_cl ', + build_invocation(['--driver-mode=cl'] + [config.target_cflags]))) if config.host_os == 'Windows': config.substitutions.append( ('%llvm_jitlink', (llvm_jitlink + ' -orc-runtime=' + Index: llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h =================================================================== --- llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h +++ llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h @@ -42,7 +42,8 @@ static Expected> Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD, const char *OrcRuntimePath, - LoadDynamicLibrary LoadDynLibrary, const char *VCRuntimePath = nullptr, + LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime = false, + const char *VCRuntimePath = nullptr, Optional RuntimeAliases = None); Error bootstrap(JITDylib &PlatformJD); @@ -141,11 +142,10 @@ static bool supportedTarget(const Triple &TT); - COFFPlatform( - ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, - JITDylib &PlatformJD, - std::unique_ptr OrcRuntimeGenerator, - LoadDynamicLibrary LoadDynLibrary, const char *VCRuntimePath, Error &Err); + COFFPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, + JITDylib &PlatformJD, const char *OrcRuntimePath, + LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime, + const char *VCRuntimePath, Error &Err); // Associate COFFPlatform JIT-side runtime support functions with handlers. Error associateRuntimeSupportFunctions(JITDylib &PlatformJD); @@ -164,6 +164,8 @@ // Build dependency graph of a JITDylib Expected buildJDDepMap(JITDylib &JD); + Expected getPerJDObjectFile(); + // Implements rt_pushInitializers by making repeat async lookups for // initializer symbols (each lookup may spawn more initializer symbols if // it pulls in new materializers, e.g. from objects in a static library). @@ -181,6 +183,9 @@ LoadDynamicLibrary LoadDynLibrary; std::unique_ptr VCRuntimeBootstrap; + std::unique_ptr OrcRuntimeArchiveBuffer; + std::unique_ptr OrcRuntimeArchive; + bool StaticVCRuntime; SymbolStringPtr COFFHeaderStartSymbol; Index: llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp =================================================================== --- llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp +++ llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp @@ -9,6 +9,7 @@ #include "llvm/ExecutionEngine/Orc/COFFPlatform.h" #include "llvm/ExecutionEngine/Orc/DebugUtils.h" #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h" +#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h" #include "llvm/Object/COFF.h" @@ -161,7 +162,7 @@ Expected> COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD, const char *OrcRuntimePath, - LoadDynamicLibrary LoadDynLibrary, + LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime, const char *VCRuntimePath, Optional RuntimeAliases) { auto &EPC = ES.getExecutorProcessControl(); @@ -192,23 +193,44 @@ JITSymbolFlags::Exported}}}))) return std::move(Err); - // Create a generator for the ORC runtime archive. - auto OrcRuntimeArchiveGenerator = - StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath); - if (!OrcRuntimeArchiveGenerator) - return OrcRuntimeArchiveGenerator.takeError(); PlatformJD.addToLinkOrder(HostFuncJD); // Create the instance. Error Err = Error::success(); auto P = std::unique_ptr(new COFFPlatform( - ES, ObjLinkingLayer, PlatformJD, std::move(*OrcRuntimeArchiveGenerator), - std::move(LoadDynLibrary), VCRuntimePath, Err)); + ES, ObjLinkingLayer, PlatformJD, OrcRuntimePath, + std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, Err)); if (Err) return std::move(Err); return std::move(P); } +Expected COFFPlatform::getPerJDObjectFile() { + auto PerJDObj = OrcRuntimeArchive->findSym("__orc_rt_coff_per_jd_marker"); + if (!PerJDObj) + return PerJDObj.takeError(); + + if (!*PerJDObj) + return make_error("Could not find per jd object file", + inconvertibleErrorCode()); + + auto Buffer = (*PerJDObj)->getAsBinary(); + if (!Buffer) + return Buffer.takeError(); + + return (*Buffer)->getMemoryBufferRef(); +} + +static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, + ArrayRef> AL) { + for (auto &KV : AL) { + auto AliasName = ES.intern(KV.first); + assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map"); + Aliases[std::move(AliasName)] = {ES.intern(KV.second), + JITSymbolFlags::Exported}; + } +} + Error COFFPlatform::setupJITDylib(JITDylib &JD) { if (auto Err = JD.define(std::make_unique( *this, COFFHeaderStartSymbol))) @@ -217,15 +239,36 @@ if (auto Err = ES.lookup({&JD}, COFFHeaderStartSymbol).takeError()) return Err; + // Define the CXX aliases. + SymbolAliasMap CXXAliases; + addAliases(ES, CXXAliases, requiredCXXAliases()); + if (auto Err = JD.define(symbolAliases(std::move(CXXAliases)))) + return std::move(Err); + + auto PerJDObj = getPerJDObjectFile(); + if (!PerJDObj) + return PerJDObj.takeError(); + + auto I = getObjectFileInterface(ES, *PerJDObj); + if (!I) + return I.takeError(); + + if (auto Err = ObjLinkingLayer.add( + JD, MemoryBuffer::getMemBuffer(*PerJDObj, false), std::move(*I))) + return Err; + if (!Bootstrapping) { - auto ImportedLibs = VCRuntimeBootstrap->loadStaticVCRuntime(JD); + auto ImportedLibs = StaticVCRuntime + ? VCRuntimeBootstrap->loadStaticVCRuntime(JD) + : VCRuntimeBootstrap->loadDynamicVCRuntime(JD); if (!ImportedLibs) return ImportedLibs.takeError(); for (auto &Lib : *ImportedLibs) if (auto Err = LoadDynLibrary(JD, Lib)) return Err; - if (auto Err = VCRuntimeBootstrap->initializeStaticVCRuntime(JD)) - return Err; + if (StaticVCRuntime) + if (auto Err = VCRuntimeBootstrap->initializeStaticVCRuntime(JD)) + return Err; } JD.addGenerator(DLLImportDefinitionGenerator::Create(ES, ObjLinkingLayer)); @@ -265,19 +308,8 @@ llvm_unreachable("Not supported yet"); } -static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, - ArrayRef> AL) { - for (auto &KV : AL) { - auto AliasName = ES.intern(KV.first); - assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map"); - Aliases[std::move(AliasName)] = {ES.intern(KV.second), - JITSymbolFlags::Exported}; - } -} - SymbolAliasMap COFFPlatform::standardPlatformAliases(ExecutionSession &ES) { SymbolAliasMap Aliases; - addAliases(ES, Aliases, requiredCXXAliases()); addAliases(ES, Aliases, standardRuntimeUtilityAliases()); return Aliases; } @@ -286,7 +318,8 @@ COFFPlatform::requiredCXXAliases() { static const std::pair RequiredCXXAliases[] = { {"_CxxThrowException", "__orc_rt_coff_cxx_throw_exception"}, - }; + {"_onexit", "__orc_rt_coff_onexit_per_jd"}, + {"atexit", "__orc_rt_coff_atexit_per_jd"}}; return ArrayRef>(RequiredCXXAliases); } @@ -315,16 +348,37 @@ } } -COFFPlatform::COFFPlatform( - ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, - JITDylib &PlatformJD, - std::unique_ptr OrcRuntimeGenerator, - LoadDynamicLibrary LoadDynLibrary, const char *VCRuntimePath, Error &Err) +COFFPlatform::COFFPlatform(ExecutionSession &ES, + ObjectLinkingLayer &ObjLinkingLayer, + JITDylib &PlatformJD, const char *OrcRuntimePath, + LoadDynamicLibrary LoadDynLibrary, + bool StaticVCRuntime, const char *VCRuntimePath, + Error &Err) : ES(ES), ObjLinkingLayer(ObjLinkingLayer), LoadDynLibrary(std::move(LoadDynLibrary)), + StaticVCRuntime(StaticVCRuntime), COFFHeaderStartSymbol(ES.intern("__ImageBase")) { ErrorAsOutParameter _(&Err); + // Create a generator for the ORC runtime archive. + auto OrcRuntimeArchiveGenerator = + StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath); + if (!OrcRuntimeArchiveGenerator) { + Err = std::move(OrcRuntimeArchiveGenerator.takeError()); + return; + } + + auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath); + if (!ArchiveBuffer) { + Err = createFileError(OrcRuntimePath, ArchiveBuffer.getError()); + return; + } + OrcRuntimeArchiveBuffer = std::move(*ArchiveBuffer); + OrcRuntimeArchive = + std::make_unique(*OrcRuntimeArchiveBuffer, Err); + if (Err) + return; + Bootstrapping.store(true); ObjLinkingLayer.addPlugin(std::make_unique(*this)); @@ -337,10 +391,12 @@ } VCRuntimeBootstrap = std::move(*VCRT); - for (auto &Lib : OrcRuntimeGenerator->getImportedDynamicLibraries()) + for (auto &Lib : (*OrcRuntimeArchiveGenerator)->getImportedDynamicLibraries()) DylibsToPreload.insert(Lib); - auto ImportedLibs = VCRuntimeBootstrap->loadStaticVCRuntime(PlatformJD); + auto ImportedLibs = + StaticVCRuntime ? VCRuntimeBootstrap->loadStaticVCRuntime(PlatformJD) + : VCRuntimeBootstrap->loadDynamicVCRuntime(PlatformJD); if (!ImportedLibs) { Err = ImportedLibs.takeError(); return; @@ -349,14 +405,14 @@ for (auto &Lib : *ImportedLibs) DylibsToPreload.insert(Lib); + PlatformJD.addGenerator(std::move(*OrcRuntimeArchiveGenerator)); + // PlatformJD hasn't been set up by the platform yet (since we're creating // the platform now), so set it up. if (auto E2 = setupJITDylib(PlatformJD)) { Err = std::move(E2); return; } - - PlatformJD.addGenerator(std::move(OrcRuntimeGenerator)); } Error COFFPlatform::bootstrap(JITDylib &PlatformJD) { @@ -364,8 +420,9 @@ if (auto Err = LoadDynLibrary(PlatformJD, Lib)) return Err; - if (auto Err = VCRuntimeBootstrap->initializeStaticVCRuntime(PlatformJD)) - return Err; + if (StaticVCRuntime) + if (auto Err = VCRuntimeBootstrap->initializeStaticVCRuntime(PlatformJD)) + return Err; // Associate wrapper function tags with JIT-side function implementations. if (auto Err = associateRuntimeSupportFunctions(PlatformJD)) { @@ -636,13 +693,6 @@ })) return Err; - // Run static initializers collected in bootstrap stage. - for (auto KV : JDBootstrapStates) { - auto &JDBState = KV.second; - if (auto Err = runBootstrapInitializers(JDBState)) - return Err; - } - // Call bootstrap functions if (auto Err = ES.callSPSWrapper(orc_rt_coff_platform_bootstrap)) return Err; @@ -664,6 +714,13 @@ return Err; } + // Run static initializers collected in bootstrap stage. + for (auto KV : JDBootstrapStates) { + auto &JDBState = KV.second; + if (auto Err = runBootstrapInitializers(JDBState)) + return Err; + } + return Error::success(); } Index: llvm/tools/llvm-jitlink/llvm-jitlink.cpp =================================================================== --- llvm/tools/llvm-jitlink/llvm-jitlink.cpp +++ llvm/tools/llvm-jitlink/llvm-jitlink.cpp @@ -1069,10 +1069,12 @@ ExitOnErr(loadProcessSymbols(*this)); else { // This symbol is used in testcases. - ExitOnErr(MainJD->define(absoluteSymbols( + auto &TestResultJD = ES.createBareJITDylib(""); + ExitOnErr(TestResultJD.define(absoluteSymbols( {{ES.intern("llvm_jitlink_setTestResultOverride"), {pointerToJITTargetAddress(llvm_jitlink_setTestResultOverride), JITSymbolFlags::Exported}}}))); + MainJD->addToLinkOrder(TestResultJD); } ExitOnErr(loadDylibs(*this));