#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
_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 :
[`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])
@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.
#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. */
}
/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler "\.data.*,\"awR\"" { target R_flag_in_section } } } */
--- /dev/null
+/* { 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 } } } */
--- /dev/null
+/* { 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 } } } */
/* { 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 } } } */
--- /dev/null
+/* { 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;
--- /dev/null
+/* { 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"
}
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
+ }
+ }]
+}
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> ();
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);
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
/* 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);
*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;