forked from OSchip/llvm-project
[ORC] Export __cxa_atexit from the main JITDylib in LLJIT.
Failure to export __cxa_atexit can lead to an attempt to import a definition from the process itself (if __cxa_atexit is referenced from another JITDylib), but the process definition will clash with the existing non-exported definition to produce an unexpected DuplicateDefinitionError. This patch fixes the immediate issue by exporting __cxa_atexit. It also fixes a bug where atexit functions in other JITDylibs were not being run by adding a copy of run_atexits_helper to every JITDylib. A follow up patch will deal with the bug where definition generators are called despite a non-exported definition being present.
This commit is contained in:
parent
32672b877d
commit
0071eaaf08
|
@ -29,14 +29,6 @@ using namespace llvm::orc;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// Add a reference to the __dso_handle global to the given module.
|
|
||||||
/// Returns a reference to the __dso_handle IR decl.
|
|
||||||
GlobalVariable *addDSOHandleDecl(Module &M) {
|
|
||||||
auto DSOHandleTy = StructType::create(M.getContext(), "lljit.dso_handle");
|
|
||||||
return new GlobalVariable(M, DSOHandleTy, true, GlobalValue::ExternalLinkage,
|
|
||||||
nullptr, "__dso_handle");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds helper function decls and wrapper functions that call the helper with
|
/// Adds helper function decls and wrapper functions that call the helper with
|
||||||
/// some additional prefix arguments.
|
/// some additional prefix arguments.
|
||||||
///
|
///
|
||||||
|
@ -143,11 +135,10 @@ public:
|
||||||
SymbolMap StdInterposes;
|
SymbolMap StdInterposes;
|
||||||
|
|
||||||
StdInterposes[Mangle("__lljit.platform_support_instance")] =
|
StdInterposes[Mangle("__lljit.platform_support_instance")] =
|
||||||
JITEvaluatedSymbol(pointerToJITTargetAddress(this), JITSymbolFlags());
|
JITEvaluatedSymbol(pointerToJITTargetAddress(this),
|
||||||
|
JITSymbolFlags::Exported);
|
||||||
StdInterposes[Mangle("__lljit.cxa_atexit_helper")] = JITEvaluatedSymbol(
|
StdInterposes[Mangle("__lljit.cxa_atexit_helper")] = JITEvaluatedSymbol(
|
||||||
pointerToJITTargetAddress(registerAtExitHelper), JITSymbolFlags());
|
pointerToJITTargetAddress(registerAtExitHelper), JITSymbolFlags());
|
||||||
StdInterposes[Mangle("__lljit.run_atexits_helper")] = JITEvaluatedSymbol(
|
|
||||||
pointerToJITTargetAddress(runAtExitsHelper), JITSymbolFlags());
|
|
||||||
|
|
||||||
cantFail(
|
cantFail(
|
||||||
J.getMainJITDylib().define(absoluteSymbols(std::move(StdInterposes))));
|
J.getMainJITDylib().define(absoluteSymbols(std::move(StdInterposes))));
|
||||||
|
@ -159,6 +150,14 @@ public:
|
||||||
|
|
||||||
/// Adds a module that defines the __dso_handle global.
|
/// Adds a module that defines the __dso_handle global.
|
||||||
Error setupJITDylib(JITDylib &JD) {
|
Error setupJITDylib(JITDylib &JD) {
|
||||||
|
|
||||||
|
// Add per-jitdylib standard interposes.
|
||||||
|
MangleAndInterner Mangle(getExecutionSession(), J.getDataLayout());
|
||||||
|
SymbolMap PerJDInterposes;
|
||||||
|
PerJDInterposes[Mangle("__lljit.run_atexits_helper")] = JITEvaluatedSymbol(
|
||||||
|
pointerToJITTargetAddress(runAtExitsHelper), JITSymbolFlags());
|
||||||
|
cantFail(JD.define(absoluteSymbols(std::move(PerJDInterposes))));
|
||||||
|
|
||||||
auto Ctx = std::make_unique<LLVMContext>();
|
auto Ctx = std::make_unique<LLVMContext>();
|
||||||
auto M = std::make_unique<Module>("__standard_lib", *Ctx);
|
auto M = std::make_unique<Module>("__standard_lib", *Ctx);
|
||||||
M->setDataLayout(J.getDataLayout());
|
M->setDataLayout(J.getDataLayout());
|
||||||
|
@ -168,9 +167,23 @@ public:
|
||||||
*M, Int64Ty, true, GlobalValue::ExternalLinkage,
|
*M, Int64Ty, true, GlobalValue::ExternalLinkage,
|
||||||
ConstantInt::get(Int64Ty, reinterpret_cast<uintptr_t>(&JD)),
|
ConstantInt::get(Int64Ty, reinterpret_cast<uintptr_t>(&JD)),
|
||||||
"__dso_handle");
|
"__dso_handle");
|
||||||
DSOHandle->setVisibility(GlobalValue::HiddenVisibility);
|
DSOHandle->setVisibility(GlobalValue::DefaultVisibility);
|
||||||
DSOHandle->setInitializer(
|
DSOHandle->setInitializer(
|
||||||
ConstantInt::get(Int64Ty, pointerToJITTargetAddress(&JD)));
|
ConstantInt::get(Int64Ty, pointerToJITTargetAddress(&JD)));
|
||||||
|
|
||||||
|
auto *GenericIRPlatformSupportTy =
|
||||||
|
StructType::create(*Ctx, "lljit.GenericLLJITIRPlatformSupport");
|
||||||
|
|
||||||
|
auto *PlatformInstanceDecl = new GlobalVariable(
|
||||||
|
*M, GenericIRPlatformSupportTy, true, GlobalValue::ExternalLinkage,
|
||||||
|
nullptr, "__lljit.platform_support_instance");
|
||||||
|
|
||||||
|
auto *VoidTy = Type::getVoidTy(*Ctx);
|
||||||
|
addHelperAndWrapper(
|
||||||
|
*M, "__lljit_run_atexits", FunctionType::get(VoidTy, {}, false),
|
||||||
|
GlobalValue::HiddenVisibility, "__lljit.run_atexits_helper",
|
||||||
|
{PlatformInstanceDecl, DSOHandle});
|
||||||
|
|
||||||
return J.addIRModule(JD, ThreadSafeModule(std::move(M), std::move(Ctx)));
|
return J.addIRModule(JD, ThreadSafeModule(std::move(M), std::move(Ctx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,6 +329,16 @@ private:
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
LLVM_DEBUG({
|
||||||
|
dbgs() << "JITDylib deinit order is [ ";
|
||||||
|
for (auto *JD : DFSLinkOrder)
|
||||||
|
dbgs() << "\"" << JD->getName() << "\" ";
|
||||||
|
dbgs() << "]\n";
|
||||||
|
dbgs() << "Looking up deinit functions:\n";
|
||||||
|
for (auto &KV : LookupSymbols)
|
||||||
|
dbgs() << " \"" << KV.first->getName() << "\": " << KV.second << "\n";
|
||||||
|
});
|
||||||
|
|
||||||
auto LookupResult = Platform::lookupInitSymbols(ES, LookupSymbols);
|
auto LookupResult = Platform::lookupInitSymbols(ES, LookupSymbols);
|
||||||
|
|
||||||
if (!LookupResult)
|
if (!LookupResult)
|
||||||
|
@ -387,11 +410,19 @@ private:
|
||||||
|
|
||||||
static void registerAtExitHelper(void *Self, void (*F)(void *), void *Ctx,
|
static void registerAtExitHelper(void *Self, void (*F)(void *), void *Ctx,
|
||||||
void *DSOHandle) {
|
void *DSOHandle) {
|
||||||
|
LLVM_DEBUG({
|
||||||
|
dbgs() << "Registering atexit function " << (void *)F << " for JD "
|
||||||
|
<< (*static_cast<JITDylib **>(DSOHandle))->getName() << "\n";
|
||||||
|
});
|
||||||
static_cast<GenericLLVMIRPlatformSupport *>(Self)->AtExitMgr.registerAtExit(
|
static_cast<GenericLLVMIRPlatformSupport *>(Self)->AtExitMgr.registerAtExit(
|
||||||
F, Ctx, DSOHandle);
|
F, Ctx, DSOHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void runAtExitsHelper(void *Self, void *DSOHandle) {
|
static void runAtExitsHelper(void *Self, void *DSOHandle) {
|
||||||
|
LLVM_DEBUG({
|
||||||
|
dbgs() << "Running atexit functions for JD "
|
||||||
|
<< (*static_cast<JITDylib **>(DSOHandle))->getName() << "\n";
|
||||||
|
});
|
||||||
static_cast<GenericLLVMIRPlatformSupport *>(Self)->AtExitMgr.runAtExits(
|
static_cast<GenericLLVMIRPlatformSupport *>(Self)->AtExitMgr.runAtExits(
|
||||||
DSOHandle);
|
DSOHandle);
|
||||||
}
|
}
|
||||||
|
@ -410,8 +441,6 @@ private:
|
||||||
*M, GenericIRPlatformSupportTy, true, GlobalValue::ExternalLinkage,
|
*M, GenericIRPlatformSupportTy, true, GlobalValue::ExternalLinkage,
|
||||||
nullptr, "__lljit.platform_support_instance");
|
nullptr, "__lljit.platform_support_instance");
|
||||||
|
|
||||||
auto *DSOHandleDecl = addDSOHandleDecl(*M);
|
|
||||||
|
|
||||||
auto *Int8Ty = Type::getInt8Ty(*Ctx);
|
auto *Int8Ty = Type::getInt8Ty(*Ctx);
|
||||||
auto *IntTy = Type::getIntNTy(*Ctx, sizeof(int) * CHAR_BIT);
|
auto *IntTy = Type::getIntNTy(*Ctx, sizeof(int) * CHAR_BIT);
|
||||||
auto *VoidTy = Type::getVoidTy(*Ctx);
|
auto *VoidTy = Type::getVoidTy(*Ctx);
|
||||||
|
@ -423,14 +452,9 @@ private:
|
||||||
*M, "__cxa_atexit",
|
*M, "__cxa_atexit",
|
||||||
FunctionType::get(IntTy, {AtExitCallbackPtrTy, BytePtrTy, BytePtrTy},
|
FunctionType::get(IntTy, {AtExitCallbackPtrTy, BytePtrTy, BytePtrTy},
|
||||||
false),
|
false),
|
||||||
GlobalValue::HiddenVisibility, "__lljit.cxa_atexit_helper",
|
GlobalValue::DefaultVisibility, "__lljit.cxa_atexit_helper",
|
||||||
{PlatformInstanceDecl});
|
{PlatformInstanceDecl});
|
||||||
|
|
||||||
addHelperAndWrapper(
|
|
||||||
*M, "__lljit_run_atexits", FunctionType::get(VoidTy, {}, false),
|
|
||||||
GlobalValue::HiddenVisibility, "__lljit.run_atexits_helper",
|
|
||||||
{PlatformInstanceDecl, DSOHandleDecl});
|
|
||||||
|
|
||||||
return ThreadSafeModule(std::move(M), std::move(Ctx));
|
return ThreadSafeModule(std::move(M), std::move(Ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,7 +700,7 @@ private:
|
||||||
auto *DSOHandle =
|
auto *DSOHandle =
|
||||||
new GlobalVariable(M, Int64Ty, true, GlobalValue::ExternalLinkage,
|
new GlobalVariable(M, Int64Ty, true, GlobalValue::ExternalLinkage,
|
||||||
ConstantInt::get(Int64Ty, 0), "__dso_handle");
|
ConstantInt::get(Int64Ty, 0), "__dso_handle");
|
||||||
DSOHandle->setVisibility(GlobalValue::HiddenVisibility);
|
DSOHandle->setVisibility(GlobalValue::DefaultVisibility);
|
||||||
|
|
||||||
return cantFail(J.getIRCompileLayer().getCompiler()(M));
|
return cantFail(J.getIRCompileLayer().getCompiler()(M));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
; RUN: lli -jit-kind=orc-lazy -orc-lazy-debug=funcs-to-stdout %s | FileCheck %s
|
; Test that global constructors and destructors are run:
|
||||||
;
|
;
|
||||||
; Test that global constructors and destructors are run.
|
; RUN: lli -jit-kind=orc-lazy -orc-lazy-debug=funcs-to-stdout -extra-module %s \
|
||||||
|
; RUN: %S/Inputs/noop-main.ll | FileCheck %s
|
||||||
|
;
|
||||||
|
; Test that this is true for global constructors and destructors in other
|
||||||
|
; JITDylibs.
|
||||||
|
; RUN: lli -jit-kind=orc-lazy -orc-lazy-debug=funcs-to-stdout \
|
||||||
|
; RUN: -jd extra -extra-module %s -jd main %S/Inputs/noop-main.ll | FileCheck %s
|
||||||
;
|
;
|
||||||
; CHECK: Hello
|
; CHECK: Hello
|
||||||
; CHECK: [ {{.*}}main{{.*}} ]
|
; CHECK: [ {{.*}}main{{.*}} ]
|
||||||
|
@ -22,11 +28,6 @@ entry:
|
||||||
|
|
||||||
declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*)
|
declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*)
|
||||||
|
|
||||||
define i32 @main(i32 %argc, i8** nocapture readnone %argv) {
|
|
||||||
entry:
|
|
||||||
ret i32 0
|
|
||||||
}
|
|
||||||
|
|
||||||
define internal void @_GLOBAL__sub_I_hello.cpp() {
|
define internal void @_GLOBAL__sub_I_hello.cpp() {
|
||||||
entry:
|
entry:
|
||||||
%puts.i.i.i = tail call i32 @puts(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @str, i64 0, i64 0))
|
%puts.i.i.i = tail call i32 @puts(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @str, i64 0, i64 0))
|
||||||
|
|
Loading…
Reference in New Issue