tingwang updated this revision to Diff 505720.
tingwang added a comment.

As verifier change and baseline test cases have been moved into 
https://reviews.llvm.org/D145767, update this patch.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125095/new/

https://reviews.llvm.org/D125095

Files:
  clang/lib/CodeGen/CGDecl.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/CodeGen/ItaniumCXXABI.cpp
  clang/test/CodeGen/PowerPC/aix-init-ref-null.cpp
  clang/test/CodeGen/PowerPC/aix-ref-static-var.cpp
  clang/test/CodeGenCXX/aix-static-init-debug-info.cpp
  clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp
  clang/test/CodeGenCXX/aix-static-init.cpp
  llvm/docs/LangRef.rst

Index: llvm/docs/LangRef.rst
===================================================================
--- llvm/docs/LangRef.rst
+++ llvm/docs/LangRef.rst
@@ -7330,11 +7330,12 @@
     @b = internal global i32 2, comdat $a, section "abc", !associated !0
     !0 = !{ptr @a}
 
-It does not have any effect on non-ELF targets. Non-ELF target may use
-``associated`` metadata for its own purpose. For example, on AIX XCOFF target,
-the ``associated`` metadata may indicate connection among static variables
-(static global variable, static class member etc.) and static init/term
-functions. This kind of association can be one-to-many.
+On AIX XCOFF target, the ``associated`` metadata indicates connection among
+static variables (static global variable, static class member etc.) and static
+init/term functions. This metadata lowers to ``.ref`` assembler pseudo-
+operation which prevents discarding of the functions in linker GC.
+
+It does not have any effect on other non-ELF targets.
 
 '``prof``' Metadata
 ^^^^^^^^^^^^^^^^^^^
Index: clang/test/CodeGenCXX/aix-static-init.cpp
===================================================================
--- clang/test/CodeGenCXX/aix-static-init.cpp
+++ clang/test/CodeGenCXX/aix-static-init.cpp
@@ -38,10 +38,10 @@
   }
 } // namespace test4
 
-// XFAIL-CHECK: @_ZN5test12t1E = global %"struct.test1::Test1" zeroinitializer, align {{[0-9]+}}, !associated ![[ASSOC0:[0-9]+]]
-// XFAIL-CHECK: @_ZN5test12t2E = global %"struct.test1::Test1" zeroinitializer, align {{[0-9]+}}, !associated ![[ASSOC0:[0-9]+]]
-// XFAIL-CHECK: @_ZN5test21xE = global i32 0, align {{[0-9]+}}, !associated ![[ASSOC1:[0-9]+]]
-// XFAIL-CHECK: @_ZN5test31tE = global %"struct.test3::Test3" undef, align {{[0-9]+}}, !associated ![[ASSOC0:[0-9]+]]
+// CHECK: @_ZN5test12t1E = global %"struct.test1::Test1" zeroinitializer, align {{[0-9]+}}, !associated ![[ASSOC0:[0-9]+]]
+// CHECK: @_ZN5test12t2E = global %"struct.test1::Test1" zeroinitializer, align {{[0-9]+}}, !associated ![[ASSOC0:[0-9]+]]
+// CHECK: @_ZN5test21xE = global i32 0, align {{[0-9]+}}, !associated ![[ASSOC1:[0-9]+]]
+// CHECK: @_ZN5test31tE = global %"struct.test3::Test3" undef, align {{[0-9]+}}, !associated ![[ASSOC0:[0-9]+]]
 // CHECK: @_ZGVZN5test41fEvE11staticLocal = internal global i64 0, align 8
 // CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I__, ptr null }]
 // CHECK: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__D_a, ptr null }]
@@ -53,8 +53,7 @@
 // CHECK:   ret void
 // CHECK: }
 
-// CHECK: define internal void @__dtor__ZN5test12t1E() [[ATTR:#[0-9]+]] {
-// XFAIL-CHECK: define internal void @__dtor__ZN5test12t1E() [[ATTR:#[0-9]+]] !associated ![[ASSOC2:[0-9]+]] {
+// CHECK: define internal void @__dtor__ZN5test12t1E() [[ATTR:#[0-9]+]] !associated ![[ASSOC2:[0-9]+]] {
 // CHECK: entry:
 // CHECK:   call void @_ZN5test15Test1D1Ev(ptr @_ZN5test12t1E)
 // CHECK:   ret void
