diff --git a/clang/test/CodeGen/PowerPC/aix-init-ref-null.cpp b/clang/test/CodeGen/PowerPC/aix-init-ref-null.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/PowerPC/aix-init-ref-null.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -emit-llvm -O3 -x c++ < %s | FileCheck %s + +// 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]+]] +// XFAIL-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} diff --git a/clang/test/CodeGen/PowerPC/aix-ref-static-var.cpp b/clang/test/CodeGen/PowerPC/aix-ref-static-var.cpp new file mode 100644 --- /dev/null +++ b/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 + +struct S { + ~S(); +}; +void f() { + 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} diff --git a/clang/test/CodeGenCXX/aix-static-init-debug-info.cpp b/clang/test/CodeGenCXX/aix-static-init-debug-info.cpp --- a/clang/test/CodeGenCXX/aix-static-init-debug-info.cpp +++ b/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]+}}) diff --git a/clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp b/clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp --- a/clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp +++ b/clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp @@ -44,8 +44,13 @@ A A::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} diff --git a/clang/test/CodeGenCXX/aix-static-init.cpp b/clang/test/CodeGenCXX/aix-static-init.cpp --- a/clang/test/CodeGenCXX/aix-static-init.cpp +++ b/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} diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -7321,8 +7321,6 @@ linker-defined encapsulation symbols ``__start_`` and ``__stop_``. -It does not have any effect on non-ELF targets. - Example: .. code-block:: text @@ -7332,6 +7330,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 ^^^^^^^^^^^^^^^^^^^ diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -661,24 +661,38 @@ if (const MDNode *Associated = GO->getMetadata(LLVMContext::MD_associated)) { - Check(Associated->getNumOperands() == 1, + // Associated metadata is used by AIX to indicate connection among static + // variables and static init/term functions, there can be multiple + // operands. + Check(Associated->getNumOperands() == 1 || + (TT.isOSAIX() && Associated->getNumOperands() > 0), "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(Op); - Check(VM, "associated metadata must be ValueAsMetadata", GO, Associated); - if (VM) { - Check(isa(VM->getValue()->getType()), - "associated value must be pointer typed", GV, Associated); - - const Value *Stripped = VM->getValue()->stripPointerCastsAndAliases(); - Check(isa(Stripped) || isa(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 || TT.isOSAIX(), + "associated metadata must have a global value", GO, Associated); + // On AIX associated global value could be optimized away. + if (!Op) + return; + + const auto *VM = dyn_cast_or_null(Op); + Check(VM, "associated metadata must be ValueAsMetadata", GO, Associated); - } + if (VM) { + Check(isa(VM->getValue()->getType()), + "associated value must be pointer typed", GV, Associated); + + const Value *Stripped = VM->getValue()->stripPointerCastsAndAliases(); + Check(isa(Stripped) || isa(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(GV), diff --git a/llvm/test/Assembler/associated-metadata-aix-xcoff.ll b/llvm/test/Assembler/associated-metadata-aix-xcoff.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Assembler/associated-metadata-aix-xcoff.ll @@ -0,0 +1,103 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +target triple = "unknown-unknown-aix-xcoff" + +@gv.decl = external constant [8 x i8] +@gv.def = constant [8 x i8] zeroinitializer + +@gv.associated.func.decl = external addrspace(1) constant [8 x i8], !associated !0 +@gv.associated.func.def = external addrspace(1) constant [8 x i8], !associated !1 + +@gv.associated.gv.decl = external addrspace(1) constant [8 x i8], !associated !2 +@gv.associated.gv.def = external addrspace(1) constant [8 x i8], !associated !3 + +@alias = alias i32, ptr @gv.def + +@gv.associated.alias.gv.def = external addrspace(1) constant [8 x i8], !associated !4 + +@gv.associated.alias.addrspacecast = external addrspace(1) constant [8 x i8], !associated !5 +@alias.addrspacecast = alias i32, ptr addrspace(1) addrspacecast (ptr @gv.def to ptr addrspace(1)) + + +@gv.def.associated.addrspacecast = external addrspace(1) constant [8 x i8], !associated !6 + +@ifunc = dso_local ifunc i32 (i32), ptr @ifunc_resolver +@gv.associated.ifunc = external constant [8 x i8], !associated !7 + +@gv.associated.null = external constant [8 x i8], !associated !8 +@gv.associated.inttoptr = external constant [8 x i8], !associated !9 +@gv.associated.poison = external constant [8 x i8], !associated !10 +@gv.associated.undef = external constant [8 x i8], !associated !11 +@associated.addrspacecast.null = external addrspace(1) constant [8 x i8], !associated !12 +@gv.associated.distinct.null = external constant [8 x i8], !associated !13 +@gv.associated.multiple = external constant [8 x i8], !associated !14 + + +;. +; CHECK: @[[GV_DECL:[a-zA-Z0-9_$"\\.-]+]] = external constant [8 x i8] +; CHECK: @[[GV_DEF:[a-zA-Z0-9_$"\\.-]+]] = constant [8 x i8] zeroinitializer +; CHECK: @[[GV_ASSOCIATED_FUNC_DECL:[a-zA-Z0-9_$"\\.-]+]] = external addrspace(1) constant [8 x i8], !associated !0 +; CHECK: @[[GV_ASSOCIATED_FUNC_DEF:[a-zA-Z0-9_$"\\.-]+]] = external addrspace(1) constant [8 x i8], !associated !1 +; CHECK: @[[GV_ASSOCIATED_GV_DECL:[a-zA-Z0-9_$"\\.-]+]] = external addrspace(1) constant [8 x i8], !associated !2 +; CHECK: @[[GV_ASSOCIATED_GV_DEF:[a-zA-Z0-9_$"\\.-]+]] = external addrspace(1) constant [8 x i8], !associated !3 +; CHECK: @[[GV_ASSOCIATED_ALIAS_GV_DEF:[a-zA-Z0-9_$"\\.-]+]] = external addrspace(1) constant [8 x i8], !associated !4 +; CHECK: @[[GV_ASSOCIATED_ALIAS_ADDRSPACECAST:[a-zA-Z0-9_$"\\.-]+]] = external addrspace(1) constant [8 x i8], !associated !5 +; CHECK: @[[GV_DEF_ASSOCIATED_ADDRSPACECAST:[a-zA-Z0-9_$"\\.-]+]] = external addrspace(1) constant [8 x i8], !associated !6 +; CHECK: @[[GV_ASSOCIATED_IFUNC:[a-zA-Z0-9_$"\\.-]+]] = external constant [8 x i8], !associated !7 +; CHECK: @[[GV_ASSOCIATED_NULL:[a-zA-Z0-9_$"\\.-]+]] = external constant [8 x i8], !associated !8 +; CHECK: @[[GV_ASSOCIATED_INTTOPTR:[a-zA-Z0-9_$"\\.-]+]] = external constant [8 x i8], !associated !9 +; CHECK: @[[GV_ASSOCIATED_POISON:[a-zA-Z0-9_$"\\.-]+]] = external constant [8 x i8], !associated !10 +; CHECK: @[[GV_ASSOCIATED_UNDEF:[a-zA-Z0-9_$"\\.-]+]] = external constant [8 x i8], !associated !11 +; CHECK: @[[GV_ASSOCIATED_DISTINCT_NULL:[a-zA-Z0-9_$"\\.-]+]] = external constant [8 x i8], !associated !13 +; CHECK: @[[GV_ASSOCIATED_MULTIPLE:[a-zA-Z0-9_$"\\.-]+]] = external constant [8 x i8], !associated !14 +; CHECK: @[[ALIAS:[a-zA-Z0-9_$"\\.-]+]] = alias i32, ptr @gv.def +; CHECK: @[[ALIAS_ADDRSPACECAST:[a-zA-Z0-9_$"\\.-]+]] = alias i32, addrspacecast (ptr @gv.def to ptr addrspace(1)) +; CHECK: @[[IFUNC:[a-zA-Z0-9_$"\\.-]+]] = dso_local ifunc i32 (i32), ptr @ifunc_resolver +;. +define ptr @ifunc_resolver() { +; CHECK-LABEL: @ifunc_resolver( +; CHECK-NEXT: ret ptr null +; + ret ptr null +} + + +declare void @func.decl() +define void @func.def() { +; CHECK-LABEL: @func.def( +; CHECK-NEXT: ret void +; + ret void +} + +!0 = !{ ptr @func.decl } +!1 = !{ ptr @func.def } +!2 = !{ ptr @gv.decl } +!3 = !{ ptr @gv.def } +!4 = !{ ptr @alias } +!5 = !{ ptr addrspace(1) @alias.addrspacecast } +!6 = !{ ptr addrspace(1) addrspacecast (ptr @gv.def to ptr addrspace(1)) } +!7 = !{ ptr @ifunc } +!8 = !{ ptr null } +!9 = !{ ptr inttoptr (i64 12345 to ptr) } +!10 = !{ ptr poison } +!11 = !{ ptr undef } +!12 = !{ptr addrspace(1) addrspacecast (ptr null to ptr addrspace(1))} +!13 = distinct !{null} +!14 = !{ ptr @func.def, ptr @ifunc_resolver } +;. +; CHECK: [[META0:![0-9]+]] = !{ptr @func.decl} +; CHECK: [[META1:![0-9]+]] = !{ptr @func.def} +; CHECK: [[META2:![0-9]+]] = !{ptr @gv.decl} +; CHECK: [[META3:![0-9]+]] = !{ptr @gv.def} +; CHECK: [[META4:![0-9]+]] = !{ptr @alias} +; CHECK: [[META5:![0-9]+]] = !{ptr addrspace(1) @alias.addrspacecast} +; CHECK: [[META6:![0-9]+]] = !{ptr addrspace(1) addrspacecast (ptr @gv.def to ptr addrspace(1))} +; CHECK: [[META7:![0-9]+]] = !{ptr @ifunc} +; CHECK: [[META8:![0-9]+]] = !{ptr null} +; CHECK: [[META9:![0-9]+]] = !{ptr inttoptr (i64 12345 to ptr)} +; CHECK: [[META10:![0-9]+]] = !{ptr poison} +; CHECK: [[META11:![0-9]+]] = !{ptr undef} +; CHECK: [[META13:![0-9]+]] = distinct !{null} +; CHECK: [[META14:![0-9]+]] = !{ptr @func.def, ptr @ifunc_resolver} +;. diff --git a/llvm/test/Linker/Inputs/associated-global-aix-xcoff.ll b/llvm/test/Linker/Inputs/associated-global-aix-xcoff.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Linker/Inputs/associated-global-aix-xcoff.ll @@ -0,0 +1,13 @@ +target triple = "unknown-unknown-aix-xcoff" + +@a = global i32 0, !associated !0 +@b = external global i32, !associated !1 +@c = internal global i32 1, !associated !2 +@e = global i32 0, !associated !3 +@g = global i32 0, !associated !4 + +!0 = !{ptr @b} +!1 = !{ptr @a} +!2 = !{ptr @e} +!3 = !{ptr @c} +!4 = distinct !{null} diff --git a/llvm/test/Linker/associated-global-aix-xcoff.ll b/llvm/test/Linker/associated-global-aix-xcoff.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Linker/associated-global-aix-xcoff.ll @@ -0,0 +1,33 @@ +; RUN: llvm-link -S %s %S/Inputs/associated-global-aix-xcoff.ll | FileCheck %s + +target triple = "unknown-unknown-aix-xcoff" + +; CHECK: @c = internal global i32 1, !associated !0 +; CHECK: @d = global i32 0, !associated !1 +; CHECK: @f = global i32 0, !associated !2 +; CHECK: @a = global i32 0, !associated !3 +; CHECK: @b = global i32 0, !associated !4 +; CHECK: @c.3 = internal global i32 1, !associated !5 +; CHECK: @e = global i32 0, !associated !6 +; CHECK: @g = global i32 0, !associated !7 + +; CHECK: !0 = !{ptr @d} +; CHECK: !1 = !{ptr @c} +; CHECK: !2 = !{ptr @a, ptr @b} +; CHECK: !3 = !{ptr @b} +; CHECK: !4 = !{ptr @a} +; CHECK: !5 = !{ptr @e} +; CHECK: !6 = !{ptr @c.3} +; CHECK: !7 = distinct !{null} + +@a = external global i32, !associated !0 +@b = global i32 0, !associated !1 +@c = internal global i32 1, !associated !2 +@d = global i32 0, !associated !3 +@f = global i32 0, !associated !4 + +!0 = !{ptr @b} +!1 = !{ptr @a} +!2 = !{ptr @d} +!3 = !{ptr @c} +!4 = !{ptr @a, ptr @b} diff --git a/llvm/test/Verifier/associated-metadata-aix-xcoff.ll b/llvm/test/Verifier/associated-metadata-aix-xcoff.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/associated-metadata-aix-xcoff.ll @@ -0,0 +1,37 @@ +; RUN: not llvm-as -disable-output < %s -o /dev/null 2>&1 | FileCheck %s + +target triple = "unknown-unknown-aix-xcoff" + +; CHECK: associated value must be pointer typed +; CHECK-NEXT: ptr addrspace(1) @associated.int +; CHECK-NEXT: !0 = !{i32 1} +@associated.int = external addrspace(1) constant [8 x i8], !associated !0 + +; CHECK: associated value must be pointer typed +; CHECK-NEXT: ptr addrspace(1) @associated.float +; CHECK-NEXT: !1 = !{float 1.000000e+00} +@associated.float = external addrspace(1) constant [8 x i8], !associated !1 + +; CHECK: associated metadata must have one operand +; CHECK-NEXT: ptr addrspace(1) @associated.empty +; CHECK-NEXT: !2 = !{} +@associated.empty = external addrspace(1) constant [8 x i8], !associated !2 + +; CHECK: global values should not associate to themselves +; CHECK-NEXT: ptr @associated.self +; CHECK-NEXT: !3 = !{ptr @associated.self} +@associated.self = external constant [8 x i8], !associated !3 + +; CHECK: associated metadata must be ValueAsMetadata +; CHECK-NEXT: ptr @associated.string +; CHECK-NEXT: !4 = !{!"string"} +@associated.string = external constant [8 x i8], !associated !4 + +@gv.decl0 = external constant [8 x i8] +@gv.decl1 = external constant [8 x i8] + +!0 = !{i32 1} +!1 = !{float 1.000000e+00} +!2 = !{} +!3 = !{ptr @associated.self} +!4 = !{!"string"}