rs6000.c (rs6000_call_indirect_aix): Rename to ...

2013-11-14  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>

	* 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<ptrsize>"): Replace this pattern ...
	("call_indirect_aix<ptrsize>_nor11"): ... and this pattern ...
	("*call_indirect_aix<mode>"): ... by this insn pattern.
	("call_value_indirect_aix<ptrsize>"): Replace this pattern ...
	("call_value_indirect_aix<ptrsize>_nor11"): ... and this pattern ...
	("*call_value_indirect_aix<mode>"): ... by this insn pattern.
	("*call_nonlocal_aix32", "*call_nonlocal_aix64"): Replace by ...
	("*call_nonlocal_aix<mode>"): ... this pattern.
	("*call_value_nonlocal_aix32", "*call_value_nonlocal_aix64"): Replace
	("*call_value_nonlocal_aix<mode>"): ... by this pattern.
	("*call_local_aix<mode>"): New insn pattern.
	("*call_value_local_aix<mode>"): Likewise.
	("sibcall" expander): Call rs6000_sibcall_aix.
	("sibcall_value" expander): Likewise.  Move earlier in file.
	("*sibcall_nonlocal_aix<mode>"): Replace by ...
	("*sibcall_aix<mode>"): ... this pattern.
	("*sibcall_value_nonlocal_aix<mode>"): Replace by ...
	("*sibcall_value_aix<mode>"): ... this pattern.
	* config/rs6000/rs6000-protos.h (rs6000_call_indirect_aix): Remove.
	(rs6000_call_aix): Add prototype.
	(rs6000_sibcall_aix): Likewise.

From-SVN: r204803
This commit is contained in:
Ulrich Weigand 2013-11-14 18:32:48 +00:00 committed by Ulrich Weigand
parent 4f883df12f
commit f90f960ca8
4 changed files with 295 additions and 300 deletions

View file

@ -1,3 +1,40 @@
2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
* 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<ptrsize>"): Replace this pattern ...
("call_indirect_aix<ptrsize>_nor11"): ... and this pattern ...
("*call_indirect_aix<mode>"): ... by this insn pattern.
("call_value_indirect_aix<ptrsize>"): Replace this pattern ...
("call_value_indirect_aix<ptrsize>_nor11"): ... and this pattern ...
("*call_value_indirect_aix<mode>"): ... by this insn pattern.
("*call_nonlocal_aix32", "*call_nonlocal_aix64"): Replace by ...
("*call_nonlocal_aix<mode>"): ... this pattern.
("*call_value_nonlocal_aix32", "*call_value_nonlocal_aix64"): Replace
("*call_value_nonlocal_aix<mode>"): ... by this pattern.
("*call_local_aix<mode>"): New insn pattern.
("*call_value_local_aix<mode>"): Likewise.
("sibcall" expander): Call rs6000_sibcall_aix.
("sibcall_value" expander): Likewise. Move earlier in file.
("*sibcall_nonlocal_aix<mode>"): Replace by ...
("*sibcall_aix<mode>"): ... this pattern.
("*sibcall_value_nonlocal_aix<mode>"): Replace by ...
("*sibcall_value_aix<mode>"): ... 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 <jakub@redhat.com> 2013-11-14 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/59122 PR sanitizer/59122

View file

