[llvm] 73c4033 - [ORC][ORC_RT][COFF] Support dynamic VC runtime.

via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 9 23:27:51 PDT 2022


Author: sunho
Date: 2022-09-10T15:25:49+09:00
New Revision: 73c4033987c5ca6cf8022f840f3c42e3324da1cb

URL: https://github.com/llvm/llvm-project/commit/73c4033987c5ca6cf8022f840f3c42e3324da1cb
DIFF: https://github.com/llvm/llvm-project/commit/73c4033987c5ca6cf8022f840f3c42e3324da1cb.diff

LOG: [ORC][ORC_RT][COFF] Support dynamic VC runtime.

Supports dynamic VC runtime. It implements atexits handling which is required to load msvcrt.lib successfully. (the object file containing atexit symbol somehow resolves to static vc runtim symbols) It also default to dynamic vc runtime which tends to be more robust.

Reviewed By: lhames

Differential Revision: https://reviews.llvm.org/D132525

Added: 
    compiler-rt/lib/orc/coff_platform.per_jd.cpp
    compiler-rt/test/orc/TestCases/Windows/x86-64/trivial-atexit.c

Modified: 
    compiler-rt/lib/orc/CMakeLists.txt
    compiler-rt/lib/orc/coff_platform.cpp
    compiler-rt/test/orc/TestCases/Windows/x86-64/Inputs/standalone-dylib.c
    compiler-rt/test/orc/TestCases/Windows/x86-64/hello-world.c
    compiler-rt/test/orc/TestCases/Windows/x86-64/hello-world.cpp
    compiler-rt/test/orc/TestCases/Windows/x86-64/priority-static-initializer-three.c
    compiler-rt/test/orc/TestCases/Windows/x86-64/priority-static-initializer.c
    compiler-rt/test/orc/TestCases/Windows/x86-64/sehframe-handling.cpp
    compiler-rt/test/orc/TestCases/Windows/x86-64/static-initializer.cpp
    compiler-rt/test/orc/TestCases/Windows/x86-64/trivial-jit-dlopen.c
    compiler-rt/test/orc/lit.cfg.py
    llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h
    llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
    llvm/tools/llvm-jitlink/llvm-jitlink.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/orc/CMakeLists.txt b/compiler-rt/lib/orc/CMakeLists.txt
index a40a1090e01b8..406830a17f17a 100644
--- a/compiler-rt/lib/orc/CMakeLists.txt
+++ b/compiler-rt/lib/orc/CMakeLists.txt
@@ -13,6 +13,7 @@ set(ORC_COMMON_SOURCES
 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 @@ else() # not Apple
     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)
 

