aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2019-02-12 01:49:59 +1030
committerAlan Modra <amodra@gcc.gnu.org>2019-02-12 01:49:59 +1030
commitff7fa4886350037f892f9565f5a26c3ecd7ffc16 (patch)
treec3d2121f3766c48ce405a451f410387388c57dd4
parent271ad97b6b353eaa40c1efd6fec3b402af137482 (diff)
downloadgcc-ff7fa4886350037f892f9565f5a26c3ecd7ffc16.zip
gcc-ff7fa4886350037f892f9565f5a26c3ecd7ffc16.tar.gz
gcc-ff7fa4886350037f892f9565f5a26c3ecd7ffc16.tar.bz2
[RS6000] No inline PLT for V4 bss-plt, implement -mno-pltseq
Inline PLT calls need PLT to be an array of addresses. PowerPC 32-bit bss-plt works differently, so this patch disables inline PLT calls when -mbss-plt. The patch also adds support for a new -mno-pltseq option, which may be required when linking with -mbss-plt code. * doc/invoke.texi (man page RS/6000 and PowerPC Options): Mention -mlongcall and -mpltseq. (RS/6000 and PowerPC Options <-mlongcall>): Mention inline PLT calls. (RS/6000 and PowerPC Options <-mpltseq>): Document. * config/rs6000/rs6000.h (TARGET_PLTSEQ): Define. * config/rs6000/sysv4.opt (mpltseq): New option. * config/rs6000/sysv4.h (TARGET_PLTSEQ): Redefine. (SUBTARGET_OVERRIDE_OPTIONS): Error if given -mpltseq when assembler support is lacking. Don't allow -mpltseq with -mbss-plt. * config/rs6000/linux64.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Warn if -mpltseq given for ELFv1. * config/rs6000/rs6000.c (rs6000_call_aix): Comment on UNSPEC_PLTSEQ. Only use UNSPEC_PLTSEQ for inline PLT calls. (rs6000_call_sysv, rs6000_sibcall_sysv): Expand comments. Only use UNSPEC_PLTSEQ for inline PLT calls. (rs6000_indirect_call_template_1, rs6000_longcall_ref), (rs6000_call_aix, rs6000_call_sysv, rs6000_sibcall_sysv): Replace uses of HAVE_AS_PLTSEQ with TARGET_PLTSEQ, simplifying. * config/rs6000/rs6000.md (pltseq_tocsave_<mode>), (pltseq_plt16_ha_<mode>, pltseq_plt16_lo_<mode>), (pltseq_mtctr_<mode>): Likewise. From-SVN: r268770
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/config/rs6000/linux64.h7
-rw-r--r--gcc/config/rs6000/rs6000.c66
-rw-r--r--gcc/config/rs6000/rs6000.h4
-rw-r--r--gcc/config/rs6000/rs6000.md11
-rw-r--r--gcc/config/rs6000/sysv4.h25
-rw-r--r--gcc/config/rs6000/sysv4.opt4
-rw-r--r--gcc/doc/invoke.texi20
8 files changed, 131 insertions, 30 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index bea63a9..b43bf02 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,27 @@
+2019-02-11 Alan Modra <amodra@gmail.com>
+
+ * doc/invoke.texi (man page RS/6000 and PowerPC Options): Mention
+ -mlongcall and -mpltseq.
+ (RS/6000 and PowerPC Options <-mlongcall>): Mention inline PLT calls.
+ (RS/6000 and PowerPC Options <-mpltseq>): Document.
+ * config/rs6000/rs6000.h (TARGET_PLTSEQ): Define.
+ * config/rs6000/sysv4.opt (mpltseq): New option.
+ * config/rs6000/sysv4.h (TARGET_PLTSEQ): Redefine.
+ (SUBTARGET_OVERRIDE_OPTIONS): Error if given -mpltseq when assembler
+ support is lacking. Don't allow -mpltseq with -mbss-plt.
+ * config/rs6000/linux64.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Warn if
+ -mpltseq given for ELFv1.
+ * config/rs6000/rs6000.c (rs6000_call_aix): Comment on UNSPEC_PLTSEQ.
+ Only use UNSPEC_PLTSEQ for inline PLT calls.
+ (rs6000_call_sysv, rs6000_sibcall_sysv): Expand comments. Only
+ use UNSPEC_PLTSEQ for inline PLT calls.
+ (rs6000_indirect_call_template_1, rs6000_longcall_ref),
+ (rs6000_call_aix, rs6000_call_sysv, rs6000_sibcall_sysv): Replace
+ uses of HAVE_AS_PLTSEQ with TARGET_PLTSEQ, simplifying.
+ * config/rs6000/rs6000.md (pltseq_tocsave_<mode>),
+ (pltseq_plt16_ha_<mode>, pltseq_plt16_lo_<mode>),
+ (pltseq_mtctr_<mode>): Likewise.
+
2019-02-11 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* acinclude.m4 (gcc_AC_INITFINI_ARRAY): Use 8-byte strings with
diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h
index 29e9afa..df1d8a9 100644
--- a/gcc/config/rs6000/linux64.h
+++ b/gcc/config/rs6000/linux64.h
@@ -155,6 +155,13 @@ extern int dot_symbols;
TARGET_NO_SUM_IN_TOC = 0; \
} \
} \
+ if (TARGET_PLTSEQ && DEFAULT_ABI != ABI_ELFv2) \
+ { \
+ if (global_options_set.x_rs6000_pltseq) \
+ warning (0, "%qs unsupported for this ABI", \
+ "-mpltseq"); \
+ rs6000_pltseq = false; \
+ } \
} \
else \
{ \
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index b4ff18d..b4db032 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -21665,7 +21665,7 @@ rs6000_indirect_call_template_1 (rtx *operands, unsigned int funop,
|| (REG_P (operands[funop])
&& REGNO (operands[funop]) == LR_REGNO));
- if (!TARGET_MACHO && HAVE_AS_PLTSEQ && GET_CODE (operands[funop]) == UNSPEC)
+ if (TARGET_PLTSEQ && GET_CODE (operands[funop]) == UNSPEC)
{
const char *rel64 = TARGET_64BIT ? "64" : "";
char tls[29];
@@ -32827,8 +32827,7 @@ rs6000_longcall_ref (rtx call_ref, rtx arg)
call_ref = gen_rtx_SYMBOL_REF (VOIDmode, IDENTIFIER_POINTER (node));
}
- if (HAVE_AS_PLTSEQ
- && (DEFAULT_ABI == ABI_ELFv2 || DEFAULT_ABI == ABI_V4))
+ if (TARGET_PLTSEQ)
{
rtx base = const0_rtx;
int regno;
@@ -37793,14 +37792,20 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
rtx call[4];
int n_call;
rtx insn;
+ bool is_pltseq_longcall;
if (global_tlsarg)
tlsarg = global_tlsarg;
/* Handle longcall attributes. */
+ is_pltseq_longcall = false;
if ((INTVAL (cookie) & CALL_LONG) != 0
&& GET_CODE (func_desc) == SYMBOL_REF)
- func = rs6000_longcall_ref (func_desc, tlsarg);
+ {
+ func = rs6000_longcall_ref (func_desc, tlsarg);
+ if (TARGET_PLTSEQ)
+ is_pltseq_longcall = true;
+ }
/* Handle indirect calls. */
if (!SYMBOL_REF_P (func)
@@ -37825,10 +37830,12 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
gen_rtx_PLUS (Pmode, stack_ptr,
stack_toc_offset));
MEM_VOLATILE_P (stack_toc_mem) = 1;
- if (HAVE_AS_PLTSEQ
- && DEFAULT_ABI == ABI_ELFv2
- && GET_CODE (func_desc) == SYMBOL_REF)
+ if (is_pltseq_longcall)
{
+ /* Use USPEC_PLTSEQ here to emit every instruction in an
+ inline PLT call sequence with a reloc, enabling the
+ linker to edit the sequence back to a direct call
+ when that makes sense. */
rtvec v = gen_rtvec (3, toc_reg, func_desc, tlsarg);
rtx mark_toc_reg = gen_rtx_UNSPEC (Pmode, v, UNSPEC_PLTSEQ);
emit_insn (gen_rtx_SET (stack_toc_mem, mark_toc_reg));
@@ -37849,8 +37856,7 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
calls via LR, so move the address there. Needed to mark
this insn for linker plt sequence editing too. */
func_addr = gen_rtx_REG (Pmode, CTR_REGNO);
- if (HAVE_AS_PLTSEQ
- && GET_CODE (func_desc) == SYMBOL_REF)
+ if (is_pltseq_longcall)
{
rtvec v = gen_rtvec (3, abi_reg, func_desc, tlsarg);
rtx mark_func = gen_rtx_UNSPEC (Pmode, v, UNSPEC_PLTSEQ);
@@ -37988,9 +37994,15 @@ rs6000_call_sysv (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
&& GET_CODE (func_desc) == SYMBOL_REF)
{
func = rs6000_longcall_ref (func_desc, tlsarg);
- /* If the longcall was implemented using PLT16 relocs, then r11
- needs to be valid at the call for lazy linking. */
- if (HAVE_AS_PLTSEQ)
+ /* If the longcall was implemented as an inline PLT call using
+ PLT unspecs then func will be REG:r11. If not, func will be
+ a pseudo reg. The inline PLT call sequence supports lazy
+ linking (and longcalls to functions in dlopen'd libraries).
+ The other style of longcalls don't. The lazy linking entry
+ to the dynamic symbol resolver requires r11 be the function
+ address (as it is for linker generated PLT stubs). Ensure
+ r11 stays valid to the bctrl by marking r11 used by the call. */
+ if (TARGET_PLTSEQ)
abi_reg = func;
}
@@ -38000,11 +38012,12 @@ rs6000_call_sysv (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
func = force_reg (Pmode, func);
/* Indirect calls via CTR are strongly preferred over indirect
- calls via LR, so move the address there. Needed to mark
- this insn for linker plt sequence editing too. */
+ calls via LR, so move the address there. That can't be left
+ to reload because we want to mark every instruction in an
+ inline PLT call sequence with a reloc, enabling the linker to
+ edit the sequence back to a direct call when that makes sense. */
func_addr = gen_rtx_REG (Pmode, CTR_REGNO);
- if (HAVE_AS_PLTSEQ
- && GET_CODE (func_desc) == SYMBOL_REF)
+ if (abi_reg)
{
rtvec v = gen_rtvec (3, func, func_desc, tlsarg);
rtx mark_func = gen_rtx_UNSPEC (Pmode, v, UNSPEC_PLTSEQ);
@@ -38058,9 +38071,15 @@ rs6000_sibcall_sysv (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
&& GET_CODE (func_desc) == SYMBOL_REF)
{
func = rs6000_longcall_ref (func_desc, tlsarg);
- /* If the longcall was implemented using PLT16 relocs, then r11
- needs to be valid at the call for lazy linking. */
- if (HAVE_AS_PLTSEQ)
+ /* If the longcall was implemented as an inline PLT call using
+ PLT unspecs then func will be REG:r11. If not, func will be
+ a pseudo reg. The inline PLT call sequence supports lazy
+ linking (and longcalls to functions in dlopen'd libraries).
+ The other style of longcalls don't. The lazy linking entry
+ to the dynamic symbol resolver requires r11 be the function
+ address (as it is for linker generated PLT stubs). Ensure
+ r11 stays valid to the bctr by marking r11 used by the call. */
+ if (TARGET_PLTSEQ)
abi_reg = func;
}
@@ -38069,11 +38088,12 @@ rs6000_sibcall_sysv (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
{
func = force_reg (Pmode, func);
- /* Indirect sibcalls must go via CTR. Needed to mark
- this insn for linker plt sequence editing too. */
+ /* Indirect sibcalls must go via CTR. That can't be left to
+ reload because we want to mark every instruction in an inline
+ PLT call sequence with a reloc, enabling the linker to edit
+ the sequence back to a direct call when that makes sense. */
func_addr = gen_rtx_REG (Pmode, CTR_REGNO);
- if (HAVE_AS_PLTSEQ
- && GET_CODE (func_desc) == SYMBOL_REF)
+ if (abi_reg)
{
rtvec v = gen_rtvec (3, func, func_desc, tlsarg);
rtx mark_func = gen_rtx_UNSPEC (Pmode, v, UNSPEC_PLTSEQ);
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index bfe557d..3b70525 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -226,6 +226,10 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
#define HAVE_AS_PLTSEQ 0
#endif
+#ifndef TARGET_PLTSEQ
+#define TARGET_PLTSEQ 0
+#endif
+
#ifndef TARGET_LINK_STACK
#define TARGET_LINK_STACK 0
#endif
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index d246c30..5bca96b 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -10179,7 +10179,7 @@
(match_operand:P 2 "symbol_ref_operand" "s")
(match_operand:P 3 "" "")]
UNSPEC_PLTSEQ))]
- "HAVE_AS_PLTSEQ
+ "TARGET_PLTSEQ
&& DEFAULT_ABI == ABI_ELFv2"
{
return rs6000_pltseq_template (operands, 0);
@@ -10191,8 +10191,7 @@
(match_operand:P 2 "symbol_ref_operand" "s")
(match_operand:P 3 "" "")]
UNSPEC_PLT16_HA))]
- "HAVE_AS_PLTSEQ
- && (DEFAULT_ABI == ABI_ELFv2 || DEFAULT_ABI == ABI_V4)"
+ "TARGET_PLTSEQ"
{
return rs6000_pltseq_template (operands, 1);
})
@@ -10203,8 +10202,7 @@
(match_operand:P 2 "symbol_ref_operand" "s")
(match_operand:P 3 "" "")]
UNSPEC_PLT16_LO))]
- "HAVE_AS_PLTSEQ
- && (DEFAULT_ABI == ABI_ELFv2 || DEFAULT_ABI == ABI_V4)"
+ "TARGET_PLTSEQ"
{
return rs6000_pltseq_template (operands, 2);
}
@@ -10216,8 +10214,7 @@
(match_operand:P 2 "symbol_ref_operand" "s")
(match_operand:P 3 "" "")]
UNSPEC_PLTSEQ))]
- "HAVE_AS_PLTSEQ
- && (DEFAULT_ABI == ABI_ELFv2 || DEFAULT_ABI == ABI_V4)"
+ "TARGET_PLTSEQ"
{
return rs6000_pltseq_template (operands, 3);
})
diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h
index 22452b3..3861efd 100644
--- a/gcc/config/rs6000/sysv4.h
+++ b/gcc/config/rs6000/sysv4.h
@@ -59,6 +59,11 @@
#define TARGET_SECURE_PLT secure_plt
#endif
+#if HAVE_AS_PLTSEQ
+#undef TARGET_PLTSEQ
+#define TARGET_PLTSEQ rs6000_pltseq
+#endif
+
#define SDATA_DEFAULT_SIZE 8
/* The macro SUBTARGET_OVERRIDE_OPTIONS is provided for subtargets, to
@@ -192,6 +197,26 @@ do { \
error ("%qs not supported by your assembler", "-msecure-plt"); \
} \
\
+ if (TARGET_PLTSEQ != rs6000_pltseq \
+ && global_options_set.x_rs6000_pltseq) \
+ { \
+ error ("%qs not supported by your assembler", "-mpltseq"); \
+ } \
+ \
+ if (DEFAULT_ABI == ABI_V4 && TARGET_PLTSEQ && !TARGET_SECURE_PLT) \
+ { \
+ if (global_options_set.x_rs6000_pltseq) \
+ { \
+ if (global_options_set.x_secure_plt) \
+ error ("%qs and %qs are incompatible", \
+ "-mpltseq", "-mbss-plt"); \
+ else \
+ secure_plt = true; \
+ } \
+ if (!TARGET_SECURE_PLT) \
+ rs6000_pltseq = false; \
+ } \
+ \
if (flag_pic > 1 && DEFAULT_ABI == ABI_V4) \
{ \
/* Note: flag_pic should not change any option flags that would \
diff --git a/gcc/config/rs6000/sysv4.opt b/gcc/config/rs6000/sysv4.opt
index 45399a0..07e6df7 100644
--- a/gcc/config/rs6000/sysv4.opt
+++ b/gcc/config/rs6000/sysv4.opt
@@ -160,6 +160,10 @@ mbss-plt
Target Report RejectNegative Var(secure_plt, 0) Save
Generate code for old exec BSS PLT.
+mpltseq
+Target Report Var(rs6000_pltseq) Init(1) Save
+Use inline plt sequences to implement long calls and -fno-plt.
+
mgnu-attribute
Target Report Var(rs6000_gnu_attr) Init(1) Save
Emit .gnu_attribute tags.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index c625350..f5044a6 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1095,6 +1095,7 @@ See RS/6000 and PowerPC Options.
-mtraceback=@var{traceback_type} @gol
-maix-struct-return -msvr4-struct-return @gol
-mabi=@var{abi-type} -msecure-plt -mbss-plt @gol
+-mlongcall -mno-longcall -mpltseq -mno-pltseq @gol
-mblock-move-inline-limit=@var{num} @gol
-mblock-compare-inline-limit=@var{num} @gol
-mblock-compare-inline-loop-limit=@var{num} @gol
@@ -24834,6 +24835,11 @@ generate slower code. As of this writing, the AIX linker can do this,
as can the GNU linker for PowerPC/64. It is planned to add this feature
to the GNU linker for 32-bit PowerPC systems as well.
+On PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU linkers,
+GCC can generate long calls using an inline PLT call sequence (see
+@option{-mpltseq}). PowerPC with @option{-mbss-plt} and PowerPC64
+ELFv1 (big-endian) do not support inline PLT calls.
+
On Darwin/PPC systems, @code{#pragma longcall} generates @code{jbsr
callee, L42}, plus a @dfn{branch island} (glue code). The two target
addresses represent the callee and the branch island. The
@@ -24851,6 +24857,20 @@ to use or discard it.
In the future, GCC may ignore all longcall specifications
when the linker is known to generate glue.
+@item -mpltseq
+@itemx -mno-pltseq
+@opindex mpltseq
+@opindex mno-pltseq
+Implement (do not implement) -fno-plt and long calls using an inline
+PLT call sequence that supports lazy linking and long calls to
+functions in dlopen'd shared libraries. Inline PLT calls are only
+supported on PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU
+linkers, and are enabled by default if the support is detected when
+configuring GCC, and, in the case of 32-bit PowerPC, if GCC is
+configured with @option{--enable-secureplt}. @option{-mpltseq} code
+and @option{-mbss-plt} 32-bit PowerPC relocatable objects may not be
+linked together.
+
@item -mtls-markers
@itemx -mno-tls-markers
@opindex mtls-markers