@@ -85,8 +84,7 @@
 // CHECK:   ret void
 // CHECK: }
 
-// CHECK: define internal void @__dtor__ZN5test12t2E() [[ATTR:#[0-9]+]] {
-// XFAIL-CHECK: define internal void @__dtor__ZN5test12t2E() [[ATTR:#[0-9]+]] !associated ![[ASSOC2:[0-9]+]] {
+// CHECK: define internal void @__dtor__ZN5test12t2E() [[ATTR:#[0-9]+]] !associated ![[ASSOC2:[0-9]+]] {
 // CHECK: entry:
 // CHECK:   call void @_ZN5test15Test1D1Ev(ptr @_ZN5test12t2E)
 // CHECK:   ret void
@@ -120,8 +118,7 @@
 // CHECK:   ret void
 // CHECK: }
 
-// CHECK: define internal void @__dtor__ZN5test31tE() [[ATTR:#[0-9]+]] {
-// XFAIL-CHECK: define internal void @__dtor__ZN5test31tE() [[ATTR:#[0-9]+]] !associated ![[ASSOC2:[0-9]+]] {
+// CHECK: define internal void @__dtor__ZN5test31tE() [[ATTR:#[0-9]+]] !associated ![[ASSOC2:[0-9]+]] {
 // CHECK: entry:
 // CHECK:   call void @_ZN5test35Test3D1Ev(ptr @_ZN5test31tE)
 // CHECK:   ret void
@@ -162,8 +159,7 @@
 // CHECK:   ret void
 // CHECK: }
 
-// CHECK: define internal void @__dtor__ZZN5test41fEvE11staticLocal() [[ATTR:#[0-9]+]] {
-// XFAIL-CHECK: define internal void @__dtor__ZZN5test41fEvE11staticLocal() [[ATTR:#[0-9]+]] !associated ![[ASSOC2:[0-9]+]] {
+// CHECK: define internal void @__dtor__ZZN5test41fEvE11staticLocal() [[ATTR:#[0-9]+]] !associated ![[ASSOC2:[0-9]+]] {
 // CHECK: entry:
 // CHECK:   call void @_ZN5test45Test4D1Ev(ptr @_ZZN5test41fEvE11staticLocal)
 // CHECK:   ret void
@@ -201,6 +197,6 @@
 // CHECK:   ret void
 // CHECK: }
 
-// XFAIL-CHECK: ![[ASSOC0]] = !{ptr @{{_GLOBAL__sub_I__|_GLOBAL__D_a}}, ptr @{{_GLOBAL__sub_I__|_GLOBAL__D_a}}}
-// XFAIL-CHECK: ![[ASSOC1]] = !{ptr @_GLOBAL__sub_I__}
-// XFAIL-CHECK: ![[ASSOC2]] = !{ptr @_GLOBAL__D_a}
+// CHECK: ![[ASSOC0]] = !{ptr @{{_GLOBAL__sub_I__|_GLOBAL__D_a}}, ptr @{{_GLOBAL__sub_I__|_GLOBAL__D_a}}}
+// CHECK: ![[ASSOC1]] = !{ptr @_GLOBAL__sub_I__}
+// CHECK: ![[ASSOC2]] = !{ptr @_GLOBAL__D_a}
Index: clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp
===================================================================
--- clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp
+++ clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp
@@ -44,13 +44,13 @@
 A<int> A<int>::instance = bar();
 } // namespace test2
 
-// XFAIL-CHECK: @_ZN5test12t0E = global %"struct.test1::Test1" zeroinitializer, align {{[0-9]+}}, !associated ![[ASSOC0:[0-9]+]]
-// XFAIL-CHECK: @_ZN5test12t2E = linkonce_odr global %"struct.test1::Test1" zeroinitializer, align {{[0-9]+}}, !associated ![[ASSOC1:[0-9]+]]
+// CHECK: @_ZN5test12t0E = global %"struct.test1::Test1" zeroinitializer, align {{[0-9]+}}, !associated ![[ASSOC0:[0-9]+]]
+// CHECK: @_ZN5test12t2E = linkonce_odr global %"struct.test1::Test1" zeroinitializer, align {{[0-9]+}}, !associated ![[ASSOC1:[0-9]+]]
 // CHECK: @_ZGVN5test12t2E = linkonce_odr global i64 0, align 8
