rs6000, update Darwin call handling to latest scheme.
authorIain Sandoe <iain@sandoe.co.uk>
Wed, 12 Dec 2018 08:47:16 +0000 (08:47 +0000)
committerIain Sandoe <iains@gcc.gnu.org>
Wed, 12 Dec 2018 08:47:16 +0000 (08:47 +0000)
This patch mormalises Darwin's call handling to match the scheme
recently introduced and gives it target-specific call expanders.

2018-12-12  Iain Sandoe  <iain@sandoe.co.uk>

* config/rs6000/rs6000-protos.h (rs6000_call_darwin): New.
(rs6000_sibcall_darwin): New. (macho_call_template): Remove.
* config/rs6000/rs6000.c (get_prev_label): Forward declaration.
(rs6000_call_template_1): Handle Darwin.
(macho_call_template): Remove.
(rs6000_call_sysv): Remove handling for Darwin.
(rs6000_call_darwin_1, rs6000_call_darwin): New
(rs6000_sibcall_darwin): New.
* config/rs6000/rs6000.md (define_expand “call”): Handle Darwin
with its own expander. (define_expand “call_value”): Likewise.
(define_expand “sibcall”): Likewise.
(define_expand “sibcall_value”): Likewise.
(call_nonlocal_sysv): Remove Darwin special-casing.
(call_value_nonlocal_sysv): Likewise.

From-SVN: r267048

gcc/ChangeLog
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md

index 2fba17e1ffc0f23fc2152089500338bfb4cf9b17..c561bce2627f8013730d6a93442f7c3387802132 100644 (file)
@@ -1,3 +1,20 @@
+2018-12-12  Iain Sandoe  <iain@sandoe.co.uk>
+
+       * config/rs6000/rs6000-protos.h (rs6000_call_darwin): New.
+       (rs6000_sibcall_darwin): New. (macho_call_template): Remove.
+       * config/rs6000/rs6000.c (get_prev_label): Forward declaration. 
+       (rs6000_call_template_1): Handle Darwin.
+       (macho_call_template): Remove.
+       (rs6000_call_sysv): Remove handling for Darwin.
+       (rs6000_call_darwin_1, rs6000_call_darwin): New
+       (rs6000_sibcall_darwin): New.
+       * config/rs6000/rs6000.md (define_expand “call”): Handle Darwin
+       with its own expander. (define_expand “call_value”): Likewise.
+       (define_expand “sibcall”): Likewise.
+       (define_expand “sibcall_value”): Likewise.
+       (call_nonlocal_sysv): Remove Darwin special-casing.
+       (call_value_nonlocal_sysv): Likewise.
+
 2018-12-12  Iain Sandoe  <iain@sandoe.co.uk>
 
        * config/rs6000/darwin.md (call_indirect_nonlocal_darwin64): Remove.
index dfee1f28aa9ed3d4907999ee21c576fb6342be3e..5ac864e83eedd7d29f38a7c963033930d0fc7d50 100644 (file)
@@ -199,6 +199,8 @@ extern void rs6000_call_aix (rtx, rtx, rtx, rtx);
 extern void rs6000_sibcall_aix (rtx, rtx, rtx, rtx);
 extern void rs6000_call_sysv (rtx, rtx, rtx, rtx);
 extern void rs6000_sibcall_sysv (rtx, rtx, rtx, rtx);
+extern void rs6000_call_darwin (rtx, rtx, rtx, rtx);
+extern void rs6000_sibcall_darwin (rtx, rtx, rtx, rtx);
 extern void rs6000_aix_asm_output_dwarf_table_ref (char *);
 extern void get_ppc476_thunk_name (char name[32]);
 extern bool rs6000_overloaded_builtin_p (enum rs6000_builtins);
