> On 3 Dec 2018, at 01:28, Iain Sandoe <i...@sandoe.co.uk> wrote:

> The second patch normalises Darwin’s call handling to follow the same pattern 
> that Alan introduced recently.

revised version, on top of the revised patch 1 attached.  I’ve taken the 
opportunity to reduce the number of TARGET_MACHO conditionals in rs6000.md 
(handle in rs6000.c instead)

Iain

> Hopefully it makes it clearer where there are differences (actually quite 
> small in this case, but enough to make it better to separate the lowering).  
> It isn’t needed to fix bootstrap, but it was a good time to figure it out 
> when dealing with this.
> 
> OK for trunk / next stage #1 / comments?
> Iain
> 
> gcc/
> 
>       * config/rs6000/rs6000-protos.h (rs6000_call_darwin, 
> 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, save cookie value.
>       (rs6000_call_darwin_1, rs6000_call_darwin, 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 cf45459dc7f317bcf5f415219884e6b846fe01a1 Mon Sep 17 00:00:00 2001
> From: Iain Sandoe <i...@sandoe.co.uk>
> Date: Sat, 1 Dec 2018 16:23:20 +0000
> Subject: [PATCH] [darwin,ppc] Update call expansions to follow the new scheme.
> 
> This also makes it a bit more apparent what we can remove when the
> mlongcall optimisation is removed.
> ---
> gcc/config/rs6000/rs6000-protos.h |   8 +-
> gcc/config/rs6000/rs6000.c        | 195 +++++++++++++++++++++---------
> gcc/config/rs6000/rs6000.md       |  47 +++++--
> 3 files changed, 180 insertions(+), 70 deletions(-)
> 
> diff --git a/gcc/config/rs6000/rs6000-protos.h 
> b/gcc/config/rs6000/rs6000-protos.h
> index dfee1f28aa..6d2b7ed917 100644
> --- a/gcc/config/rs6000/rs6000-protos.h
> +++ b/gcc/config/rs6000/rs6000-protos.h
> @@ -199,6 +199,10 @@ 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);
> +#if TARGET_MACHO
> +extern void rs6000_call_darwin (rtx, rtx, rtx, rtx);
> +extern void rs6000_sibcall_darwin (rtx, rtx, rtx, rtx);
> +#endif
> 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 +230,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
> diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
> index bce968516c..5fef3fa036 100644
> --- a/gcc/config/rs6000/rs6000.c
> +++ b/gcc/config/rs6000/rs6000.c
> @@ -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 *);
> @@ -21513,13 +21514,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/ELFv2 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;
> @@ -33167,49 +33194,6 @@ get_prev_label (tree function_name)
>   return NULL_TREE;
> }
> 
> -/* INSN is either a function call or a millicode call.  It may have an
> -   unconditional jump in its delay slot.
> -
> -   CALL_DEST is the routine we are calling.  */
> -
> -char *
> -macho_call_template (rtx_insn *insn, rtx *operands, int dest_operand_number,
> -                  int cookie_operand_number)
> -{
> -  static char buf[256];
> -  if (darwin_emit_branch_islands
> -      && GET_CODE (operands[dest_operand_number]) == SYMBOL_REF
> -      && (INTVAL (operands[cookie_operand_number]) & CALL_LONG))
> -    {
> -      tree labelname;
> -      tree funname = get_identifier (XSTR (operands[dest_operand_number], 
> 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;
> -       labelname = get_identifier (label_buf);
> -       add_compiler_branch_island (labelname, funname, insn_line (insn));
> -     }
> -      else
> -     labelname = get_prev_label (funname);
> -
> -      /* "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 (buf, "jbsr %%z%d,%.246s",
> -            dest_operand_number, IDENTIFIER_POINTER (labelname));
> -    }
> -  else
> -    sprintf (buf, "bl %%z%d", dest_operand_number);
> -  return buf;
> -}
> -
> /* Generate PIC and indirect symbol stubs.  */
> 
> void
> @@ -37932,13 +37916,13 @@ rs6000_call_sysv (rtx value, rtx func_desc, rtx 
> tlsarg, rtx cookie)
>   rtx call[3];
>   rtx insn;
>   rtx abi_reg = NULL_RTX;
> +  int cookie_val = INTVAL (cookie);
> 
>   if (global_tlsarg)
>     tlsarg = global_tlsarg;
> 
>   /* Handle longcall attributes.  */
> -  if ((INTVAL (cookie) & CALL_LONG) != 0
> -      && DEFAULT_ABI != ABI_DARWIN /* Darwin does it's own thing.  */
> +  if ((cookie_val & CALL_LONG) != 0
>       && GET_CODE (func_desc) == SYMBOL_REF)
>     {
>       func = rs6000_longcall_ref (func_desc, tlsarg);
> @@ -37979,14 +37963,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 (cookie_val & mask));
>   call[2] = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNO));
> 
>   insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (3, call));
> @@ -38060,6 +38038,113 @@ 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));
> +     }
> +     }
> +}
> +
> +void
> +rs6000_call_darwin (rtx value, rtx func_desc,
> +                 rtx tlsarg ATTRIBUTE_UNUSED, rtx cookie)
> +{
> +  rs6000_call_darwin_1 (value, func_desc, tlsarg, cookie, false);
> +}
> +
> +
> +void
> +rs6000_sibcall_darwin (rtx value, rtx func_desc,
> +                    rtx tlsarg ATTRIBUTE_UNUSED, rtx cookie)
> +{
> +  rs6000_call_darwin_1 (value, func_desc, tlsarg, cookie, true);
> +}
> +
> +#endif
> +
> /* Return whether we need to always update the saved TOC pointer when we 
> update
>    the stack pointer.  */
> 
> diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
> index d684bed3ae..e4a71439ef 100644
> --- a/gcc/config/rs6000/rs6000.md
> +++ b/gcc/config/rs6000/rs6000.md
> @@ -10289,12 +10289,20 @@
>       DONE;
>     }
> 
> -  if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN)
> +  if (DEFAULT_ABI == ABI_V4)
>     {
>       rs6000_call_sysv (NULL_RTX, operands[0], operands[1], operands[2]);
>       DONE;
>     }
> 
> +#if TARGET_MACHO
> +  if (DEFAULT_ABI == ABI_DARWIN)
> +    {
> +      rs6000_call_darwin (NULL_RTX, operands[0], operands[1], operands[2]);
> +      DONE;
> +    }
> +#endif
> +
>   if (GET_CODE (operands[0]) != SYMBOL_REF)
>     operands[0] = force_reg (Pmode, operands[0]);
> })
> @@ -10322,12 +10330,20 @@
>       DONE;
>     }
> 
> -  if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN)
> +  if (DEFAULT_ABI == ABI_V4)
>     {
>       rs6000_call_sysv (operands[0], operands[1], operands[2], operands[3]);
>       DONE;
>     }
> 
> +#if TARGET_MACHO
> +  if (DEFAULT_ABI == ABI_DARWIN)
> +    {
> +      rs6000_call_darwin (operands[0], operands[1], operands[2], 
> operands[3]);
> +      DONE;
> +    }
> +#endif
> +
>   if (GET_CODE (operands[1]) != SYMBOL_REF)
>     operands[1] = force_reg (Pmode, operands[1]);
> })
> @@ -10463,11 +10479,7 @@
>   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])
> @@ -10549,11 +10561,7 @@
>   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])
> @@ -10771,6 +10779,14 @@
>       rs6000_sibcall_sysv (NULL_RTX, operands[0], operands[1], operands[2]);
>       DONE;
>     }
> +
> +#if TARGET_MACHO
> +  if (DEFAULT_ABI == ABI_DARWIN)
> +    {
> +      rs6000_sibcall_darwin (NULL_RTX, operands[0], operands[1], 
> operands[2]);
> +      DONE;
> +    }
> +#endif
> })
> 
> (define_expand "sibcall_value"
> @@ -10797,11 +10813,20 @@
>       DONE;
>     }
> 
> -  if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN)
> +  if (DEFAULT_ABI == ABI_V4)
>     {
>       rs6000_sibcall_sysv (operands[0], operands[1], operands[2], 
> operands[3]);
>       DONE;
>     }
> +
> +#if TARGET_MACHO
> +  if (DEFAULT_ABI == ABI_DARWIN)
> +    {
> +      rs6000_sibcall_darwin (operands[0], operands[1],
> +                          operands[2], operands[3]);
> +      DONE;
> +    }
> +#endif
> })
> 
> (define_insn "*sibcall_local32"
> -- 
> 2.17.1
From 82ac030d49fd2ae78b75a350c5efc59375df42a6 Mon Sep 17 00:00:00 2001
From: Iain Sandoe <i...@sandoe.co.uk>
Date: Sat, 1 Dec 2018 16:23:20 +0000
Subject: [PATCH] [darwin,ppc] Update call expansions to follow the new scheme.

This also makes it a bit more apparent what we can remove when the
mlongcall optimisation is removed.
---
 gcc/config/rs6000/rs6000-protos.h |   6 +-
 gcc/config/rs6000/rs6000.c        | 205 ++++++++++++++++++++++--------
 gcc/config/rs6000/rs6000.md       |  24 ++--
 3 files changed, 163 insertions(+), 72 deletions(-)

diff --git a/gcc/config/rs6000/rs6000-protos.h 
b/gcc/config/rs6000/rs6000-protos.h
index dfee1f28aa..5ac864e83e 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -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
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index bce968516c..a036a3cb50 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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 *);
@@ -21513,13 +21514,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;
@@ -33122,7 +33149,7 @@ macho_branch_islands (void)
        }
       else
        {
-         strcat (tmp_buf, ":\nlis r12,hi16(");
+         strcat (tmp_buf, ":\n\tlis r12,hi16(");
          strcat (tmp_buf, name_buf);
          strcat (tmp_buf, ")\n\tori r12,r12,lo16(");
          strcat (tmp_buf, name_buf);
@@ -33167,49 +33194,6 @@ get_prev_label (tree function_name)
   return NULL_TREE;
 }
 