-// XFAIL-CHECK: @_ZN5test12t1IiEE = linkonce_odr global %"struct.test1::Test1" zeroinitializer, align {{[0-9]+}}, !associated ![[ASSOC2:[0-9]+]]
-// XFAIL-CHECK: @_ZN5test21AIvE8instanceE = weak_odr global %"struct.test2::A" zeroinitializer, align {{[0-9]+}}, !associated ![[ASSOC3:[0-9]+]]
+// CHECK: @_ZN5test12t1IiEE = linkonce_odr global %"struct.test1::Test1" zeroinitializer, align {{[0-9]+}}, !associated ![[ASSOC2:[0-9]+]]
+// CHECK: @_ZN5test21AIvE8instanceE = weak_odr global %"struct.test2::A" zeroinitializer, align {{[0-9]+}}, !associated ![[ASSOC3:[0-9]+]]
 // CHECK: @_ZGVN5test21AIvE8instanceE = weak_odr global i64 0, align 8
-// XFAIL-CHECK: @_ZN5test21AIiE8instanceE = global %"struct.test2::A.0" zeroinitializer, align {{[0-9]+}}, !associated ![[ASSOC0:[0-9]+]]
+// CHECK: @_ZN5test21AIiE8instanceE = global %"struct.test2::A.0" zeroinitializer, align {{[0-9]+}}, !associated ![[ASSOC0:[0-9]+]]
 // CHECK: @_ZGVN5test12t1IiEE = linkonce_odr global i64 0, align 8
 // CHECK: @llvm.global_ctors = appending global [4 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.1, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.2, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.4, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I__, ptr null }]
 // CHECK: @llvm.global_dtors = appending global [4 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__finalize__ZN5test12t2E, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__finalize__ZN5test21AIvE8instanceE, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__finalize__ZN5test12t1IiEE, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__D_a, ptr null }]
@@ -63,8 +63,7 @@
 // CHECK:   ret void
 // CHECK: }
 
-// CHECK: define internal void @__dtor__ZN5test12t0E() [[ATTR:#[0-9]+]] {
-// XFAIL-CHECK: define internal void @__dtor__ZN5test12t0E() [[ATTR:#[0-9]+]] !associated ![[ASSOC4:[0-9]+]] {
+// CHECK: define internal void @__dtor__ZN5test12t0E() [[ATTR:#[0-9]+]] !associated ![[ASSOC4:[0-9]+]] {
 // CHECK: entry:
 // CHECK:   call void @_ZN5test15Test1D1Ev(ptr @_ZN5test12t0E)
 // CHECK:   ret void
@@ -106,8 +105,7 @@
 // CHECK:   ret void
 // CHECK: }
 
-// CHECK: define internal void @__dtor__ZN5test12t2E() [[ATTR:#[0-9]+]] {
-// XFAIL-CHECK: define internal void @__dtor__ZN5test12t2E() [[ATTR:#[0-9]+]] !associated ![[ASSOC5:[0-9]+]] {
+// CHECK: define internal void @__dtor__ZN5test12t2E() [[ATTR:#[0-9]+]] !associated ![[ASSOC5:[0-9]+]] {
 // CHECK: entry:
 // CHECK:   call void @_ZN5test15Test1D1Ev(ptr @_ZN5test12t2E)
 // CHECK:   ret void
@@ -143,8 +141,7 @@
 // CHECK:   ret void
 // CHECK: }
 
-// CHECK: define internal void @__dtor__ZN5test21AIvE8instanceE() [[ATTR:#[0-9]+]] {
-// XFAIL-CHECK: define internal void @__dtor__ZN5test21AIvE8instanceE() [[ATTR:#[0-9]+]] !associated ![[ASSOC6:[0-9]+]] {
+// CHECK: define internal void @__dtor__ZN5test21AIvE8instanceE() [[ATTR:#[0-9]+]] !associated ![[ASSOC6:[0-9]+]] {
 // CHECK: entry:
 // CHECK:   call void @_ZN5test21AIvED1Ev(ptr @_ZN5test21AIvE8instanceE)
 // CHECK:   ret void
@@ -171,8 +168,7 @@
 // CHECK:   ret void
 // CHECK: }
 