@@ -226,10 +228,6 @@ extern void (*rs6000_target_modify_macros_ptr) (bool, HOST_WIDE_INT,
 /* Declare functions in rs6000-d.c  */
 extern void rs6000_d_target_versions (void);
 
-#if TARGET_MACHO
-char *macho_call_template (rtx_insn *, rtx *, int, int);
-#endif
-
 #ifdef NO_DOLLAR_IN_LABEL
 const char * rs6000_xcoff_strip_dollar (const char *);
 #endif
index 5c7207598b6788559d8fef433aca411f5ce8ab83..5beb8dfe24af2936982b49c4c9509ad4cde3b112 100644 (file)
@@ -1364,6 +1364,7 @@ static rtx rs6000_darwin64_record_arg (CUMULATIVE_ARGS *, const_tree,
                                       bool, bool);
 #if TARGET_MACHO
 static void macho_branch_islands (void);
+static tree get_prev_label (tree);
 #endif
 static rtx rs6000_legitimize_reload_address (rtx, machine_mode, int, int,
                                             int, int *);
@@ -21534,13 +21535,39 @@ rs6000_call_template_1 (rtx *operands, unsigned int funop, bool sibcall)
            ? "+32768" : ""));
 
   static char str[32];  /* 2 spare */
-  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2
-      || DEFAULT_ABI == ABI_DARWIN)
+  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     sprintf (str, "b%s %s%s%s", sibcall ? "" : "l", z, arg,
             sibcall ? "" : "\n\tnop");
   else if (DEFAULT_ABI == ABI_V4)
     sprintf (str, "b%s %s%s%s", sibcall ? "" : "l", z, arg,
             flag_pic ? "@plt" : "");
+#if TARGET_MACHO
+  /* If/when we remove the mlongcall opt, we can share the AIX/ELGv2 case. */
+   else if (DEFAULT_ABI == ABI_DARWIN)
+    {
+      /* The cookie is in operand func+2.  */
+      gcc_checking_assert (GET_CODE (operands[funop + 2]) == CONST_INT);
+      int cookie = INTVAL (operands[funop + 2]);
+      if (cookie & CALL_LONG)
+       {
+         tree funname = get_identifier (XSTR (operands[funop], 0));
+         tree labelname = get_prev_label (funname);
+         gcc_checking_assert (labelname && !sibcall);
+
+         /* "jbsr foo, L42" is Mach-O for "Link as 'bl foo' if a 'bl'
+            instruction will reach 'foo', otherwise link as 'bl L42'".
+            "L42" should be a 'branch island', that will do a far jump to
+            'foo'.  Branch islands are generated in
+            macho_branch_islands().  */
+         sprintf (str, "jbsr %%z%u,%.10s", funop,
+                  IDENTIFIER_POINTER (labelname));
+       }
+      else
+        /* Same as AIX or ELFv2, except to keep backwards compat, no nop
+          after the call.  */
+       sprintf (str, "b%s %s%s", sibcall ? "" : "l", z, arg);
+    }
+#endif
   else
     gcc_unreachable ();
   return str;
@@ -37959,7 +37986,6 @@ rs6000_call_sysv (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
 
   /* Handle longcall attributes.  */
   if ((INTVAL (cookie) & CALL_LONG) != 0
-      && DEFAULT_ABI != ABI_DARWIN /* Darwin does it's own thing.  */
       && GET_CODE (func_desc) == SYMBOL_REF)
     {
       func = rs6000_longcall_ref (func_desc, tlsarg);
@@ -38000,14 +38026,8 @@ rs6000_call_sysv (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
   if (value != NULL_RTX)
     call[0] = gen_rtx_SET (value, call[0]);
 
-  if (DEFAULT_ABI == ABI_DARWIN && TARGET_32BIT)
-    call[1] = gen_rtx_USE (VOIDmode, GEN_INT (INTVAL (cookie)));
-  else
-    {
-      unsigned int mask = CALL_V4_SET_FP_ARGS | CALL_V4_CLEAR_FP_ARGS;
-      call[1] = gen_rtx_USE (VOIDmode, GEN_INT (INTVAL (cookie) & mask));
-    }
-
+  unsigned int mask = CALL_V4_SET_FP_ARGS | CALL_V4_CLEAR_FP_ARGS;
+  call[1] = gen_rtx_USE (VOIDmode, GEN_INT (INTVAL (cookie) & mask));
   call[2] = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNO));
 
   insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (3, call));
