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
  • [PATCH] D96838: CodeGen: Set ... Fangrui Song via Phabricator via cfe-commits

Reply via email to