-// CHECK: define internal void @__dtor__ZN5test21AIiE8instanceE() [[ATTR:#[0-9]+]] {
-// XFAIL-CHECK: define internal void @__dtor__ZN5test21AIiE8instanceE() [[ATTR:#[0-9]+]] !associated ![[ASSOC4:[0-9]+]] {
+// CHECK: define internal void @__dtor__ZN5test21AIiE8instanceE() [[ATTR:#[0-9]+]] !associated ![[ASSOC4:[0-9]+]] {
 // CHECK: entry:
 // CHECK:   call void @_ZN5test21AIiED1Ev(ptr @_ZN5test21AIiE8instanceE)
 // CHECK:   ret void
@@ -209,8 +205,7 @@
 // CHECK:   ret void
 // CHECK: }
 
-// CHECK: define internal void @__dtor__ZN5test12t1IiEE() [[ATTR:#[0-9]+]] {
-// XFAIL-CHECK: define internal void @__dtor__ZN5test12t1IiEE() [[ATTR:#[0-9]+]] !associated ![[ASSOC7:[0-9]+]] {
+// CHECK: define internal void @__dtor__ZN5test12t1IiEE() [[ATTR:#[0-9]+]] !associated ![[ASSOC7:[0-9]+]] {
 // CHECK: entry:
 // CHECK:   call void @_ZN5test15Test1D1Ev(ptr @_ZN5test12t1IiEE)
 // CHECK:   ret void
@@ -244,11 +239,11 @@
 // CHECK:   ret void
 // CHECK: }
 
-// XFAIL-CHECK: ![[ASSOC0]] = !{ptr @{{_GLOBAL__sub_I__|_GLOBAL__D_a}}, ptr @{{_GLOBAL__sub_I__|_GLOBAL__D_a}}}
-// XFAIL-CHECK: ![[ASSOC1]] = !{ptr @{{__cxx_global_var_init.1|__finalize__ZN5test12t2E}}, ptr @{{__cxx_global_var_init.1|__finalize__ZN5test12t2E}}}
-// XFAIL-CHECK: ![[ASSOC2]] = !{ptr @{{__cxx_global_var_init.4|__finalize__ZN5test12t1IiEE}}, ptr @{{__cxx_global_var_init.4|__finalize__ZN5test12t1IiEE}}}
-// XFAIL-CHECK: ![[ASSOC3]] = !{ptr @{{__finalize__ZN5test21AIvE8instanceE|__cxx_global_var_init.2}}, ptr @{{__finalize__ZN5test21AIvE8instanceE|__cxx_global_var_init.2}}}
-// XFAIL-CHECK: ![[ASSOC4]] = !{ptr @_GLOBAL__D_a}
-// XFAIL-CHECK: ![[ASSOC5]] = !{ptr @__finalize__ZN5test12t2E}
-// XFAIL-CHECK: ![[ASSOC6]] = !{ptr @__finalize__ZN5test21AIvE8instanceE}
-// XFAIL-CHECK: ![[ASSOC7]] = !{ptr @__finalize__ZN5test12t1IiEE}
+// CHECK: ![[ASSOC0]] = !{ptr @{{_GLOBAL__sub_I__|_GLOBAL__D_a}}, ptr @{{_GLOBAL__sub_I__|_GLOBAL__D_a}}}
+// CHECK: ![[ASSOC1]] = !{ptr @{{__cxx_global_var_init.1|__finalize__ZN5test12t2E}}, ptr @{{__cxx_global_var_init.1|__finalize__ZN5test12t2E}}}
+// CHECK: ![[ASSOC2]] = !{ptr @{{__cxx_global_var_init.4|__finalize__ZN5test12t1IiEE}}, ptr @{{__cxx_global_var_init.4|__finalize__ZN5test12t1IiEE}}}
+// CHECK: ![[ASSOC3]] = !{ptr @{{__finalize__ZN5test21AIvE8instanceE|__cxx_global_var_init.2}}, ptr @{{__finalize__ZN5test21AIvE8instanceE|__cxx_global_var_init.2}}}
+// CHECK: ![[ASSOC4]] = !{ptr @_GLOBAL__D_a}
+// CHECK: ![[ASSOC5]] = !{ptr @__finalize__ZN5test12t2E}
+// CHECK: ![[ASSOC6]] = !{ptr @__finalize__ZN5test21AIvE8instanceE}
+// CHECK: ![[ASSOC7]] = !{ptr @__finalize__ZN5test12t1IiEE}
Index: clang/test/CodeGenCXX/aix-static-init-debug-info.cpp
===================================================================
--- clang/test/CodeGenCXX/aix-static-init-debug-info.cpp
+++ clang/test/CodeGenCXX/aix-static-init-debug-info.cpp
@@ -13,7 +13,7 @@
 
 X v;
 
