re PR target/41246 (should "sorry" when regparm=3 and nested functions are encountered)

PR target/41246
	* target.h (struct gcc_target): Add asm_out.trampoline_template,
	calls.static_chain, calls.trampoline_init,
	calls.trampoline_adjust_address.
	* target-def.h (TARGET_ASM_TRAMPOLINE_TEMPLATE): New.
	(TARGET_STATIC_CHAIN, TARGET_TRAMPOLINE_INIT): New.
	(TARGET_TRAMPOLINE_ADJUST_ADDRESS): New.
	* builtins.c (expand_builtin_setjmp_receiver): Use
	targetm.calls.static_chain; only clobber registers.
	(expand_builtin_init_trampoline): Use targetm.calls.trampoline_init;
	set up memory attributes properly for the trampoline block.
	(expand_builtin_adjust_trampoline): Use
	targetm.calls.trampoline_adjust_address.
	* calls.c (prepare_call_address): Add fndecl argument.  Use
	targetm.calls.static_chain.
	* df-scan.c (df_need_static_chain_reg): Remove.
	(df_get_entry_block_def_set): Use targetm.calls.static_chain;
	consolodate static chain handling.
	* doc/tm.texi: Document new hooks.
	* emit-rtl.c (static_chain_rtx, static_chain_incoming_rtx): Remove.
	(init_emit_regs): Don't initialize them.
	* expr.h (prepare_call_address): Update decl.
	* final.c (profile_function): Use targetm.calls.static_chain.
	* function.c (expand_function_start): Likewise.
	* rtl.h (static_chain_rtx, static_chain_incoming_rtx): Remove.
	* stmt.c (expand_nl_goto_receiver): Use targetm.calls.static_chain;
	only clobber registers.
	* targhooks.c (default_static_chain): New.
	(default_asm_trampoline_template, default_trampoline_init): New.
	(default_trampoline_adjust_address): New.
	* targhooks.h: Declare them.
	* varasm.c (assemble_trampoline_template): Use
	targetm.asm_out.trampoline_template.  Make the memory block const
	and set its size.

From-SVN: r151983
This commit is contained in:
Richard Henderson 2009-09-22 08:11:37 -07:00 committed by Richard Henderson
parent 2df373c2eb
commit 531ca746f9
18 changed files with 278 additions and 190 deletions

View File

@ -1,3 +1,40 @@
2009-09-22 Richard Henderson <rth@redhat.com>
PR target/41246
* target.h (struct gcc_target): Add asm_out.trampoline_template,
calls.static_chain, calls.trampoline_init,
calls.trampoline_adjust_address.
* target-def.h (TARGET_ASM_TRAMPOLINE_TEMPLATE): New.
(TARGET_STATIC_CHAIN, TARGET_TRAMPOLINE_INIT): New.
(TARGET_TRAMPOLINE_ADJUST_ADDRESS): New.
* builtins.c (expand_builtin_setjmp_receiver): Use
targetm.calls.static_chain; only clobber registers.
(expand_builtin_init_trampoline): Use targetm.calls.trampoline_init;
set up memory attributes properly for the trampoline block.
(expand_builtin_adjust_trampoline): Use
targetm.calls.trampoline_adjust_address.
* calls.c (prepare_call_address): Add fndecl argument. Use
targetm.calls.static_chain.
* df-scan.c (df_need_static_chain_reg): Remove.
(df_get_entry_block_def_set): Use targetm.calls.static_chain;
consolodate static chain handling.
* doc/tm.texi: Document new hooks.
* emit-rtl.c (static_chain_rtx, static_chain_incoming_rtx): Remove.
(init_emit_regs): Don't initialize them.
* expr.h (prepare_call_address): Update decl.
* final.c (profile_function): Use targetm.calls.static_chain.
* function.c (expand_function_start): Likewise.
* rtl.h (static_chain_rtx, static_chain_incoming_rtx): Remove.
* stmt.c (expand_nl_goto_receiver): Use targetm.calls.static_chain;
only clobber registers.
* targhooks.c (default_static_chain): New.
(default_asm_trampoline_template, default_trampoline_init): New.
(default_trampoline_adjust_address): New.
* targhooks.h: Declare them.
* varasm.c (assemble_trampoline_template): Use
targetm.asm_out.trampoline_template. Make the memory block const
and set its size.
2009-09-22 Richard Guenther <rguenther@suse.de>
PR middle-end/41395

