aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/config.in7
-rwxr-xr-xgcc/configure51
-rw-r--r--gcc/configure.ac20
-rw-r--r--gcc/doc/sourcebuild.texi3
-rw-r--r--gcc/output.h6
-rw-r--r--gcc/testsuite/c-c++-common/attr-used-2.c1
-rw-r--r--gcc/testsuite/c-c++-common/attr-used-3.c7
-rw-r--r--gcc/testsuite/c-c++-common/attr-used-4.c7
-rw-r--r--gcc/testsuite/c-c++-common/attr-used.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c35
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c16
-rw-r--r--gcc/testsuite/lib/target-supports.exp40
-rw-r--r--gcc/varasm.c15
13 files changed, 205 insertions, 4 deletions
diff --git a/gcc/config.in b/gcc/config.in
index cc6276d..b6e041d 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1386,6 +1386,13 @@
#endif
+/* Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN
+ flag. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_SHF_GNU_RETAIN
+#endif
+
+
/* Define 0/1 if your assembler supports marking sections with SHF_MERGE flag.
*/
#ifndef USED_FOR_TARGET
diff --git a/gcc/configure b/gcc/configure
index 5206f0d9..7478222 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -24430,6 +24430,57 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+# Test if the assembler supports the section flag 'R' for specifying
+# section with SHF_GNU_RETAIN.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'R', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_shf_gnu_retain=no
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section 'R' flag" >&5
+$as_echo_n "checking assembler for section 'R' flag... " >&6; }
+if ${gcc_cv_as_shf_gnu_retain+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_shf_gnu_retain=no
+ if test $in_tree_gas = yes; then
+ if test $in_tree_gas_is_elf = yes \
+ && test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 36 \) \* 1000 + 0`
+ then gcc_cv_as_shf_gnu_retain=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ $as_echo '.section .foo,"awR",%progbits
+.byte 0' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ gcc_cv_as_shf_gnu_retain=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_shf_gnu_retain" >&5
+$as_echo "$gcc_cv_as_shf_gnu_retain" >&6; }
+
+
+ ;;
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_SHF_GNU_RETAIN `if test $gcc_cv_as_shf_gnu_retain = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section merging support" >&5
$as_echo_n "checking assembler for section merging support... " >&6; }
if ${gcc_cv_as_shf_merge+:} false; then :
diff --git a/gcc/configure.ac b/gcc/configure.ac
index ded124c..478d0d6 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3330,6 +3330,26 @@ AC_DEFINE_UNQUOTED(HAVE_GAS_SECTION_EXCLUDE,
[`if test $gcc_cv_as_section_exclude_e = yes || test $gcc_cv_as_section_exclude_hash = yes; then echo 1; else echo 0; fi`],
[Define if your assembler supports specifying the exclude section flag.])
+# Test if the assembler supports the section flag 'R' for specifying
+# section with SHF_GNU_RETAIN.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'R', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_shf_gnu_retain=no
+ ;;
+ *)
+ gcc_GAS_CHECK_FEATURE([section 'R' flag], gcc_cv_as_shf_gnu_retain,
+ [elf,2,36,0], [--fatal-warnings],
+ [.section .foo,"awR",%progbits
+.byte 0])
+ ;;
+esac
+AC_DEFINE_UNQUOTED(HAVE_GAS_SHF_GNU_RETAIN,
+ [`if test $gcc_cv_as_shf_gnu_retain = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN flag.])
+
gcc_GAS_CHECK_FEATURE(section merging support, gcc_cv_as_shf_merge,
[elf,2,12,0], [--fatal-warnings],
[.section .rodata.str, "aMS", @progbits, 1])
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 4f7af20..55538c3 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -2462,6 +2462,9 @@ Target supports wide characters.
@subsubsection Other attributes
@table @code
+@item R_flag_in_section
+Target supports the 'R' flag in .section directive in assembly inputs.
+
@item automatic_stack_alignment
Target supports automatic stack alignment.
diff --git a/gcc/output.h b/gcc/output.h
index b44c1bd..729c520 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -381,7 +381,11 @@ extern void no_asm_to_stream (FILE *);
#define SECTION_COMMON 0x800000 /* contains common data */
#define SECTION_RELRO 0x1000000 /* data is readonly after relocation processing */
#define SECTION_EXCLUDE 0x2000000 /* discarded by the linker */
-#define SECTION_MACH_DEP 0x4000000 /* subsequent bits reserved for target */
+#define SECTION_RETAIN 0x4000000 /* retained by the linker. */
+
+/* NB: The maximum SECTION_MACH_DEP is 0x10000000 since AVR needs 4 bits
+ in SECTION_MACH_DEP. */
+#define SECTION_MACH_DEP 0x8000000 /* subsequent bits reserved for target */
/* This SECTION_STYLE is used for unnamed sections that we can switch
to using a special assembler directive. */
diff --git a/gcc/testsuite/c-c++-common/attr-used-2.c b/gcc/testsuite/c-c++-common/attr-used-2.c
index f78b94b..eef2519 100644
--- a/gcc/testsuite/c-c++-common/attr-used-2.c
+++ b/gcc/testsuite/c-c++-common/attr-used-2.c
@@ -9,3 +9,4 @@ void foo()
}
/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler "\.data.*,\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-3.c b/gcc/testsuite/c-c++-common/attr-used-3.c
new file mode 100644
index 0000000..ca64197
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-3.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2 -fcommon" } */
+
+static int xyzzy __attribute__((__used__));
+
+/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler ",\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-4.c b/gcc/testsuite/c-c++-common/attr-used-4.c
new file mode 100644
index 0000000..1cbc4c7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-4.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2 -fcommon" } */
+
+int xyzzy __attribute__((__used__));
+
+/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler ",\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used.c b/gcc/testsuite/c-c++-common/attr-used.c
index ba7705a..2036533 100644
--- a/gcc/testsuite/c-c++-common/attr-used.c
+++ b/gcc/testsuite/c-c++-common/attr-used.c
@@ -11,3 +11,4 @@ static void function_declaration_after(void) __attribute__((__used__));
/* { dg-final { scan-assembler "function_declaration_before" } } */
/* { dg-final { scan-assembler "function_declaration_after" } } */
+/* { dg-final { scan-assembler "\.text.*,\"axR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c
new file mode 100644
index 0000000..5f6cbca
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target R_flag_in_section } */
+/* { dg-final { scan-assembler ".text.*,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss.*,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.*,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata.*,\"aR\"" } } */
+/* { dg-final { scan-assembler ".data.used_foo_sec,\"awR\"" } } */
+
+void __attribute__((used)) used_fn (void) { }
+void unused_fn (void) { }
+void __attribute__((hot,used)) used_hot_fn (void) { }
+void __attribute__((hot)) unused_hot_fn (void) { }
+void __attribute__((cold,used)) used_cold_fn (void) { }
+void __attribute__((cold)) unused_cold_fn (void) { }
+int __attribute__((used)) used_bss = 0;
+int __attribute__((used)) used_data = 1;
+const int __attribute__((used)) used_rodata = 2;
+int __attribute__((used)) used_comm;
+static int __attribute__((used)) used_lcomm;
+
+int unused_bss = 0;
+int unused_data = 1;
+const int unused_rodata = 2;
+int unused_comm;
+static int unused_lcomm;
+
+/* Test switching back to the retained sections. */
+void __attribute__((used)) used_fn2 (void) { }
+int __attribute__((used)) used_bss2 = 0;
+int __attribute__((used)) used_data2 = 1;
+const int __attribute__((used)) used_rodata2 = 2;
+int __attribute__((used)) used_comm2;
+static int __attribute__((used)) used_lcomm2;
+
+int __attribute__((used,section(".data.used_foo_sec"))) used_foo = 2;
diff --git a/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c
new file mode 100644
index 0000000..be5f391
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target R_flag_in_section } */
+/* { dg-final { scan-assembler ".text.used_fn,\"axR\"" } } */
+/* { dg-final { scan-assembler ".text.used_fn2,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss,\"awR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata,\"aR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata2,\"aR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_lcomm,\"awR\"" { target arm-*-* } } } */
+/* { dg-final { scan-assembler ".bss.used_lcomm2,\"awR\"" { target arm-*-* } } } */
+/* { dg-final { scan-assembler ".data.used_foo_sec,\"awR\"" } } */
+/* { dg-options "-ffunction-sections -fdata-sections" } */
+
+#include "attr-used-retain-1.c"
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index ff6bc5f..9d0a25d 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -10662,3 +10662,43 @@ proc check_effective_target_no_fsanitize_address {} {
}
return 0;
}
+
+# Return 1 if this target supports 'R' flag in .section directive, 0
+# otherwise. Cache the result.
+
+proc check_effective_target_R_flag_in_section { } {
+ global tool
+ global GCC_UNDER_TEST
+
+ # Need auto-host.h to check linker support.
+ if { ![file exists ../../auto-host.h ] } {
+ return 0
+ }
+
+ return [check_cached_effective_target R_flag_in_section {
+
+ set src pie[pid].c
+ set obj pie[pid].o
+
+ set f [open $src "w"]
+ puts $f "#include \"../../auto-host.h\""
+ puts $f "#if HAVE_GAS_SHF_GNU_RETAIN == 0"
+ puts $f "# error Assembler does not support 'R' flag in .section directive."
+ puts $f "#endif"
+ close $f
+
+ verbose "check_effective_target_R_flag_in_section compiling testfile $src" 2
+ set lines [${tool}_target_compile $src $obj assembly ""]
+
+ file delete $src
+ file delete $obj
+
+ if [string match "" $lines] then {
+ verbose "check_effective_target_R_flag_in_section testfile compilation passed" 2
+ return 1
+ } else {
+ verbose "check_effective_target_R_flag_in_section testfile compilation failed" 2
+ return 0
+ }
+ }]
+}
diff --git a/gcc/varasm.c b/gcc/varasm.c
index b92da26..6c13f52 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -289,6 +289,10 @@ get_section (const char *name, unsigned int flags, tree decl,
slot = section_htab->find_slot_with_hash (name, htab_hash_string (name),
INSERT);
flags |= SECTION_NAMED;
+ if (HAVE_GAS_SHF_GNU_RETAIN
+ && decl != nullptr
+ && DECL_PRESERVE_P (decl))
+ flags |= SECTION_RETAIN;
if (*slot == NULL)
{
sect = ggc_alloc<section> ();
@@ -469,6 +473,7 @@ resolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED,
if (DECL_SECTION_NAME (decl) == NULL
&& targetm_common.have_named_sections
&& (flag_function_or_data_sections
+ || (HAVE_GAS_SHF_GNU_RETAIN && DECL_PRESERVE_P (decl))
|| DECL_COMDAT_GROUP (decl)))
{
targetm.asm_out.unique_section (decl, reloc);
@@ -1207,7 +1212,8 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
if (vnode)
vnode->get_constructor ();
- if (DECL_COMMON (decl))
+ if (DECL_COMMON (decl)
+ && !(HAVE_GAS_SHF_GNU_RETAIN && DECL_PRESERVE_P (decl)))
{
/* If the decl has been given an explicit section name, or it resides
in a non-generic address space, then it isn't common, and shouldn't
@@ -6745,9 +6751,10 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
/* If we have already declared this section, we can use an
abbreviated form to switch back to it -- unless this section is
- part of a COMDAT groups, in which case GAS requires the full
- declaration every time. */
+ part of a COMDAT groups or with SHF_GNU_RETAIN, in which case GAS
+ requires the full declaration every time. */
if (!(HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
+ && !(flags & SECTION_RETAIN)
&& (flags & SECTION_DECLARED))
{
fprintf (asm_out_file, "\t.section\t%s\n", name);
@@ -6780,6 +6787,8 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
*f++ = TLS_SECTION_ASM_FLAG;
if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
*f++ = 'G';
+ if (flags & SECTION_RETAIN)
+ *f++ = 'R';
#ifdef MACH_DEP_SECTION_ASM_FLAG
if (flags & SECTION_MACH_DEP)
*f++ = MACH_DEP_SECTION_ASM_FLAG;