diff mbox series

[1/6,RS6000] rs6000_output_call for external call insn assembly output

Message ID 20181107053715.GN29482@bubble.grove.modra.org
State New
Headers show
Series inline plt call support | expand

Commit Message

Alan Modra Nov. 7, 2018, 5:37 a.m. UTC
This is a first step in tidying rs6000 call patterns, in preparation
to support inline plt calls.

	* config/rs6000/rs6000-protos.h (rs6000_output_call): Declare.
	(macho_output_call): Rename from output_call.
	* config/rs6000/rs6000.c (rs6000_output_call): New function.
	(macho_output_call): Rename from output_call.
	* config/rs6000/rs6000.md (tls_gd_aix): Use rs6000_output_call
	to emit call.
	(tls_gd_sysv, tls_gd_call_aix, tls_gd_call_sysv): Likewise.
	(tls_ld_aix, tls_ld_sysv, tls_ld_call_aix): Likewise.
	(tls_ld_call_sysv, call_nonlocal_sysv): Likewise.
	(call_nonlocal_sysv_secure, call_value_nonlocal_sysv): Likewise.
	(call_value_nonlocal_sysv_secure, call_nonlocal_aix): Likewise.
	(call_value_nonlocal_aix, sibcall_nonlocal_sysv): Likewise.
	(sibcall_value_nonlocal_sysv, sibcall_aix): Likewise.
	(sibcall_value_aix): Likewise.

Comments

Segher Boessenkool Nov. 8, 2018, 12:08 a.m. UTC | #1
On Wed, Nov 07, 2018 at 04:07:15PM +1030, Alan Modra wrote:
> +extern const char *rs6000_output_call (rtx *, unsigned int, bool, const char *);

Maybe have a separate rs6000_output_call and rs6000_output_sibcall?  Bare
boolean function parameters aren't great.  (They can of course both call
rs6000_output_call_1 or whatever, if that makes sense).

> --- a/gcc/config/rs6000/rs6000.c
> +++ b/gcc/config/rs6000/rs6000.c
> @@ -21380,6 +21380,37 @@ rs6000_assemble_integer (rtx x, unsigned int size, int aligned_p)
>    return default_assemble_integer (x, size, aligned_p);
>  }
>  
> +/* Return a template string for assembly to emit when making an
> +   external call.  FUN is the %z argument, ARG is either NULL or
> +   a @TLSGD or @TLSLD __tls_get_addr argument specifier.  */
> +
> +const char *
> +rs6000_output_call (rtx *operands, unsigned int fun, bool sibcall,
> +		    const char *arg)
> +{
> +  /* -Wformat-overflow workaround, without which gcc thinks that %u
> +      might produce 10 digits.  FUN is 0 or 1 as of 2018-03.  */
> +  gcc_assert (fun <= 6);

So "fun" is the operand number.  Rename it, and use MAX_RECOG_OPERANDS
instead of 6?  And allow for it to take 2 or 3 chars to print :-)

"operands" is unused here, compiling this will warn.

"output" is a lie, this function doesn't output anything.  Hardly the
only case of this in the rs6000 port, but it is annoying.  What would be
a good name for this...  "rs6000_template_for_call"?


Are there some patterns that can be collapsed to one after this?


Segher
Alan Modra Nov. 8, 2018, 1:21 p.m. UTC | #2
On Wed, Nov 07, 2018 at 06:08:33PM -0600, Segher Boessenkool wrote:
> On Wed, Nov 07, 2018 at 04:07:15PM +1030, Alan Modra wrote:
> > +extern const char *rs6000_output_call (rtx *, unsigned int, bool, const char *);
> 
> Maybe have a separate rs6000_output_call and rs6000_output_sibcall?  Bare
> boolean function parameters aren't great.  (They can of course both call
> rs6000_output_call_1 or whatever, if that makes sense).
> 
> > --- a/gcc/config/rs6000/rs6000.c
> > +++ b/gcc/config/rs6000/rs6000.c
> > @@ -21380,6 +21380,37 @@ rs6000_assemble_integer (rtx x, unsigned int size, int aligned_p)
> >    return default_assemble_integer (x, size, aligned_p);
> >  }
> >  
> > +/* Return a template string for assembly to emit when making an
> > +   external call.  FUN is the %z argument, ARG is either NULL or
> > +   a @TLSGD or @TLSLD __tls_get_addr argument specifier.  */
> > +
> > +const char *
> > +rs6000_output_call (rtx *operands, unsigned int fun, bool sibcall,
> > +		    const char *arg)
> > +{
> > +  /* -Wformat-overflow workaround, without which gcc thinks that %u
> > +      might produce 10 digits.  FUN is 0 or 1 as of 2018-03.  */
> > +  gcc_assert (fun <= 6);
> 
> So "fun" is the operand number.  Rename it, and use MAX_RECOG_OPERANDS
> instead of 6?  And allow for it to take 2 or 3 chars to print :-)