View File

@ -755,13 +755,17 @@ expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
void
expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
{
rtx chain;
/* Clobber the FP when we get here, so we have to make sure it's
marked as used by this function. */
emit_use (hard_frame_pointer_rtx);
/* Mark the static chain as clobbered here so life information
doesn't get messed up for it. */
emit_clobber (static_chain_rtx);
chain = targetm.calls.static_chain (current_function_decl, true);
if (chain && REG_P (chain))
emit_clobber (chain);
/* Now put in the code to restore the frame pointer, and argument
pointer, if needed. */
@ -839,11 +843,8 @@ expand_builtin_longjmp (rtx buf_addr, rtx value)
buf_addr = force_reg (Pmode, buf_addr);
/* We used to store value in static_chain_rtx, but that fails if pointers
are smaller than integers. We instead require that the user must pass
a second argument of 1, because that is what builtin_setjmp will
return. This also makes EH slightly more efficient, since we are no
longer copying around a value that we don't care about. */
/* We require that the user must pass a second argument of 1, because
that is what builtin_setjmp will return. */
gcc_assert (value == const1_rtx);
last = get_last_insn ();
@ -1590,7 +1591,7 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
}
/* All arguments and registers used for the call are set up by now! */
function = prepare_call_address (function, NULL, &call_fusage, 0, 0);
function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
/* Ensure address is valid. SYMBOL_REF is already valid, so no need,
and we don't want to load it into a register as an optimization,
@ -5815,10 +5816,7 @@ static rtx
expand_builtin_init_trampoline (tree exp)
{
tree t_tramp, t_func, t_chain;
rtx r_tramp, r_func, r_chain;
#ifdef TRAMPOLINE_TEMPLATE
rtx blktramp;
#endif
rtx m_tramp, r_tramp, r_chain, tmp;
if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
POINTER_TYPE, VOID_TYPE))
@ -5829,20 +5827,36 @@ expand_builtin_init_trampoline (tree exp)
t_chain = CALL_EXPR_ARG (exp, 2);
r_tramp = expand_normal (t_tramp);
r_func = expand_normal (t_func);
m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
MEM_NOTRAP_P (m_tramp) = 1;
/* The TRAMP argument should be the address of a field within the
local function's FRAME decl. Let's see if we can fill in the
to fill in the MEM_ATTRs for this memory. */
if (TREE_CODE (t_tramp) == ADDR_EXPR)
set_mem_attributes_minus_bitpos (m_tramp, TREE_OPERAND (t_tramp, 0),
true, 0);
tmp = round_trampoline_addr (r_tramp);
if (tmp != r_tramp)
{
m_tramp = change_address (m_tramp, BLKmode, tmp);
set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
set_mem_size (m_tramp, GEN_INT (TRAMPOLINE_SIZE));
}
/* The FUNC argument should be the address of the nested function.
Extract the actual function decl to pass to the hook. */
gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
t_func = TREE_OPERAND (t_func, 0);
gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
r_chain = expand_normal (t_chain);
/* Generate insns to initialize the trampoline. */
r_tramp = round_trampoline_addr (r_tramp);
#ifdef TRAMPOLINE_TEMPLATE
blktramp = gen_rtx_MEM (BLKmode, r_tramp);
set_mem_align (blktramp, TRAMPOLINE_ALIGNMENT);
emit_block_move (blktramp, assemble_trampoline_template (),
GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
#endif
trampolines_created = 1;
INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
trampolines_created = 1;
return const0_rtx;
}
@ -5856,9 +5870,8 @@ expand_builtin_adjust_trampoline (tree exp)
tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
tramp = round_trampoline_addr (tramp);
#ifdef TRAMPOLINE_ADJUST_ADDRESS
TRAMPOLINE_ADJUST_ADDRESS (tramp);
#endif
if (targetm.calls.trampoline_adjust_address)
tramp = targetm.calls.trampoline_adjust_address (tramp);
return tramp;
}

View File

