[RS6000] No inline PLT for V4 bss-plt, implement -mno-pltseq
authorAlan Modra <amodra@gmail.com>
Mon, 11 Feb 2019 15:19:59 +0000 (01:49 +1030)
committerAlan Modra <amodra@gcc.gnu.org>
Mon, 11 Feb 2019 15:19:59 +0000 (01:49 +1030)
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

gcc/ChangeLog
gcc/config/rs6000/linux64.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/sysv4.h
gcc/config/rs6000/sysv4.opt
gcc/doc/invoke.texi

index bea63a9e09a2ccfc8637efb6a9c0bc547545a055..b43bf022066f18ec769bdde155123a2343d90929 100644 (file)
@@ -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
index 29e9afa7f3d9e198186a68af49f956180ff10bd0..df1d8a9f45a63880e14f25782f19ebeb20ec078a 100644 (file)
@@ -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                                                     \
        {                                                       \
index b4ff18d414c34501b0c1435782bd1c7e4a31b813..b4db03203a24abde5890b3900c1ce83cc8ab60a2 100644 (file)
@@ -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);
index bfe557d63250895d1e994ae4c2e16fc0edfe88ed..3b7052552192db6840d278e9bbfb267169d89633 100644 (file)
@@ -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
index d246c30d13686b12b8f8968953a8813a552e784d..5bca96b70d13ab5b748d4739b58d2f5ce8c8f19d 100644 (file)
                   (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);
 })
index 22452b3c4f09e3bc6341864bda7a22f0566ca81e..3861efdfee6fcd95a9ff792f22c0134797c2ed74 100644 (file)
 #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  \
index 45399a088061c88d47c1d50d5cb122983b4550d6..07e6df72495553d0ccc6db9a993bd41de85ccc35 100644 (file)
@@ -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.
index c625350d04d19efaab4c7dffcc112a40ad898f12..f5044a6294d5be0c6411bf5fd696e9940d971ad3 100644 (file)
@@ -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