@ -182,7 +182,8 @@ extern unsigned int rs6000_dbx_register_number (unsigned int);
extern void rs6000_emit_epilogue (int); extern void rs6000_emit_epilogue (int);
extern void rs6000_emit_eh_reg_restore (rtx, rtx); extern void rs6000_emit_eh_reg_restore (rtx, rtx);
extern const char * output_isel (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 rs6000_aix_asm_output_dwarf_table_ref (char *);
extern void get_ppc476_thunk_name (char name[32]); extern void get_ppc476_thunk_name (char name[32]);
extern bool rs6000_overloaded_builtin_p (enum rs6000_builtins); extern bool rs6000_overloaded_builtin_p (enum rs6000_builtins);

View file

@ -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 /* Expand code to perform a call under the AIX ABI. */
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. */
void 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 func_addr;
rtx toc_reg; rtx abi_reg = NULL_RTX;
rtx sc_reg; rtx call[4];
rtx stack_ptr; int n_call;
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 insn; 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); /* Handle longcall attributes. */
toc_reg = gen_rtx_REG (Pmode, TOC_REGNUM); if (INTVAL (cookie) & CALL_LONG)
func_desc = rs6000_longcall_ref (func_desc);
/* Load up address of the actual function. */ /* Handle indirect calls. */
func_desc = force_reg (Pmode, func_desc); if (GET_CODE (func_desc) != SYMBOL_REF
func_addr = gen_reg_rtx (Pmode); || !SYMBOL_REF_FUNCTION_P (func_desc))
emit_move_insn (func_addr, gen_rtx_MEM (Pmode, func_desc));
if (TARGET_32BIT)
{ {
/* Save the TOC into its reserved slot before the call,
stack_toc_offset = GEN_INT (TOC_SAVE_OFFSET_32BIT); and prepare to restore it after the call. */
func_toc_offset = GEN_INT (AIX_FUNC_DESC_TOC_32BIT); rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
func_sc_offset = GEN_INT (AIX_FUNC_DESC_SC_32BIT); rtx stack_toc_offset = GEN_INT (5 * GET_MODE_SIZE (Pmode));
if (TARGET_POINTERS_TO_NESTED_FUNCTIONS) rtx stack_toc_mem = gen_frame_mem (Pmode,
{ gen_rtx_PLUS (Pmode, stack_ptr,
call_func = gen_call_indirect_aix32bit;
call_value_func = gen_call_value_indirect_aix32bit;
}
else
{
call_func = gen_call_indirect_aix32bit_nor11;
call_value_func = gen_call_value_indirect_aix32bit_nor11;
}
}
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;
}
}
/* Reserved spot to store the TOC. */
stack_toc_mem = gen_frame_mem (Pmode,
gen_rtx_PLUS (Pmode,
stack_ptr,
stack_toc_offset)); stack_toc_offset));
toc_restore = gen_rtx_SET (VOIDmode, toc_reg, stack_toc_mem);
gcc_assert (cfun); /* Can we optimize saving the TOC in the prologue or
gcc_assert (cfun->machine); do we need to do it at every call? */
/* 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) if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca)
cfun->machine->save_toc_in_prologue = true; cfun->machine->save_toc_in_prologue = true;
else else
{ {
MEM_VOLATILE_P (stack_toc_mem) = 1; MEM_VOLATILE_P (stack_toc_mem) = 1;
emit_move_insn (stack_toc_mem, toc_reg); emit_move_insn (stack_toc_mem, toc_reg);
} }
/* Calculate the address to load the TOC of the called function. We don't /* A function pointer under AIX is a pointer to a data area whose
actually load this until the split after reload. */ first word contains the actual address of the function, whose
func_toc_mem = gen_rtx_MEM (Pmode, second word contains a pointer to its TOC, and whose third word
gen_rtx_PLUS (Pmode, contains a value to place in the static chain register (r11).
func_desc, 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)); func_toc_offset));
toc_load = gen_rtx_USE (VOIDmode, func_toc_mem);
/* If we have a static chain, load it up. */ /* If we have a static chain, load it up. */
if (TARGET_POINTERS_TO_NESTED_FUNCTIONS) if (TARGET_POINTERS_TO_NESTED_FUNCTIONS)
{ {
func_sc_mem = gen_rtx_MEM (Pmode, rtx sc_reg = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
gen_rtx_PLUS (Pmode, rtx func_sc_offset = GEN_INT (2 * GET_MODE_SIZE (Pmode));
func_desc, rtx func_sc_mem = gen_rtx_MEM (Pmode,
gen_rtx_PLUS (Pmode, func_desc,
func_sc_offset)); func_sc_offset));
sc_reg = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
emit_move_insn (sc_reg, func_sc_mem); emit_move_insn (sc_reg, func_sc_mem);
abi_reg = sc_reg;
}
}
else
{
/* 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;
} }
/* Create the call. */ /* Create the call. */
if (value) call[0] = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (SImode, func_addr), flag);
insn = call_value_func (value, func_addr, flag, func_toc_mem, if (value != NULL_RTX)
stack_toc_mem); call[0] = gen_rtx_SET (VOIDmode, value, call[0]);
else n_call = 1;
insn = call_func (func_addr, flag, func_toc_mem, stack_toc_mem);
emit_call_insn (insn); if (toc_load)
call[n_call++] = toc_load;
if (toc_restore)
call[n_call++] = toc_restore;
call[n_call++] = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNO));
insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (n_call, call));
insn = emit_call_insn (insn);
/* 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);
}
/* Expand code to perform a sibling call under the AIX ABI. */
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. */
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);
/* 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 /* Return whether we need to always update the saved TOC pointer when we update

View file

@ -56,18 +56,6 @@
(TFHAR_REGNO 114) (TFHAR_REGNO 114)
(TFIAR_REGNO 115) (TFIAR_REGNO 115)
(TEXASR_REGNO 116) (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); 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 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)) || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[2]) & CALL_LONG) != 0))
{ {
if (INTVAL (operands[2]) & CALL_LONG) if (INTVAL (operands[2]) & CALL_LONG)
@ -12107,12 +12100,6 @@
operands[0] = force_reg (Pmode, operands[0]); operands[0] = force_reg (Pmode, operands[0]);
break; 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: default:
gcc_unreachable (); gcc_unreachable ();
} }
@ -12138,8 +12125,13 @@
operands[1] = XEXP (operands[1], 0); 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 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)) || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[3]) & CALL_LONG) != 0))
{ {
if (INTVAL (operands[3]) & CALL_LONG) if (INTVAL (operands[3]) & CALL_LONG)
@ -12152,12 +12144,6 @@
operands[1] = force_reg (Pmode, operands[1]); operands[1] = force_reg (Pmode, operands[1]);
break; 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: default:
gcc_unreachable (); gcc_unreachable ();
} }
@ -12249,135 +12235,6 @@
[(set_attr "type" "branch") [(set_attr "type" "branch")
(set_attr "length" "4,8")]) (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<ptrsize>"
[(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
(match_operand 1 "" "g,g"))
(use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
(set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
(use (reg:P STATIC_CHAIN_REGNUM))
(clobber (reg:P LR_REGNO))]
"DEFAULT_ABI == ABI_AIX && TARGET_POINTERS_TO_NESTED_FUNCTIONS"
"<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3"
[(set_attr "type" "jmpreg")
(set_attr "length" "12")])
;; Like call_indirect_aix<ptrsize>, 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<ptrsize>_nor11"
[(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
(match_operand 1 "" "g,g"))
(use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
(set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
(clobber (reg:P LR_REGNO))]
"DEFAULT_ABI == ABI_AIX && !TARGET_POINTERS_TO_NESTED_FUNCTIONS"
"<ptrload> 2,%2\;b%T0l\;<ptrload> 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<ptrsize>"
[(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" "<ptrm>,<ptrm>"))
(set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>"))
(use (reg:P STATIC_CHAIN_REGNUM))
(clobber (reg:P LR_REGNO))]
"DEFAULT_ABI == ABI_AIX && TARGET_POINTERS_TO_NESTED_FUNCTIONS"
"<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4"
[(set_attr "type" "jmpreg")
(set_attr "length" "12")])
;; Like call_value_indirect_aix<ptrsize>, 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<ptrsize>_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" "<ptrm>,<ptrm>"))
(set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>"))
(clobber (reg:P LR_REGNO))]
"DEFAULT_ABI == ABI_AIX && !TARGET_POINTERS_TO_NESTED_FUNCTIONS"
"<ptrload> 2,%3\;b%T1l\;<ptrload> 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 ;; A function pointer under System V is just a normal pointer
;; operands[0] is the function pointer ;; operands[0] is the function pointer
@ -12560,6 +12417,79 @@
[(set_attr "type" "branch,branch") [(set_attr "type" "branch,branch")
(set_attr "length" "4,8")]) (set_attr "length" "4,8")])
;; Call to AIX abi function in the same module.
(define_insn "*call_local_aix<mode>"
[(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<mode>"
[(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<mode>"
[(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<mode>"
[(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<mode>"
[(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
(match_operand 1 "" "g,g"))
(use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
(set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
(clobber (reg:P LR_REGNO))]
"DEFAULT_ABI == ABI_AIX"
"<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3"
[(set_attr "type" "jmpreg")
(set_attr "length" "12")])
(define_insn "*call_value_indirect_aix<mode>"
[(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" "<ptrm>,<ptrm>"))
(set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>"))
(clobber (reg:P LR_REGNO))]
"DEFAULT_ABI == ABI_AIX"
"<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4"
[(set_attr "type" "jmpreg")
(set_attr "length" "12")])
;; Call subroutine returning any type. ;; Call subroutine returning any type.
(define_expand "untyped_call" (define_expand "untyped_call"
[(parallel [(call (match_operand 0 "" "") [(parallel [(call (match_operand 0 "" "")
@ -12607,6 +12537,39 @@
gcc_assert (GET_CODE (operands[1]) == CONST_INT); gcc_assert (GET_CODE (operands[1]) == CONST_INT);
operands[0] = XEXP (operands[0], 0); 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 ;; this and similar patterns must be marked as using LR, otherwise
@ -12674,7 +12637,6 @@
[(set_attr "type" "branch") [(set_attr "type" "branch")
(set_attr "length" "4,8")]) (set_attr "length" "4,8")])
(define_insn "*sibcall_value_local64" (define_insn "*sibcall_value_local64"
[(set (match_operand 0 "" "") [(set (match_operand 0 "" "")
(call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s")) (call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s"))
@ -12696,35 +12658,6 @@
[(set_attr "type" "branch") [(set_attr "type" "branch")
(set_attr "length" "4,8")]) (set_attr "length" "4,8")])
(define_insn "*sibcall_nonlocal_aix<mode>"
[(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<mode>"
[(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<mode>" (define_insn "*sibcall_nonlocal_sysv<mode>"
[(call (mem:SI (match_operand:P 0 "call_operand" "s,s,c,c")) [(call (mem:SI (match_operand:P 0 "call_operand" "s,s,c,c"))
(match_operand 1 "" "")) (match_operand 1 "" ""))
@ -12755,27 +12688,6 @@
[(set_attr "type" "branch") [(set_attr "type" "branch")
(set_attr "length" "4,8,4,8")]) (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<mode>" (define_insn "*sibcall_value_nonlocal_sysv<mode>"
[(set (match_operand 0 "" "") [(set (match_operand 0 "" "")
(call (mem:SI (match_operand:P 1 "call_operand" "s,s,c,c")) (call (mem:SI (match_operand:P 1 "call_operand" "s,s,c,c"))
@ -12807,6 +12719,31 @@
[(set_attr "type" "branch") [(set_attr "type" "branch")
(set_attr "length" "4,8,4,8")]) (set_attr "length" "4,8,4,8")])
;; AIX ABI sibling call patterns.
(define_insn "*sibcall_aix<mode>"
[(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<mode>"
[(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" (define_expand "sibcall_epilogue"
[(use (const_int 0))] [(use (const_int 0))]
"" ""