@ -166,7 +166,7 @@ static void restore_fixed_argument_area (rtx, rtx, int, int);
CALL_INSN_FUNCTION_USAGE information. */
rtx
prepare_call_address (rtx funexp, rtx static_chain_value,
prepare_call_address (tree fndecl, rtx funexp, rtx static_chain_value,
rtx *call_fusage, int reg_parm_seen, int sibcallp)
{
/* Make a valid memory address and copy constants through pseudo-regs,
@ -187,11 +187,15 @@ prepare_call_address (rtx funexp, rtx static_chain_value,
if (static_chain_value != 0)
{
static_chain_value = convert_memory_address (Pmode, static_chain_value);
emit_move_insn (static_chain_rtx, static_chain_value);
rtx chain;
if (REG_P (static_chain_rtx))
use_reg (call_fusage, static_chain_rtx);
gcc_assert (fndecl);
chain = targetm.calls.static_chain (fndecl, false);
static_chain_value = convert_memory_address (Pmode, static_chain_value);
emit_move_insn (chain, static_chain_value);
if (REG_P (chain))
use_reg (call_fusage, chain);
}
return funexp;
@ -2807,7 +2811,7 @@ expand_call (tree exp, rtx target, int ignore)
}
after_args = get_last_insn ();
funexp = prepare_call_address (funexp, static_chain_value,
funexp = prepare_call_address (fndecl, funexp, static_chain_value,
&call_fusage, reg_parm_seen, pass == 0);
load_register_parameters (args, num_actuals, &call_fusage, flags,
@ -3735,7 +3739,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
else
argnum = 0;
fun = prepare_call_address (fun, NULL, &call_fusage, 0, 0);
fun = prepare_call_address (NULL, fun, NULL, &call_fusage, 0, 0);
/* Now load any reg parms into their regs. */

View File

@ -982,7 +982,7 @@ void add_framework_path (char *);
#endif
/* Attempt to turn on execute permission for the stack. This may be
used by INITIALIZE_TRAMPOLINE of the target needs it (that is,
used by TARGET_TRAMPOLINE_INIT if the target needs it (that is,
if the target machine can change execute permissions on a page).
There is no way to query the execute permission of the stack, so

View File

@ -180,7 +180,7 @@ along with GCC; see the file COPYING3. If not see
/* Attempt to turn on execute permission for the stack. This may be
used by INITIALIZE_TRAMPOLINE of the target needs it (that is,
used by TARGET_TRAMPOLINE_INIT if the target needs it (that is,
if the target machine can change execute permissions on a page).
There is no way to query the execute permission of the stack, so

View File

@ -3601,18 +3601,6 @@ df_recompute_luids (basic_block bb)
}
/* Returns true if the function entry needs to
define the static chain register. */
static bool
df_need_static_chain_reg (struct function *fun)
{
tree fun_context = decl_function_context (fun->decl);
return fun_context
&& DECL_NO_STATIC_CHAIN (fun_context) == false;
}
/* Collect all artificial refs at the block level for BB and add them
to COLLECTION_REC. */
@ -3891,24 +3879,17 @@ df_get_entry_block_def_set (bitmap entry_block_defs)
if ((call_used_regs[i] == 0) && (df_regs_ever_live_p (i)))
bitmap_set_bit (entry_block_defs, i);
}
else
{
/* If STATIC_CHAIN_INCOMING_REGNUM == STATIC_CHAIN_REGNUM
only STATIC_CHAIN_REGNUM is defined. If they are different,
we only care about the STATIC_CHAIN_INCOMING_REGNUM. */
#ifdef STATIC_CHAIN_INCOMING_REGNUM
bitmap_set_bit (entry_block_defs, STATIC_CHAIN_INCOMING_REGNUM);
#else
#ifdef STATIC_CHAIN_REGNUM
bitmap_set_bit (entry_block_defs, STATIC_CHAIN_REGNUM);
#endif
#endif
}
r = targetm.calls.struct_value_rtx (current_function_decl, true);
if (r && REG_P (r))
bitmap_set_bit (entry_block_defs, REGNO (r));
/* If the function has an incoming STATIC_CHAIN, it has to show up
in the entry def set. */
r = targetm.calls.static_chain (current_function_decl, true);
if (r && REG_P (r))
bitmap_set_bit (entry_block_defs, REGNO (r));
if ((!reload_completed) || frame_pointer_needed)
{
/* Any reference to any pseudo before reload is a potential
@ -3946,19 +3927,6 @@ df_get_entry_block_def_set (bitmap entry_block_defs)
#endif
targetm.live_on_entry (entry_block_defs);
/* If the function has an incoming STATIC_CHAIN,
it has to show up in the entry def set. */
if (df_need_static_chain_reg (cfun))
{
#ifdef STATIC_CHAIN_INCOMING_REGNUM
bitmap_set_bit (entry_block_defs, STATIC_CHAIN_INCOMING_REGNUM);
#else
#ifdef STATIC_CHAIN_REGNUM
bitmap_set_bit (entry_block_defs, STATIC_CHAIN_REGNUM);
#endif
#endif
}
}

View File

@ -3684,6 +3684,16 @@ If the static chain is passed in a register, the two previous macros should
be defined instead.
@end defmac
@deftypefn {Target Hook} rtx TARGET_STATIC_CHAIN (const_tree @var{fndecl}, bool @var{incoming_p})
This hook replaces the use of @code{STATIC_CHAIN_REGNUM} et al for
targets that may use different static chain locations for different
nested functions. This may be required if the target has function
attributes that affect the calling conventions of the function and
those calling conventions use different static chain locations.
The default version of this hook uses @code{STATIC_CHAIN_REGNUM} et al.
@end deftypefn
@defmac DWARF_FRAME_REGISTERS
This macro specifies the maximum number of hard registers that can be
saved in a call frame. This is used to size data structures used in
@ -5099,17 +5109,17 @@ proper offset from the start of the trampoline. On a RISC machine, it
may be necessary to take out pieces of the address and store them
separately.
@defmac TRAMPOLINE_TEMPLATE (@var{file})
A C statement to output, on the stream @var{file}, assembler code for a
block of data that contains the constant parts of a trampoline. This
code should not include a label---the label is taken care of
automatically.
@deftypefn {Target Hook} void TARGET_ASM_TRAMPOLINE_TEMPLATE (FILE *@var{f})
This hook is called by @code{assemble_trampoline_template} to output,
on the stream @var{f}, assembler code for a block of data that contains
the constant parts of a trampoline. This code should not include a
label---the label is taken care of automatically.
If you do not define this macro, it means no template is needed
for the target. Do not define this macro on systems where the block move
If you do not define this hook, it means no template is needed
for the target. Do not define this hook on systems where the block move
code to copy the trampoline into place would be larger than the code
to generate it on the spot.
@end defmac
@end deftypefn
@defmac TRAMPOLINE_SECTION
Return the section into which the trampoline template is to be placed
@ -5123,43 +5133,38 @@ A C expression for the size in bytes of the trampoline, as an integer.
@defmac TRAMPOLINE_ALIGNMENT
Alignment required for trampolines, in bits.
If you don't define this macro, the value of @code{BIGGEST_ALIGNMENT}
If you don't define this macro, the value of @code{FUNCTION_ALIGNMENT}
is used for aligning trampolines.
@end defmac
@defmac INITIALIZE_TRAMPOLINE (@var{addr}, @var{fnaddr}, @var{static_chain})
A C statement to initialize the variable parts of a trampoline.
@var{addr} is an RTX for the address of the trampoline; @var{fnaddr} is
an RTX for the address of the nested function; @var{static_chain} is an
@deftypefn {Target Hook} void TARGET_TRAMPOLINE_INIT (rtx @var{m_tramp}, tree @var{fndecl}, rtx @var{static_chain})
This hook is called to initialize a trampoline.
@var{m_tramp} is an RTX for the memory block for the trampoline; @var{fndecl}
is the @code{FUNCTION_DECL} for the nested function; @var{static_chain} is an
RTX for the static chain value that should be passed to the function
when it is called.
@end defmac
@defmac TRAMPOLINE_ADJUST_ADDRESS (@var{addr})
A C statement that should perform any machine-specific adjustment in
the address of the trampoline. Its argument contains the address that
was passed to @code{INITIALIZE_TRAMPOLINE}. In case the address to be
used for a function call should be different from the address in which
the template was stored, the different address should be assigned to
@var{addr}. If this macro is not defined, @var{addr} will be used for
function calls.
If the target defines @code{TARGET_ASM_TRAMPOLINE_TEMPLATE}, then the
first thing this hook should do is emit a block move into @var{m_tramp}
from the memory block returned by @code{assemble_trampoline_template}.
Note that the block move need only cover the constant parts of the
trampoline. If the target isolates the variable parts of the trampoline
to the end, not all @code{TRAMPOLINE_SIZE} bytes need be copied.
@cindex @code{TARGET_ASM_FUNCTION_EPILOGUE} and trampolines
@cindex @code{TARGET_ASM_FUNCTION_PROLOGUE} and trampolines
If this macro is not defined, by default the trampoline is allocated as
a stack slot. This default is right for most machines. The exceptions
are machines where it is impossible to execute instructions in the stack
area. On such machines, you may have to implement a separate stack,
using this macro in conjunction with @code{TARGET_ASM_FUNCTION_PROLOGUE}
and @code{TARGET_ASM_FUNCTION_EPILOGUE}.
If the target requires any other actions, such as flushing caches or
enabling stack execution, these actions should be performed after
initializing the trampoline proper.
@end deftypefn
@var{fp} points to a data structure, a @code{struct function}, which
describes the compilation status of the immediate containing function of
the function which the trampoline is for. The stack slot for the
trampoline is in the stack frame of this containing function. Other
allocation strategies probably must do something analogous with this
information.
@end defmac
@deftypefn {Target Hook} rtx TARGET_TRAMPOLINE_ADJUST_ADDRESS (rtx @var{addr})
This hook should perform any machine-specific adjustment in
the address of the trampoline. Its argument contains the address of the
memory block that was passed to @code{TARGET_TRAMPOLINE_INIT}. In case
the address to be used for a function call should be different from the
address at which the template was stored, the different address should
be returned; otherwise @var{addr} should be returned unchanged.
If this hook is not defined, @var{addr} will be used for function calls.
@end deftypefn
Implementing trampolines is difficult on many machines because they have
separate instruction and data caches. Writing into a stack location
@ -5192,7 +5197,7 @@ code located on the stack. The macro should expand to a series of C
file-scope constructs (e.g.@: functions) and provide a unique entry point
named @code{__enable_execute_stack}. The target is responsible for
emitting calls to the entry point in the code, for example from the
@code{INITIALIZE_TRAMPOLINE} macro.
@code{TARGET_TRAMPOLINE_INIT} hook.
@end defmac
To use a standard subroutine, define the following macro. In addition,

View File

@ -136,8 +136,6 @@ FIXED_VALUE_TYPE fconst1[MAX_FCONST1];
In an inline procedure, the stack and frame pointer rtxs may not be
used for anything else. */
rtx static_chain_rtx; /* (REG:Pmode STATIC_CHAIN_REGNUM) */
rtx static_chain_incoming_rtx; /* (REG:Pmode STATIC_CHAIN_INCOMING_REGNUM) */
rtx pic_offset_table_rtx; /* (REG:Pmode PIC_OFFSET_TABLE_REGNUM) */
/* This is used to implement __builtin_return_address for some machines.
@ -5671,28 +5669,6 @@ init_emit_regs (void)
= gen_raw_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM);
#endif
#ifdef STATIC_CHAIN_REGNUM
static_chain_rtx = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
#ifdef STATIC_CHAIN_INCOMING_REGNUM
if (STATIC_CHAIN_INCOMING_REGNUM != STATIC_CHAIN_REGNUM)
static_chain_incoming_rtx
= gen_rtx_REG (Pmode, STATIC_CHAIN_INCOMING_REGNUM);
else
#endif
static_chain_incoming_rtx = static_chain_rtx;
#endif
#ifdef STATIC_CHAIN
static_chain_rtx = STATIC_CHAIN;
#ifdef STATIC_CHAIN_INCOMING
static_chain_incoming_rtx = STATIC_CHAIN_INCOMING;
#else
static_chain_incoming_rtx = static_chain_rtx;
#endif
#endif
if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
else

View File

@ -618,7 +618,7 @@ extern HOST_WIDE_INT int_expr_size (tree);
in its original home. This becomes invalid if any more code is emitted. */
extern rtx hard_function_value (const_tree, const_tree, const_tree, int);
extern rtx prepare_call_address (rtx, rtx, rtx *, int, int);
extern rtx prepare_call_address (tree, rtx, rtx, rtx *, int, int);
extern bool shift_return_value (enum machine_mode, bool, rtx);

View File

@ -1594,12 +1594,14 @@ profile_function (FILE *file ATTRIBUTE_UNUSED)
#ifndef NO_PROFILE_COUNTERS
# define NO_PROFILE_COUNTERS 0
#endif
#if defined(ASM_OUTPUT_REG_PUSH)
int sval = cfun->returns_struct;
rtx svrtx = targetm.calls.struct_value_rtx (TREE_TYPE (current_function_decl), 1);
#if defined(STATIC_CHAIN_INCOMING_REGNUM) || defined(STATIC_CHAIN_REGNUM)
int cxt = cfun->static_chain_decl != NULL;
#endif
#ifdef ASM_OUTPUT_REG_PUSH
rtx sval = NULL, chain = NULL;
if (cfun->returns_struct)
sval = targetm.calls.struct_value_rtx (TREE_TYPE (current_function_decl),
true);
if (cfun->static_chain_decl)
chain = targetm.calls.static_chain (current_function_decl, true);
#endif /* ASM_OUTPUT_REG_PUSH */
if (! NO_PROFILE_COUNTERS)
@ -1613,44 +1615,20 @@ profile_function (FILE *file ATTRIBUTE_UNUSED)
switch_to_section (current_function_section ());
#if defined(ASM_OUTPUT_REG_PUSH)
if (sval && svrtx != NULL_RTX && REG_P (svrtx))
{
ASM_OUTPUT_REG_PUSH (file, REGNO (svrtx));
}
#endif
#if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (cxt)
ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM);
#else
#if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (cxt)
{
ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM);
}
#endif
#ifdef ASM_OUTPUT_REG_PUSH
if (sval && REG_P (sval))
ASM_OUTPUT_REG_PUSH (file, REGNO (sval));
if (chain && REG_P (chain))
ASM_OUTPUT_REG_PUSH (file, REGNO (chain));
#endif
FUNCTION_PROFILER (file, current_function_funcdef_no);
#if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (cxt)
ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM);
#else
#if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (cxt)
{
ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM);
}
#endif
#endif
#if defined(ASM_OUTPUT_REG_PUSH)
if (sval && svrtx != NULL_RTX && REG_P (svrtx))
{
ASM_OUTPUT_REG_POP (file, REGNO (svrtx));
}
#ifdef ASM_OUTPUT_REG_PUSH
if (chain && REG_P (chain))
ASM_OUTPUT_REG_POP (file, REGNO (chain));
if (sval && REG_P (sval))
ASM_OUTPUT_REG_POP (file, REGNO (sval));
#endif
}

