diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp --- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp +++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp @@ -143,7 +143,7 @@ JITEvaluatedSymbol(pointerToJITTargetAddress(this), JITSymbolFlags::Exported); StdInterposes[J.mangleAndIntern("__lljit.cxa_atexit_helper")] = - JITEvaluatedSymbol(pointerToJITTargetAddress(registerAtExitHelper), + JITEvaluatedSymbol(pointerToJITTargetAddress(registerCxaAtExitHelper), JITSymbolFlags()); cantFail( @@ -162,6 +162,9 @@ PerJDInterposes[J.mangleAndIntern("__lljit.run_atexits_helper")] = JITEvaluatedSymbol(pointerToJITTargetAddress(runAtExitsHelper), JITSymbolFlags()); + PerJDInterposes[J.mangleAndIntern("__lljit.atexit_helper")] = + JITEvaluatedSymbol(pointerToJITTargetAddress(registerAtExitHelper), + JITSymbolFlags()); cantFail(JD.define(absoluteSymbols(std::move(PerJDInterposes)))); auto Ctx = std::make_unique(); @@ -190,6 +193,14 @@ GlobalValue::HiddenVisibility, "__lljit.run_atexits_helper", {PlatformInstanceDecl, DSOHandle}); + auto *IntTy = Type::getIntNTy(*Ctx, sizeof(int) * CHAR_BIT); + auto *AtExitCallbackTy = FunctionType::get(VoidTy, {}, false); + auto *AtExitCallbackPtrTy = PointerType::getUnqual(AtExitCallbackTy); + addHelperAndWrapper(*M, "atexit", + FunctionType::get(IntTy, {AtExitCallbackPtrTy}, false), + GlobalValue::HiddenVisibility, "__lljit.atexit_helper", + {PlatformInstanceDecl, DSOHandle}); + return J.addIRModule(JD, ThreadSafeModule(std::move(M), std::move(Ctx))); } @@ -413,16 +424,25 @@ .takeError(); } - static void registerAtExitHelper(void *Self, void (*F)(void *), void *Ctx, - void *DSOHandle) { + static void registerCxaAtExitHelper(void *Self, void (*F)(void *), void *Ctx, + void *DSOHandle) { LLVM_DEBUG({ - dbgs() << "Registering atexit function " << (void *)F << " for JD " + dbgs() << "Registering cxa atexit function " << (void *)F << " for JD " << (*static_cast(DSOHandle))->getName() << "\n"; }); static_cast(Self)->AtExitMgr.registerAtExit( F, Ctx, DSOHandle); } + static void registerAtExitHelper(void *Self, void *DSOHandle, void (*F)()) { + LLVM_DEBUG({ + dbgs() << "Registering atexit function " << (void *)F << " for JD " + << (*static_cast(DSOHandle))->getName() << "\n"; + }); + static_cast(Self)->AtExitMgr.registerAtExit( + reinterpret_cast(F), nullptr, DSOHandle); + } + static void runAtExitsHelper(void *Self, void *DSOHandle) { LLVM_DEBUG({ dbgs() << "Running atexit functions for JD " @@ -450,12 +470,12 @@ auto *IntTy = Type::getIntNTy(*Ctx, sizeof(int) * CHAR_BIT); auto *VoidTy = Type::getVoidTy(*Ctx); auto *BytePtrTy = PointerType::getUnqual(Int8Ty); - auto *AtExitCallbackTy = FunctionType::get(VoidTy, {BytePtrTy}, false); - auto *AtExitCallbackPtrTy = PointerType::getUnqual(AtExitCallbackTy); + auto *CxaAtExitCallbackTy = FunctionType::get(VoidTy, {BytePtrTy}, false); + auto *CxaAtExitCallbackPtrTy = PointerType::getUnqual(CxaAtExitCallbackTy); addHelperAndWrapper( *M, "__cxa_atexit", - FunctionType::get(IntTy, {AtExitCallbackPtrTy, BytePtrTy, BytePtrTy}, + FunctionType::get(IntTy, {CxaAtExitCallbackPtrTy, BytePtrTy, BytePtrTy}, false), GlobalValue::DefaultVisibility, "__lljit.cxa_atexit_helper", {PlatformInstanceDecl}); diff --git a/llvm/test/ExecutionEngine/OrcLazy/global-ctors-and-dtors.ll b/llvm/test/ExecutionEngine/OrcLazy/global-ctors-and-dtors.ll --- a/llvm/test/ExecutionEngine/OrcLazy/global-ctors-and-dtors.ll +++ b/llvm/test/ExecutionEngine/OrcLazy/global-ctors-and-dtors.ll @@ -11,8 +11,9 @@ ; CHECK: Hello from constructor ; CHECK: Hello ; CHECK: [ {{.*}}main{{.*}} ] -; CHECK: Goodbye -; CHECK: Goodbye again +; CHECK: Goodbye from atexit +; CHECK: Goodbye from __cxa_atexit +; CHECK: Goodbye from destructor %class.Foo = type { i8 } @@ -21,28 +22,39 @@ @llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_hello.cpp, i8* null }, { i32, void ()*, i8* } { i32 1024, void ()* @constructor, i8* null }] @llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @printf_wrapper, i8* null }] @str = private unnamed_addr constant [6 x i8] c"Hello\00" -@str2 = private unnamed_addr constant [8 x i8] c"Goodbye\00" -@str3 = global [14 x i8] c"Goodbye again\00" -@str4 = private unnamed_addr constant [23 x i8] c"Hello from constructor\00" +@str2 = private unnamed_addr constant [23 x i8] c"Hello from constructor\00" +@str3 = private unnamed_addr constant [24 x i8] c"Goodbye from destructor\00" +@str4 = global [26 x i8] c"Goodbye from __cxa_atexit\00" +@str5 = global [20 x i8] c"Goodbye from atexit\00" + define linkonce_odr void @_ZN3FooD1Ev(%class.Foo* nocapture readnone %this) unnamed_addr align 2 { entry: - %puts.i = tail call i32 @puts(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @str2, i64 0, i64 0)) + %puts.i = tail call i32 @puts(i8* getelementptr inbounds ([26 x i8], [26 x i8]* @str4, i64 0, i64 0)) + ret void +} + +define void @atexit_handler() { +entry: + %puts.i = tail call i32 @puts(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @str5, i64 0, i64 0)) ret void } declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) +declare i32 @atexit(void ()*) + define internal void @_GLOBAL__sub_I_hello.cpp() { entry: %puts.i.i.i = tail call i32 @puts(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @str, i64 0, i64 0)) %0 = tail call i32 @__cxa_atexit(void (i8*)* bitcast (void (%class.Foo*)* @_ZN3FooD1Ev to void (i8*)*), i8* getelementptr inbounds (%class.Foo, %class.Foo* @f, i64 0, i32 0), i8* @__dso_handle) + %1 = tail call i32 @atexit(void ()* @atexit_handler) ret void } define void @printf_wrapper() { entry: - %0 = tail call i32 @puts(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @str3, i64 0, i64 0)) + %0 = tail call i32 @puts(i8* getelementptr inbounds ([24 x i8], [24 x i8]* @str3, i64 0, i64 0)) ret void } @@ -50,6 +62,6 @@ define void @constructor() { entry: - %0 = tail call i32 @puts(i8* getelementptr inbounds ([23 x i8], [23 x i8]* @str4, i64 0, i64 0)) + %0 = tail call i32 @puts(i8* getelementptr inbounds ([23 x i8], [23 x i8]* @str2, i64 0, i64 0)) ret void }