diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -442,7 +442,7 @@ var->setSection(SA->getName()); if (D.hasAttr()) - CGM.addUsedGlobal(var); + CGM.addUsedOrCompilerUsedGlobal(var); // We may have to cast the constant because of the initializer // mismatch above. diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1054,6 +1054,9 @@ /// Add a global to a list to be added to the llvm.compiler.used metadata. void addCompilerUsedGlobal(llvm::GlobalValue *GV); + /// Add a global to a list to be added to the llvm.compiler.used metadata. + void addUsedOrCompilerUsedGlobal(llvm::GlobalValue *GV); + /// Add a destructor and object to add to the C++ global destructor function. void AddCXXDtorEntry(llvm::FunctionCallee DtorFn, llvm::Constant *Object) { CXXGlobalDtorsOrStermFinalizers.emplace_back(DtorFn.getFunctionType(), diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1820,13 +1820,13 @@ GV->setVisibility(llvm::GlobalValue::DefaultVisibility); if (D && D->hasAttr()) - addUsedGlobal(GV); + addUsedOrCompilerUsedGlobal(GV); if (CodeGenOpts.KeepStaticConsts && D && isa(D)) { const auto *VD = cast(D); if (VD->getType().isConstQualified() && VD->getStorageDuration() == SD_Static) - addUsedGlobal(GV); + addUsedOrCompilerUsedGlobal(GV); } } @@ -2087,6 +2087,15 @@ LLVMCompilerUsed.emplace_back(GV); } +void CodeGenModule::addUsedOrCompilerUsedGlobal(llvm::GlobalValue *GV) { + assert((isa(GV) || !GV->isDeclaration()) && + "Only globals with definition can force usage."); + if (this->getTarget().getTriple().isOSBinFormatELF()) + LLVMCompilerUsed.emplace_back(GV); + else + LLVMUsed.emplace_back(GV); +} + static void emitUsed(CodeGenModule &CGM, StringRef Name, std::vector &List) { // Don't create llvm.used if there is no need. @@ -5912,7 +5921,8 @@ IdentifierInfo *Name = I.first; llvm::GlobalValue *Val = I.second; if (Val && !getModule().getNamedValue(Name->getName())) - addUsedGlobal(llvm::GlobalAlias::create(Name->getName(), Val)); + addUsedOrCompilerUsedGlobal( + llvm::GlobalAlias::create(Name->getName(), Val)); } } diff --git a/clang/test/CodeGen/2005-12-04-AttributeUsed.c b/clang/test/CodeGen/2005-12-04-AttributeUsed.c --- a/clang/test/CodeGen/2005-12-04-AttributeUsed.c +++ b/clang/test/CodeGen/2005-12-04-AttributeUsed.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s // CHECK: @llvm.used = appending global [2 x i8*] [i8* bitcast (void ()* @foo to i8*), i8* bitcast (i32* @X to i8*)], section "llvm.metadata" int X __attribute__((used)); diff --git a/clang/test/CodeGen/attr-msp430.c b/clang/test/CodeGen/attr-msp430.c --- a/clang/test/CodeGen/attr-msp430.c +++ b/clang/test/CodeGen/attr-msp430.c @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -triple msp430-unknown-unknown -emit-llvm < %s| FileCheck %s __attribute__((interrupt(1))) void foo(void) {} -// CHECK: @llvm.used +// CHECK: @llvm.compiler.used = // CHECK-SAME: @foo // CHECK: define{{.*}} msp430_intrcc void @foo() #0 diff --git a/clang/test/CodeGen/attr-target-mv.c b/clang/test/CodeGen/attr-target-mv.c --- a/clang/test/CodeGen/attr-target-mv.c +++ b/clang/test/CodeGen/attr-target-mv.c @@ -65,7 +65,7 @@ __attribute__((target("default"))) inline void foo_used2(int i, double d) {} __attribute__((target("avx,sse4.2"), used)) inline void foo_used2(int i, double d) {} -// LINUX: @llvm.used = appending global [2 x i8*] [i8* bitcast (void (i32, double)* @foo_used to i8*), i8* bitcast (void (i32, double)* @foo_used2.avx_sse4.2 to i8*)], section "llvm.metadata" +// LINUX: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast (void (i32, double)* @foo_used to i8*), i8* bitcast (void (i32, double)* @foo_used2.avx_sse4.2 to i8*)], section "llvm.metadata" // WINDOWS: @llvm.used = appending global [2 x i8*] [i8* bitcast (void (i32, double)* @foo_used to i8*), i8* bitcast (void (i32, double)* @foo_used2.avx_sse4.2 to i8*)], section "llvm.metadata" // LINUX: @foo.ifunc = weak_odr ifunc i32 (), i32 ()* ()* @foo.resolver diff --git a/clang/test/CodeGen/attr-used.c b/clang/test/CodeGen/attr-used.c --- a/clang/test/CodeGen/attr-used.c +++ b/clang/test/CodeGen/attr-used.c @@ -1,9 +1,12 @@ -// RUN: %clang_cc1 -emit-llvm -o %t %s -// RUN: grep '@llvm.used = .*@a0' %t -// RUN: grep '@llvm.used = .*@g0' %t -// RUN: grep '@llvm.used = .*@f0' %t -// RUN: grep '@llvm.used = .*@f1.l0' %t +// RUN: %clang_cc1 -emit-llvm -triple x86_64 %s -o - | FileCheck %s --check-prefixes=CHECK,CUSED +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin %s -o - | FileCheck %s --check-prefixes=CHECK,USED +// USED: @llvm.used = +// CUSED: @llvm.compiler.used = +// CHECK-SAME: @f0 +// CHECK-SAME: @f1.l0 +// CHECK-SAME: @g0 +// CHECK-SAME: @a0 int g0 __attribute__((used)); diff --git a/clang/test/CodeGen/attr-x86-interrupt.c b/clang/test/CodeGen/attr-x86-interrupt.c --- a/clang/test/CodeGen/attr-x86-interrupt.c +++ b/clang/test/CodeGen/attr-x86-interrupt.c @@ -12,12 +12,12 @@ __attribute__((interrupt)) void foo7(int *a, uword b) {} __attribute__((interrupt)) void foo8(int *a) {} -// X86_64_LINUX: @llvm.used = appending global [2 x i8*] [i8* bitcast (void (i32*, i64)* @foo7 to i8*), i8* bitcast (void (i32*)* @foo8 to i8*)], section "llvm.metadata" +// X86_64_LINUX: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast (void (i32*, i64)* @foo7 to i8*), i8* bitcast (void (i32*)* @foo8 to i8*)], section "llvm.metadata" // X86_64_LINUX: define{{.*}} x86_intrcc void @foo7(i32* byval(i32) %{{.+}}, i64 %{{.+}}) // X86_64_LINUX: define{{.*}} x86_intrcc void @foo8(i32* byval(i32) %{{.+}}) // X86_64_LINUX: "disable-tail-calls"="true" // X86_64_LINUX-NOT: "disable-tail-calls"="false" -// X86_LINUX: @llvm.used = appending global [2 x i8*] [i8* bitcast (void (i32*, i32)* @foo7 to i8*), i8* bitcast (void (i32*)* @foo8 to i8*)], section "llvm.metadata" +// X86_LINUX: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast (void (i32*, i32)* @foo7 to i8*), i8* bitcast (void (i32*)* @foo8 to i8*)], section "llvm.metadata" // X86_LINUX: define{{.*}} x86_intrcc void @foo7(i32* byval(i32) %{{.+}}, i32 %{{.+}}) // X86_LINUX: define{{.*}} x86_intrcc void @foo8(i32* byval(i32) %{{.+}}) // X86_LINUX: "disable-tail-calls"="true" diff --git a/clang/test/CodeGen/keep-static-consts.cpp b/clang/test/CodeGen/keep-static-consts.cpp --- a/clang/test/CodeGen/keep-static-consts.cpp +++ b/clang/test/CodeGen/keep-static-consts.cpp @@ -3,7 +3,7 @@ // CHECK: @_ZL7srcvers = internal constant [4 x i8] c"xyz\00", align 1 // CHECK: @_ZL8srcvers2 = internal constant [4 x i8] c"abc\00", align 1 // CHECK: @_ZL1N = internal constant i32 2, align 4 -// CHECK: @llvm.used = appending global [4 x i8*] [i8* getelementptr inbounds ([4 x i8], [4 x i8]* @_ZL7srcvers, i32 0, i32 0), i8* bitcast (i32* @b to i8*), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @_ZL8srcvers2, i32 0, i32 0), i8* bitcast (i32* @_ZL1N to i8*)], section "llvm.metadata" +// CHECK: @llvm.compiler.used = appending global [4 x i8*] [i8* getelementptr inbounds ([4 x i8], [4 x i8]* @_ZL7srcvers, i32 0, i32 0), i8* bitcast (i32* @b to i8*), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @_ZL8srcvers2, i32 0, i32 0), i8* bitcast (i32* @_ZL1N to i8*)], section "llvm.metadata" static const char srcvers[] = "xyz"; extern const int b = 1; diff --git a/clang/test/CodeGenCUDA/llvm-used.cu b/clang/test/CodeGenCUDA/llvm-used.cu --- a/clang/test/CodeGenCUDA/llvm-used.cu +++ b/clang/test/CodeGenCUDA/llvm-used.cu @@ -4,5 +4,5 @@ // 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.used = appending global [1 x i8*] [i8* addrspacecast (i8 addrspace(1)* bitcast ([0 x i32] addrspace(1)* @a to i8 addrspace(1)*) to i8*)], section "llvm.metadata" +// CHECK: @llvm.compiler.used = appending global [1 x i8*] [i8* addrspacecast (i8 addrspace(1)* bitcast ([0 x i32] addrspace(1)* @a to i8 addrspace(1)*) to i8*)], section "llvm.metadata" __attribute__((device)) __attribute__((__used__)) int a[] = {}; diff --git a/clang/test/CodeGenCXX/attr-x86-interrupt.cpp b/clang/test/CodeGenCXX/attr-x86-interrupt.cpp --- a/clang/test/CodeGenCXX/attr-x86-interrupt.cpp +++ b/clang/test/CodeGenCXX/attr-x86-interrupt.cpp @@ -17,11 +17,11 @@ struct St { static void foo9(int *a) __attribute__((interrupt)) {} }; -// X86_64_LINUX: @llvm.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i64)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata" +// X86_64_LINUX: @llvm.compiler.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i64)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata" // X86_64_LINUX: define{{.*}} x86_intrcc void @{{.*}}foo7{{.*}}(i32* byval(i32) %{{.+}}, i64 %{{.+}}) // X86_64_LINUX: define{{.*}} x86_intrcc void @{{.*}}foo8{{.*}}(i32* byval(i32) %{{.+}}) // X86_64_LINUX: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* byval(i32) %{{.+}}) -// X86_LINUX: @llvm.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i32)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata" +// X86_LINUX: @llvm.compiler.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i32)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata" // X86_LINUX: define{{.*}} x86_intrcc void @{{.*}}foo7{{.*}}(i32* byval(i32) %{{.+}}, i32 %{{.+}}) // X86_LINUX: define{{.*}} x86_intrcc void @{{.*}}foo8{{.*}}(i32* byval(i32) %{{.+}}) // X86_LINUX: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* byval(i32) %{{.+}}) diff --git a/clang/test/CodeGenCXX/extern-c.cpp b/clang/test/CodeGenCXX/extern-c.cpp --- a/clang/test/CodeGenCXX/extern-c.cpp +++ b/clang/test/CodeGenCXX/extern-c.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64 -emit-llvm %s -o - | FileCheck %s namespace foo { // CHECK-NOT: @a = global @@ -70,7 +70,7 @@ __attribute__((used)) static int duplicate_internal_fn() { return 0; } } - // CHECK: @llvm.used = appending global {{.*}} @internal_var {{.*}} @internal_fn + // CHECK: @llvm.compiler.used = appending global {{.*}} @internal_var {{.*}} @internal_fn // CHECK-NOT: @unused // CHECK-NOT: @duplicate_internal