View File

@ -4453,13 +4453,21 @@ expand_function_start (tree subr)
if (cfun->static_chain_decl)
{
tree parm = cfun->static_chain_decl;
rtx local = gen_reg_rtx (Pmode);
rtx local, chain, insn;
set_decl_incoming_rtl (parm, static_chain_incoming_rtx, false);
local = gen_reg_rtx (Pmode);
chain = targetm.calls.static_chain (current_function_decl, true);
set_decl_incoming_rtl (parm, chain, false);
SET_DECL_RTL (parm, local);
mark_reg_pointer (local, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (parm))));
emit_move_insn (local, static_chain_incoming_rtx);
insn = emit_move_insn (local, chain);
/* Mark the register as eliminable, similar to parameters. */
if (MEM_P (chain)
&& reg_mentioned_p (arg_pointer_rtx, XEXP (chain, 0)))
set_unique_reg_note (insn, REG_EQUIV, chain);
}
/* If the function receives a non-local goto, then store the

View File

@ -2024,8 +2024,6 @@ extern GTY(()) rtx global_rtl[GR_MAX];
#define arg_pointer_rtx (global_rtl[GR_ARG_POINTER])
extern GTY(()) rtx pic_offset_table_rtx;
extern GTY(()) rtx static_chain_rtx;
extern GTY(()) rtx static_chain_incoming_rtx;
extern GTY(()) rtx return_address_pointer_rtx;
/* Include the RTL generation functions. */

