[llvm] 02ac5e5 - [Orc] Fix global variable destructor function support when --jit-kind=orc-lazy
via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 9 00:58:36 PDT 2021
Author: luxufan
Date: 2021-10-09T15:58:21+08:00
New Revision: 02ac5e5cf12925cbd09213f3a4dfd5575d8c56d2
URL: https://github.com/llvm/llvm-project/commit/02ac5e5cf12925cbd09213f3a4dfd5575d8c56d2
DIFF: https://github.com/llvm/llvm-project/commit/02ac5e5cf12925cbd09213f3a4dfd5575d8c56d2.diff
LOG: [Orc] Fix global variable destructor function support when --jit-kind=orc-lazy
The bug was reported here https://bugs.llvm.org/show_bug.cgi?id=52030
This patch follows the idea that @lhames commented in the above webpage.
Reviewed By: lhames
Differential Revision: https://reviews.llvm.org/D110990
Added:
Modified:
llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
llvm/test/ExecutionEngine/OrcLazy/global-ctors-and-dtors.ll
Removed:
################################################################################
diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
index 2ac32293e4dba..0ab0d7d2e2b64 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -105,16 +105,18 @@ class GenericLLVMIRPlatform : public Platform {
/// llvm.global_ctors.
class GlobalCtorDtorScraper {
public:
-
GlobalCtorDtorScraper(GenericLLVMIRPlatformSupport &PS,
- StringRef InitFunctionPrefix)
- : PS(PS), InitFunctionPrefix(InitFunctionPrefix) {}
+ StringRef InitFunctionPrefix,
+ StringRef DeInitFunctionPrefix)
+ : PS(PS), InitFunctionPrefix(InitFunctionPrefix),
+ DeInitFunctionPrefix(DeInitFunctionPrefix) {}
Expected<ThreadSafeModule> operator()(ThreadSafeModule TSM,
MaterializationResponsibility &R);
private:
GenericLLVMIRPlatformSupport &PS;
StringRef InitFunctionPrefix;
+ StringRef DeInitFunctionPrefix;
};
/// Generic IR Platform Support
@@ -125,12 +127,14 @@ class GlobalCtorDtorScraper {
class GenericLLVMIRPlatformSupport : public LLJIT::PlatformSupport {
public:
GenericLLVMIRPlatformSupport(LLJIT &J)
- : J(J), InitFunctionPrefix(J.mangle("__orc_init_func.")) {
+ : J(J), InitFunctionPrefix(J.mangle("__orc_init_func.")),
+ DeInitFunctionPrefix(J.mangle("__orc_deinit_func.")) {
getExecutionSession().setPlatform(
std::make_unique<GenericLLVMIRPlatform>(*this));
- setInitTransform(J, GlobalCtorDtorScraper(*this, InitFunctionPrefix));
+ setInitTransform(J, GlobalCtorDtorScraper(*this, InitFunctionPrefix,
+ DeInitFunctionPrefix));
SymbolMap StdInterposes;
@@ -203,6 +207,8 @@ class GenericLLVMIRPlatformSupport : public LLJIT::PlatformSupport {
InitSymbols[&JD].add(KV.first,
SymbolLookupFlags::WeaklyReferencedSymbol);
InitFunctions[&JD].add(KV.first);
+ } else if ((*KV.first).startswith(DeInitFunctionPrefix)) {
+ DeInitFunctions[&JD].add(KV.first);
}
}
return Error::success();
@@ -256,6 +262,11 @@ class GenericLLVMIRPlatformSupport : public LLJIT::PlatformSupport {
});
}
+ void registerDeInitFunc(JITDylib &JD, SymbolStringPtr DeInitName) {
+ getExecutionSession().runSessionLocked(
+ [&]() { DeInitFunctions[&JD].add(DeInitName); });
+ }
+
private:
Expected<std::vector<JITTargetAddress>> getInitializers(JITDylib &JD) {
@@ -438,6 +449,7 @@ class GenericLLVMIRPlatformSupport : public LLJIT::PlatformSupport {
LLJIT &J;
std::string InitFunctionPrefix;
+ std::string DeInitFunctionPrefix;
DenseMap<JITDylib *, SymbolLookupSet> InitSymbols;
DenseMap<JITDylib *, SymbolLookupSet> InitFunctions;
DenseMap<JITDylib *, SymbolLookupSet> DeInitFunctions;
@@ -459,40 +471,63 @@ GlobalCtorDtorScraper::operator()(ThreadSafeModule TSM,
auto Err = TSM.withModuleDo([&](Module &M) -> Error {
auto &Ctx = M.getContext();
auto *GlobalCtors = M.getNamedGlobal("llvm.global_ctors");
-
- // If there's no llvm.global_ctors or it's just a decl then skip.
- if (!GlobalCtors || GlobalCtors->isDeclaration())
+ auto *GlobalDtors = M.getNamedGlobal("llvm.global_dtors");
+
+ auto RegisterCOrDtors = [&](GlobalVariable *GlobalCOrDtors,
+ bool isCtor) -> Error {
+ // If there's no llvm.global_c/dtor or it's just a decl then skip.
+ if (!GlobalCOrDtors || GlobalCOrDtors->isDeclaration())
+ return Error::success();
+ std::string InitOrDeInitFunctionName;
+ if (isCtor)
+ raw_string_ostream(InitOrDeInitFunctionName)
+ << InitFunctionPrefix << M.getModuleIdentifier();
+ else
+ raw_string_ostream(InitOrDeInitFunctionName)
+ << DeInitFunctionPrefix << M.getModuleIdentifier();
+
+ MangleAndInterner Mangle(PS.getExecutionSession(), M.getDataLayout());
+ auto InternedInitOrDeInitName = Mangle(InitOrDeInitFunctionName);
+ if (auto Err = R.defineMaterializing(
+ {{InternedInitOrDeInitName, JITSymbolFlags::Callable}}))
+ return Err;
+
+ auto *InitOrDeInitFunc = Function::Create(
+ FunctionType::get(Type::getVoidTy(Ctx), {}, false),
+ GlobalValue::ExternalLinkage, InitOrDeInitFunctionName, &M);
+ InitOrDeInitFunc->setVisibility(GlobalValue::HiddenVisibility);
+ std::vector<std::pair<Function *, unsigned>> InitsOrDeInits;
+ auto COrDtors = isCtor ? getConstructors(M) : getDestructors(M);
+
+ for (auto E : COrDtors)
+ InitsOrDeInits.push_back(std::make_pair(E.Func, E.Priority));
+ llvm::sort(InitsOrDeInits,
+ [](const std::pair<Function *, unsigned> &LHS,
+ const std::pair<Function *, unsigned> &RHS) {
+ return LHS.first < RHS.first;
+ });
+
+ auto *InitOrDeInitFuncEntryBlock =
+ BasicBlock::Create(Ctx, "entry", InitOrDeInitFunc);
+ IRBuilder<> IB(InitOrDeInitFuncEntryBlock);
+ for (auto &KV : InitsOrDeInits)
+ IB.CreateCall(KV.first);
+ IB.CreateRetVoid();
+
+ if (isCtor)
+ PS.registerInitFunc(R.getTargetJITDylib(), InternedInitOrDeInitName);
+ else
+ PS.registerDeInitFunc(R.getTargetJITDylib(), InternedInitOrDeInitName);
+
+ GlobalCOrDtors->eraseFromParent();
return Error::success();
+ };
- std::string InitFunctionName;
- raw_string_ostream(InitFunctionName)
- << InitFunctionPrefix << M.getModuleIdentifier();
-
- MangleAndInterner Mangle(PS.getExecutionSession(), M.getDataLayout());
- auto InternedName = Mangle(InitFunctionName);
- if (auto Err =
- R.defineMaterializing({{InternedName, JITSymbolFlags::Callable}}))
+ if (auto Err = RegisterCOrDtors(GlobalCtors, true))
+ return Err;
+ if (auto Err = RegisterCOrDtors(GlobalDtors, false))
return Err;
- auto *InitFunc =
- Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {}, false),
- GlobalValue::ExternalLinkage, InitFunctionName, &M);
- InitFunc->setVisibility(GlobalValue::HiddenVisibility);
- std::vector<std::pair<Function *, unsigned>> Inits;
- for (auto E : getConstructors(M))
- Inits.push_back(std::make_pair(E.Func, E.Priority));
- llvm::sort(Inits, [](const std::pair<Function *, unsigned> &LHS,
- const std::pair<Function *, unsigned> &RHS) {
- return LHS.first < RHS.first;
- });
- auto *EntryBlock = BasicBlock::Create(Ctx, "entry", InitFunc);
- IRBuilder<> IB(EntryBlock);
- for (auto &KV : Inits)
- IB.CreateCall(KV.first);
- IB.CreateRetVoid();
-
- PS.registerInitFunc(R.getTargetJITDylib(), InternedName);
- GlobalCtors->eraseFromParent();
return Error::success();
});
diff --git a/llvm/test/ExecutionEngine/OrcLazy/global-ctors-and-dtors.ll b/llvm/test/ExecutionEngine/OrcLazy/global-ctors-and-dtors.ll
index 67d392e71456a..3b1cf7f9ed63b 100644
--- a/llvm/test/ExecutionEngine/OrcLazy/global-ctors-and-dtors.ll
+++ b/llvm/test/ExecutionEngine/OrcLazy/global-ctors-and-dtors.ll
@@ -11,14 +11,17 @@
; CHECK: Hello
; CHECK: [ {{.*}}main{{.*}} ]
; CHECK: Goodbye
+; CHECK: Goodbye again
%class.Foo = type { i8 }
@f = global %class.Foo zeroinitializer, align 1
@__dso_handle = external global i8
- at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_hello.cpp, i8* null }]
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_hello.cpp, i8* null }]
+ at 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"
+ at str3 = global [14 x i8] c"Goodbye again\00"
define linkonce_odr void @_ZN3FooD1Ev(%class.Foo* nocapture readnone %this) unnamed_addr align 2 {
entry:
@@ -35,4 +38,10 @@ entry:
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))
+ ret void
+}
+
declare i32 @puts(i8* nocapture readonly)
More information about the llvm-commits
mailing list