@@ -38081,6 +38101,121 @@ rs6000_sibcall_sysv (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
     use_reg (&CALL_INSN_FUNCTION_USAGE (insn), abi_reg);
 }
 
+#if TARGET_MACHO
+
+/* Expand code to perform a call under the Darwin ABI.
+   Modulo handling of mlongcall, this is much the same as sysv.
+   if/when the longcall optimisation is removed, we could drop this
+   code and use the sysv case (taking care to avoid the tls stuff).
+
+   We can use this for sibcalls too, if needed.  */
+
+void
+rs6000_call_darwin_1 (rtx value, rtx func_desc, rtx tlsarg,
+                     rtx cookie, bool sibcall)
+{
+  rtx func = func_desc;
+  rtx func_addr;
+  rtx call[3];
+  rtx insn;
+  int cookie_val = INTVAL (cookie);
+  bool make_island = false;
+
+  /* Handle longcall attributes, there are two cases for Darwin:
+     1) Newer linkers are capable of synthesising any branch islands needed.
+     2) We need a helper branch island synthesised by the compiler.
+     The second case has mostly been retired and we don't use it for m64.
+     In fact, it's is an optimisation, we could just indirect as sysv does..
+     ... however, backwards compatibility for now.
+     If we're going to use this, then we need to keep the CALL_LONG bit set,
+     so that we can pick up the special insn form later.  */
+  if ((cookie_val & CALL_LONG) != 0
+      && GET_CODE (func_desc) == SYMBOL_REF)
+    {
+      if (darwin_emit_branch_islands && TARGET_32BIT)
+       make_island = true; /* Do nothing yet, retain the CALL_LONG flag.  */
+      else
+       {
+         /* The linker is capable of doing this, but the user explicitly
+            asked for -mlongcall, so we'll do the 'normal' version.  */
+         func = rs6000_longcall_ref (func_desc, NULL_RTX);
+         cookie_val &= ~CALL_LONG; /* Handled, zap it.  */
+       }
+    }
+
+  /* Handle indirect calls.  */
+  if (GET_CODE (func) != SYMBOL_REF)
+    {
+      func = force_reg (Pmode, func);
+
+      /* Indirect calls via CTR are strongly preferred over indirect
+        calls via LR, and are required for indirect sibcalls, so move
+        the address there.   */
+      func_addr = gen_rtx_REG (Pmode, CTR_REGNO);
+      emit_move_insn (func_addr, func);
+    }
+  else
+    func_addr = func;
+
+  /* Create the call.  */
+  call[0] = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (SImode, func_addr), tlsarg);
+  if (value != NULL_RTX)
+    call[0] = gen_rtx_SET (value, call[0]);
+
+  call[1] = gen_rtx_USE (VOIDmode, GEN_INT (cookie_val));
+
+  if (sibcall)
+    call[2] = simple_return_rtx;
+  else
+    call[2] = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNO));
+
+  insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (3, call));
+  insn = emit_call_insn (insn);
+  /* Now we have the debug info in the insn, we can set up the branch island
+     if we're using one.  */
+  if (make_island)
+    {
+      tree funname = get_identifier (XSTR (func_desc, 0));
+
+      if (no_previous_def (funname))
+       {
+         rtx label_rtx = gen_label_rtx ();
+         char *label_buf, temp_buf[256];
+         ASM_GENERATE_INTERNAL_LABEL (temp_buf, "L",
+                                      CODE_LABEL_NUMBER (label_rtx));
+         label_buf = temp_buf[0] == '*' ? temp_buf + 1 : temp_buf;
+         tree labelname = get_identifier (label_buf);
+         add_compiler_branch_island (labelname, funname,
+                                    insn_line ((const rtx_insn*)insn));
+       }
+     }
+}
+#endif
+
+void
+rs6000_call_darwin (rtx value ATTRIBUTE_UNUSED, rtx func_desc ATTRIBUTE_UNUSED,
+                   rtx tlsarg ATTRIBUTE_UNUSED, rtx cookie ATTRIBUTE_UNUSED)
+{
+#if TARGET_MACHO
+  rs6000_call_darwin_1 (value, func_desc, tlsarg, cookie, false);
+#else
+  gcc_unreachable();
+#endif
+}
+
+
+void
+rs6000_sibcall_darwin (rtx value ATTRIBUTE_UNUSED, rtx func_desc ATTRIBUTE_UNUSED,
+                      rtx tlsarg ATTRIBUTE_UNUSED, rtx cookie ATTRIBUTE_UNUSED)
+{
+#if TARGET_MACHO
+  rs6000_call_darwin_1 (value, func_desc, tlsarg, cookie, true);
+#else
+  gcc_unreachable();
+#endif
+}
+
+
 /* Return whether we need to always update the saved TOC pointer when we update
    the stack pointer.  */
 