-// XFAIL-CHECK: @v = global %struct.X zeroinitializer, align {{[0-9]+}}, !dbg !{{[0-9]+}}, !associated ![[ASSOC1:[0-9]+]]
+// CHECK: @v = global %struct.X zeroinitializer, align {{[0-9]+}}, !dbg !{{[0-9]+}}, !associated ![[ASSOC1:[0-9]+]]
 
 // CHECK: define internal void @__cxx_global_var_init() [[ATTR:#[0-9]+]] !dbg ![[DBGVAR16:[0-9]+]] {
 // CHECK: entry:
@@ -22,8 +22,7 @@
 // CHECK:   ret void, !dbg ![[DBGVAR19]]
 // CHECK: }
 
-// CHECK: define internal void @__dtor_v() [[ATTR:#[0-9]+]] !dbg ![[DBGVAR20:[0-9]+]] {
-// XFAIL-CHECK: define internal void @__dtor_v() [[ATTR:#[0-9]+]] !dbg ![[DBGVAR20:[0-9]+]] !associated ![[ASSOC2:[0-9]+]] {
+// CHECK: define internal void @__dtor_v() [[ATTR:#[0-9]+]] !dbg ![[DBGVAR20:[0-9]+]] !associated ![[ASSOC2:[0-9]+]] {
 // CHECK: entry:
 // CHECK:   call void @_ZN1XD1Ev(ptr @v), !dbg ![[DBGVAR21b:[0-9]+]]
 // CHECK:   ret void, !dbg ![[DBGVAR21:[0-9]+]]
@@ -55,12 +54,12 @@
 // CHECK:   ret void
 // CHECK: }
 
-// XFAIL-CHECK: ![[ASSOC1]] = !{ptr @{{_GLOBAL__sub_I__|_GLOBAL__D_a}}, ptr @{{_GLOBAL__sub_I__|_GLOBAL__D_a}}}
+// CHECK: ![[ASSOC1]] = !{ptr @{{_GLOBAL__sub_I__|_GLOBAL__D_a}}, ptr @{{_GLOBAL__sub_I__|_GLOBAL__D_a}}}
 // CHECK: ![[DBGVAR16]] = distinct !DISubprogram(name: "__cxx_global_var_init", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, type: !{{[0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !{{[0-9]+}}, retainedNodes: !{{[0-9]+}})
 // CHECK: ![[DBGVAR19]] = !DILocation(line: 14, column: 3, scope: ![[DBGVAR16]])
 // CHECK: ![[DBGVAR19b]] = !DILocation(line: 0, scope: ![[DBGVAR16]])
 // CHECK: ![[DBGVAR20]] = distinct !DISubprogram(name: "__dtor_v", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 14, type: !{{[0-9]+}}, scopeLine: 14, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !{{[0-9]+}}, retainedNodes: !{{[0-9]+}})
-// XFAIL-CHECK: ![[ASSOC2]] = !{ptr @_GLOBAL__D_a}
+// CHECK: ![[ASSOC2]] = !{ptr @_GLOBAL__D_a}
 // CHECK: ![[DBGVAR21b]] = !DILocation(line: 0, scope: ![[DBGVAR20]])
 // CHECK: ![[DBGVAR21]] = !DILocation(line: 14, column: 3, scope: ![[DBGVAR20]])
 // CHECK: ![[DBGVAR22]] = distinct !DISubprogram(linkageName: "__finalize_v", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 14, type: !{{[0-9]+}}, scopeLine: 14, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !{{[0-9]+}}, retainedNodes: !{{[0-9]+}})
Index: clang/test/CodeGen/PowerPC/aix-ref-static-var.cpp
===================================================================
--- clang/test/CodeGen/PowerPC/aix-ref-static-var.cpp
+++ clang/test/CodeGen/PowerPC/aix-ref-static-var.cpp
@@ -7,8 +7,6 @@
   static S s;
 }
 
