probinson created this revision. probinson added a reviewer: 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, the programmer is indicating the function has some special purpose, and is not expected to be garbage collected. In that case, add the function to the "llvm.used" list, which for ELF adds SHF_GNU_RETAIN to the section flags, preventing GC. https://reviews.llvm.org/D145173 Files: clang/lib/CodeGen/CodeGenModule.cpp clang/test/CodeGen/section-retain.cpp Index: clang/test/CodeGen/section-retain.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/section-retain.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s | \ +// RUN: FileCheck %s --check-prefix=UNUSED +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -ffunction-sections -o - %s | \ +// RUN: FileCheck %s --check-prefix=USED + +// 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; } + +// UNUSED-NOT: llvm.used +// USED: @llvm.used = {{.*}} [ptr +// USED-NOT: ftemplate +// USED-SAME: fglobal +// USED-NOT: ftemplate +// USED-SAME: ] + +// USED-DAG: define {{.*}}ftemplate{{.*}} section "foo" +// USED-DAG: define {{.*}}fglobal{{.*}} section "foo" Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -2279,6 +2279,11 @@ if (auto *SA = D->getAttr<PragmaClangTextSectionAttr>()) if (!D->getAttr<SectionAttr>()) F->addFnAttr("implicit-section-name", SA->getName()); + // If we have -ffunction-sections, and an explicit section name, + // and the function is not COMDAT, explicitly retain it. + if (CodeGenOpts.FunctionSections && D->hasAttr<SectionAttr>() && + !F->getComdat()) + addUsedGlobal(F); llvm::AttrBuilder Attrs(F->getContext()); if (GetCPUAndFeaturesAttributes(GD, Attrs)) {
Index: clang/test/CodeGen/section-retain.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/section-retain.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s | \ +// RUN: FileCheck %s --check-prefix=UNUSED +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -ffunction-sections -o - %s | \ +// RUN: FileCheck %s --check-prefix=USED + +// 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; } + +// UNUSED-NOT: llvm.used +// USED: @llvm.used = {{.*}} [ptr +// USED-NOT: ftemplate +// USED-SAME: fglobal +// USED-NOT: ftemplate +// USED-SAME: ] + +// USED-DAG: define {{.*}}ftemplate{{.*}} section "foo" +// USED-DAG: define {{.*}}fglobal{{.*}} section "foo" Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -2279,6 +2279,11 @@ if (auto *SA = D->getAttr<PragmaClangTextSectionAttr>()) if (!D->getAttr<SectionAttr>()) F->addFnAttr("implicit-section-name", SA->getName()); + // If we have -ffunction-sections, and an explicit section name, + // and the function is not COMDAT, explicitly retain it. + if (CodeGenOpts.FunctionSections && D->hasAttr<SectionAttr>() && + !F->getComdat()) + addUsedGlobal(F); 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