-/* INSN is either a function call or a millicode call.  It may have an
-   unconditional jump in its delay slot.
-
-   CALL_DEST is the routine we are calling.  */
-
-char *
-macho_call_template (rtx_insn *insn, rtx *operands, int dest_operand_number,
-                    int cookie_operand_number)
-{
-  static char buf[256];
-  if (darwin_emit_branch_islands
-      && GET_CODE (operands[dest_operand_number]) == SYMBOL_REF
-      && (INTVAL (operands[cookie_operand_number]) & CALL_LONG))
-    {
-      tree labelname;
-      tree funname = get_identifier (XSTR (operands[dest_operand_number], 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;
-         labelname = get_identifier (label_buf);
-         add_compiler_branch_island (labelname, funname, insn_line (insn));
-       }
-      else
-       labelname = get_prev_label (funname);
-
-      /* "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 (buf, "jbsr %%z%d,%.246s",
-              dest_operand_number, IDENTIFIER_POINTER (labelname));
-    }
-  else
-    sprintf (buf, "bl %%z%d", dest_operand_number);
-  return buf;
-}
-
 /* Generate PIC and indirect symbol stubs.  */
 
 void
@@ -37932,13 +37916,13 @@ rs6000_call_sysv (rtx value, rtx func_desc, rtx 
tlsarg, rtx cookie)
   rtx call[3];
   rtx insn;
   rtx abi_reg = NULL_RTX;
+  int cookie_val = INTVAL (cookie);
 
   if (global_tlsarg)
     tlsarg = global_tlsarg;
 
   /* Handle longcall attributes.  */
-  if ((INTVAL (cookie) & CALL_LONG) != 0
-      && DEFAULT_ABI != ABI_DARWIN /* Darwin does it's own thing.  */
+  if ((cookie_val & CALL_LONG) != 0
       && GET_CODE (func_desc) == SYMBOL_REF)
     {
       func = rs6000_longcall_ref (func_desc, tlsarg);
@@ -37979,14 +37963,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 (cookie_val & mask));
   call[2] = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNO));
 
   insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (3, call));
@@ -38060,6 +38038,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.  */
 
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index f84b09b35a..6e6c984a51 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -10285,8 +10285,10 @@
 
   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
+    rs6000_call_darwin (NULL_RTX, operands[0], operands[1], operands[2]);
 
   DONE;
 })
@@ -10310,8 +10312,10 @@
 
   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
+    rs6000_call_darwin (operands[0], operands[1], operands[2], operands[3]);
 
   DONE;
 })
@@ -10447,11 +10451,7 @@
   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])
@@ -10533,11 +10533,7 @@
   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])
@@ -10746,8 +10742,10 @@
 
   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
+    rs6000_sibcall_darwin (NULL_RTX, operands[0], operands[1], operands[2]);
 
   DONE;
 })
@@ -10772,8 +10770,10 @@
 
   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
+    rs6000_sibcall_darwin (operands[0], operands[1], operands[2], operands[3]);
 
   DONE;
 })
-- 
2.17.1

> 

Reply via email to