[PATCH] D106925: COFF/ELF: Place llvm.global_ctors elements in llvm.used if comdat is used

Fangrui Song via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 27 17:05:25 PDT 2021


MaskRay created this revision.
MaskRay added reviewers: rnk, rsmith.
MaskRay requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

On ELF, an SHT_INIT_ARRAY outside a section group is a GC root. The current
codegen abuses SHT_INIT_ARRAY in a section group to mean a GC root.

On PE/COFF, the dynamic initialization for `__declspec(selectany)` in a comdat
can be garbage collected by `-opt:ref`.

Call `addUsedGlobal` for the two cases to fix the abuse/bug.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D106925

Files:
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/test/CodeGenCXX/microsoft-abi-template-static-init.cpp
  clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp


Index: clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
===================================================================
--- clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
+++ clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
@@ -1,5 +1,20 @@
 // 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
+
+#ifdef SELECTANY
+struct S {
+  S();
+  ~S();
+};
+
+int f();
+
+// ELF-SELECTANY: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @__cxx_global_var_init, i8* bitcast (i32* @selectany to i8*) }]
+// ELF-SELECTANY: @llvm.used = appending global [1 x i8*] [i8* bitcast (i32* @selectany to i8*)]
+int __declspec(selectany) selectany = f();
+
+#else
 
 // ALL: ; ModuleID
 
@@ -38,6 +53,9 @@
 
 // ALL:  { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp, i8* null }]
 
+/// llvm.used ensures SHT_INIT_ARRAY in a section group cannot be GCed.
+// ELF: @llvm.used = appending global [6 x i8*] [i8* bitcast (i32* @_ZN1AIsE1aE to i8*), i8* bitcast (i16* @_Z1xIsE to i8*), i8* bitcast (i32* @_ZN2ns1aIiE1iE to i8*), i8* bitcast (i32* @_ZN2ns1b1iIiEE to i8*), i8* bitcast (i32* @_ZN1AIvE1aE to i8*), i8* @_Z1xIcE]
+
 template int A<short>::a;  // Unordered
 int b = foo();
 int c = foo();
@@ -76,6 +94,8 @@
 }
 int *use_internal_a = &Internal<int>::a;
 
+#endif
+
 // ALL: define internal void @[[unordered1]](
 // ALL: call i32 @foo()
 // ALL: store {{.*}} @_ZN1AIsE1aE
Index: clang/test/CodeGenCXX/microsoft-abi-template-static-init.cpp
===================================================================
--- clang/test/CodeGenCXX/microsoft-abi-template-static-init.cpp
+++ clang/test/CodeGenCXX/microsoft-abi-template-static-init.cpp
@@ -88,5 +88,4 @@
 inline int zoo = foo();
 inline static int boo = foo();
 
-
-// CHECK: @llvm.used = appending global [7 x i8*] [i8* bitcast (i32* @"?x1 at selectany_init@@3HA" to i8*), i8* bitcast (i32* @"?x@?$A at H@explicit_template_instantiation@@2HA" to i8*), i8* bitcast (i32* @"?ioo@?$X_ at H@@2HA" to i8*), i8* getelementptr inbounds (%struct.A, %struct.A* @"?aoo at S1@@2UA@@A", i32 0, i32 0), i8* bitcast (i32* @"?zoo@@3HA" to i8*), i8* getelementptr inbounds (%struct.S, %struct.S* @"?s@?$ExportedTemplate at H@@2US@@A", i32 0, i32 0), i8* bitcast (i32* @"?x@?$A at H@implicit_template_instantiation@@2HA" to i8*)], section "llvm.metadata"
+// CHECK: @llvm.used = appending global [8 x i8*] [i8* bitcast (i32* @"?x at selectany_init@@3HA" to i8*), i8* bitcast (i32* @"?x1 at selectany_init@@3HA" to i8*), i8* bitcast (i32* @"?x@?$A at H@explicit_template_instantiation@@2HA" to i8*), i8* bitcast (i32* @"?ioo@?$X_ at H@@2HA" to i8*), i8* getelementptr inbounds (%struct.A, %struct.A* @"?aoo at S1@@2UA@@A", i32 0, i32 0), i8* bitcast (i32* @"?zoo@@3HA" to i8*), i8* getelementptr inbounds (%struct.S, %struct.S* @"?s@?$ExportedTemplate at H@@2US@@A", i32 0, i32 0), i8* bitcast (i32* @"?x@?$A at H@implicit_template_instantiation@@2HA" to i8*)], section "llvm.metadata"
Index: clang/lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- clang/lib/CodeGen/CGDeclCXX.cpp
+++ clang/lib/CodeGen/CGDeclCXX.cpp
@@ -555,7 +555,8 @@
                                           PrioritizedCXXGlobalInits.size());
     PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
   } else if (isTemplateInstantiation(D->getTemplateSpecializationKind()) ||
-             getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR) {
+             getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR ||
+             D->hasAttr<SelectAnyAttr>()) {
     // C++ [basic.start.init]p2:
     //   Definitions of explicitly specialized class template static data
     //   members have ordered initialization. Other class template static data
@@ -568,17 +569,18 @@
     // group with the global being initialized.  On most platforms, this is a
     // minor startup time optimization.  In the MS C++ ABI, there are no guard
     // variables, so this COMDAT key is required for correctness.
-    AddGlobalCtor(Fn, 65535, COMDATKey);
-    if (getTarget().getCXXABI().isMicrosoft() && COMDATKey) {
-      // In The MS C++, MS add template static data member in the linker
-      // drective.
-      addUsedGlobal(COMDATKey);
-    }
-  } else if (D->hasAttr<SelectAnyAttr>()) {
+    //
     // SelectAny globals will be comdat-folded. Put the initializer into a
     // COMDAT group associated with the global, so the initializers get folded
     // too.
+
     AddGlobalCtor(Fn, 65535, COMDATKey);
+    if (COMDATKey && (getTriple().isOSBinFormatELF() ||
+                      getTarget().getCXXABI().isMicrosoft())) {
+      // When COMDAT is used on ELF or in the MS C++ ABI, the key must be in
+      // llvm.used to prevent linker GC.
+      addUsedGlobal(COMDATKey);
+    }
   } else {
     I = DelayedCXXInitPosition.find(D); // Re-do lookup in case of re-hash.
     if (I == DelayedCXXInitPosition.end()) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D106925.362236.patch
Type: text/x-patch
Size: 5406 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20210728/f9a9514c/attachment-0001.bin>


More information about the cfe-commits mailing list