aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2018-12-12 08:47:16 +0000
committerIain Sandoe <iains@gcc.gnu.org>2018-12-12 08:47:16 +0000
commitaa3a2eca42d9bcebdaa2441e050df8b5bc24e4fa (patch)
tree335db18cac33323d402d0de8b75c469160970324
parent13de99bc7d085125e614ffdb75d486e9a7a8a48f (diff)
downloadgcc-aa3a2eca42d9bcebdaa2441e050df8b5bc24e4fa.zip
gcc-aa3a2eca42d9bcebdaa2441e050df8b5bc24e4fa.tar.gz
gcc-aa3a2eca42d9bcebdaa2441e050df8b5bc24e4fa.tar.bz2
rs6000, update Darwin call handling to latest scheme.
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
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/config/rs6000/rs6000-protos.h6
-rw-r--r--gcc/config/rs6000/rs6000.c157
-rw-r--r--gcc/config/rs6000/rs6000.md32
4 files changed, 185 insertions, 27 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2fba17e..c561bce 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,22 @@
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.
(call_nonlocal_darwin64): Remove.
(call_value_indirect_nonlocal_darwin64): Remove.
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index dfee1f2..5ac864e 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 5c72075..5beb8df 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 *);
@@ -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. */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index fa77e45..4499371 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -10285,8 +10285,12 @@
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;
})
@@ -10310,8 +10314,12 @@
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;
})
@@ -10447,11 +10455,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 +10537,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 +10746,12 @@
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;
})
@@ -10772,8 +10776,12 @@
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;
})