MaskRay created this revision. Herald added subscribers: krytarowski, arichardson, emaste. MaskRay requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
GCC 11 will set SHF_GNU_RETAIN on the section of a `__attribute__((used))` function/variable, if the configure-time GNU as supports SHF_GNU_RETAIN (binutils 2.36 or above on Linux or FreeBSD). This patch sets !retain metadata on UsedAttr definitions. We let the backend to figure out whether the ELF section flag SHF_GNU_RETAIN should be used (integrated assembler or `-fno-integrated-as -fbinutils-version=2.36`). Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D96838 Files: clang/lib/CodeGen/CGDecl.cpp clang/lib/CodeGen/CodeGenModule.cpp clang/lib/CodeGen/CodeGenModule.h clang/test/CodeGen/attr-used.c clang/test/CodeGenCXX/attr-used.cpp
Index: clang/test/CodeGenCXX/attr-used.cpp =================================================================== --- clang/test/CodeGenCXX/attr-used.cpp +++ clang/test/CodeGenCXX/attr-used.cpp @@ -1,10 +1,13 @@ // RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux -o - %s | FileCheck %s --check-prefix=RETAIN // <rdar://problem/8684363>: clang++ not respecting __attribute__((used)) on destructors struct X0 { // CHECK-DAG: define linkonce_odr {{.*}} @_ZN2X0C1Ev + // RETAIN-DAG: define linkonce_odr {{.*}} @_ZN2X0C1Ev({{.*}} !retain __attribute__((used)) X0() {} // CHECK-DAG: define linkonce_odr {{.*}} @_ZN2X0D1Ev + // RETAIN-DAG: define linkonce_odr {{.*}} @_ZN2X0D1Ev({{.*}} !retain __attribute__((used)) ~X0() {} }; @@ -12,6 +15,7 @@ struct X1 { struct Nested { // CHECK-DAG: define linkonce_odr {{.*}} @_ZN2X16Nested1fEv + // RETAIN-DAG: define linkonce_odr {{.*}} @_ZN2X16Nested1fEv({{.*}} !retain void __attribute__((used)) f() {} }; }; @@ -24,4 +28,5 @@ // CHECK-DAG: define linkonce_odr {{.*}} @_ZN2X23barEv // CHECK-DAG: define linkonce_odr {{.*}} @_ZN2X23fooEv + // RETAIN-DAG: define linkonce_odr {{.*}} @_ZN2X23barEv({{.*}} !retain }; Index: clang/test/CodeGen/attr-used.c =================================================================== --- clang/test/CodeGen/attr-used.c +++ clang/test/CodeGen/attr-used.c @@ -1,10 +1,23 @@ -// 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-linux %s -o - | FileCheck %s --check-prefixes=CHECK,RETAIN +// RUN: %clang_cc1 -emit-llvm -triple x86_64-freebsd %s -o - | FileCheck %s --check-prefixes=CHECK,RETAIN +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin %s -o - | FileCheck %s --check-prefixes=CHECK,NORETAIN +// RETAIN: @r0 ={{.*}} constant i32 {{.*}} !retain ![[#EMPTY:]] +// RETAIN: @f1.l0 = internal global i32 {{.*}} !retain ![[#EMPTY]] +// RETAIN: @a0 ={{.*}} global i32 {{.*}} !retain ![[#EMPTY]] +// RETAIN: @g0 ={{.*}} global i32 {{.*}} !retain ![[#EMPTY]] +/// Set !retain only on Linux and FreeBSD. +// NORETAIN-NOT: !retain + +// CHECK: @llvm.used ={{.*}} @f0 +// CHECK-SAME: @f1.l0 +// CHECK-SAME: @g0 +// CHECK-SAME: @a0 + +// RETAIN: [[#EMPTY]] = !{} + +const int r0 __attribute__((used)) = 42; int g0 __attribute__((used)); static void __attribute__((used)) f0(void) { Index: clang/lib/CodeGen/CodeGenModule.h =================================================================== --- clang/lib/CodeGen/CodeGenModule.h +++ clang/lib/CodeGen/CodeGenModule.h @@ -1048,6 +1048,9 @@ template<typename SomeDecl> void MaybeHandleStaticInExternC(const SomeDecl *D, llvm::GlobalValue *GV); + /// Set !retain metadata if the target supports. + void maybeSetRetain(llvm::GlobalObject *GO); + /// Add a global to a list to be added to the llvm.used metadata. void addUsedGlobal(llvm::GlobalValue *GV); Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -1883,6 +1883,8 @@ if (D) { if (auto *GV = dyn_cast<llvm::GlobalVariable>(GO)) { + if (D->hasAttr<UsedAttr>()) + maybeSetRetain(GV); if (auto *SA = D->getAttr<PragmaClangBSSSectionAttr>()) GV->addAttribute("bss-section", SA->getName()); if (auto *SA = D->getAttr<PragmaClangDataSectionAttr>()) @@ -1894,6 +1896,8 @@ } if (auto *F = dyn_cast<llvm::Function>(GO)) { + if (D->hasAttr<UsedAttr>()) + maybeSetRetain(F); if (auto *SA = D->getAttr<PragmaClangTextSectionAttr>()) if (!D->getAttr<SectionAttr>()) F->addFnAttr("implicit-section-name", SA->getName()); @@ -2062,6 +2066,13 @@ } } +void CodeGenModule::maybeSetRetain(llvm::GlobalObject *GO) { + const llvm::Triple &T = getTarget().getTriple(); + if (T.isOSFreeBSD() || T.isOSLinux()) + GO->setMetadata(llvm::LLVMContext::MD_retain, + llvm::MDNode::get(getLLVMContext(), None)); +} + void CodeGenModule::addUsedGlobal(llvm::GlobalValue *GV) { assert((isa<llvm::Function>(GV) || !GV->isDeclaration()) && "Only globals with definition can force usage."); Index: clang/lib/CodeGen/CGDecl.cpp =================================================================== --- clang/lib/CodeGen/CGDecl.cpp +++ clang/lib/CodeGen/CGDecl.cpp @@ -441,8 +441,10 @@ if (const SectionAttr *SA = D.getAttr<SectionAttr>()) var->setSection(SA->getName()); - if (D.hasAttr<UsedAttr>()) + if (D.hasAttr<UsedAttr>()) { CGM.addUsedGlobal(var); + CGM.maybeSetRetain(var); + } // We may have to cast the constant because of the initializer // mismatch above.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits