tingwang updated this revision to Diff 504952.
tingwang added a reviewer: PowerPC.
tingwang added a comment.
Herald added subscribers: cfe-commits, jdoerfert.
Herald added a project: clang.

Address comments:
(1) Add test case to show how associated metadata will be used on AIX 
(currently not supported, marked with XFAIL).
(2) Add langref changes to explain.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145767

Files:
  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
  llvm/lib/IR/Verifier.cpp

Index: llvm/lib/IR/Verifier.cpp
===================================================================
--- llvm/lib/IR/Verifier.cpp
+++ llvm/lib/IR/Verifier.cpp
@@ -663,22 +663,29 @@
             GO->getMetadata(LLVMContext::MD_associated)) {
       Check(Associated->getNumOperands() == 1,
             "associated metadata must have one operand", &GV, Associated);
-      const Metadata *Op = Associated->getOperand(0).get();
-      Check(Op, "associated metadata must have a global value", GO, Associated);
-
-      const auto *VM = dyn_cast_or_null<ValueAsMetadata>(Op);
-      Check(VM, "associated metadata must be ValueAsMetadata", GO, Associated);
-      if (VM) {
-        Check(isa<PointerType>(VM->getValue()->getType()),
-              "associated value must be pointer typed", GV, Associated);
-
-        const Value *Stripped = VM->getValue()->stripPointerCastsAndAliases();
-        Check(isa<GlobalObject>(Stripped) || isa<Constant>(Stripped),
-              "associated metadata must point to a GlobalObject", GO, Stripped);
-        Check(Stripped != GO,
-              "global values should not associate to themselves", GO,
+      auto CheckAssocOperand = [this, &GV, GO, Associated](const Metadata *Op) {
+        Check(Op, "associated metadata must have a global value", GO,
               Associated);
-      }
+
+        const auto *VM = dyn_cast_or_null<ValueAsMetadata>(Op);
+        Check(VM, "associated metadata must be ValueAsMetadata", GO,
+              Associated);
+        if (VM) {
+          Check(isa<PointerType>(VM->getValue()->getType()),
+                "associated value must be pointer typed", GV, Associated);
+
+          const Value *Stripped = VM->getValue()->stripPointerCastsAndAliases();
+          Check(isa<GlobalObject>(Stripped) || isa<Constant>(Stripped),
+                "associated metadata must point to a GlobalObject", GO,
+                Stripped);
+          Check(Stripped != GO,
+                "global values should not associate to themselves", GO,
+                Associated);
+        }
+      };
+
+      for (unsigned i = 0, e = Associated->getNumOperands(); i != e; ++i)
+        CheckAssocOperand(Associated->getOperand(i).get());
     }
   }
   Check(!GV.hasAppendingLinkage() || isa<GlobalVariable>(GV),
Index: llvm/docs/LangRef.rst
===================================================================
--- llvm/docs/LangRef.rst
+++ llvm/docs/LangRef.rst
@@ -7318,8 +7318,6 @@
 linker-defined encapsulation symbols ``__start_<section_name>`` and
 ``__stop_<section_name>``.
 
-It does not have any effect on non-ELF targets.
-
 Example:
 
 .. code-block:: text
@@ -7329,6 +7327,11 @@
     @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.
 
 '``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,6 +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: @_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 }]
@@ -50,6 +54,7 @@
 // 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: entry:
 // CHECK:   call void @_ZN5test15Test1D1Ev(ptr @_ZN5test12t1E)
 // CHECK:   ret void
@@ -81,6 +86,7 @@
 // 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: entry:
 // CHECK:   call void @_ZN5test15Test1D1Ev(ptr @_ZN5test12t2E)
 // CHECK:   ret void
@@ -115,6 +121,7 @@
 // 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: entry:
 // CHECK:   call void @_ZN5test35Test3D1Ev(ptr @_ZN5test31tE)
 // CHECK:   ret void
@@ -156,6 +163,7 @@
 // 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: entry:
 // CHECK:   call void @_ZN5test45Test4D1Ev(ptr @_ZZN5test41fEvE11staticLocal)
 // CHECK:   ret void
@@ -192,3 +200,7 @@
 // CHECK:   call void @__finalize__ZN5test12t1E()
 // 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}
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,8 +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: @_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: @_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: @_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 }]
@@ -59,6 +64,7 @@
 // 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: entry:
 // CHECK:   call void @_ZN5test15Test1D1Ev(ptr @_ZN5test12t0E)
 // CHECK:   ret void
@@ -101,6 +107,7 @@
 // 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: entry:
 // CHECK:   call void @_ZN5test15Test1D1Ev(ptr @_ZN5test12t2E)
 // CHECK:   ret void
@@ -137,6 +144,7 @@
 // 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: entry:
 // CHECK:   call void @_ZN5test21AIvED1Ev(ptr @_ZN5test21AIvE8instanceE)
 // CHECK:   ret void
@@ -164,6 +172,7 @@
 // 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: entry:
 // CHECK:   call void @_ZN5test21AIiED1Ev(ptr @_ZN5test21AIiE8instanceE)
 // CHECK:   ret void
@@ -201,6 +210,7 @@
 // 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: entry:
 // CHECK:   call void @_ZN5test15Test1D1Ev(ptr @_ZN5test12t1IiEE)
 // CHECK:   ret void
@@ -233,3 +243,12 @@
 // CHECK:   call void @__finalize__ZN5test12t0E()
 // 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}
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,6 +13,8 @@
 
 X v;
 
+// XFAIL-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:
 // CHECK:   call void @_ZN1XC1Ev(ptr {{[^,]*}} @v), !dbg ![[DBGVAR19:[0-9]+]]
@@ -21,6 +23,7 @@
 // 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: entry:
 // CHECK:   call void @_ZN1XD1Ev(ptr @v), !dbg ![[DBGVAR21b:[0-9]+]]
 // CHECK:   ret void, !dbg ![[DBGVAR21:[0-9]+]]
@@ -52,10 +55,12 @@
 // CHECK:   ret void
 // CHECK: }
 
+// XFAIL-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: ![[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
===================================================================
--- /dev/null
+++ clang/test/CodeGen/PowerPC/aix-ref-static-var.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -emit-llvm -x c++ < %s | FileCheck %s
+// XFAIL: *
+// This function should fail until .ref is support on AIX.
+
+struct S {
+  ~S();
+};
+void f() {
+  static S s;
+}
+
+// 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
===================================================================
--- /dev/null
+++ clang/test/CodeGen/PowerPC/aix-init-ref-null.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -emit-llvm -O3 -x c++ < %s | FileCheck %s
+// XFAIL: *
+// This function should fail until .ref is support on AIX.
+
+// Global Ctors present at -O0, removed by -O3
+typedef enum {
+  A, B
+} E;
+
+class base {
+protected:
+  base(E v): m(v) { }
+private:
+  E m;
+};
+
+struct ext: base {
+      ext():base(A){}
+};
+
+ext base_rview;
+
+// 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
+// CHECK: ![[ASSOC0]] = distinct !{null}
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to