From 82ac030d49fd2ae78b75a350c5efc59375df42a6 Mon Sep 17 00:00:00 2001 From: Iain Sandoe 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