974 lines
31 KiB
Diff
974 lines
31 KiB
Diff
From 8ef0203090dab33a177f0b45f6bf69246047e463 Mon Sep 17 00:00:00 2001
|
|
From: "H.J. Lu" <hjl.tools@gmail.com>
|
|
Date: Wed, 2 Dec 2020 05:32:37 -0800
|
|
Subject: [PATCH 19/22] Backport Use the section flag 'o' for
|
|
__patchable_function_entries
|
|
|
|
This commit in GNU binutils 2.35:
|
|
|
|
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=b7d072167715829eed0622616f6ae0182900de3e
|
|
|
|
added the section flag 'o' to .section directive:
|
|
|
|
.section __patchable_function_entries,"awo",@progbits,foo
|
|
|
|
which specifies the symbol name which the section references. Assembler
|
|
creates a unique __patchable_function_entries section with the section,
|
|
where foo is defined, as its linked-to section. Linker keeps a section
|
|
if its linked-to section is kept during garbage collection.
|
|
|
|
This patch checks assembler support for the section flag 'o' and uses
|
|
it to implement __patchable_function_entries section. Since Solaris may
|
|
use GNU assembler with Solairs ld. Even if GNU assembler supports the
|
|
section flag 'o', it doesn't mean that Solairs ld supports it. This
|
|
feature is disabled for Solairs targets.
|
|
|
|
gcc/
|
|
|
|
PR middle-end/93195
|
|
PR middle-end/93197
|
|
* configure.ac (HAVE_GAS_SECTION_LINK_ORDER): New. Define 1 if
|
|
the assembler supports the section flag 'o' for specifying
|
|
section with link-order.
|
|
* output.h (SECTION_LINK_ORDER): New. Defined to 0x8000000.
|
|
(SECTION_MACH_DEP): Changed from 0x8000000 to 0x10000000.
|
|
* targhooks.c (default_print_patchable_function_entry): Pass
|
|
SECTION_LINK_ORDER to switch_to_section if the section flag 'o'
|
|
works. Pass current_function_decl to switch_to_section.
|
|
* varasm.c (default_elf_asm_named_section): Use 'o' flag for
|
|
SECTION_LINK_ORDER if assembler supports it.
|
|
* config.in: Regenerated.
|
|
* configure: Likewise.
|
|
* doc/sourcebuild.texi: Document o_flag_in_section.
|
|
|
|
gcc/testsuite/
|
|
|
|
PR middle-end/93195
|
|
* g++.dg/pr93195b.C: New test.
|
|
* lib/target-supports.exp
|
|
(check_effective_target_o_flag_in_section): New proc.
|
|
---
|
|
gcc/config.in | 13 +
|
|
gcc/configure | 186 ++++++++++
|
|
gcc/configure.ac | 70 ++++
|
|
gcc/doc/sourcebuild.texi | 9 +
|
|
gcc/output.h | 7 +-
|
|
gcc/targhooks.c | 5 +-
|
|
gcc/testsuite/g++.dg/pr93195b.C | 14 +
|
|
gcc/testsuite/lib/target-supports.exp | 493 ++++++++++++++++++++++++++
|
|
gcc/varasm.c | 12 +
|
|
9 files changed, 807 insertions(+), 2 deletions(-)
|
|
create mode 100644 gcc/testsuite/g++.dg/pr93195b.C
|
|
|
|
diff --git a/gcc/config.in b/gcc/config.in
|
|
index eca3fd810fb..12b61991ff2 100644
|
|
--- a/gcc/config.in
|
|
+++ b/gcc/config.in
|
|
@@ -1315,6 +1315,19 @@
|
|
#endif
|
|
|
|
|
|
+/* Define 0/1 if your assembler supports 'o' flag in .section directive. */
|
|
+#ifndef USED_FOR_TARGET
|
|
+#undef HAVE_GAS_SECTION_LINK_ORDER
|
|
+#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 5dab9142e1a..06ff33c271b 100755
|
|
--- a/gcc/configure
|
|
+++ b/gcc/configure
|
|
@@ -23505,6 +23505,192 @@ $as_echo "#define USE_AS_TRADITIONAL_FORMAT 1" >>confdefs.h
|
|
|
|
fi
|
|
|
|
+# Test if the assembler supports the section flag 'e' or #exclude for
|
|
+# specifying an excluded section.
|
|
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section exclude flag" >&5
|
|
+$as_echo_n "checking assembler for section exclude flag... " >&6; }
|
|
+if ${gcc_cv_as_section_exclude_e+:} false; then :
|
|
+ $as_echo_n "(cached) " >&6
|
|
+else
|
|
+ gcc_cv_as_section_exclude_e=no
|
|
+ if test $in_tree_gas = yes; then
|
|
+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 22 \) \* 1000 + 51`
|
|
+ then gcc_cv_as_section_exclude_e=yes
|
|
+fi
|
|
+ elif test x$gcc_cv_as != x; then
|
|
+ $as_echo '.section foo1,"e"
|
|
+ .byte 0,0,0,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_section_exclude_e=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_section_exclude_e" >&5
|
|
+$as_echo "$gcc_cv_as_section_exclude_e" >&6; }
|
|
+
|
|
+
|
|
+if test $gcc_cv_as_section_exclude_e = no; then
|
|
+ case "${target}" in
|
|
+ # Solaris as uses #exclude instead.
|
|
+ *-*-solaris2*)
|
|
+ case "${target}" in
|
|
+ sparc*-*-solaris2*)
|
|
+ conftest_s='.section "foo1", #exclude'
|
|
+ ;;
|
|
+ i?86-*-solaris2* | x86_64-*-solaris2*)
|
|
+ conftest_s='.section foo1, #exclude'
|
|
+ ;;
|
|
+ esac
|
|
+ ;;
|
|
+ esac
|
|
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section exclude flag" >&5
|
|
+$as_echo_n "checking assembler for section exclude flag... " >&6; }
|
|
+if ${gcc_cv_as_section_exclude_hash+:} false; then :
|
|
+ $as_echo_n "(cached) " >&6
|
|
+else
|
|
+ gcc_cv_as_section_exclude_hash=no
|
|
+ if test x$gcc_cv_as != x; then
|
|
+ $as_echo "$conftest_s
|
|
+ .byte 0,0,0,0" > conftest.s
|
|
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -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_section_exclude_hash=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_section_exclude_hash" >&5
|
|
+$as_echo "$gcc_cv_as_section_exclude_hash" >&6; }
|
|
+
|
|
+
|
|
+fi
|
|
+
|
|
+cat >>confdefs.h <<_ACEOF
|
|
+#define 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`
|
|
+_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
|
|
+
|
|
+
|
|
+# Test if the assembler supports the section flag 'o' for specifying
|
|
+# section with link-order.
|
|
+case "${target}" in
|
|
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
|
|
+ # assembler supports the section flag 'o', it doesn't mean that
|
|
+ # Solairs ld supports it.
|
|
+ *-*-solaris2*)
|
|
+ gcc_cv_as_section_link_order=no
|
|
+ ;;
|
|
+ *)
|
|
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section 'o' flag" >&5
|
|
+$as_echo_n "checking assembler for section 'o' flag... " >&6; }
|
|
+if ${gcc_cv_as_section_link_order+:} false; then :
|
|
+ $as_echo_n "(cached) " >&6
|
|
+else
|
|
+ gcc_cv_as_section_link_order=no
|
|
+ if test $in_tree_gas = yes; then
|
|
+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 35 \) \* 1000 + 0`
|
|
+ then gcc_cv_as_section_link_order=yes
|
|
+fi
|
|
+ elif test x$gcc_cv_as != x; then
|
|
+ $as_echo '.section .foo,"a"
|
|
+.byte 0
|
|
+.section __patchable_function_entries,"awo",%progbits,.foo
|
|
+.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_section_link_order=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_section_link_order" >&5
|
|
+$as_echo "$gcc_cv_as_section_link_order" >&6; }
|
|
+
|
|
+
|
|
+ ;;
|
|
+esac
|
|
+
|
|
+cat >>confdefs.h <<_ACEOF
|
|
+#define HAVE_GAS_SECTION_LINK_ORDER `if test $gcc_cv_as_section_link_order = 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 test "${gcc_cv_as_shf_merge+set}" = set; then :
|
|
diff --git a/gcc/configure.ac b/gcc/configure.ac
|
|
index e1fa8af5e4f..8bef9fd27b4 100644
|
|
--- a/gcc/configure.ac
|
|
+++ b/gcc/configure.ac
|
|
@@ -2938,6 +2938,76 @@ if test $gcc_cv_as_eh_frame = buggy; then
|
|
[Define if your assembler mis-optimizes .eh_frame data.])
|
|
fi
|
|
|
|
+# Test if the assembler supports the section flag 'e' or #exclude for
|
|
+# specifying an excluded section.
|
|
+gcc_GAS_CHECK_FEATURE([section exclude flag], gcc_cv_as_section_exclude_e,
|
|
+ [2,22,51], [--fatal-warnings],
|
|
+ [.section foo1,"e"
|
|
+ .byte 0,0,0,0])
|
|
+if test $gcc_cv_as_section_exclude_e = no; then
|
|
+ case "${target}" in
|
|
+ # Solaris as uses #exclude instead.
|
|
+ *-*-solaris2*)
|
|
+ case "${target}" in
|
|
+ sparc*-*-solaris2*)
|
|
+ conftest_s='.section "foo1", #exclude'
|
|
+ ;;
|
|
+ i?86-*-solaris2* | x86_64-*-solaris2*)
|
|
+ conftest_s='.section foo1, #exclude'
|
|
+ ;;
|
|
+ esac
|
|
+ ;;
|
|
+ esac
|
|
+ gcc_GAS_CHECK_FEATURE([section exclude flag], gcc_cv_as_section_exclude_hash,,,
|
|
+ [$conftest_s
|
|
+ .byte 0,0,0,0])
|
|
+fi
|
|
+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.])
|
|
+
|
|
+# Test if the assembler supports the section flag 'o' for specifying
|
|
+# section with link-order.
|
|
+case "${target}" in
|
|
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
|
|
+ # assembler supports the section flag 'o', it doesn't mean that
|
|
+ # Solairs ld supports it.
|
|
+ *-*-solaris2*)
|
|
+ gcc_cv_as_section_link_order=no
|
|
+ ;;
|
|
+ *)
|
|
+ gcc_GAS_CHECK_FEATURE([section 'o' flag], gcc_cv_as_section_link_order,
|
|
+ [2,35,0], [--fatal-warnings],
|
|
+ [.section .foo,"a"
|
|
+.byte 0
|
|
+.section __patchable_function_entries,"awo",%progbits,.foo
|
|
+.byte 0])
|
|
+ ;;
|
|
+esac
|
|
+AC_DEFINE_UNQUOTED(HAVE_GAS_SECTION_LINK_ORDER,
|
|
+ [`if test $gcc_cv_as_section_link_order = yes; then echo 1; else echo 0; fi`],
|
|
+ [Define 0/1 if your assembler supports 'o' flag in .section directive.])
|
|
+
|
|
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 f0e9bb8d35f..6d81c4a937d 100644
|
|
--- a/gcc/doc/sourcebuild.texi
|
|
+++ b/gcc/doc/sourcebuild.texi
|
|
@@ -2072,6 +2072,15 @@ Target uses natural alignment (aligned to type size) for types of
|
|
@item nonpic
|
|
Target does not generate PIC by default.
|
|
|
|
+@item o_flag_in_section
|
|
+Target supports the 'o' flag in .section directive in assembly inputs.
|
|
+
|
|
+@item offload_gcn
|
|
+Target has been configured for OpenACC/OpenMP offloading on AMD GCN.
|
|
+
|
|
+@item persistent
|
|
+Target supports the @code{persistent} variable attribute.
|
|
+
|
|
@item pie_enabled
|
|
Target generates PIE by default.
|
|
|
|
diff --git a/gcc/output.h b/gcc/output.h
|
|
index 7a93fa89cab..049f184e009 100644
|
|
--- a/gcc/output.h
|
|
+++ b/gcc/output.h
|
|
@@ -383,7 +383,12 @@ 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. */
|
|
+#define SECTION_LINK_ORDER 0x8000000 /* section needs link-order. */
|
|
+
|
|
+/* NB: The maximum SECTION_MACH_DEP is 0x10000000 since AVR needs 4 bits
|
|
+ in SECTION_MACH_DEP. */
|
|
+#define SECTION_MACH_DEP 0x10000000 /* 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/targhooks.c b/gcc/targhooks.c
|
|
index 185dc7b0b6b..8aa610f5cde 100644
|
|
--- a/gcc/targhooks.c
|
|
+++ b/gcc/targhooks.c
|
|
@@ -1642,8 +1642,11 @@ default_print_patchable_function_entry (FILE *file,
|
|
patch_area_number++;
|
|
ASM_GENERATE_INTERNAL_LABEL (buf, "LPFE", patch_area_number);
|
|
|
|
+ unsigned int flags = SECTION_WRITE | SECTION_RELRO;
|
|
+ if (HAVE_GAS_SECTION_LINK_ORDER)
|
|
+ flags |= SECTION_LINK_ORDER;
|
|
switch_to_section (get_section ("__patchable_function_entries",
|
|
- SECTION_WRITE | SECTION_RELRO, NULL));
|
|
+ flags, current_function_decl));
|
|
assemble_align (POINTER_SIZE);
|
|
fputs (asm_op, file);
|
|
assemble_name_raw (file, buf);
|
|
diff --git a/gcc/testsuite/g++.dg/pr93195b.C b/gcc/testsuite/g++.dg/pr93195b.C
|
|
new file mode 100644
|
|
index 00000000000..303d8588c0f
|
|
--- /dev/null
|
|
+++ b/gcc/testsuite/g++.dg/pr93195b.C
|
|
@@ -0,0 +1,14 @@
|
|
+/* { dg-do compile { target { ! { nvptx*-*-* visium-*-* } } } } */
|
|
+/* { dg-options "-O0 -fpatchable-function-entry=1" } */
|
|
+/* { dg-additional-options "-fno-pie" { target sparc*-*-* } } */
|
|
+
|
|
+inline void
|
|
+foo (void)
|
|
+{
|
|
+}
|
|
+
|
|
+void
|
|
+bar1 (void)
|
|
+{
|
|
+ foo ();
|
|
+}
|
|
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
|
|
index d33136f7aa4..37d5d5432f8 100644
|
|
--- a/gcc/testsuite/lib/target-supports.exp
|
|
+++ b/gcc/testsuite/lib/target-supports.exp
|
|
@@ -8445,3 +8445,496 @@ proc check_effective_target_arm_coproc4_ok { } {
|
|
return [check_cached_effective_target arm_coproc4_ok \
|
|
check_effective_target_arm_coproc4_ok_nocache]
|
|
}
|
|
+
|
|
+# Return 1 if the target supports the auto_inc_dec optimization pass.
|
|
+proc check_effective_target_autoincdec { } {
|
|
+ if { ![check_no_compiler_messages auto_incdec assembly { void f () { }
|
|
+ } "-O2 -fdump-rtl-auto_inc_dec" ] } {
|
|
+ return 0
|
|
+ }
|
|
+
|
|
+ set dumpfile [glob -nocomplain "auto_incdec[pid].c.\[0-9\]\[0-9\]\[0-9\]r.auto_inc_dec"]
|
|
+ if { [file exists $dumpfile ] } {
|
|
+ file delete $dumpfile
|
|
+ return 1
|
|
+ }
|
|
+ return 0
|
|
+}
|
|
+
|
|
+# Return 1 if the target has support for stack probing designed
|
|
+# to avoid stack-clash style attacks.
|
|
+#
|
|
+# This is used to restrict the stack-clash mitigation tests to
|
|
+# just those targets that have been explicitly supported.
|
|
+#
|
|
+# In addition to the prologue work on those targets, each target's
|
|
+# properties should be described in the functions below so that
|
|
+# tests do not become a mess of unreadable target conditions.
|
|
+#
|
|
+proc check_effective_target_supports_stack_clash_protection { } {
|
|
+
|
|
+ if { [istarget x86_64-*-*] || [istarget i?86-*-*]
|
|
+ || [istarget powerpc*-*-*] || [istarget rs6000*-*-*]
|
|
+ || [istarget aarch64*-**] || [istarget s390*-*-*] } {
|
|
+ return 1
|
|
+ }
|
|
+ return 0
|
|
+}
|
|
+
|
|
+# Return 1 if the target creates a frame pointer for non-leaf functions
|
|
+# Note we ignore cases where we apply tail call optimization here.
|
|
+proc check_effective_target_frame_pointer_for_non_leaf { } {
|
|
+ # Solaris/x86 defaults to -fno-omit-frame-pointer.
|
|
+ if { [istarget i?86-*-solaris*] || [istarget x86_64-*-solaris*] } {
|
|
+ return 1
|
|
+ }
|
|
+
|
|
+ return 0
|
|
+}
|
|
+
|
|
+# Return 1 if the target's calling sequence or its ABI
|
|
+# create implicit stack probes at or prior to function entry.
|
|
+proc check_effective_target_caller_implicit_probes { } {
|
|
+
|
|
+ # On x86/x86_64 the call instruction itself pushes the return
|
|
+ # address onto the stack. That is an implicit probe of *sp.
|
|
+ if { [istarget x86_64-*-*] || [istarget i?86-*-*] } {
|
|
+ return 1
|
|
+ }
|
|
+
|
|
+ # On PPC, the ABI mandates that the address of the outer
|
|
+ # frame be stored at *sp. Thus each allocation of stack
|
|
+ # space is itself an implicit probe of *sp.
|
|
+ if { [istarget powerpc*-*-*] || [istarget rs6000*-*-*] } {
|
|
+ return 1
|
|
+ }
|
|
+
|
|
+ # s390's ABI has a register save area allocated by the
|
|
+ # caller for use by the callee. The mere existence does
|
|
+ # not constitute a probe by the caller, but when the slots
|
|
+ # used by the callee those stores are implicit probes.
|
|
+ if { [istarget s390*-*-*] } {
|
|
+ return 1
|
|
+ }
|
|
+
|
|
+ # Not strictly true on aarch64, but we have agreed that we will
|
|
+ # consider any function that pushes SP more than 3kbytes into
|
|
+ # the guard page as broken. This essentially means that we can
|
|
+ # consider the aarch64 as having a caller implicit probe at
|
|
+ # *(sp + 1k).
|
|
+ if { [istarget aarch64*-*-*] } {
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ return 0
|
|
+}
|
|
+
|
|
+# Targets that potentially realign the stack pointer often cause residual
|
|
+# stack allocations and make it difficult to elimination loops or residual
|
|
+# allocations for dynamic stack allocations
|
|
+proc check_effective_target_callee_realigns_stack { } {
|
|
+ if { [istarget x86_64-*-*] || [istarget i?86-*-*] } {
|
|
+ return 1
|
|
+ }
|
|
+ return 0
|
|
+}
|
|
+
|
|
+# Return 1 if CET instructions can be compiled.
|
|
+proc check_effective_target_cet { } {
|
|
+ if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
|
|
+ return 0
|
|
+ }
|
|
+ return [check_no_compiler_messages cet object {
|
|
+ void foo (void)
|
|
+ {
|
|
+ asm ("setssbsy");
|
|
+ }
|
|
+ } "-O2 -fcf-protection" ]
|
|
+}
|
|
+
|
|
+# Return 1 if target supports floating point "infinite"
|
|
+proc check_effective_target_inf { } {
|
|
+ return [check_no_compiler_messages supports_inf assembly {
|
|
+ const double pinf = __builtin_inf ();
|
|
+ }]
|
|
+}
|
|
+
|
|
+# Return 1 if target supports floating point "infinite" for float.
|
|
+proc check_effective_target_inff { } {
|
|
+ return [check_no_compiler_messages supports_inff assembly {
|
|
+ const float pinf = __builtin_inff ();
|
|
+ }]
|
|
+}
|
|
+
|
|
+# Return 1 if the target supports ARMv8.3 Adv.SIMD Complex instructions
|
|
+# instructions, 0 otherwise. The test is valid for ARM and for AArch64.
|
|
+# Record the command line options needed.
|
|
+
|
|
+proc check_effective_target_arm_v8_3a_complex_neon_ok_nocache { } {
|
|
+ global et_arm_v8_3a_complex_neon_flags
|
|
+ set et_arm_v8_3a_complex_neon_flags ""
|
|
+
|
|
+ if { ![istarget arm*-*-*] && ![istarget aarch64*-*-*] } {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ # Iterate through sets of options to find the compiler flags that
|
|
+ # need to be added to the -march option.
|
|
+ foreach flags {"" "-mfloat-abi=softfp -mfpu=auto" "-mfloat-abi=hard -mfpu=auto"} {
|
|
+ if { [check_no_compiler_messages_nocache \
|
|
+ arm_v8_3a_complex_neon_ok object {
|
|
+ #if !defined (__ARM_FEATURE_COMPLEX)
|
|
+ #error "__ARM_FEATURE_COMPLEX not defined"
|
|
+ #endif
|
|
+ } "$flags -march=armv8.3-a"] } {
|
|
+ set et_arm_v8_3a_complex_neon_flags "$flags -march=armv8.3-a"
|
|
+ return 1
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+proc check_effective_target_arm_v8_3a_complex_neon_ok { } {
|
|
+ return [check_cached_effective_target arm_v8_3a_complex_neon_ok \
|
|
+ check_effective_target_arm_v8_3a_complex_neon_ok_nocache]
|
|
+}
|
|
+
|
|
+proc add_options_for_arm_v8_3a_complex_neon { flags } {
|
|
+ if { ! [check_effective_target_arm_v8_3a_complex_neon_ok] } {
|
|
+ return "$flags"
|
|
+ }
|
|
+ global et_arm_v8_3a_complex_neon_flags
|
|
+ return "$flags $et_arm_v8_3a_complex_neon_flags"
|
|
+}
|
|
+
|
|
+# Return 1 if the target supports executing AdvSIMD instructions from ARMv8.3
|
|
+# with the complex instruction extension, 0 otherwise. The test is valid for
|
|
+# ARM and for AArch64.
|
|
+
|
|
+proc check_effective_target_arm_v8_3a_complex_neon_hw { } {
|
|
+ if { ![check_effective_target_arm_v8_3a_complex_neon_ok] } {
|
|
+ return 0;
|
|
+ }
|
|
+ return [check_runtime arm_v8_3a_complex_neon_hw_available {
|
|
+ #include "arm_neon.h"
|
|
+ int
|
|
+ main (void)
|
|
+ {
|
|
+
|
|
+ float32x2_t results = {-4.0,5.0};
|
|
+ float32x2_t a = {1.0,3.0};
|
|
+ float32x2_t b = {2.0,5.0};
|
|
+
|
|
+ #ifdef __ARM_ARCH_ISA_A64
|
|
+ asm ("fcadd %0.2s, %1.2s, %2.2s, #90"
|
|
+ : "=w"(results)
|
|
+ : "w"(a), "w"(b)
|
|
+ : /* No clobbers. */);
|
|
+
|
|
+ #else
|
|
+ asm ("vcadd.f32 %P0, %P1, %P2, #90"
|
|
+ : "=w"(results)
|
|
+ : "w"(a), "w"(b)
|
|
+ : /* No clobbers. */);
|
|
+ #endif
|
|
+
|
|
+ return (results[0] == 8 && results[1] == 24) ? 1 : 0;
|
|
+ }
|
|
+ } [add_options_for_arm_v8_3a_complex_neon ""]]
|
|
+}
|
|
+
|
|
+# Return 1 if the assembler supports assembling the Armv8.3 pointer authentication B key directive
|
|
+proc check_effective_target_arm_v8_3a_bkey_directive { } {
|
|
+ return [check_no_compiler_messages cet object {
|
|
+ int main(void) {
|
|
+ asm (".cfi_b_key_frame");
|
|
+ return 0;
|
|
+ }
|
|
+ }]
|
|
+}
|
|
+
|
|
+# Return 1 if the target supports executing the Armv8.1-M Mainline Low
|
|
+# Overhead Loop, 0 otherwise. The test is valid for ARM.
|
|
+
|
|
+proc check_effective_target_arm_v8_1_lob_ok { } {
|
|
+ if { ![check_effective_target_arm_cortex_m] } {
|
|
+ return 0;
|
|
+ } else {
|
|
+ return [check_runtime arm_v8_1_lob_hw_available {
|
|
+ int
|
|
+ main (void)
|
|
+ { int i = 0;
|
|
+ asm ("movw r3, #10\n\t" /* movs? */
|
|
+ "dls lr, r3" : : : "r3", "lr");
|
|
+ loop:
|
|
+ i++;
|
|
+ asm goto ("le lr, %l0" : : : "lr" : loop);
|
|
+ return i != 10;
|
|
+ }
|
|
+ } "-march=armv8.1-m.main -mthumb" ]
|
|
+ }
|
|
+}
|
|
+
|
|
+# Return 1 is this is an ARM target where -mthumb causes Thumb-2 to be
|
|
+# used and the target does not support executing the Armv8.1-M
|
|
+# Mainline Low Overhead Loop, 0 otherwise. The test is valid for ARM.
|
|
+
|
|
+proc check_effective_target_arm_thumb2_ok_no_arm_v8_1_lob { } {
|
|
+ if { [check_effective_target_arm_thumb2_ok]
|
|
+ && ![check_effective_target_arm_v8_1_lob_ok] } {
|
|
+ return 1
|
|
+ }
|
|
+ return 0
|
|
+}
|
|
+
|
|
+# Returns 1 if the target is using glibc, 0 otherwise.
|
|
+
|
|
+proc check_effective_target_glibc { } {
|
|
+ return [check_no_compiler_messages glibc_object assembly {
|
|
+ #include <stdlib.h>
|
|
+ #if !defined(__GLIBC__)
|
|
+ #error undefined
|
|
+ #endif
|
|
+ }]
|
|
+}
|
|
+
|
|
+# Return 1 if the target plus current options supports a vector
|
|
+# complex addition with rotate of half and single float modes, 0 otherwise.
|
|
+#
|
|
+# This won't change for different subtargets so cache the result.
|
|
+
|
|
+foreach N {hf sf} {
|
|
+ eval [string map [list N $N] {
|
|
+ proc check_effective_target_vect_complex_rot_N { } {
|
|
+ return [check_cached_effective_target_indexed vect_complex_rot_N {
|
|
+ expr { [istarget aarch64*-*-*]
|
|
+ || [istarget arm*-*-*] }}]
|
|
+ }
|
|
+ }]
|
|
+}
|
|
+
|
|
+# Return 1 if the target plus current options supports a vector
|
|
+# complex addition with rotate of double float modes, 0 otherwise.
|
|
+#
|
|
+# This won't change for different subtargets so cache the result.
|
|
+
|
|
+foreach N {df} {
|
|
+ eval [string map [list N $N] {
|
|
+ proc check_effective_target_vect_complex_rot_N { } {
|
|
+ return [check_cached_effective_target_indexed vect_complex_rot_N {
|
|
+ expr { [istarget aarch64*-*-*] }}]
|
|
+ }
|
|
+ }]
|
|
+}
|
|
+
|
|
+# Return 1 if this target uses an LLVM assembler and/or linker
|
|
+proc check_effective_target_llvm_binutils { } {
|
|
+ return [check_cached_effective_target llvm_binutils {
|
|
+ expr { [istarget amdgcn*-*-*]
|
|
+ || [check_effective_target_offload_gcn] }}]
|
|
+}
|
|
+
|
|
+# Return 1 if the compiler supports '-mfentry'.
|
|
+
|
|
+proc check_effective_target_mfentry { } {
|
|
+ if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
|
|
+ return 0
|
|
+ }
|
|
+ return [check_no_compiler_messages mfentry object {
|
|
+ void foo (void) { }
|
|
+ } "-mfentry"]
|
|
+}
|
|
+
|
|
+# Return 1 if this target supports indirect calls
|
|
+proc check_effective_target_indirect_calls { } {
|
|
+ if { [istarget bpf-*-*] } {
|
|
+ return 0
|
|
+ }
|
|
+ return 1
|
|
+}
|
|
+
|
|
+# Return 1 if we can use the -lgccjit option, 0 otherwise.
|
|
+
|
|
+proc check_effective_target_lgccjit { } {
|
|
+ if { [info procs jit_target_compile] == "" } then {
|
|
+ global GCC_UNDER_TEST
|
|
+ if ![info exists GCC_UNDER_TEST] {
|
|
+ set GCC_UNDER_TEST "[find_gcc]"
|
|
+ }
|
|
+ proc jit_target_compile { source dest type options } [info body gcc_target_compile]
|
|
+ }
|
|
+ return [check_no_compiler_messages lgccjit executable {
|
|
+ int main() { return 0; }
|
|
+ } "-lgccjit"]
|
|
+}
|
|
+
|
|
+# Return 1 if the MSP430 small memory model is in use.
|
|
+proc check_effective_target_msp430_small {} {
|
|
+ return [check_no_compiler_messages msp430_small assembly {
|
|
+ #if (!defined __MSP430__ || defined __MSP430X_LARGE__)
|
|
+ #error !msp430 || __MSP430X_LARGE__
|
|
+ #endif
|
|
+ } ""]
|
|
+}
|
|
+
|
|
+# Return 1 if the MSP430 large memory model is in use.
|
|
+proc check_effective_target_msp430_large {} {
|
|
+ return [check_no_compiler_messages msp430_large assembly {
|
|
+ #ifndef __MSP430X_LARGE__
|
|
+ #error __MSP430X_LARGE__
|
|
+ #endif
|
|
+ } ""]
|
|
+}
|
|
+
|
|
+# Return 1 if the target has an efficient means to encode large initializers
|
|
+# in the assembly.
|
|
+
|
|
+proc check_effective_target_large_initializer { } {
|
|
+ if { [istarget nvptx*-*-*] } {
|
|
+ return 0
|
|
+ }
|
|
+
|
|
+ return 1
|
|
+}
|
|
+
|
|
+# Return 1 if the target allows function prototype mismatches
|
|
+# in the assembly.
|
|
+
|
|
+proc check_effective_target_non_strict_prototype { } {
|
|
+ if { [istarget nvptx*-*-*] } {
|
|
+ return 0
|
|
+ }
|
|
+
|
|
+ return 1
|
|
+}
|
|
+
|
|
+# Returns 1 if the target toolchain supports extended
|
|
+# syntax of .symver directive, 0 otherwise.
|
|
+
|
|
+proc check_symver_available { } {
|
|
+ return [check_no_compiler_messages symver_available object {
|
|
+ int foo(void) { return 0; }
|
|
+ int main (void) {
|
|
+ asm volatile (".symver foo,foo@VER_1, local");
|
|
+ return 0;
|
|
+ }
|
|
+ }]
|
|
+}
|
|
+
|
|
+# Return 1 if emitted assembly contains .ident directive.
|
|
+
|
|
+proc check_effective_target_ident_directive {} {
|
|
+ return [check_no_messages_and_pattern ident_directive \
|
|
+ "(?n)^\[\t\]+\\.ident" assembly {
|
|
+ int i;
|
|
+ }]
|
|
+}
|
|
+
|
|
+# Return 1 if we're able to assemble movdiri and movdir64b
|
|
+
|
|
+proc check_effective_target_movdir { } {
|
|
+ return [check_no_compiler_messages movdir object {
|
|
+ void
|
|
+ foo (unsigned int *d, unsigned int s)
|
|
+ {
|
|
+ __builtin_ia32_directstoreu_u32 (d, s);
|
|
+ }
|
|
+ void
|
|
+ bar (void *d, const void *s)
|
|
+ {
|
|
+ __builtin_ia32_movdir64b (d, s);
|
|
+ }
|
|
+ } "-mmovdiri -mmovdir64b" ]
|
|
+}
|
|
+
|
|
+# Return 1 if target is not support address sanitize, 1 otherwise.
|
|
+
|
|
+proc check_effective_target_no_fsanitize_address {} {
|
|
+ if ![check_no_compiler_messages fsanitize_address executable {
|
|
+ int main (void) { return 0; }
|
|
+ }] {
|
|
+ return 1;
|
|
+ }
|
|
+ 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
|
|
+ }
|
|
+ }]
|
|
+}
|
|
+
|
|
+# Return 1 if this target supports 'o' flag in .section directive, 0
|
|
+# otherwise. Cache the result.
|
|
+
|
|
+proc check_effective_target_o_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 o_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_SECTION_LINK_ORDER == 0"
|
|
+ puts $f "# error Assembler does not support 'o' flag in .section directive."
|
|
+ puts $f "#endif"
|
|
+ close $f
|
|
+
|
|
+ verbose "check_effective_target_o_flag_in_section compiling testfile $src" 2
|
|
+ set lines [${tool}_target_compile $src $obj object ""]
|
|
+
|
|
+ file delete $src
|
|
+ file delete $obj
|
|
+
|
|
+ if [string match "" $lines] then {
|
|
+ verbose "check_effective_target_o_flag_in_section testfile compilation passed" 2
|
|
+ return 1
|
|
+ } else {
|
|
+ verbose "check_effective_target_o_flag_in_section testfile compilation failed" 2
|
|
+ return 0
|
|
+ }
|
|
+ }]
|
|
+}
|
|
diff --git a/gcc/varasm.c b/gcc/varasm.c
|
|
index 8d4c0386fe3..7b0792ddaed 100644
|
|
--- a/gcc/varasm.c
|
|
+++ b/gcc/varasm.c
|
|
@@ -6398,6 +6398,10 @@ 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';
|
|
+ if (flags & SECTION_LINK_ORDER)
|
|
+ *f++ = 'o';
|
|
#ifdef MACH_DEP_SECTION_ASM_FLAG
|
|
if (flags & SECTION_MACH_DEP)
|
|
*f++ = MACH_DEP_SECTION_ASM_FLAG;
|
|
@@ -6426,6 +6430,14 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
|
|
|
|
if (flags & SECTION_ENTSIZE)
|
|
fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
|
|
+ if (flags & SECTION_LINK_ORDER)
|
|
+ {
|
|
+ tree id = DECL_ASSEMBLER_NAME (decl);
|
|
+ ultimate_transparent_alias_target (&id);
|
|
+ const char *name = IDENTIFIER_POINTER (id);
|
|
+ name = targetm.strip_name_encoding (name);
|
|
+ fprintf (asm_out_file, ",%s", name);
|
|
+ }
|
|
if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
|
|
{
|
|
if (TREE_CODE (decl) == IDENTIFIER_NODE)
|
|
--
|
|
2.33.1
|
|
|