View File

@ -1799,13 +1799,17 @@ expand_return (tree retval)
static void
expand_nl_goto_receiver (void)
{
rtx chain;
/* Clobber the FP when we get here, so we have to make sure it's
marked as used by this function. */
emit_use (hard_frame_pointer_rtx);
/* Mark the static chain as clobbered here so life information
doesn't get messed up for it. */
emit_clobber (static_chain_rtx);
chain = targetm.calls.static_chain (current_function_decl, true);
if (chain && REG_P (chain))
emit_clobber (chain);
#ifdef HAVE_nonlocal_goto
if (! HAVE_nonlocal_goto)

View File

@ -247,6 +247,12 @@
#define TARGET_ASM_RECORD_GCC_SWITCHES_SECTION ".GCC.command.line"
#endif
#ifdef TRAMPOLINE_TEMPLATE
# define TARGET_ASM_TRAMPOLINE_TEMPLATE default_asm_trampoline_template
#else
# define TARGET_ASM_TRAMPOLINE_TEMPLATE NULL
#endif
#define TARGET_ASM_ALIGNED_INT_OP \
{TARGET_ASM_ALIGNED_HI_OP, \
TARGET_ASM_ALIGNED_SI_OP, \
@ -296,7 +302,8 @@
TARGET_ASM_RECORD_GCC_SWITCHES_SECTION, \
TARGET_ASM_OUTPUT_ANCHOR, \
TARGET_ASM_OUTPUT_DWARF_DTPREL, \
TARGET_ASM_FINAL_POSTSCAN_INSN}
TARGET_ASM_FINAL_POSTSCAN_INSN, \
TARGET_ASM_TRAMPOLINE_TEMPLATE }
/* Scheduler hooks. All of these default to null pointers, which
haifa-sched.c looks for and handles. */
@ -607,6 +614,14 @@
#define TARGET_UPDATE_STACK_BOUNDARY NULL
#define TARGET_GET_DRAP_RTX NULL
#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS hook_bool_void_true
#define TARGET_STATIC_CHAIN default_static_chain
#define TARGET_TRAMPOLINE_INIT default_trampoline_init
#ifdef TRAMPOLINE_ADJUST_ADDRESS
# define TARGET_TRAMPOLINE_ADJUST_ADDRESS default_trampoline_adjust_address
#else
# define TARGET_TRAMPOLINE_ADJUST_ADDRESS NULL
#endif
#define TARGET_CALLS { \
TARGET_PROMOTE_FUNCTION_MODE, \
@ -629,7 +644,10 @@
TARGET_INTERNAL_ARG_POINTER, \
TARGET_UPDATE_STACK_BOUNDARY, \
TARGET_GET_DRAP_RTX, \
TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS \
TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS, \
TARGET_STATIC_CHAIN, \
TARGET_TRAMPOLINE_INIT, \
TARGET_TRAMPOLINE_ADJUST_ADDRESS \
}
#ifndef TARGET_UNWIND_TABLES_DEFAULT