Eh, so I can't have a little fun?  funop then?  (It's the index of the
call operand that has the function symref or whatever to call.)

> "operands" is unused here, compiling this will warn.

Oops, I did bootstrap each patch individually at one stage..
Probably happened when I edited the patchset, to reduce the size of
later changes.  rs6000_output_call didn't have "operands" to start
with.

> "output" is a lie, this function doesn't output anything.  Hardly the
> only case of this in the rs6000 port, but it is annoying.  What would be
> a good name for this...  "rs6000_template_for_call"?

OK, I went with rs6000_call_template and rs6000_sibcall_template.
Next patch also changed to use rs6000_indirect_call_template and
rs6000_indirect_sibcall_template.  Final patch uses
rs6000_pltseq_template.

> Are there some patterns that can be collapsed to one after this?

No, I don't think so.  Patch 5/6 does some of that for TLS calls.
diff mbox series

Patch

diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index fb69019c47c..f1a421dde16 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -111,6 +111,7 @@  extern int ccr_bit (rtx, int);
 extern void rs6000_output_function_entry (FILE *, const char *);
 extern void print_operand (FILE *, rtx, int);
 extern void print_operand_address (FILE *, rtx);
+extern const char *rs6000_output_call (rtx *, unsigned int, bool, const char *);
 extern enum rtx_code rs6000_reverse_condition (machine_mode,
 					       enum rtx_code);
 extern rtx rs6000_emit_eqne (machine_mode, rtx, rtx, rtx);
@@ -228,7 +229,7 @@  extern void (*rs6000_target_modify_macros_ptr) (bool, HOST_WIDE_INT,
 extern void rs6000_d_target_versions (void);
 
 #if TARGET_MACHO
-char *output_call (rtx_insn *, rtx *, int, int);
+char *macho_output_call (rtx_insn *, rtx *, int, int);
 #endif
 
 #ifdef NO_DOLLAR_IN_LABEL
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 75b197f458c..b22cae55a0d 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -21380,6 +21380,37 @@  rs6000_assemble_integer (rtx x, unsigned int size, int aligned_p)
   return default_assemble_integer (x, size, aligned_p);
 }
 
+/* Return a template string for assembly to emit when making an
+   external call.  FUN is the %z argument, ARG is either NULL or
+   a @TLSGD or @TLSLD __tls_get_addr argument specifier.  */
+
+const char *
+rs6000_output_call (rtx *operands, unsigned int fun, bool sibcall,
+		    const char *arg)
+{
+  /* -Wformat-overflow workaround, without which gcc thinks that %u
+      might produce 10 digits.  FUN is 0 or 1 as of 2018-03.  */
+  gcc_assert (fun <= 6);
+
+  /* The magic 32768 offset here corresponds to the offset of
+     r30 in .got2, as given by LCTOC1.  See sysv4.h:toc_section.  */
+  char z[10];
+  sprintf (z, "%%z%u%s", fun,
+	   (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT && flag_pic == 2
+	    ? "+32768" : ""));
+
+  static char str[32];  /* 5 spare */
+  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+    sprintf (str, "b%s %s%s%s", "l" + sibcall, z, arg,
+	     sibcall ? "" : "\n\tnop");
+  else if (DEFAULT_ABI == ABI_V4)
+    sprintf (str, "b%s %s%s%s", "l" + sibcall, z, arg,
+	     flag_pic ? "@plt" : "");
+  else
+    gcc_unreachable ();
+  return str;
+}
+
 #if defined (HAVE_GAS_HIDDEN) && !TARGET_MACHO
 /* Emit an assembler directive to set symbol visibility for DECL to
    VISIBILITY_TYPE.  */