-// CHECK: @_ZZ1fvE1s = internal global %struct.S zeroinitializer, align [[ALIGN:[0-9]+]]
-// XFAIL-CHECK: @_ZZ1fvE1s = internal global %struct.S zeroinitializer, align [[ALIGN:[0-9]+]], !associated ![[ASSOC0:[0-9]+]]
-// CHECK: define internal void @__dtor__ZZ1fvE1s() [[ATTR:#[0-9]+]] {
-// XFAIL-CHECK: define internal void @__dtor__ZZ1fvE1s() [[ATTR:#[0-9]+]] !associated ![[ASSOC0:[0-9]+]] {
-// XFAIL-CHECK: ![[ASSOC0]] = !{ptr @_GLOBAL__D_a}
+// CHECK: @_ZZ1fvE1s = internal global %struct.S zeroinitializer, align [[ALIGN:[0-9]+]], !associated ![[ASSOC0:[0-9]+]]
+// CHECK: define internal void @__dtor__ZZ1fvE1s() [[ATTR:#[0-9]+]] !associated ![[ASSOC0:[0-9]+]] {
+// CHECK: ![[ASSOC0]] = !{ptr @_GLOBAL__D_a}
Index: clang/test/CodeGen/PowerPC/aix-init-ref-null.cpp
===================================================================
--- clang/test/CodeGen/PowerPC/aix-init-ref-null.cpp
+++ clang/test/CodeGen/PowerPC/aix-init-ref-null.cpp
@@ -18,7 +18,6 @@
 
 ext base_rview;
 
-// CHECK: @base_rview = local_unnamed_addr global %struct.ext zeroinitializer, align [[ALIGN:[0-9]+]]
-// XFAIL-CHECK: @base_rview = local_unnamed_addr global %struct.ext zeroinitializer, align [[ALIGN:[0-9]+]], !associated ![[ASSOC0:[0-9]+]]
+// CHECK: @base_rview = local_unnamed_addr global %struct.ext zeroinitializer, align [[ALIGN:[0-9]+]], !associated ![[ASSOC0:[0-9]+]]
 // CHECK: @llvm.global_ctors = appending global [0 x { i32, ptr, ptr }] zeroinitializer
-// XFAIL-CHECK: ![[ASSOC0]] = distinct !{null}
+// CHECK: ![[ASSOC0]] = distinct !{null}
Index: clang/lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -4821,6 +4821,11 @@
   llvm::Function *StermFinalizer = CGM.CreateGlobalInitOrCleanUpFunction(
       FTy, FnName.str(), FI, D.getLocation());
 
+  if (CGM.getTriple().isOSAIX() && D.getTLSKind() == VarDecl::TLS_None) {
+    CGM.addVarTermAssoc(&D, StermFinalizer);
+    CGM.addDtorTermAssoc(dtorStub, StermFinalizer);
+  }
+
   CodeGenFunction CGF(CGM);
 
   CGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, StermFinalizer, FI,
Index: clang/lib/CodeGen/CodeGenModule.h
===================================================================
--- clang/lib/CodeGen/CodeGenModule.h
+++ clang/lib/CodeGen/CodeGenModule.h
@@ -482,6 +482,15 @@
   /// init_priority attribute.
   SmallVector<GlobalInitData, 8> PrioritizedCXXGlobalInits;
 
+  /// To support `-bcdtors:csect` on AIX, we are adding .ref pseudo-op to
+  /// associate variable with init/term functions, and maintain the dependency
+  /// between dtor and term functions.
+  llvm::SmallVector<std::pair<const Decl *, llvm::Constant *>, 8>
+      VFInitTermAssoc;
+  llvm::SmallVector<std::pair<llvm::Function *, llvm::Constant *>, 8>
+      FFDtorTermAssoc;
+  llvm::DenseMap<const Decl *, llvm::Constant *> VarsWithInitTerm;
+
   /// Global destructor functions and arguments that need to run on termination.
   /// When UseSinitAndSterm is set, it instead contains sterm finalizer
   /// functions, which also run on unloading a shared library.
@@ -626,6 +635,42 @@
 
   const std::string &getModuleNameHash() const { return ModuleNameHash; }
 