diff  --git a/compiler-rt/lib/orc/coff_platform.cpp b/compiler-rt/lib/orc/coff_platform.cpp
index 57a83ebeabddb..4cccf2bce5679 100644
--- a/compiler-rt/lib/orc/coff_platform.cpp
+++ b/compiler-rt/lib/orc/coff_platform.cpp
@@ -81,6 +81,7 @@ class COFFPlatformRuntimeState {
     size_t LinkedAgainstRefCount = 0;
     size_t DlRefCount = 0;
     std::vector<JITDylibState *> Deps;
+    std::vector<void (*)(void)> AtExits;
     XtorSection CInitSection;    // XIA~XIZ
     XtorSection CXXInitSection;  // XCA~XCZ
     XtorSection CPreTermSection; // XPA~XPZ
@@ -94,6 +95,7 @@ class COFFPlatformRuntimeState {
 public:
   static void initialize();
   static COFFPlatformRuntimeState &get();
+  static bool isInitialized() { return CPS; }
   static void destroy();
 
   COFFPlatformRuntimeState() = default;
@@ -113,6 +115,8 @@ class COFFPlatformRuntimeState {
   Error registerJITDylib(std::string Name, void *Header);
   Error deregisterJITDylib(void *Header);
 
+  Error registerAtExit(ExecutorAddr HeaderAddr, void (*AtExit)(void));
+
   Error registerObjectSections(
       ExecutorAddr HeaderAddr,
       std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs,
@@ -410,7 +414,10 @@ Error COFFPlatformRuntimeState::dlcloseDeinitialize(JITDylibState &JDS) {
              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 @@ Error COFFPlatformRuntimeState::registerObjectSections(
   auto I = JDStates.find(HeaderAddr.toPtr<void *>());
   if (I == JDStates.end()) {
     std::ostringstream ErrStream;
-    ErrStream << "Attempted to register unrecognized header "
-              << HeaderAddr.getValue();
+    ErrStream << "Unrecognized header " << HeaderAddr.getValue();
     return make_error<StringError>(ErrStream.str());
   }
   auto &JDState = I->second;
@@ -499,7 +505,7 @@ Error COFFPlatformRuntimeState::deregisterObjectSections(
   auto I = JDStates.find(HeaderAddr.toPtr<void *>());
   if (I == JDStates.end()) {
     std::ostringstream ErrStream;
-    ErrStream << "Attempted to register unrecognized header "
+    ErrStream << "Attempted to deregister unrecognized header "
               << HeaderAddr.getValue();
     return make_error<StringError>(ErrStream.str());
   }
@@ -549,6 +555,19 @@ Error COFFPlatformRuntimeState::deregisterBlockRange(ExecutorAddr HeaderAddr,
   return Error::success();
 }
 
+Error COFFPlatformRuntimeState::registerAtExit(ExecutorAddr HeaderAddr,
+                                               void (*AtExit)(void)) {
+  std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
+  auto I = JDStates.find(HeaderAddr.toPtr<void *>());
+  if (I == JDStates.end()) {
+    std::ostringstream ErrStream;
+    ErrStream << "Unrecognized header " << HeaderAddr.getValue();
+    return make_error<StringError>(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 @@ ORC_RT_INTERFACE void __stdcall __orc_rt_coff_cxx_throw_exception(
                  _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
 //------------------------------------------------------------------------------

diff  --git a/compiler-rt/lib/orc/coff_platform.per_jd.cpp b/compiler-rt/lib/orc/coff_platform.per_jd.cpp
new file mode 100644
index 0000000000000..698ee200229a2
--- /dev/null
+++ b/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

diff  --git a/compiler-rt/test/orc/TestCases/Windows/x86-64/Inputs/standalone-dylib.c b/compiler-rt/test/orc/TestCases/Windows/x86-64/Inputs/standalone-dylib.c
index 638752a7c9f69..b8c56053f1c9f 100644
--- a/compiler-rt/test/orc/TestCases/Windows/x86-64/Inputs/standalone-dylib.c
+++ b/compiler-rt/test/orc/TestCases/Windows/x86-64/Inputs/standalone-dylib.c
@@ -1,9 +1,13 @@
 #include <stdio.h>
+#include <stdlib.h>
+
+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

diff  --git a/compiler-rt/test/orc/TestCases/Windows/x86-64/hello-world.c b/compiler-rt/test/orc/TestCases/Windows/x86-64/hello-world.c
index 20f229d6889fe..5d64ffa8ccd04 100644
--- a/compiler-rt/test/orc/TestCases/Windows/x86-64/hello-world.c
+++ b/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!
 

diff  --git a/compiler-rt/test/orc/TestCases/Windows/x86-64/hello-world.cpp b/compiler-rt/test/orc/TestCases/Windows/x86-64/hello-world.cpp
index 3eb0521a10d90..3b59cc2b33daa 100644
--- a/compiler-rt/test/orc/TestCases/Windows/x86-64/hello-world.cpp
+++ b/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!
 

diff  --git a/compiler-rt/test/orc/TestCases/Windows/x86-64/priority-static-initializer-three.c b/compiler-rt/test/orc/TestCases/Windows/x86-64/priority-static-initializer-three.c
index c7fc4de424385..964ceca0ca7ce 100644
--- a/compiler-rt/test/orc/TestCases/Windows/x86-64/priority-static-initializer-three.c
+++ b/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

diff  --git a/compiler-rt/test/orc/TestCases/Windows/x86-64/priority-static-initializer.c b/compiler-rt/test/orc/TestCases/Windows/x86-64/priority-static-initializer.c
index a19ec797911e6..adde02e73c493 100644
--- a/compiler-rt/test/orc/TestCases/Windows/x86-64/priority-static-initializer.c
+++ b/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

diff  --git a/compiler-rt/test/orc/TestCases/Windows/x86-64/sehframe-handling.cpp b/compiler-rt/test/orc/TestCases/Windows/x86-64/sehframe-handling.cpp
index 7fe162f2af0c3..713a4cf516b1c 100644
--- a/compiler-rt/test/orc/TestCases/Windows/x86-64/sehframe-handling.cpp
+++ b/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(

diff  --git a/compiler-rt/test/orc/TestCases/Windows/x86-64/static-initializer.cpp b/compiler-rt/test/orc/TestCases/Windows/x86-64/static-initializer.cpp
index 58edb3affe430..1c3b514b2469a 100644
--- a/compiler-rt/test/orc/TestCases/Windows/x86-64/static-initializer.cpp
+++ b/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(

diff  --git a/compiler-rt/test/orc/TestCases/Windows/x86-64/trivial-atexit.c b/compiler-rt/test/orc/TestCases/Windows/x86-64/trivial-atexit.c
new file mode 100644
index 0000000000000..a06940d6a7fed
--- /dev/null
+++ b/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 <stdio.h>
+#include <stdlib.h>
+
+void meow() {
+  printf("Meow\n");
+  fflush(stdout);
+}
+
+int main(int argc, char *argv[]) {
+  atexit(meow);
+  printf("Entering main\n");
+  return 0;
+}

diff  --git a/compiler-rt/test/orc/TestCases/Windows/x86-64/trivial-jit-dlopen.c b/compiler-rt/test/orc/TestCases/Windows/x86-64/trivial-jit-dlopen.c
index f07abaca9af11..6a9182b0d7ab8 100644
--- a/compiler-rt/test/orc/TestCases/Windows/x86-64/trivial-jit-dlopen.c
+++ b/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 <stdio.h>
-__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");

diff  --git a/compiler-rt/test/orc/lit.cfg.py b/compiler-rt/test/orc/lit.cfg.py
index 696395687239d..de0d899b5a570 100644
--- a/compiler-rt/test/orc/lit.cfg.py
+++ b/compiler-rt/test/orc/lit.cfg.py
@@ -37,6 +37,9 @@ def build_invocation(compile_flags):
 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=' +

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h b/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h
index 958b49dab1281..4b954cd0c1302 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h
@@ -42,7 +42,8 @@ class COFFPlatform : public Platform {
   static Expected<std::unique_ptr<COFFPlatform>>
   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<SymbolAliasMap> RuntimeAliases = None);
 
   Error bootstrap(JITDylib &PlatformJD);
@@ -141,11 +142,10 @@ class COFFPlatform : public Platform {
 
   static bool supportedTarget(const Triple &TT);
 
-  COFFPlatform(
-      ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
-      JITDylib &PlatformJD,
-      std::unique_ptr<StaticLibraryDefinitionGenerator> 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 @@ class COFFPlatform : public Platform {
   // Build dependency graph of a JITDylib
   Expected<JITDylibDepMap> buildJDDepMap(JITDylib &JD);
 
+  Expected<MemoryBufferRef> 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 @@ class COFFPlatform : public Platform {
 
   LoadDynamicLibrary LoadDynLibrary;
   std::unique_ptr<COFFVCRuntimeBootstrapper> VCRuntimeBootstrap;
+  std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer;
+  std::unique_ptr<object::Archive> OrcRuntimeArchive;
+  bool StaticVCRuntime;
 
   SymbolStringPtr COFFHeaderStartSymbol;
 

diff  --git a/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
index 15ca2df3df8d0..4730f7d4fab60 100644
--- a/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
+++ b/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 @@ namespace orc {
 Expected<std::unique_ptr<COFFPlatform>>
 COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
                      JITDylib &PlatformJD, const char *OrcRuntimePath,
-                     LoadDynamicLibrary LoadDynLibrary,
+                     LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
                      const char *VCRuntimePath,
                      Optional<SymbolAliasMap> RuntimeAliases) {
   auto &EPC = ES.getExecutorProcessControl();
@@ -192,23 +193,44 @@ COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
              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<COFFPlatform>(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<MemoryBufferRef> COFFPlatform::getPerJDObjectFile() {
+  auto PerJDObj = OrcRuntimeArchive->findSym("__orc_rt_coff_per_jd_marker");
+  if (!PerJDObj)
+    return PerJDObj.takeError();
+
+  if (!*PerJDObj)
+    return make_error<StringError>("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<std::pair<const char *, const char *>> 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<COFFHeaderMaterializationUnit>(
           *this, COFFHeaderStartSymbol)))
@@ -217,15 +239,36 @@ Error COFFPlatform::setupJITDylib(JITDylib &JD) {
   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 @@ Error COFFPlatform::notifyRemoving(ResourceTracker &RT) {
   llvm_unreachable("Not supported yet");
 }
 
-static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
-                       ArrayRef<std::pair<const char *, const char *>> 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 @@ ArrayRef<std::pair<const char *, const char *>>
 COFFPlatform::requiredCXXAliases() {
   static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
       {"_CxxThrowException", "__orc_rt_coff_cxx_throw_exception"},
-  };
+      {"_onexit", "__orc_rt_coff_onexit_per_jd"},
+      {"atexit", "__orc_rt_coff_atexit_per_jd"}};
 
   return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
 }
@@ -315,16 +348,37 @@ bool COFFPlatform::supportedTarget(const Triple &TT) {
   }
 }
 
-COFFPlatform::COFFPlatform(
-    ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
-    JITDylib &PlatformJD,
-    std::unique_ptr<StaticLibraryDefinitionGenerator> 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<object::Archive>(*OrcRuntimeArchiveBuffer, Err);
+  if (Err)
+    return;
+
   Bootstrapping.store(true);
   ObjLinkingLayer.addPlugin(std::make_unique<COFFPlatformPlugin>(*this));
 
@@ -337,10 +391,12 @@ COFFPlatform::COFFPlatform(
   }
   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 @@ COFFPlatform::COFFPlatform(
   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 @@ Error COFFPlatform::bootstrap(JITDylib &PlatformJD) {
     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 @@ Error COFFPlatform::bootstrapCOFFRuntime(JITDylib &PlatformJD) {
           }))
     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<void()>(orc_rt_coff_platform_bootstrap))
     return Err;
@@ -664,6 +714,13 @@ Error COFFPlatform::bootstrapCOFFRuntime(JITDylib &PlatformJD) {
         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();
 }
 

diff  --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index 53c708fd77e24..5efbd6538388d 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -1197,10 +1197,12 @@ Session::Session(std::unique_ptr<ExecutorProcessControl> EPC, Error &Err)
     ExitOnErr(loadProcessSymbols(*this));
   else {
     // This symbol is used in testcases.
-    ExitOnErr(MainJD->define(absoluteSymbols(
+    auto &TestResultJD = ES.createBareJITDylib("<TestResultJD>");
+    ExitOnErr(TestResultJD.define(absoluteSymbols(
         {{ES.intern("llvm_jitlink_setTestResultOverride"),
           {pointerToJITTargetAddress(llvm_jitlink_setTestResultOverride),
            JITSymbolFlags::Exported}}})));
+    MainJD->addToLinkOrder(TestResultJD);
   }
 
   ExitOnErr(loadDylibs(*this));


        


More information about the llvm-commits mailing list