index fa77e45145912b4f5f6e377f9ff89fc50593a5d8..4499371a50b29d641fe925d6d3b618d213e083aa 100644 (file)
 
   if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     rs6000_call_aix (NULL_RTX, operands[0], operands[1], operands[2]);
-  else
+  else if (DEFAULT_ABI == ABI_V4)
     rs6000_call_sysv (NULL_RTX, operands[0], operands[1], operands[2]);
+  else if (DEFAULT_ABI == ABI_DARWIN)
+    rs6000_call_darwin (NULL_RTX, operands[0], operands[1], operands[2]);
+  else
+    gcc_unreachable ();
 
   DONE;
 })
 
   if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     rs6000_call_aix (operands[0], operands[1], operands[2], operands[3]);
-  else
+  else if (DEFAULT_ABI == ABI_V4)
     rs6000_call_sysv (operands[0], operands[1], operands[2], operands[3]);
+  else if (DEFAULT_ABI == ABI_DARWIN)
+    rs6000_call_darwin (operands[0], operands[1], operands[2], operands[3]);
+  else
+    gcc_unreachable ();
 
   DONE;
 })
   else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
     output_asm_insn ("creqv 6,6,6", operands);
 
-#if TARGET_MACHO
-  return macho_call_template (insn, operands, 0, 2);
-#else
   return rs6000_call_template (operands, 0);
-#endif
 }
   "DEFAULT_ABI == ABI_V4
    && TARGET_SECURE_PLT && flag_pic && !SYMBOL_REF_LOCAL_P (operands[0])
   else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
     output_asm_insn ("creqv 6,6,6", operands);
 
-#if TARGET_MACHO
-  return macho_call_template (insn, operands, 1, 3);
-#else
   return rs6000_call_template (operands, 1);
-#endif
 }
   "DEFAULT_ABI == ABI_V4
    && TARGET_SECURE_PLT && flag_pic && !SYMBOL_REF_LOCAL_P (operands[1])
 
   if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     rs6000_sibcall_aix (NULL_RTX, operands[0], operands[1], operands[2]);
-  else
+  else if (DEFAULT_ABI == ABI_V4)
     rs6000_sibcall_sysv (NULL_RTX, operands[0], operands[1], operands[2]);
+  else if (DEFAULT_ABI == ABI_DARWIN)
+    rs6000_sibcall_darwin (NULL_RTX, operands[0], operands[1], operands[2]);
+  else
+    gcc_unreachable ();
 
   DONE;
 })
 
   if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     rs6000_sibcall_aix (operands[0], operands[1], operands[2], operands[3]);
-  else
+  else if (DEFAULT_ABI == ABI_V4)
     rs6000_sibcall_sysv (operands[0], operands[1], operands[2], operands[3]);
+  else if (DEFAULT_ABI == ABI_DARWIN)
+    rs6000_sibcall_darwin (operands[0], operands[1], operands[2], operands[3]);
+  else
+    gcc_unreachable ();
 
   DONE;
 })