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>
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_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);

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
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);
/* Handle longcall attributes. */
if (INTVAL (cookie) & CALL_LONG)
func_desc = rs6000_longcall_ref (func_desc);
/* 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)
/* 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);
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;
}
/* 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;
}
}
/* Reserved spot to store the TOC. */
stack_toc_mem = gen_frame_mem (Pmode,
gen_rtx_PLUS (Pmode,
stack_ptr,
stack_toc_offset));
gcc_assert (cfun);
gcc_assert (cfun->machine);
/* 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
{
MEM_VOLATILE_P (stack_toc_mem) = 1;
emit_move_insn (stack_toc_mem, toc_reg);
}
/* 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));
/* 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));
sc_reg = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
emit_move_insn (sc_reg, func_sc_mem);
/* 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. */
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_addr), flag);
if (value != NULL_RTX)
call[0] = gen_rtx_SET (VOIDmode, value, call[0]);
n_call = 1;
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

View file

@ -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<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
;; 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<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.
(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<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>"
[(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<mode>"
[(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<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"
[(use (const_int 0))]
""