diff mbox series

Fix attribute((section)) with -flto

Message ID CAC-ggsGzp3nR2oKWKX-jDe_S9TXm3tUTp_M7CuFNguDRwX1zbA@mail.gmail.com
State New
Headers show
Series Fix attribute((section)) with -flto | expand

Commit Message

Strager Neds Nov. 21, 2019, 6:09 a.m. UTC
When building an executable with LTO, GCC effectively ignores
__attribute__((section)) on C++ inline member functions. Moving such
functions into the .text section seems to be intentional, but I think
ignoring the section attribute is unintentional:

https://gcc.gnu.org/ml/gcc-patches/2010-07/msg00580.html

> From: Jan Hubicka <hubicka at ucw dot cz>
>
> The patch uncovered two latent problems.  [...]  Also I think we
> should clear NAMED_SECTION for comdats to conserve size.  This is the
> cgraph_make_decl_local change.

Stop resetting the section of localized comdat symbols. This fixes
__attribute__((section)) with -flto.

Testing: Bootstrap on x86_64-linux-gnu with --disable-multilib
--enable-checking=release --enable-languages=c,c++. Observe no change in
test results (aside from the added tests).

2019-11-12  Matthew Glazar <strager.nds@gmail.com>

* gcc/ipa-visibility.c (localize_node): Never set section_name to NULL.
---
 gcc/ipa-visibility.c                          |  4 ---
 .../ext/section-class-inline-function-lto.C   | 17 +++++++++++
 .../ext/section-class-inline-function.C       | 25 ++++++++++++++++
 gcc/testsuite/lib/scanasm.exp                 | 30 ++++++++++++++++++-
 4 files changed, 71 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/section-class-inline-function-lto.C
 create mode 100644 gcc/testsuite/g++.dg/ext/section-class-inline-function.C

 # Check that symbols are emitted in the desired section.
 #
 # Symbols and sections are interpreted as regexp patterns.
@@ -724,11 +747,16 @@ proc dg-function-on-line { args } {

 proc scan-lto-assembler { args } {
     set testcase [testname-for-summary]
+    set output_file [lto_assembly_output_file $testcase]
+    dg-scan "scan-lto-assembler" 1 $testcase $output_file $args
+}
+
+proc lto_assembly_output_file { testcase } {
     # The name might include a list of options; extract the file name.
     set filename [lindex $testcase 0]
     set output_file "[file rootname [file tail $filename]].exe.ltrans0.s"
     verbose "output_file: $output_file"
-    dg-scan "scan-lto-assembler" 1 $testcase $output_file $args
+    return $output_file
 }

 # Read assembly file FILENAME and store a mapping from function names
diff mbox series

Patch

diff --git gcc/ipa-visibility.c gcc/ipa-visibility.c
index f470465f935..cf4c9101a2a 100644
--- gcc/ipa-visibility.c
+++ gcc/ipa-visibility.c
@@ -571,8 +571,6 @@  localize_node (bool whole_program, symtab_node *node)
        next != node; next = next->same_comdat_group)
     {
       next->set_comdat_group (NULL);
-      if (!next->alias)
-        next->set_section (NULL);
       if (!next->transparent_alias)
         next->make_decl_local ();
       next->unique_name
@@ -595,8 +593,6 @@  localize_node (bool whole_program, symtab_node *node)

   if (TREE_PUBLIC (node->decl))
     node->set_comdat_group (NULL);
-  if (DECL_COMDAT (node->decl) && !node->alias)
-    node->set_section (NULL);
   if (!node->transparent_alias)
     {
       node->resolution = LDPR_PREVAILING_DEF_IRONLY;
diff --git gcc/testsuite/g++.dg/ext/section-class-inline-function-lto.C
gcc/testsuite/g++.dg/ext/section-class-inline-function-lto.C
new file mode 100644
index 00000000000..4567d03a512
--- /dev/null
+++ gcc/testsuite/g++.dg/ext/section-class-inline-function-lto.C
@@ -0,0 +1,17 @@ 
+// attribute((section)) should affect inline member functions even with -flto.
+
+// { dg-do link }
+// { dg-require-effective-target lto }
+// { dg-require-named-sections "" }
+// { dg-options "-flto --save-temps" }
+
+// { dg-final { scan-lto-assembler-symbol-section {callee}
{^(\.testsection|__TEXT,__testsection)$} } }
+#include "section-class-inline-function.C"
+
+// { dg-final { cleanup-saved-temps } }
+
+int
+main()
+{
+  return f();
+}
diff --git gcc/testsuite/g++.dg/ext/section-class-inline-function.C
gcc/testsuite/g++.dg/ext/section-class-inline-function.C
new file mode 100644
index 00000000000..01a12d02aff
--- /dev/null
+++ gcc/testsuite/g++.dg/ext/section-class-inline-function.C
@@ -0,0 +1,25 @@ 
+// attribute((section)) should affect inline member functions.
+
+// { dg-do compile }
+// { dg-require-named-sections "" }
+
+#if defined(__APPLE__)
+#define TESTSECTION "__TEXT,__testsection"
+#else
+#define TESTSECTION ".testsection"
+#endif
+
+// { dg-final { scan-assembler-symbol-section {callee}
{^(\.testsection|__TEXT,__testsection)$} } }
+struct s {
+  __attribute__((section(TESTSECTION)))
+      int callee()
+  {
+    return 0;
+  }
+};
+
+int
+f()
+{
+  return s().callee();
+}
diff --git gcc/testsuite/lib/scanasm.exp gcc/testsuite/lib/scanasm.exp
index e9ebf52d77e..2eeb5b1e1fb 100644
--- gcc/testsuite/lib/scanasm.exp
+++ gcc/testsuite/lib/scanasm.exp
@@ -183,6 +183,29 @@  proc scan-assembler-symbol-section { args } {
     $expected_section_pattern
 }

+# Check that symbols are emitted in the desired section.
+# Like scan-assembler-symbol-section, but using the assembly output
generated by
+# the compiler with '-flto --save-temps'.
+#
+# Example:
+#
+# // All numbered functions (func1, func2, etc.) must be in the .text
section or
+# // in a .text sub-section (like .text._func1).
+# { dg-final { scan-lto-assembler-symbol-section {^_func[1-5]$}
{^\.text($|\.)} } }
+
+proc scan-lto-assembler-symbol-section { args } {
+    set testcase [testname-for-summary]
+    set output_file [lto_assembly_output_file $testcase]
+    set symbol_pattern [lindex $args 0]
+    set expected_section_pattern [lindex $args 1]
+    dg-scan-symbol-section \
+    "scan-lto-assembler-symbol-section" \
+    $testcase \
+    $output_file \
+    $symbol_pattern \
+    $expected_section_pattern
+}
+