View File

@ -253,6 +253,9 @@ struct gcc_target
/* Some target machines need to postscan each insn after it is output. */
void (*final_postscan_insn) (FILE *, rtx, rtx *, int);
/* Emit the trampoline template. This hook may be NULL. */
void (*trampoline_template) (FILE *);
} asm_out;
/* Functions relating to instruction scheduling. */
@ -915,7 +918,17 @@ struct gcc_target
/* Return true if all function parameters should be spilled to the
stack. */
bool (*allocate_stack_slots_for_args) (void);
/* Return an rtx for the static chain for FNDECL. If INCOMING_P is true,
then it should be for the callee; otherwise for the caller. */
rtx (*static_chain) (const_tree fndecl, bool incoming_p);
/* Fill in the trampoline at MEM with a call to FNDECL and a
static chain value of CHAIN. */
void (*trampoline_init) (rtx mem, tree fndecl, rtx chain);
/* Adjust the address of the trampoline in a target-specific way. */
rtx (*trampoline_adjust_address) (rtx addr);
} calls;
/* Return the diagnostic message string if conversion from FROMTYPE

View File

@ -628,6 +628,69 @@ default_internal_arg_pointer (void)
return virtual_incoming_args_rtx;
}
rtx
default_static_chain (const_tree fndecl, bool incoming_p)
{
if (DECL_NO_STATIC_CHAIN (fndecl))
return NULL;
if (incoming_p)
{
#ifdef STATIC_CHAIN_INCOMING
return STATIC_CHAIN_INCOMING;
#endif
#ifdef STATIC_CHAIN_INCOMING_REGNUM
return gen_rtx_REG (Pmode, STATIC_CHAIN_INCOMING_REGNUM);
#endif
}
#ifdef STATIC_CHAIN
return STATIC_CHAIN;
#endif
#ifdef STATIC_CHAIN_REGNUM
return gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
#endif
gcc_unreachable ();
}
#ifdef TRAMPOLINE_TEMPLATE
void
default_asm_trampoline_template (FILE *f)
{
TRAMPOLINE_TEMPLATE (f);
}
#endif
void
default_trampoline_init (rtx ARG_UNUSED (m_tramp), tree ARG_UNUSED (t_func),
rtx ARG_UNUSED (r_chain))
{
#ifdef INITIALIZE_TRAMPOLINE
rtx r_tramp, r_func;
if (targetm.asm_out.trampoline_template)
emit_block_move (m_tramp, assemble_trampoline_template (),
GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
r_func = XEXP (DECL_RTL (t_func), 0);
r_tramp = XEXP (m_tramp, 0);
INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
#else
sorry ("nested function trampolines not supported on this target");
#endif
}
rtx
default_trampoline_adjust_address (rtx addr)
{
#ifdef TRAMPOLINE_ADJUST_ADDRESS
TRAMPOLINE_ADJUST_ADDRESS (addr);
#endif
return addr;
}
enum reg_class
default_branch_target_register_class (void)
{

View File

@ -100,6 +100,10 @@ extern bool hook_bool_const_rtx_commutative_p (const_rtx, int);
extern rtx default_function_value (const_tree, const_tree, bool);
extern rtx default_libcall_value (enum machine_mode, rtx);
extern rtx default_internal_arg_pointer (void);
extern rtx default_static_chain (const_tree, bool);
extern void default_asm_trampoline_template (FILE *);
extern void default_trampoline_init (rtx, tree, rtx);
extern rtx default_trampoline_adjust_address (rtx);
extern enum reg_class default_branch_target_register_class (void);
#ifdef IRA_COVER_CLASSES
extern const enum reg_class *default_ira_cover_classes (void);

View File

@ -2507,7 +2507,6 @@ assemble_static_space (unsigned HOST_WIDE_INT size)
static GTY(()) rtx initial_trampoline;
#ifdef TRAMPOLINE_TEMPLATE
rtx
assemble_trampoline_template (void)
{
@ -2516,6 +2515,8 @@ assemble_trampoline_template (void)
int align;
rtx symbol;
gcc_assert (targetm.asm_out.trampoline_template != NULL);
if (initial_trampoline)
return initial_trampoline;
@ -2530,12 +2531,10 @@ assemble_trampoline_template (void)
/* Write the assembler code to define one. */
align = floor_log2 (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
if (align > 0)
{
ASM_OUTPUT_ALIGN (asm_out_file, align);
}
ASM_OUTPUT_ALIGN (asm_out_file, align);
targetm.asm_out.internal_label (asm_out_file, "LTRAMP", 0);
TRAMPOLINE_TEMPLATE (asm_out_file);
targetm.asm_out.trampoline_template (asm_out_file);
/* Record the rtl to refer to it. */
ASM_GENERATE_INTERNAL_LABEL (label, "LTRAMP", 0);
@ -2543,12 +2542,12 @@ assemble_trampoline_template (void)
symbol = gen_rtx_SYMBOL_REF (Pmode, name);
SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
initial_trampoline = gen_rtx_MEM (BLKmode, symbol);
initial_trampoline = gen_const_mem (BLKmode, symbol);
set_mem_align (initial_trampoline, TRAMPOLINE_ALIGNMENT);
set_mem_size (initial_trampoline, GEN_INT (TRAMPOLINE_SIZE));
return initial_trampoline;
}
#endif
/* A and B are either alignments or offsets. Return the minimum alignment
that may be assumed after adding the two together. */