+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
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 \
{ \
|| (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];
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;
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)
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));
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);
&& 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;
}
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);
&& 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;
}
{
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);
#define HAVE_AS_PLTSEQ 0
#endif
+#ifndef TARGET_PLTSEQ
+#define TARGET_PLTSEQ 0
+#endif
+
#ifndef TARGET_LINK_STACK
#define TARGET_LINK_STACK 0
#endif
(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);
(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);
})
(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);
}
(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);
})
#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
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 \
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.
-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
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
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