From f90f960ca83c76fd82d45dccf91f5c2db4741d5e Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Thu, 14 Nov 2013 18:32:48 +0000 Subject: [PATCH] rs6000.c (rs6000_call_indirect_aix): Rename to ... 2013-11-14 Ulrich Weigand * config/rs6000/rs6000.c (rs6000_call_indirect_aix): Rename to ... (rs6000_call_aix): ... this. Handle both direct and indirect calls. Create call insn directly instead of via various gen_... routines. Mention special registers used by the call in CALL_INSN_FUNCTION_USAGE. (rs6000_sibcall_aix): New function. * config/rs6000/rs6000.md (TOC_SAVE_OFFSET_32BIT): Remove. (TOC_SAVE_OFFSET_64BIT): Likewise. (AIX_FUNC_DESC_TOC_32BIT): Likewise. (AIX_FUNC_DESC_TOC_64BIT): Likewise. (AIX_FUNC_DESC_SC_32BIT): Likewise. (AIX_FUNC_DESC_SC_64BIT): Likewise. ("call" expander): Call rs6000_call_aix. ("call_value" expander): Likewise. ("call_indirect_aix"): Replace this pattern ... ("call_indirect_aix_nor11"): ... and this pattern ... ("*call_indirect_aix"): ... by this insn pattern. ("call_value_indirect_aix"): Replace this pattern ... ("call_value_indirect_aix_nor11"): ... and this pattern ... ("*call_value_indirect_aix"): ... by this insn pattern. ("*call_nonlocal_aix32", "*call_nonlocal_aix64"): Replace by ... ("*call_nonlocal_aix"): ... this pattern. ("*call_value_nonlocal_aix32", "*call_value_nonlocal_aix64"): Replace ("*call_value_nonlocal_aix"): ... by this pattern. ("*call_local_aix"): New insn pattern. ("*call_value_local_aix"): Likewise. ("sibcall" expander): Call rs6000_sibcall_aix. ("sibcall_value" expander): Likewise. Move earlier in file. ("*sibcall_nonlocal_aix"): Replace by ... ("*sibcall_aix"): ... this pattern. ("*sibcall_value_nonlocal_aix"): Replace by ... ("*sibcall_value_aix"): ... this pattern. * config/rs6000/rs6000-protos.h (rs6000_call_indirect_aix): Remove. (rs6000_call_aix): Add prototype. (rs6000_sibcall_aix): Likewise. From-SVN: r204803 --- gcc/ChangeLog | 37 ++++ gcc/config/rs6000/rs6000-protos.h | 3 +- gcc/config/rs6000/rs6000.c | 198 +++++++++++---------- gcc/config/rs6000/rs6000.md | 349 ++++++++++++++++---------------------- 4 files changed, 291 insertions(+), 296 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8d0d893..e27898d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,40 @@ +2013-11-14 Ulrich Weigand + + * config/rs6000/rs6000.c (rs6000_call_indirect_aix): Rename to ... + (rs6000_call_aix): ... this. Handle both direct and indirect calls. + Create call insn directly instead of via various gen_... routines. + Mention special registers used by the call in CALL_INSN_FUNCTION_USAGE. + (rs6000_sibcall_aix): New function. + * config/rs6000/rs6000.md (TOC_SAVE_OFFSET_32BIT): Remove. + (TOC_SAVE_OFFSET_64BIT): Likewise. + (AIX_FUNC_DESC_TOC_32BIT): Likewise. + (AIX_FUNC_DESC_TOC_64BIT): Likewise. + (AIX_FUNC_DESC_SC_32BIT): Likewise. + (AIX_FUNC_DESC_SC_64BIT): Likewise. + ("call" expander): Call rs6000_call_aix. + ("call_value" expander): Likewise. + ("call_indirect_aix"): Replace this pattern ... + ("call_indirect_aix_nor11"): ... and this pattern ... + ("*call_indirect_aix"): ... by this insn pattern. + ("call_value_indirect_aix"): Replace this pattern ... + ("call_value_indirect_aix_nor11"): ... and this pattern ... + ("*call_value_indirect_aix"): ... by this insn pattern. + ("*call_nonlocal_aix32", "*call_nonlocal_aix64"): Replace by ... + ("*call_nonlocal_aix"): ... this pattern. + ("*call_value_nonlocal_aix32", "*call_value_nonlocal_aix64"): Replace + ("*call_value_nonlocal_aix"): ... by this pattern. + ("*call_local_aix"): New insn pattern. + ("*call_value_local_aix"): Likewise. + ("sibcall" expander): Call rs6000_sibcall_aix. + ("sibcall_value" expander): Likewise. Move earlier in file. + ("*sibcall_nonlocal_aix"): Replace by ... + ("*sibcall_aix"): ... this pattern. + ("*sibcall_value_nonlocal_aix"): Replace by ... + ("*sibcall_value_aix"): ... this pattern. + * config/rs6000/rs6000-protos.h (rs6000_call_indirect_aix): Remove. + (rs6000_call_aix): Add prototype. + (rs6000_sibcall_aix): Likewise. + 2013-11-14 Jakub Jelinek PR sanitizer/59122 diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index d1d1737..3c99c3c 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -182,7 +182,8 @@ extern unsigned int rs6000_dbx_register_number (unsigned int); extern void rs6000_emit_epilogue (int); extern void rs6000_emit_eh_reg_restore (rtx, rtx); extern const char * output_isel (rtx *); -extern void rs6000_call_indirect_aix (rtx, rtx, rtx); +extern void rs6000_call_aix (rtx, rtx, rtx, rtx); +extern void rs6000_sibcall_aix (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); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 1628bf3..e3ca62e 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -30604,118 +30604,138 @@ rs6000_legitimate_constant_p (enum machine_mode mode, rtx x) } -/* A function pointer under AIX is a pointer to a data area whose first word - contains the actual address of the function, whose second word contains a - pointer to its TOC, and whose third word contains a value to place in the - static chain register (r11). Note that if we load the static chain, our - "trampoline" need not have any executable code. */ + +/* Expand code to perform a call under the AIX ABI. */ void -rs6000_call_indirect_aix (rtx value, rtx func_desc, rtx flag) +rs6000_call_aix (rtx value, rtx func_desc, rtx flag, rtx cookie) { + rtx toc_reg = gen_rtx_REG (Pmode, TOC_REGNUM); + rtx toc_load = NULL_RTX; + rtx toc_restore = NULL_RTX; rtx func_addr; - rtx toc_reg; - rtx sc_reg; - rtx stack_ptr; - rtx stack_toc_offset; - rtx stack_toc_mem; - rtx func_toc_offset; - rtx func_toc_mem; - rtx func_sc_offset; - rtx func_sc_mem; + rtx abi_reg = NULL_RTX; + rtx call[4]; + int n_call; rtx insn; - rtx (*call_func) (rtx, rtx, rtx, rtx); - rtx (*call_value_func) (rtx, rtx, rtx, rtx, rtx); - - stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM); - toc_reg = gen_rtx_REG (Pmode, TOC_REGNUM); - - /* Load up address of the actual function. */ - func_desc = force_reg (Pmode, func_desc); - func_addr = gen_reg_rtx (Pmode); - emit_move_insn (func_addr, gen_rtx_MEM (Pmode, func_desc)); - - if (TARGET_32BIT) - { - stack_toc_offset = GEN_INT (TOC_SAVE_OFFSET_32BIT); - func_toc_offset = GEN_INT (AIX_FUNC_DESC_TOC_32BIT); - func_sc_offset = GEN_INT (AIX_FUNC_DESC_SC_32BIT); - if (TARGET_POINTERS_TO_NESTED_FUNCTIONS) - { - call_func = gen_call_indirect_aix32bit; - call_value_func = gen_call_value_indirect_aix32bit; - } + /* Handle longcall attributes. */ + if (INTVAL (cookie) & CALL_LONG) + func_desc = rs6000_longcall_ref (func_desc); + + /* Handle indirect calls. */ + if (GET_CODE (func_desc) != SYMBOL_REF + || !SYMBOL_REF_FUNCTION_P (func_desc)) + { + /* Save the TOC into its reserved slot before the call, + and prepare to restore it after the call. */ + rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM); + rtx stack_toc_offset = GEN_INT (5 * GET_MODE_SIZE (Pmode)); + rtx stack_toc_mem = gen_frame_mem (Pmode, + gen_rtx_PLUS (Pmode, stack_ptr, + stack_toc_offset)); + toc_restore = gen_rtx_SET (VOIDmode, toc_reg, stack_toc_mem); + + /* Can we optimize saving the TOC in the prologue or + do we need to do it at every call? */ + if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca) + cfun->machine->save_toc_in_prologue = true; else { - call_func = gen_call_indirect_aix32bit_nor11; - call_value_func = gen_call_value_indirect_aix32bit_nor11; + MEM_VOLATILE_P (stack_toc_mem) = 1; + emit_move_insn (stack_toc_mem, toc_reg); + } + + /* A function pointer under AIX is a pointer to a data area whose + first word contains the actual address of the function, whose + second word contains a pointer to its TOC, and whose third word + contains a value to place in the static chain register (r11). + Note that if we load the static chain, our "trampoline" need + not have any executable code. */ + + /* Load up address of the actual function. */ + func_desc = force_reg (Pmode, func_desc); + func_addr = gen_reg_rtx (Pmode); + emit_move_insn (func_addr, gen_rtx_MEM (Pmode, func_desc)); + + /* Prepare to load the TOC of the called function. Note that the + TOC load must happen immediately before the actual call so + that unwinding the TOC registers works correctly. See the + comment in frob_update_context. */ + rtx func_toc_offset = GEN_INT (GET_MODE_SIZE (Pmode)); + rtx func_toc_mem = gen_rtx_MEM (Pmode, + gen_rtx_PLUS (Pmode, func_desc, + func_toc_offset)); + toc_load = gen_rtx_USE (VOIDmode, func_toc_mem); + + /* If we have a static chain, load it up. */ + if (TARGET_POINTERS_TO_NESTED_FUNCTIONS) + { + rtx sc_reg = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM); + rtx func_sc_offset = GEN_INT (2 * GET_MODE_SIZE (Pmode)); + rtx func_sc_mem = gen_rtx_MEM (Pmode, + gen_rtx_PLUS (Pmode, func_desc, + func_sc_offset)); + emit_move_insn (sc_reg, func_sc_mem); + abi_reg = sc_reg; } } else { - stack_toc_offset = GEN_INT (TOC_SAVE_OFFSET_64BIT); - func_toc_offset = GEN_INT (AIX_FUNC_DESC_TOC_64BIT); - func_sc_offset = GEN_INT (AIX_FUNC_DESC_SC_64BIT); - if (TARGET_POINTERS_TO_NESTED_FUNCTIONS) - { - call_func = gen_call_indirect_aix64bit; - call_value_func = gen_call_value_indirect_aix64bit; - } - else - { - call_func = gen_call_indirect_aix64bit_nor11; - call_value_func = gen_call_value_indirect_aix64bit_nor11; - } + /* Direct calls use the TOC: for local calls, the callee will + assume the TOC register is set; for non-local calls, the + PLT stub needs the TOC register. */ + abi_reg = toc_reg; + func_addr = func_desc; } - /* Reserved spot to store the TOC. */ - stack_toc_mem = gen_frame_mem (Pmode, - gen_rtx_PLUS (Pmode, - stack_ptr, - stack_toc_offset)); + /* Create the call. */ + call[0] = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (SImode, func_addr), flag); + if (value != NULL_RTX) + call[0] = gen_rtx_SET (VOIDmode, value, call[0]); + n_call = 1; - gcc_assert (cfun); - gcc_assert (cfun->machine); + if (toc_load) + call[n_call++] = toc_load; + if (toc_restore) + call[n_call++] = toc_restore; - /* Can we optimize saving the TOC in the prologue or do we need to do it at - every call? */ - if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca) - cfun->machine->save_toc_in_prologue = true; + call[n_call++] = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNO)); - else - { - MEM_VOLATILE_P (stack_toc_mem) = 1; - emit_move_insn (stack_toc_mem, toc_reg); - } + insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (n_call, call)); + insn = emit_call_insn (insn); - /* Calculate the address to load the TOC of the called function. We don't - actually load this until the split after reload. */ - func_toc_mem = gen_rtx_MEM (Pmode, - gen_rtx_PLUS (Pmode, - func_desc, - func_toc_offset)); + /* Mention all registers defined by the ABI to hold information + as uses in CALL_INSN_FUNCTION_USAGE. */ + if (abi_reg) + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), abi_reg); +} - /* If we have a static chain, load it up. */ - if (TARGET_POINTERS_TO_NESTED_FUNCTIONS) - { - func_sc_mem = gen_rtx_MEM (Pmode, - gen_rtx_PLUS (Pmode, - func_desc, - func_sc_offset)); +/* Expand code to perform a sibling call under the AIX ABI. */ - sc_reg = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM); - emit_move_insn (sc_reg, func_sc_mem); - } +void +rs6000_sibcall_aix (rtx value, rtx func_desc, rtx flag, rtx cookie) +{ + rtx call[2]; + rtx insn; + + gcc_assert (INTVAL (cookie) == 0); /* Create the call. */ - if (value) - insn = call_value_func (value, func_addr, flag, func_toc_mem, - stack_toc_mem); - else - insn = call_func (func_addr, flag, func_toc_mem, stack_toc_mem); + call[0] = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (SImode, func_desc), flag); + if (value != NULL_RTX) + call[0] = gen_rtx_SET (VOIDmode, value, call[0]); + + call[1] = simple_return_rtx; + + insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (2, call)); + insn = emit_call_insn (insn); - emit_call_insn (insn); + /* Note use of the TOC register. */ + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, TOC_REGNUM)); + /* We need to also mark a use of the link register since the function we + sibling-call to will use it to return to our caller. */ + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, LR_REGNO)); } /* Return whether we need to always update the saved TOC pointer when we update diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 2020468..b3311e6 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -56,18 +56,6 @@ (TFHAR_REGNO 114) (TFIAR_REGNO 115) (TEXASR_REGNO 116) - - ; ABI defined stack offsets for storing the TOC pointer with AIX calls. - (TOC_SAVE_OFFSET_32BIT 20) - (TOC_SAVE_OFFSET_64BIT 40) - - ; Function TOC offset in the AIX function descriptor. - (AIX_FUNC_DESC_TOC_32BIT 4) - (AIX_FUNC_DESC_TOC_64BIT 8) - - ; Static chain offset in the AIX function descriptor. - (AIX_FUNC_DESC_SC_32BIT 8) - (AIX_FUNC_DESC_SC_64BIT 16) ]) ;; @@ -12093,8 +12081,13 @@ operands[0] = XEXP (operands[0], 0); + if (DEFAULT_ABI == ABI_AIX) + { + rs6000_call_aix (NULL_RTX, operands[0], operands[1], operands[2]); + DONE; + } + if (GET_CODE (operands[0]) != SYMBOL_REF - || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[0])) || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[2]) & CALL_LONG) != 0)) { if (INTVAL (operands[2]) & CALL_LONG) @@ -12107,12 +12100,6 @@ operands[0] = force_reg (Pmode, operands[0]); break; - case ABI_AIX: - /* AIX function pointers are really pointers to a three word - area. */ - rs6000_call_indirect_aix (NULL_RTX, operands[0], operands[1]); - DONE; - default: gcc_unreachable (); } @@ -12138,8 +12125,13 @@ operands[1] = XEXP (operands[1], 0); + if (DEFAULT_ABI == ABI_AIX) + { + rs6000_call_aix (operands[0], operands[1], operands[2], operands[3]); + DONE; + } + if (GET_CODE (operands[1]) != SYMBOL_REF - || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[1])) || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[3]) & CALL_LONG) != 0)) { if (INTVAL (operands[3]) & CALL_LONG) @@ -12152,12 +12144,6 @@ operands[1] = force_reg (Pmode, operands[1]); break; - case ABI_AIX: - /* AIX function pointers are really pointers to a three word - area. */ - rs6000_call_indirect_aix (operands[0], operands[1], operands[2]); - DONE; - default: gcc_unreachable (); } @@ -12249,135 +12235,6 @@ [(set_attr "type" "branch") (set_attr "length" "4,8")]) -;; Call to indirect functions with the AIX abi using a 3 word descriptor. -;; Operand0 is the addresss of the function to call -;; Operand1 is the flag for System V.4 for unprototyped or FP registers -;; Operand2 is the location in the function descriptor to load r2 from -;; Operand3 is the stack location to hold the current TOC pointer - -(define_insn "call_indirect_aix" - [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l")) - (match_operand 1 "" "g,g")) - (use (match_operand:P 2 "memory_operand" ",")) - (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" ",")) - (use (reg:P STATIC_CHAIN_REGNUM)) - (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_AIX && TARGET_POINTERS_TO_NESTED_FUNCTIONS" - " 2,%2\;b%T0l\; 2,%3" - [(set_attr "type" "jmpreg") - (set_attr "length" "12")]) - -;; Like call_indirect_aix, but no use of the static chain -;; Operand0 is the addresss of the function to call -;; Operand1 is the flag for System V.4 for unprototyped or FP registers -;; Operand2 is the location in the function descriptor to load r2 from -;; Operand3 is the stack location to hold the current TOC pointer - -(define_insn "call_indirect_aix_nor11" - [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l")) - (match_operand 1 "" "g,g")) - (use (match_operand:P 2 "memory_operand" ",")) - (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" ",")) - (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_AIX && !TARGET_POINTERS_TO_NESTED_FUNCTIONS" - " 2,%2\;b%T0l\; 2,%3" - [(set_attr "type" "jmpreg") - (set_attr "length" "12")]) - -;; Operand0 is the return result of the function -;; Operand1 is the addresss of the function to call -;; Operand2 is the flag for System V.4 for unprototyped or FP registers -;; Operand3 is the location in the function descriptor to load r2 from -;; Operand4 is the stack location to hold the current TOC pointer - -(define_insn "call_value_indirect_aix" - [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) - (match_operand 2 "" "g,g"))) - (use (match_operand:P 3 "memory_operand" ",")) - (set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" ",")) - (use (reg:P STATIC_CHAIN_REGNUM)) - (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_AIX && TARGET_POINTERS_TO_NESTED_FUNCTIONS" - " 2,%3\;b%T1l\; 2,%4" - [(set_attr "type" "jmpreg") - (set_attr "length" "12")]) - -;; Like call_value_indirect_aix, but no use of the static chain -;; Operand0 is the return result of the function -;; Operand1 is the addresss of the function to call -;; Operand2 is the flag for System V.4 for unprototyped or FP registers -;; Operand3 is the location in the function descriptor to load r2 from -;; Operand4 is the stack location to hold the current TOC pointer - -(define_insn "call_value_indirect_aix_nor11" - [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) - (match_operand 2 "" "g,g"))) - (use (match_operand:P 3 "memory_operand" ",")) - (set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" ",")) - (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_AIX && !TARGET_POINTERS_TO_NESTED_FUNCTIONS" - " 2,%3\;b%T1l\; 2,%4" - [(set_attr "type" "jmpreg") - (set_attr "length" "12")]) - -;; Call to function which may be in another module. Restore the TOC -;; pointer (r2) after the call unless this is System V. -;; Operand2 is nonzero if we are using the V.4 calling sequence and -;; either the function was not prototyped, or it was prototyped as a -;; variable argument function. It is > 0 if FP registers were passed -;; and < 0 if they were not. - -(define_insn "*call_nonlocal_aix32" - [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s")) - (match_operand 1 "" "g")) - (use (match_operand:SI 2 "immediate_operand" "O")) - (clobber (reg:SI LR_REGNO))] - "TARGET_32BIT - && DEFAULT_ABI == ABI_AIX - && (INTVAL (operands[2]) & CALL_LONG) == 0" - "bl %z0\;nop" - [(set_attr "type" "branch") - (set_attr "length" "8")]) - -(define_insn "*call_nonlocal_aix64" - [(call (mem:SI (match_operand:DI 0 "symbol_ref_operand" "s")) - (match_operand 1 "" "g")) - (use (match_operand:SI 2 "immediate_operand" "O")) - (clobber (reg:SI LR_REGNO))] - "TARGET_64BIT - && DEFAULT_ABI == ABI_AIX - && (INTVAL (operands[2]) & CALL_LONG) == 0" - "bl %z0\;nop" - [(set_attr "type" "branch") - (set_attr "length" "8")]) - -(define_insn "*call_value_nonlocal_aix32" - [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s")) - (match_operand 2 "" "g"))) - (use (match_operand:SI 3 "immediate_operand" "O")) - (clobber (reg:SI LR_REGNO))] - "TARGET_32BIT - && DEFAULT_ABI == ABI_AIX - && (INTVAL (operands[3]) & CALL_LONG) == 0" - "bl %z1\;nop" - [(set_attr "type" "branch") - (set_attr "length" "8")]) - -(define_insn "*call_value_nonlocal_aix64" - [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:DI 1 "symbol_ref_operand" "s")) - (match_operand 2 "" "g"))) - (use (match_operand:SI 3 "immediate_operand" "O")) - (clobber (reg:SI LR_REGNO))] - "TARGET_64BIT - && DEFAULT_ABI == ABI_AIX - && (INTVAL (operands[3]) & CALL_LONG) == 0" - "bl %z1\;nop" - [(set_attr "type" "branch") - (set_attr "length" "8")]) ;; A function pointer under System V is just a normal pointer ;; operands[0] is the function pointer @@ -12560,6 +12417,79 @@ [(set_attr "type" "branch,branch") (set_attr "length" "4,8")]) + +;; Call to AIX abi function in the same module. + +(define_insn "*call_local_aix" + [(call (mem:SI (match_operand:P 0 "current_file_function_operand" "s")) + (match_operand 1 "" "g")) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_AIX" + "bl %z0" + [(set_attr "type" "branch") + (set_attr "length" "4")]) + +(define_insn "*call_value_local_aix" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:P 1 "current_file_function_operand" "s")) + (match_operand 2 "" "g"))) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_AIX" + "bl %z1" + [(set_attr "type" "branch") + (set_attr "length" "4")]) + +;; Call to AIX abi function which may be in another module. +;; Restore the TOC pointer (r2) after the call. + +(define_insn "*call_nonlocal_aix" + [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s")) + (match_operand 1 "" "g")) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_AIX" + "bl %z0\;nop" + [(set_attr "type" "branch") + (set_attr "length" "8")]) + +(define_insn "*call_value_nonlocal_aix" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s")) + (match_operand 2 "" "g"))) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_AIX" + "bl %z1\;nop" + [(set_attr "type" "branch") + (set_attr "length" "8")]) + +;; Call to indirect functions with the AIX abi using a 3 word descriptor. +;; Operand0 is the addresss of the function to call +;; Operand2 is the location in the function descriptor to load r2 from +;; Operand3 is the stack location to hold the current TOC pointer + +(define_insn "*call_indirect_aix" + [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l")) + (match_operand 1 "" "g,g")) + (use (match_operand:P 2 "memory_operand" ",")) + (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" ",")) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_AIX" + " 2,%2\;b%T0l\; 2,%3" + [(set_attr "type" "jmpreg") + (set_attr "length" "12")]) + +(define_insn "*call_value_indirect_aix" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) + (match_operand 2 "" "g,g"))) + (use (match_operand:P 3 "memory_operand" ",")) + (set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" ",")) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_AIX" + " 2,%3\;b%T1l\; 2,%4" + [(set_attr "type" "jmpreg") + (set_attr "length" "12")]) + + ;; Call subroutine returning any type. (define_expand "untyped_call" [(parallel [(call (match_operand 0 "" "") @@ -12607,6 +12537,39 @@ gcc_assert (GET_CODE (operands[1]) == CONST_INT); operands[0] = XEXP (operands[0], 0); + + if (DEFAULT_ABI == ABI_AIX) + { + rs6000_sibcall_aix (NULL_RTX, operands[0], operands[1], operands[2]); + DONE; + } +}") + +(define_expand "sibcall_value" + [(parallel [(set (match_operand 0 "register_operand" "") + (call (mem:SI (match_operand 1 "address_operand" "")) + (match_operand 2 "" ""))) + (use (match_operand 3 "" "")) + (use (reg:SI LR_REGNO)) + (simple_return)])] + "" + " +{ +#if TARGET_MACHO + if (MACHOPIC_INDIRECT) + operands[1] = machopic_indirect_call_target (operands[1]); +#endif + + gcc_assert (GET_CODE (operands[1]) == MEM); + gcc_assert (GET_CODE (operands[2]) == CONST_INT); + + operands[1] = XEXP (operands[1], 0); + + if (DEFAULT_ABI == ABI_AIX) + { + rs6000_sibcall_aix (operands[0], operands[1], operands[2], operands[3]); + DONE; + } }") ;; this and similar patterns must be marked as using LR, otherwise @@ -12674,7 +12637,6 @@ [(set_attr "type" "branch") (set_attr "length" "4,8")]) - (define_insn "*sibcall_value_local64" [(set (match_operand 0 "" "") (call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s")) @@ -12696,35 +12658,6 @@ [(set_attr "type" "branch") (set_attr "length" "4,8")]) -(define_insn "*sibcall_nonlocal_aix" - [(call (mem:SI (match_operand:P 0 "call_operand" "s,c")) - (match_operand 1 "" "g,g")) - (use (match_operand:SI 2 "immediate_operand" "O,O")) - (use (reg:SI LR_REGNO)) - (simple_return)] - "DEFAULT_ABI == ABI_AIX - && (INTVAL (operands[2]) & CALL_LONG) == 0" - "@ - b %z0 - b%T0" - [(set_attr "type" "branch") - (set_attr "length" "4")]) - -(define_insn "*sibcall_value_nonlocal_aix" - [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:P 1 "call_operand" "s,c")) - (match_operand 2 "" "g,g"))) - (use (match_operand:SI 3 "immediate_operand" "O,O")) - (use (reg:SI LR_REGNO)) - (simple_return)] - "DEFAULT_ABI == ABI_AIX - && (INTVAL (operands[3]) & CALL_LONG) == 0" - "@ - b %z1 - b%T1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) - (define_insn "*sibcall_nonlocal_sysv" [(call (mem:SI (match_operand:P 0 "call_operand" "s,s,c,c")) (match_operand 1 "" "")) @@ -12755,27 +12688,6 @@ [(set_attr "type" "branch") (set_attr "length" "4,8,4,8")]) -(define_expand "sibcall_value" - [(parallel [(set (match_operand 0 "register_operand" "") - (call (mem:SI (match_operand 1 "address_operand" "")) - (match_operand 2 "" ""))) - (use (match_operand 3 "" "")) - (use (reg:SI LR_REGNO)) - (simple_return)])] - "" - " -{ -#if TARGET_MACHO - if (MACHOPIC_INDIRECT) - operands[1] = machopic_indirect_call_target (operands[1]); -#endif - - gcc_assert (GET_CODE (operands[1]) == MEM); - gcc_assert (GET_CODE (operands[2]) == CONST_INT); - - operands[1] = XEXP (operands[1], 0); -}") - (define_insn "*sibcall_value_nonlocal_sysv" [(set (match_operand 0 "" "") (call (mem:SI (match_operand:P 1 "call_operand" "s,s,c,c")) @@ -12807,6 +12719,31 @@ [(set_attr "type" "branch") (set_attr "length" "4,8,4,8")]) +;; AIX ABI sibling call patterns. + +(define_insn "*sibcall_aix" + [(call (mem:SI (match_operand:P 0 "call_operand" "s,c")) + (match_operand 1 "" "g,g")) + (simple_return)] + "DEFAULT_ABI == ABI_AIX" + "@ + b %z0 + b%T0" + [(set_attr "type" "branch") + (set_attr "length" "4")]) + +(define_insn "*sibcall_value_aix" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:P 1 "call_operand" "s,c")) + (match_operand 2 "" "g,g"))) + (simple_return)] + "DEFAULT_ABI == ABI_AIX" + "@ + b %z1 + b%T1" + [(set_attr "type" "branch") + (set_attr "length" "4")]) + (define_expand "sibcall_epilogue" [(use (const_int 0))] "" -- 2.7.4