probinson created this revision.
probinson added reviewers: rjmccall, MaskRay.
Herald added a project: All.
probinson requested review of this revision.

People use -ffunction-sections to put each function into its own
object-file section; this makes linker garbage-collection simpler.
However, if there's an explicit __attribute__((section("name"))
on the function, all functions with that attribute end up in a
single section, defeating the linker GC.

Use section groups to make these things work together.


https://reviews.llvm.org/D143745

Files:
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/test/CodeGen/section-attr-comdat.cpp


Index: clang/test/CodeGen/section-attr-comdat.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/section-attr-comdat.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple=x86_64-linux -emit-llvm  %s -o - | \
+// RUN:     FileCheck %s --check-prefix=NOCOMDAT
+// RUN: %clang_cc1 -triple=x86_64-linux -emit-llvm -ffunction-sections %s -o - 
| \
+// RUN:     FileCheck %s --check-prefix=COMDAT
+
+// template function = comdat always.
+template<typename T>
+__attribute__((section("foo"))) T ftemplate(T a) { return a + 1; }
+__attribute__((section("foo"))) int fglobal(int a) { return ftemplate(a) + 2; }
+
+// NOCOMDAT-DAG: ${{.*}}ftemplate{{.*}} = comdat any
+// NOCOMDAT-DAG: define {{.*}}ftemplate{{.*}} section "foo" comdat {
+// NOCOMDAT-DAG: define {{.*}}fglobal{{.*}} section "foo" {
+
+// COMDAT-DAG: ${{.*}}ftemplate{{.*}} = comdat any
+// COMDAT-DAG: ${{.*}}fglobal{{.*}} = comdat nodeduplicate
+// COMDAT-DAG: define {{.*}}ftemplate{{.*}} section "foo" comdat {
+// COMDAT-DAG: define {{.*}}fglobal{{.*}} section "foo" comdat {
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -2293,6 +2293,18 @@
       if (auto *SA = D->getAttr<PragmaClangTextSectionAttr>())
         if (!D->getAttr<SectionAttr>())
           F->addFnAttr("implicit-section-name", SA->getName());
+      // If we have -ffunction-sections, and also an explicit section name,
+      // put the function into a section group so that various linker GC
+      // operations will still work with this function.
+      if (CodeGenOpts.FunctionSections && getTriple().supportsCOMDAT() &&
+          D->hasAttr<SectionAttr>()) {
+        // Don't replace a real comdat.
+        if (!F->getComdat()) {
+          llvm::Comdat *C = TheModule.getOrInsertComdat(F->getName());
+          C->setSelectionKind(llvm::Comdat::NoDeduplicate);
+          F->setComdat(C);
+        }
+      }
 
       llvm::AttrBuilder Attrs(F->getContext());
       if (GetCPUAndFeaturesAttributes(GD, Attrs)) {


Index: clang/test/CodeGen/section-attr-comdat.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/section-attr-comdat.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple=x86_64-linux -emit-llvm  %s -o - | \
+// RUN:     FileCheck %s --check-prefix=NOCOMDAT
+// RUN: %clang_cc1 -triple=x86_64-linux -emit-llvm -ffunction-sections %s -o - | \
+// RUN:     FileCheck %s --check-prefix=COMDAT
+
+// template function = comdat always.
+template<typename T>
+__attribute__((section("foo"))) T ftemplate(T a) { return a + 1; }
+__attribute__((section("foo"))) int fglobal(int a) { return ftemplate(a) + 2; }
+
+// NOCOMDAT-DAG: ${{.*}}ftemplate{{.*}} = comdat any
+// NOCOMDAT-DAG: define {{.*}}ftemplate{{.*}} section "foo" comdat {
+// NOCOMDAT-DAG: define {{.*}}fglobal{{.*}} section "foo" {
+
+// COMDAT-DAG: ${{.*}}ftemplate{{.*}} = comdat any
+// COMDAT-DAG: ${{.*}}fglobal{{.*}} = comdat nodeduplicate
+// COMDAT-DAG: define {{.*}}ftemplate{{.*}} section "foo" comdat {
+// COMDAT-DAG: define {{.*}}fglobal{{.*}} section "foo" comdat {
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -2293,6 +2293,18 @@
       if (auto *SA = D->getAttr<PragmaClangTextSectionAttr>())
         if (!D->getAttr<SectionAttr>())
           F->addFnAttr("implicit-section-name", SA->getName());
+      // If we have -ffunction-sections, and also an explicit section name,
+      // put the function into a section group so that various linker GC
+      // operations will still work with this function.
+      if (CodeGenOpts.FunctionSections && getTriple().supportsCOMDAT() &&
+          D->hasAttr<SectionAttr>()) {
+        // Don't replace a real comdat.
+        if (!F->getComdat()) {
+          llvm::Comdat *C = TheModule.getOrInsertComdat(F->getName());
+          C->setSelectionKind(llvm::Comdat::NoDeduplicate);
+          F->setComdat(C);
+        }
+      }
 
       llvm::AttrBuilder Attrs(F->getContext());
       if (GetCPUAndFeaturesAttributes(GD, Attrs)) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to