From aa3a2eca42d9bcebdaa2441e050df8b5bc24e4fa Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Wed, 12 Dec 2018 08:47:16 +0000 Subject: [PATCH] rs6000, update Darwin call handling to latest scheme. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 * 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 | 17 ++++ gcc/config/rs6000/rs6000-protos.h | 6 +- gcc/config/rs6000/rs6000.c | 157 +++++++++++++++++++++++++++--- gcc/config/rs6000/rs6000.md | 32 +++--- 4 files changed, 185 insertions(+), 27 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2fba17e1ffc..c561bce2627 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2018-12-12 Iain Sandoe + + * 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 * config/rs6000/darwin.md (call_indirect_nonlocal_darwin64): Remove. diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index dfee1f28aa9..5ac864e83ee 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 5c7207598b6..5beb8dfe24a 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 fa77e451459..4499371a50b 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; }) -- 2.30.2