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