-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang][CodeGen] Global constructors/destructors are globals #93914
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…_globals_are_still_globals
@llvm/pr-subscribers-clang-codegen Author: Alex Voicu (AlexVlx) ChangesCurrently the payload for global ctors/dtors is passed as an unqualified pointer, which relies on the target being reasonable regarding what AS 0 means, and also is overly conservative. This change correctly places the payload in the target's global AS, and does the same thing for the Full diff: https://github.com/llvm/llvm-project/pull/93914.diff 9 Files Affected:
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index c2314c3a57d33..b59c5c52783e9 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2047,9 +2047,9 @@ void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
llvm::Type *CtorPFTy = llvm::PointerType::get(CtorFTy,
TheModule.getDataLayout().getProgramAddressSpace());
- // Get the type of a ctor entry, { i32, void ()*, i8* }.
- llvm::StructType *CtorStructTy = llvm::StructType::get(
- Int32Ty, CtorPFTy, VoidPtrTy);
+ // Get the type of a ctor entry, { i32, program void ()*, global i8* }.
+ llvm::StructType *CtorStructTy =
+ llvm::StructType::get(Int32Ty, CtorPFTy, GlobalsInt8PtrTy);
// Construct the constructor and destructor arrays.
ConstantInitBuilder builder(*this);
@@ -2061,14 +2061,15 @@ void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
if (I.AssociatedData)
ctor.add(I.AssociatedData);
else
- ctor.addNullPointer(VoidPtrTy);
+ ctor.addNullPointer(GlobalsInt8PtrTy);
ctor.finishAndAddTo(ctors);
}
auto list =
ctors.finishAndCreateGlobal(GlobalName, getPointerAlign(),
/*constant*/ false,
- llvm::GlobalValue::AppendingLinkage);
+ llvm::GlobalValue::AppendingLinkage,
+ GlobalsInt8PtrTy->getAddressSpace());
// The LTO linker doesn't seem to like it when we set an alignment
// on appending variables. Take it off as a workaround.
diff --git a/clang/test/CodeGen/asan-constructor.c b/clang/test/CodeGen/asan-constructor.c
index 762bf0778565d..41212d45a5c63 100644
--- a/clang/test/CodeGen/asan-constructor.c
+++ b/clang/test/CodeGen/asan-constructor.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple wasm32-unknown-emscripten -fsanitize=address -emit-llvm -o - %s | FileCheck %s --check-prefix=EMSCRIPTEN
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fsanitize=address -emit-llvm -o - %s | FileCheck %s --check-prefix=GLOBALAS
// CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @asan.module_ctor, ptr null }]
// EMSCRIPTEN: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 50, ptr @asan.module_ctor, ptr null }]
+// GLOBALAS: @llvm.global_ctors = appending addrspace(1) global [1 x { i32, ptr, ptr addrspace(1) }] [{ i32, ptr, ptr addrspace(1) } { i32 1, ptr @asan.module_ctor, ptr addrspace(1) null }]
diff --git a/clang/test/CodeGen/attr-retain.c b/clang/test/CodeGen/attr-retain.c
index fc41be76f9d0a..6a9869c00392d 100644
--- a/clang/test/CodeGen/attr-retain.c
+++ b/clang/test/CodeGen/attr-retain.c
@@ -11,7 +11,6 @@
// CHECK: @llvm.used = appending global [8 x ptr] [ptr @c0, ptr @foo.l0, ptr @f0, ptr @f2, ptr @g0, ptr @g1, ptr @g3, ptr @g4], section "llvm.metadata"
// CHECK: @llvm.compiler.used = appending global [3 x ptr] [ptr @f2, ptr @g3, ptr @g4], section "llvm.metadata"
-
const int c0 __attribute__((retain)) = 42;
void foo(void) {
diff --git a/clang/test/CodeGenCUDA/llvm-used.cu b/clang/test/CodeGenCUDA/llvm-used.cu
index c39111dd48036..9f22dabde3c2d 100644
--- a/clang/test/CodeGenCUDA/llvm-used.cu
+++ b/clang/test/CodeGenCUDA/llvm-used.cu
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -fcuda-is-device -triple nvptx64-unknown-unknown | FileCheck %s
-// Make sure we emit the proper addrspacecast for llvm.used. PR22383 exposed an
+// Make sure we emit the proper addrspacecast for llvm.used. PR22383 exposed an
// issue where we were generating a bitcast instead of an addrspacecast.
// CHECK: @llvm.compiler.used = appending global [1 x ptr] [ptr addrspacecast (ptr addrspace(1) @a to ptr)], section "llvm.metadata"
diff --git a/clang/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/clang/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
index aa2f078a5fb0c..2e22192e8b388 100644
--- a/clang/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/clang/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -90,7 +90,8 @@ std::initializer_list<int> thread_local x = {1, 2, 3, 4};
// AMDGCN: @[[REFTMP1:.*]] = private addrspace(4) constant [2 x i32] [i32 42, i32 43], align 4
// AMDGCN: @[[REFTMP2:.*]] = private addrspace(4) constant [3 x %{{.*}}] [%{{.*}} { i32 1 }, %{{.*}} { i32 2 }, %{{.*}} { i32 3 }], align 4
-// CHECK: appending global
+// X86: appending global
+// AMDGCN: appending addrspace(1) global
// thread_local initializer:
// X86-LABEL: define internal void @__cxx_global_var_init
diff --git a/clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp b/clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
index 46c4c4d391769..58055130cd708 100644
--- a/clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
+++ b/clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
@@ -1,6 +1,8 @@
// RUN: %clang_cc1 %s -std=c++1y -triple=x86_64-pc-linux -emit-llvm -o - | FileCheck --check-prefix=ELF --check-prefix=ALL %s
// RUN: %clang_cc1 %s -std=c++1y -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck --check-prefix=MACHO --check-prefix=ALL %s
// RUN: %clang_cc1 %s -std=c++1y -triple=x86_64-pc-linux -emit-llvm -fdeclspec -DSELECTANY -o - | FileCheck --check-prefix=ELF-SELECTANY %s
+// RUN: %clang_cc1 %s -std=c++1y -triple=amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck --check-prefix=GLOBALAS-ELF %s
+// RUN: %clang_cc1 %s -std=c++1y -triple=amdgcn-amd-amdhsa -emit-llvm -fdeclspec -DSELECTANY -o - | FileCheck --check-prefix=GLOBALAS-ELF-SELECTANY %s
#ifdef SELECTANY
struct S {
@@ -12,6 +14,7 @@ int f();
// ELF-SELECTANY: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init, ptr @selectany }]
// ELF-SELECTANY: @llvm.used = appending global [1 x ptr] [ptr @selectany]
+// GLOBALAS-ELF-SELECTANY: @llvm.global_ctors = appending addrspace(1) global [1 x { i32, ptr, ptr addrspace(1) }] [{ i32, ptr, ptr addrspace(1) } { i32 65535, ptr @__cxx_global_var_init, ptr addrspace(1) @selectany }]
int __declspec(selectany) selectany = f();
#else
@@ -30,6 +33,7 @@ template<> int A<char>::a;
template<> int A<bool>::a = 10;
// ALL: @llvm.global_ctors = appending global [16 x { i32, ptr, ptr }]
+// GLOBALAS-ELF: @llvm.global_ctors = appending addrspace(1) global [16 x { i32, ptr, ptr addrspace(1) }]
// ELF: [{ i32, ptr, ptr } { i32 65535, ptr @[[unordered:[^,]*]], ptr @_ZN1AIsE1aE },
// MACHO: [{ i32, ptr, ptr } { i32 65535, ptr @[[unordered:[^,]*]], ptr null },
@@ -73,7 +77,7 @@ template<> int A<bool>::a = 10;
// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered22:[^,]*]], ptr null },
// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered21:[^,]*]], ptr @_ZN4Fib2ILi5EE1aE },
-// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered21:[^,]*]], ptr null },
+// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered21:[^,]*]], ptr null },
// ALL: { i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp, ptr null }]
diff --git a/clang/test/OpenMP/amdgcn_target_global_constructor.cpp b/clang/test/OpenMP/amdgcn_target_global_constructor.cpp
index 80a5067b357a2..fe414b59588c0 100644
--- a/clang/test/OpenMP/amdgcn_target_global_constructor.cpp
+++ b/clang/test/OpenMP/amdgcn_target_global_constructor.cpp
@@ -21,8 +21,8 @@ S A;
#endif
//.
-// CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_amdgcn_target_global_constructor.cpp, ptr null }]
-// CHECK: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__dtor_A, ptr null }]
+// CHECK: @llvm.global_ctors = appending addrspace(1) global [1 x { i32, ptr, ptr addrspace(1) }] [{ i32, ptr, ptr addrspace(1) } { i32 65535, ptr @_GLOBAL__sub_I_amdgcn_target_global_constructor.cpp, ptr addrspace(1) null }]
+// CHECK: @llvm.global_dtors = appending addrspace(1) global [1 x { i32, ptr, ptr addrspace(1) }] [{ i32, ptr, ptr addrspace(1) } { i32 65535, ptr @__dtor_A, ptr addrspace(1) null }]
//.
// CHECK-LABEL: define {{[^@]+}}@__cxx_global_var_init
// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
index 122279160cc7e..7151cc869bc95 100644
--- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp
+++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
@@ -30,6 +30,8 @@ static void appendToGlobalArray(StringRef ArrayName, Module &M, Function *F,
int Priority, Constant *Data) {
IRBuilder<> IRB(M.getContext());
FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false);
+ PointerType *GlobalsInt8PtrTy = PointerType::get(
+ M.getContext(), M.getDataLayout().getDefaultGlobalsAddressSpace());
// Get the current set of static global constructors and add the new ctor
// to the list.
@@ -47,15 +49,15 @@ static void appendToGlobalArray(StringRef ArrayName, Module &M, Function *F,
} else {
EltTy = StructType::get(IRB.getInt32Ty(),
PointerType::get(FnTy, F->getAddressSpace()),
- IRB.getPtrTy());
+ GlobalsInt8PtrTy);
}
// Build a 3 field global_ctor entry. We don't take a comdat key.
Constant *CSVals[3];
CSVals[0] = IRB.getInt32(Priority);
CSVals[1] = F;
- CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, IRB.getPtrTy())
- : Constant::getNullValue(IRB.getPtrTy());
+ CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, GlobalsInt8PtrTy)
+ : Constant::getNullValue(GlobalsInt8PtrTy);
Constant *RuntimeCtorInit =
ConstantStruct::get(EltTy, ArrayRef(CSVals, EltTy->getNumElements()));
@@ -437,12 +439,9 @@ bool llvm::lowerGlobalIFuncUsersAsGlobalCtor(
InitBuilder.CreateRetVoid();
- PointerType *ConstantDataTy = PointerType::get(Ctx, 0);
-
// TODO: Is this the right priority? Probably should be before any other
// constructors?
const int Priority = 10;
- appendToGlobalCtors(M, NewCtor, Priority,
- ConstantPointerNull::get(ConstantDataTy));
+ appendToGlobalCtors(M, NewCtor, Priority, nullptr);
return UnhandledUsers;
}
diff --git a/llvm/test/tools/llvm-reduce/remove-ifunc-program-addrspace.ll b/llvm/test/tools/llvm-reduce/remove-ifunc-program-addrspace.ll
index e275d61764b21..7ddab0b6a815e 100644
--- a/llvm/test/tools/llvm-reduce/remove-ifunc-program-addrspace.ll
+++ b/llvm/test/tools/llvm-reduce/remove-ifunc-program-addrspace.ll
@@ -15,8 +15,8 @@ define void @existing_ctor() addrspace(1) {
; CHECK-FINAL: [[TABLE:@[0-9]+]] = internal addrspace(2) global [6 x ptr addrspace(1)] poison, align 8
-; CHECK-FINAL: @llvm.global_ctors = appending addrspace(2) global [2 x { i32, ptr addrspace(1), ptr }] [{ i32, ptr addrspace(1), ptr } { i32 0, ptr addrspace(1) @existing_ctor, ptr null }, { i32, ptr addrspace(1), ptr } { i32 10, ptr addrspace(1) [[TABLE_CTOR:@[0-9]+]], ptr null }]
-@llvm.global_ctors = appending global [1 x { i32, ptr addrspace(1), ptr }] [{ i32, ptr addrspace(1), ptr } { i32 0, ptr addrspace(1) @existing_ctor, ptr null }]
+; CHECK-FINAL: @llvm.global_ctors = appending addrspace(2) global [2 x { i32, ptr addrspace(1), ptr addrspace(2) }] [{ i32, ptr addrspace(1), ptr addrspace(2) } { i32 0, ptr addrspace(1) @existing_ctor, ptr addrspace(2) null }, { i32, ptr addrspace(1), ptr addrspace(2) } { i32 10, ptr addrspace(1) [[TABLE_CTOR:@[0-9]+]], ptr addrspace(2) null }]
+@llvm.global_ctors = appending global [1 x { i32, ptr addrspace(1), ptr addrspace(2) }] [{ i32, ptr addrspace(1), ptr addrspace(2) } { i32 0, ptr addrspace(1) @existing_ctor, ptr addrspace(2) null }]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
llvm datalayout defines P - program addr space for functions https://llvm.org/docs/LangRef.html#langref-datalayout should we use P for llvm.global_ctors instead of G? |
The third argument here is like for llvm.used, it's a way to associate the entry with a global or function. If the corresponding global or function is omitted from the output then the entry will be removed. It isn't used for anything at run time. So I think there should be a consistent story between llvm.used and llvm.global_[cd]tors. |
I briefly skimmed the codegen and as far as I could tell an addrspacecast constant expression in global_ctors won't do the right thing, we probably should fix that too |
I'm not sure we can do that for anything but the ctor function (where it's already used), since, per langref, the third element can be either a global or a function, and whilst all functions are globals not all globals are functions (the distinction is arbitrary for many targets and, as @jrtc27 says, it's just lifetime ensuring hook, but we should probably stick with doing what we claim to do in the public documents). |
IMHO, and I could be wrong, the key challenge that we have both here and re Emitting these unconditionally as unqualified |
I think this is the correct way to handle it. Also we'll need a few stripPointerCasts added somewhere |
+1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this redundant with #93601?
I don't think so, they're paired, this is an offshoot of that. |
Currently the payload for global ctors/dtors is passed as an unqualified pointer, which relies on the target being reasonable regarding what AS 0 means, and also is overly conservative. This change correctly places the payload in the target's global AS, and does the same thing for the
global_ctors
/global_dtors
arrays.