@@ -32818,8 +32849,8 @@  get_prev_label (tree function_name)
    CALL_DEST is the routine we are calling.  */
 
 char *
-output_call (rtx_insn *insn, rtx *operands, int dest_operand_number,
-	     int cookie_operand_number)
+macho_output_call (rtx_insn *insn, rtx *operands, int dest_operand_number,
+		      int cookie_operand_number)
 {
   static char buf[256];
   if (darwin_emit_branch_islands
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 66742f66a89..52088fdfbdb 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -9454,10 +9454,11 @@  (define_insn_and_split "tls_gd_aix<TLSmode:tls_abi_suffix>"
   "HAVE_AS_TLS && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
 {
   if (TARGET_CMODEL != CMODEL_SMALL)
-    return "addis %0,%1,%2@got@tlsgd@ha\;addi %0,%0,%2@got@tlsgd@l\;"
-	   "bl %z3\;nop";
+    output_asm_insn ("addis %0,%1,%2@got@tlsgd@ha\;"
+		     "addi %0,%0,%2@got@tlsgd@l", operands);
   else
-    return "addi %0,%1,%2@got@tlsgd\;bl %z3\;nop";
+    output_asm_insn ("addi %0,%1,%2@got@tlsgd", operands);
+  return rs6000_output_call (operands, 3, false, "");
 }
   "&& TARGET_TLS_MARKERS"
   [(set (match_dup 0)
@@ -9486,15 +9487,8 @@  (define_insn_and_split "tls_gd_sysv<TLSmode:tls_sysv_suffix>"
    (clobber (reg:SI LR_REGNO))]
   "HAVE_AS_TLS && DEFAULT_ABI == ABI_V4"
 {
-  if (flag_pic)
-    {
-      if (TARGET_SECURE_PLT && flag_pic == 2)
-	return "addi %0,%1,%2@got@tlsgd\;bl %z3+32768@plt";
-      else
-	return "addi %0,%1,%2@got@tlsgd\;bl %z3@plt";
-    }
-  else
-    return "addi %0,%1,%2@got@tlsgd\;bl %z3";
+  output_asm_insn ("addi %0,%1,%2@got@tlsgd", operands);
+  return rs6000_output_call (operands, 3, false, "");
 }
   "&& TARGET_TLS_MARKERS"
   [(set (match_dup 0)
@@ -9559,7 +9553,9 @@  (define_insn "*tls_gd_call_aix<TLSmode:tls_abi_suffix>"
    (clobber (reg:SI LR_REGNO))]
   "HAVE_AS_TLS && TARGET_TLS_MARKERS
    && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
-  "bl %z1(%3@tlsgd)\;nop"
+{
+  return rs6000_output_call (operands, 1, false, "(%3@tlsgd)");
+}
   [(set_attr "type" "branch")
    (set_attr "length" "8")])
 
@@ -9572,13 +9568,7 @@  (define_insn "*tls_gd_call_sysv<TLSmode:tls_abi_suffix>"
    (clobber (reg:SI LR_REGNO))]
   "HAVE_AS_TLS && DEFAULT_ABI == ABI_V4 && TARGET_TLS_MARKERS"
 {
-  if (flag_pic)
-    {
-      if (TARGET_SECURE_PLT && flag_pic == 2)
-	return "bl %z1+32768(%3@tlsgd)@plt";
-      return "bl %z1(%3@tlsgd)@plt";
-    }
-  return "bl %z1(%3@tlsgd)";
+  return rs6000_output_call (operands, 1, false, "(%3@tlsgd)");
 }
   [(set_attr "type" "branch")])
 
@@ -9592,10 +9582,11 @@  (define_insn_and_split "tls_ld_aix<TLSmode:tls_abi_suffix>"
   "HAVE_AS_TLS && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
 {
   if (TARGET_CMODEL != CMODEL_SMALL)
-    return "addis %0,%1,%&@got@tlsld@ha\;addi %0,%0,%&@got@tlsld@l\;"
-	   "bl %z2\;nop";
+    output_asm_insn ("addis %0,%1,%&@got@tlsld@ha\;"
+		     "addi %0,%0,%&@got@tlsld@l", operands);
   else
-    return "addi %0,%1,%&@got@tlsld\;bl %z2\;nop";
+    output_asm_insn ("addi %0,%1,%&@got@tlsld", operands);
+  return rs6000_output_call (operands, 2, false, "");
 }
   "&& TARGET_TLS_MARKERS"
   [(set (match_dup 0)
@@ -9622,15 +9613,8 @@  (define_insn_and_split "tls_ld_sysv<TLSmode:tls_sysv_suffix>"
    (clobber (reg:SI LR_REGNO))]
   "HAVE_AS_TLS && DEFAULT_ABI == ABI_V4"
 {
-  if (flag_pic)
-    {
-      if (TARGET_SECURE_PLT && flag_pic == 2)
-	return "addi %0,%1,%&@got@tlsld\;bl %z2+32768@plt";
-      else
-	return "addi %0,%1,%&@got@tlsld\;bl %z2@plt";
-    }
-  else
-    return "addi %0,%1,%&@got@tlsld\;bl %z2";
+  output_asm_insn ("addi %0,%1,%&@got@tlsld", operands);
+  return rs6000_output_call (operands, 2, false, "");
 }
   "&& TARGET_TLS_MARKERS"
   [(set (match_dup 0)
@@ -9691,7 +9675,9 @@  (define_insn "*tls_ld_call_aix<TLSmode:tls_abi_suffix>"
    (clobber (reg:SI LR_REGNO))]
   "HAVE_AS_TLS && TARGET_TLS_MARKERS
    && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
-  "bl %z1(%&@tlsld)\;nop"
+{
+  return rs6000_output_call (operands, 1, false, "(%&@tlsld)");
+}
   [(set_attr "type" "branch")
    (set_attr "length" "8")])
 
@@ -9703,13 +9689,7 @@  (define_insn "*tls_ld_call_sysv<TLSmode:tls_abi_suffix>"
    (clobber (reg:SI LR_REGNO))]
   "HAVE_AS_TLS && DEFAULT_ABI == ABI_V4 && TARGET_TLS_MARKERS"
 {
-  if (flag_pic)
-    {
-      if (TARGET_SECURE_PLT && flag_pic == 2)
-	return "bl %z1+32768(%&@tlsld)@plt";
-      return "bl %z1(%&@tlsld)@plt";
-    }
-  return "bl %z1(%&@tlsld)";
+  return rs6000_output_call (operands, 1, false, "(%&@tlsld)");
 }
   [(set_attr "type" "branch")])
 
@@ -10595,15 +10575,9 @@  (define_insn_and_split "*call_nonlocal_sysv<mode>"
     output_asm_insn ("creqv 6,6,6", operands);
 
 #if TARGET_MACHO
-  return output_call(insn, operands, 0, 2);
+  return macho_output_call(insn, operands, 0, 2);
 #else
-  if (DEFAULT_ABI == ABI_V4 && flag_pic)
-    {
-      gcc_assert (!TARGET_SECURE_PLT);
-      return "bl %z0@plt";
-    }
-  else
-    return "bl %z0";
+  return rs6000_output_call (operands, 0, false, "");
 #endif
 }
   "DEFAULT_ABI == ABI_V4
@@ -10636,13 +10610,7 @@  (define_insn "*call_nonlocal_sysv_secure<mode>"
   else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
     output_asm_insn ("creqv 6,6,6", operands);
 
-  if (flag_pic == 2)
-    /* The magic 32768 offset here and in the other sysv call insns
-       corresponds to the offset of r30 in .got2, as given by LCTOC1.
-       See sysv4.h:toc_section.  */
-    return "bl %z0+32768@plt";
-  else
-    return "bl %z0@plt";
+  return rs6000_output_call (operands, 0, false, "");
 }
   [(set_attr "type" "branch,branch")
    (set_attr "length" "4,8")])
@@ -10698,15 +10666,9 @@  (define_insn_and_split "*call_value_nonlocal_sysv<mode>"
     output_asm_insn ("creqv 6,6,6", operands);
 
 #if TARGET_MACHO
-  return output_call(insn, operands, 1, 3);
+  return macho_output_call(insn, operands, 1, 3);
 #else
-  if (DEFAULT_ABI == ABI_V4 && flag_pic)
-    {
-      gcc_assert (!TARGET_SECURE_PLT);
-      return "bl %z1@plt";
-    }
-  else
-    return "bl %z1";
+  return rs6000_output_call (operands, 1, false, "");
 #endif
 }
   "DEFAULT_ABI == ABI_V4
@@ -10741,10 +10703,7 @@  (define_insn "*call_value_nonlocal_sysv_secure<mode>"
   else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
     output_asm_insn ("creqv 6,6,6", operands);
 
-  if (flag_pic == 2)
-    return "bl %z1+32768@plt";
-  else
-    return "bl %z1@plt";
+  return rs6000_output_call (operands, 1, false, "");
 }
   [(set_attr "type" "branch,branch")
    (set_attr "length" "4,8")])
@@ -10777,7 +10736,9 @@  (define_insn "*call_nonlocal_aix<mode>"
 	 (match_operand 1 "" "g"))
    (clobber (reg:P LR_REGNO))]
   "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
-  "bl %z0\;nop"
+{
+  return rs6000_output_call (operands, 0, false, "");
+}
   [(set_attr "type" "branch")
    (set_attr "length" "8")])
 
@@ -10787,7 +10748,9 @@  (define_insn "*call_value_nonlocal_aix<mode>"
 	      (match_operand 2 "" "g")))
    (clobber (reg:P LR_REGNO))]
   "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
-  "bl %z1\;nop"
+{
+  return rs6000_output_call (operands, 1, false, "");
+}
   [(set_attr "type" "branch")
    (set_attr "length" "8")])
 
@@ -11064,13 +11027,8 @@  (define_insn "*sibcall_nonlocal_sysv<mode>"
 	/* Can use CR0 since it is volatile across sibcalls.  */
 	return "crset 2\;beq%T0-\;b $";
     }
-  else if (DEFAULT_ABI == ABI_V4 && flag_pic)
-    {
-      gcc_assert (!TARGET_SECURE_PLT);
-      return "b %z0@plt";
-    }
   else
-    return "b %z0";
+    return rs6000_output_call (operands, 0, true, "");
 }
   [(set_attr "type" "branch")
    (set_attr_alternative "length"
@@ -11109,13 +11067,8 @@  (define_insn "*sibcall_value_nonlocal_sysv<mode>"
 	/* Can use CR0 since it is volatile across sibcalls.  */
 	return "crset 2\;beq%T1-\;b $";
     }
-  else if (DEFAULT_ABI == ABI_V4 && flag_pic)
-    {
-      gcc_assert (!TARGET_SECURE_PLT);
-      return "b %z1@plt";
-    }
   else
-    return "b %z1";
+    return rs6000_output_call (operands, 1, true, "");
 }
   [(set_attr "type" "branch")
    (set_attr_alternative "length"
@@ -11137,9 +11090,12 @@  (define_insn "*sibcall_aix<mode>"
 	 (match_operand 1 "" "g,g"))
    (simple_return)]
   "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
-  "@
-   b %z0
-   b%T0"
+{
+  if (which_alternative == 0)
+    return rs6000_output_call (operands, 0, true, "");
+  else
+    return "b%T0";
+}
   [(set_attr "type" "branch")])
 
 (define_insn "*sibcall_value_aix<mode>"
@@ -11148,9 +11104,12 @@  (define_insn "*sibcall_value_aix<mode>"
 	      (match_operand 2 "" "g,g")))
    (simple_return)]
   "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
-  "@
-   b %z1
-   b%T1"
+{
+  if (which_alternative == 0)
+    return rs6000_output_call (operands, 1, true, "");
+  else
+    return "b%T1";
+}
   [(set_attr "type" "branch")])
 
 (define_expand "sibcall_epilogue"