+  /// As wrapper functions are generated, update .ref association point to the
+  /// wrapper
+  template <typename TA, typename TB, typename F>
+  void updateAssociatedFunc(
+      llvm::SmallVector<std::pair<TA, llvm::Constant *>, 8> &Assoc, TB &Funcs,
+      F &GetElem, llvm::Function *Fn) {
+    for (auto I = Assoc.begin(), E = Assoc.end(); I != E; ++I) {
+      bool Found = false;
+      for (unsigned i = 0, e = Funcs.size(); i != e; ++i)
+        if (I->second == GetElem(Funcs, i)) {
+          Found = true;
+          break;
+        }
+
+      if (Found)
+        *I = std::make_pair(I->first, Fn);
+    }
+  }
+
+  template <typename T, typename F>
+  void updateInitTermAssociatedFunc(T &Funcs, F &GetElem, llvm::Function *Fn) {
+    updateAssociatedFunc(VFInitTermAssoc, Funcs, GetElem, Fn);
+  }
+
+  void addVarTermAssoc(const Decl *Src, llvm::Constant *Target) {
+    VFInitTermAssoc.push_back(std::make_pair(Src, Target));
+  }
+
+  void addDtorTermAssoc(llvm::Function *Src, llvm::Constant *Target) {
+    FFDtorTermAssoc.push_back(std::make_pair(Src, Target));
+  }
+
+  void addVarWithInitTerm(const Decl *Var, llvm::Constant *C) {
+    VarsWithInitTerm[Var] = C;
+  }
+
   /// Return a reference to the configured OpenCL runtime.
   CGOpenCLRuntime &getOpenCLRuntime() {
     assert(OpenCLRuntime != nullptr);
@@ -1655,6 +1700,9 @@
   /// Call replaceAllUsesWith on all pairs in GlobalValReplacements.
   void applyGlobalValReplacements();
 
+  /// Generate associated metadata for static init/term
+  void EmitAssociatedMetadata();
+
   void checkAliases();
 
   std::map<int, llvm::TinyPtrVector<llvm::Function *>> DtorsUsingAtExit;
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -555,6 +555,9 @@
   EmitCXXGlobalCleanUpFunc();
   registerGlobalDtorsWithAtExit();
   EmitCXXThreadLocalInitFunc();
+  if (getTriple().isOSAIX()) {
+    EmitAssociatedMetadata();
+  }
   if (ObjCRuntime)
     if (llvm::Function *ObjCInitFunction = ObjCRuntime->ModuleInitFunction())
       AddGlobalCtor(ObjCInitFunction);
@@ -5079,8 +5082,11 @@
   maybeSetTrivialComdat(*D, *GV);
 
   // Emit the initializer function if necessary.
-  if (NeedsGlobalCtor || NeedsGlobalDtor)
+  if (NeedsGlobalCtor || NeedsGlobalDtor) {
     EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
+    if (getTriple().isOSAIX() && D->getTLSKind() == VarDecl::TLS_None)
+      addVarWithInitTerm(D, GV);
+  }
 
   SanitizerMD->reportGlobal(GV, *D, NeedsGlobalCtor);
 
Index: clang/lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- clang/lib/CodeGen/CGDeclCXX.cpp
+++ clang/lib/CodeGen/CGDeclCXX.cpp
@@ -539,6 +539,8 @@
   llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
       FTy, FnName.str(), getTypes().arrangeNullaryFunction(), D->getLocation());
 
+  if (getTriple().isOSAIX() && D->getTLSKind() == VarDecl::TLS_None)
+    addVarTermAssoc(D, Fn);
   auto *ISA = D->getAttr<InitSegAttr>();
   CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr,
                                                           PerformInit);
@@ -862,6 +864,10 @@
       for (; I < PrioE; ++I)
         LocalCXXGlobalInits.push_back(I->second);
 
+      if (getTriple().isOSAIX()) {
+        auto GetElem = [](auto &V, unsigned i) { return V[i]; };
+        updateAssociatedFunc(VFInitTermAssoc, LocalCXXGlobalInits, GetElem, Fn);
+      }
       CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, LocalCXXGlobalInits);
       AddGlobalCtor(Fn, Priority);
     }
@@ -894,6 +900,10 @@
         llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())),
         FI);
 
+  if (getTriple().isOSAIX()) {
+    auto GetElem = [](auto &V, unsigned i) { return V[i]; };
+    updateAssociatedFunc(VFInitTermAssoc, ModuleInits, GetElem, Fn);
+  }
   CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, ModuleInits);
   AddGlobalCtor(Fn);
 
@@ -920,6 +930,39 @@
   ModuleInits.clear();
 }
 
+void CodeGenModule::EmitAssociatedMetadata() {
+  auto AddMeta = [this](auto &Assoc, auto &LA) {
+    for (auto I = Assoc.begin(), E = Assoc.end(); I != E;) {
+      llvm::SmallVector<llvm::Metadata *, 2> Metas;
+      auto Src = I->first;
+
+      for (; I < E && I->first == Src; ++I)
+        Metas.push_back(llvm::ValueAsMetadata::get(I->second));
+
+      llvm::MDNode *MD = llvm::MDNode::get(getLLVMContext(), Metas);
+      if (auto *GO = dyn_cast<llvm::GlobalObject>(LA(Src)))
+        GO->addMetadata(llvm::LLVMContext::MD_associated, *MD);
+    }
+  };
+  // Generate dtor to term .ref
+  auto LM1 = [](llvm::Function *C) { return C; };
+  AddMeta(FFDtorTermAssoc, LM1);
+
+  // Generate var to init/term .ref
+  auto LM2 = [this](const Decl *C) {
+    assert((VarsWithInitTerm.find(C) != VarsWithInitTerm.end()) &&
+           "EmitAssociatedMetadata does not have var info");
+    return VarsWithInitTerm[C];
+  };
+  llvm::array_pod_sort(VFInitTermAssoc.begin(), VFInitTermAssoc.end());
+  AddMeta(VFInitTermAssoc, LM2);
+
+  // Cleanup
+  VFInitTermAssoc.clear();
+  FFDtorTermAssoc.clear();
+  VarsWithInitTerm.clear();
+}
+
 void CodeGenModule::EmitCXXGlobalCleanUpFunc() {
   if (CXXGlobalDtorsOrStermFinalizers.empty() &&
       PrioritizedCXXStermFinalizers.empty())
@@ -955,6 +998,13 @@
                                              DtorFn.getCallee(), nullptr);
       }
 
+      if (getTriple().isOSAIX()) {
+        auto GetElem = [](auto &V, unsigned i) { return std::get<1>(V[i]); };
+        updateAssociatedFunc(VFInitTermAssoc, LocalCXXStermFinalizers, GetElem,
+                             Fn);
+        updateAssociatedFunc(FFDtorTermAssoc, LocalCXXStermFinalizers, GetElem,
+                             Fn);
+      }
       CodeGenFunction(*this).GenerateCXXGlobalCleanUpFunc(
           Fn, LocalCXXStermFinalizers);
       AddGlobalDtor(Fn, Priority);
@@ -969,6 +1019,13 @@
   llvm::Function *Fn =
       CreateGlobalInitOrCleanUpFunction(FTy, "_GLOBAL__D_a", FI);
 
+  if (getTriple().isOSAIX()) {
+    auto GetElem = [](auto &V, unsigned i) { return std::get<1>(V[i]); };
+    updateAssociatedFunc(VFInitTermAssoc, CXXGlobalDtorsOrStermFinalizers,
+                         GetElem, Fn);
+    updateAssociatedFunc(FFDtorTermAssoc, CXXGlobalDtorsOrStermFinalizers,
+                         GetElem, Fn);
+  }
   CodeGenFunction(*this).GenerateCXXGlobalCleanUpFunc(
       Fn, CXXGlobalDtorsOrStermFinalizers);
   AddGlobalDtor(Fn);
Index: clang/lib/CodeGen/CGDecl.cpp
===================================================================
--- clang/lib/CodeGen/CGDecl.cpp
+++ clang/lib/CodeGen/CGDecl.cpp
@@ -442,8 +442,11 @@
   bool isCudaSharedVar = getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
                          D.hasAttr<CUDASharedAttr>();
   // If this value has an initializer, emit it.
-  if (D.getInit() && !isCudaSharedVar)
+  if (D.getInit() && !isCudaSharedVar) {
     var = AddInitializerToStaticVarDecl(D, var);
+    if (CGM.getTriple().isOSAIX() && D.getTLSKind() == VarDecl::TLS_None)
+      CGM.addVarWithInitTerm(&D, var);
+  }
 
   var->setAlignment(alignment.getAsAlign());
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to