re PR target/9350 (-fomit-frame-pointer does not work for main)
PR target/9350 PR target/24374 * dwarf2out.c (dwarf2out_reg_save_reg): New. (dwarf2out_frame_debug_expr): Return after dwarf_handle_frame_unspec. * function.c (assign_parms): Use calls.internal_arg_pointer. (expand_main_function): Remove FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN code. * target-def.h (TARGET_INTERNAL_ARG_POINTER): New. (TARGET_CALLS): Add it. * target.h (struct gcc_target): Add calls.internal_arg_pointer. * targhooks.c (default_internal_arg_pointer): New. * targhooks.h (default_internal_arg_pointer): Declare. * tree.h (dwarf2out_reg_save_reg): Declare. * doc/tm.texi (FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN): Remove. * config/i386/i386.c (dbx_register_map): Add return column. (dbx64_register_map, svr4_dbx_register_map): Likewise. (TARGET_INTERNAL_ARG_POINTER, ix86_internal_arg_pointer): New. (TARGET_DWARF_HANDLE_FRAME_UNSPEC, ix86_dwarf_handle_frame_unspec): New. (ix86_function_ok_for_sibcall): Disable if force_align_arg_pointer. (ix86_save_reg): Save force_align_arg_pointer. (ix86_emit_save_regs): Make regno unsigned. (ix86_emit_save_regs_using_mov): Likewise. (ix86_expand_prologue): Handle force_align_arg_pointer. (ix86_expand_epilogue): Likewise. * config/i386/i386.h: (dbx_register_map): Update. (dbx64_register_map, svr4_dbx_register_map): Update. (struct machine_function): Add force_align_arg_pointer. * config/i386/i386.md (UNSPEC_REG_SAVE, UNSPEC_DEF_CFA): New. (UNSPEC_TP, UNSPEC_TLS_GD, UNSPEC_TLS_LD_BASE): Renumber. (TARGET_PUSH_MEMORY peepholes): Disable if RTX_FRAME_RELATED_P. From-SVN: r106420
This commit is contained in:
parent
3a0588c4e0
commit
150cdc9e16
12 changed files with 216 additions and 77 deletions
|
@ -1,3 +1,36 @@
|
|||
2005-11-02 Richard Henderson <rth@redhat.com>
|
||||
|
||||
PR target/9350
|
||||
PR target/24374
|
||||
* dwarf2out.c (dwarf2out_reg_save_reg): New.
|
||||
(dwarf2out_frame_debug_expr): Return after dwarf_handle_frame_unspec.
|
||||
* function.c (assign_parms): Use calls.internal_arg_pointer.
|
||||
(expand_main_function): Remove FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN
|
||||
code.
|
||||
* target-def.h (TARGET_INTERNAL_ARG_POINTER): New.
|
||||
(TARGET_CALLS): Add it.
|
||||
* target.h (struct gcc_target): Add calls.internal_arg_pointer.
|
||||
* targhooks.c (default_internal_arg_pointer): New.
|
||||
* targhooks.h (default_internal_arg_pointer): Declare.
|
||||
* tree.h (dwarf2out_reg_save_reg): Declare.
|
||||
* doc/tm.texi (FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN): Remove.
|
||||
* config/i386/i386.c (dbx_register_map): Add return column.
|
||||
(dbx64_register_map, svr4_dbx_register_map): Likewise.
|
||||
(TARGET_INTERNAL_ARG_POINTER, ix86_internal_arg_pointer): New.
|
||||
(TARGET_DWARF_HANDLE_FRAME_UNSPEC, ix86_dwarf_handle_frame_unspec): New.
|
||||
(ix86_function_ok_for_sibcall): Disable if force_align_arg_pointer.
|
||||
(ix86_save_reg): Save force_align_arg_pointer.
|
||||
(ix86_emit_save_regs): Make regno unsigned.
|
||||
(ix86_emit_save_regs_using_mov): Likewise.
|
||||
(ix86_expand_prologue): Handle force_align_arg_pointer.
|
||||
(ix86_expand_epilogue): Likewise.
|
||||
* config/i386/i386.h: (dbx_register_map): Update.
|
||||
(dbx64_register_map, svr4_dbx_register_map): Update.
|
||||
(struct machine_function): Add force_align_arg_pointer.
|
||||
* config/i386/i386.md (UNSPEC_REG_SAVE, UNSPEC_DEF_CFA): New.
|
||||
(UNSPEC_TP, UNSPEC_TLS_GD, UNSPEC_TLS_LD_BASE): Renumber.
|
||||
(TARGET_PUSH_MEMORY peepholes): Disable if RTX_FRAME_RELATED_P.
|
||||
|
||||
2005-11-02 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
PR target/23303
|
||||
|
|
|
@ -913,6 +913,8 @@ static void ix86_init_builtins (void);
|
|||
static rtx ix86_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
|
||||
static const char *ix86_mangle_fundamental_type (tree);
|
||||
static tree ix86_stack_protect_fail (void);
|
||||
static rtx ix86_internal_arg_pointer (void);
|
||||
static void ix86_dwarf_handle_frame_unspec (const char *, rtx, int);
|
||||
|
||||
/* This function is only used on Solaris. */
|
||||
static void i386_solaris_elf_named_section (const char *, unsigned int, tree)
|
||||
|
@ -1081,6 +1083,10 @@ static void x86_64_elf_select_section (tree decl, int reloc,
|
|||
#define TARGET_MUST_PASS_IN_STACK ix86_must_pass_in_stack
|
||||
#undef TARGET_PASS_BY_REFERENCE
|
||||
#define TARGET_PASS_BY_REFERENCE ix86_pass_by_reference
|
||||
#undef TARGET_INTERNAL_ARG_POINTER
|
||||
#define TARGET_INTERNAL_ARG_POINTER ix86_internal_arg_pointer
|
||||
#undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
|
||||
#define TARGET_DWARF_HANDLE_FRAME_UNSPEC ix86_dwarf_handle_frame_unspec
|
||||
|
||||
#undef TARGET_GIMPLIFY_VA_ARG_EXPR
|
||||
#define TARGET_GIMPLIFY_VA_ARG_EXPR ix86_gimplify_va_arg
|
||||
|
@ -1987,6 +1993,11 @@ ix86_function_ok_for_sibcall (tree decl, tree exp)
|
|||
return false;
|
||||
#endif
|
||||
|
||||
/* If we forced aligned the stack, then sibcalling would unalign the
|
||||
stack, which may break the called function. */
|
||||
if (cfun->machine->force_align_arg_pointer)
|
||||
return false;
|
||||
|
||||
/* Otherwise okay. That also includes certain types of indirect calls. */
|
||||
return true;
|
||||
}
|
||||
|
@ -4508,6 +4519,10 @@ ix86_save_reg (unsigned int regno, int maybe_eh_return)
|
|||
}
|
||||
}
|
||||
|
||||
if (cfun->machine->force_align_arg_pointer
|
||||
&& regno == REGNO (cfun->machine->force_align_arg_pointer))
|
||||
return 1;
|
||||
|
||||
return (regs_ever_live[regno]
|
||||
&& !call_used_regs[regno]
|
||||
&& !fixed_regs[regno]
|
||||
|
@ -4719,10 +4734,10 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
|
|||
static void
|
||||
ix86_emit_save_regs (void)
|
||||
{
|
||||
int regno;
|
||||
unsigned int regno;
|
||||
rtx insn;
|
||||
|
||||
for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
|
||||
for (regno = FIRST_PSEUDO_REGISTER; regno-- > 0; )
|
||||
if (ix86_save_reg (regno, true))
|
||||
{
|
||||
insn = emit_insn (gen_push (gen_rtx_REG (Pmode, regno)));
|
||||
|
@ -4735,7 +4750,7 @@ ix86_emit_save_regs (void)
|
|||
static void
|
||||
ix86_emit_save_regs_using_mov (rtx pointer, HOST_WIDE_INT offset)
|
||||
{
|
||||
int regno;
|
||||
unsigned int regno;
|
||||
rtx insn;
|
||||
|
||||
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
|
||||
|
@ -4783,6 +4798,47 @@ pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset, int style)
|
|||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
/* Handle the TARGET_INTERNAL_ARG_POINTER hook. */
|
||||
|
||||
static rtx
|
||||
ix86_internal_arg_pointer (void)
|
||||
{
|
||||
if (FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN
|
||||
&& DECL_NAME (current_function_decl)
|
||||
&& MAIN_NAME_P (DECL_NAME (current_function_decl))
|
||||
&& DECL_FILE_SCOPE_P (current_function_decl))
|
||||
{
|
||||
cfun->machine->force_align_arg_pointer = gen_rtx_REG (Pmode, 2);
|
||||
return copy_to_reg (cfun->machine->force_align_arg_pointer);
|
||||
}
|
||||
else
|
||||
return virtual_incoming_args_rtx;
|
||||
}
|
||||
|
||||
/* Handle the TARGET_DWARF_HANDLE_FRAME_UNSPEC hook.
|
||||
This is called from dwarf2out.c to emit call frame instructions
|
||||
for frame-related insns containing UNSPECs and UNSPEC_VOLATILEs. */
|
||||
static void
|
||||
ix86_dwarf_handle_frame_unspec (const char *label, rtx pattern, int index)
|
||||
{
|
||||
rtx unspec = SET_SRC (pattern);
|
||||
gcc_assert (GET_CODE (unspec) == UNSPEC);
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case UNSPEC_REG_SAVE:
|
||||
dwarf2out_reg_save_reg (label, XVECEXP (unspec, 0, 0),
|
||||
SET_DEST (pattern));
|
||||
break;
|
||||
case UNSPEC_DEF_CFA:
|
||||
dwarf2out_def_cfa (label, REGNO (SET_DEST (pattern)),
|
||||
INTVAL (XVECEXP (unspec, 0, 0)));
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Expand the prologue into a bunch of separate insns. */
|
||||
|
||||
void
|
||||
|
@ -4795,6 +4851,52 @@ ix86_expand_prologue (void)
|
|||
|
||||
ix86_compute_frame_layout (&frame);
|
||||
|
||||
if (cfun->machine->force_align_arg_pointer)
|
||||
{
|
||||
rtx x, y;
|
||||
|
||||
/* Grab the argument pointer. */
|
||||
x = plus_constant (stack_pointer_rtx, 4);
|
||||
y = cfun->machine->force_align_arg_pointer;
|
||||
insn = emit_insn (gen_rtx_SET (VOIDmode, y, x));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
|
||||
/* The unwind info consists of two parts: install the fafp as the cfa,
|
||||
and record the fafp as the "save register" of the stack pointer.
|
||||
The later is there in order that the unwinder can see where it
|
||||
should restore the stack pointer across the and insn. */
|
||||
x = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, const0_rtx), UNSPEC_DEF_CFA);
|
||||
x = gen_rtx_SET (VOIDmode, y, x);
|
||||
RTX_FRAME_RELATED_P (x) = 1;
|
||||
y = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, stack_pointer_rtx),
|
||||
UNSPEC_REG_SAVE);
|
||||
y = gen_rtx_SET (VOIDmode, cfun->machine->force_align_arg_pointer, y);
|
||||
RTX_FRAME_RELATED_P (y) = 1;
|
||||
x = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, x, y));
|
||||
x = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, x, NULL);
|
||||
REG_NOTES (insn) = x;
|
||||
|
||||
/* Align the stack. */
|
||||
emit_insn (gen_andsi3 (stack_pointer_rtx, stack_pointer_rtx,
|
||||
GEN_INT (-16)));
|
||||
|
||||
/* And here we cheat like madmen with the unwind info. We force the
|
||||
cfa register back to sp+4, which is exactly what it was at the
|
||||
start of the function. Re-pushing the return address results in
|
||||
the return at the same spot relative to the cfa, and thus is
|
||||
correct wrt the unwind info. */
|
||||
x = cfun->machine->force_align_arg_pointer;
|
||||
x = gen_frame_mem (Pmode, plus_constant (x, -4));
|
||||
insn = emit_insn (gen_push (x));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
|
||||
x = GEN_INT (4);
|
||||
x = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, x), UNSPEC_DEF_CFA);
|
||||
x = gen_rtx_SET (VOIDmode, stack_pointer_rtx, x);
|
||||
x = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, x, NULL);
|
||||
REG_NOTES (insn) = x;
|
||||
}
|
||||
|
||||
/* Note: AT&T enter does NOT have reversed args. Enter is probably
|
||||
slower on all targets. Also sdb doesn't like it. */
|
||||
|
||||
|
@ -5072,6 +5174,13 @@ ix86_expand_epilogue (int style)
|
|||
}
|
||||
}
|
||||
|
||||
if (cfun->machine->force_align_arg_pointer)
|
||||
{
|
||||
emit_insn (gen_addsi3 (stack_pointer_rtx,
|
||||
cfun->machine->force_align_arg_pointer,
|
||||
GEN_INT (-4)));
|
||||
}
|
||||
|
||||
/* Sibcall epilogues don't want a return instruction. */
|
||||
if (style == 0)
|
||||
return;
|
||||
|
|
|
@ -2263,6 +2263,7 @@ struct machine_function GTY(())
|
|||
{
|
||||
struct stack_local_entry *stack_locals;
|
||||
const char *some_ld_name;
|
||||
rtx force_align_arg_pointer;
|
||||
int save_varrargs_registers;
|
||||
int accesses_prev_frame;
|
||||
int optimize_mode_switching[MAX_386_ENTITIES];
|
||||
|
|
|
@ -66,11 +66,13 @@
|
|||
(UNSPEC_STACK_ALLOC 11)
|
||||
(UNSPEC_SET_GOT 12)
|
||||
(UNSPEC_SSE_PROLOGUE_SAVE 13)
|
||||
(UNSPEC_REG_SAVE 14)
|
||||
(UNSPEC_DEF_CFA 15)
|
||||
|
||||
; TLS support
|
||||
(UNSPEC_TP 15)
|
||||
(UNSPEC_TLS_GD 16)
|
||||
(UNSPEC_TLS_LD_BASE 17)
|
||||
(UNSPEC_TP 16)
|
||||
(UNSPEC_TLS_GD 17)
|
||||
(UNSPEC_TLS_LD_BASE 18)
|
||||
|
||||
; Other random patterns
|
||||
(UNSPEC_SCAS 20)
|
||||
|
@ -18934,7 +18936,8 @@
|
|||
[(set (match_operand:SI 0 "push_operand" "")
|
||||
(match_operand:SI 1 "memory_operand" ""))
|
||||
(match_scratch:SI 2 "r")]
|
||||
"! optimize_size && ! TARGET_PUSH_MEMORY"
|
||||
"!optimize_size && !TARGET_PUSH_MEMORY
|
||||
&& !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
|
||||
[(set (match_dup 2) (match_dup 1))
|
||||
(set (match_dup 0) (match_dup 2))]
|
||||
"")
|
||||
|
@ -18943,7 +18946,8 @@
|
|||
[(set (match_operand:DI 0 "push_operand" "")
|
||||
(match_operand:DI 1 "memory_operand" ""))
|
||||
(match_scratch:DI 2 "r")]
|
||||
"! optimize_size && ! TARGET_PUSH_MEMORY"
|
||||
"!optimize_size && !TARGET_PUSH_MEMORY
|
||||
&& !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
|
||||
[(set (match_dup 2) (match_dup 1))
|
||||
(set (match_dup 0) (match_dup 2))]
|
||||
"")
|
||||
|
@ -18954,7 +18958,8 @@
|
|||
[(set (match_operand:SF 0 "push_operand" "")
|
||||
(match_operand:SF 1 "memory_operand" ""))
|
||||
(match_scratch:SF 2 "r")]
|
||||
"! optimize_size && ! TARGET_PUSH_MEMORY"
|
||||
"!optimize_size && !TARGET_PUSH_MEMORY
|
||||
&& !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
|
||||
[(set (match_dup 2) (match_dup 1))
|
||||
(set (match_dup 0) (match_dup 2))]
|
||||
"")
|
||||
|
@ -18963,7 +18968,8 @@
|
|||
[(set (match_operand:HI 0 "push_operand" "")
|
||||
(match_operand:HI 1 "memory_operand" ""))
|
||||
(match_scratch:HI 2 "r")]
|
||||
"! optimize_size && ! TARGET_PUSH_MEMORY"
|
||||
"!optimize_size && !TARGET_PUSH_MEMORY
|
||||
&& !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
|
||||
[(set (match_dup 2) (match_dup 1))
|
||||
(set (match_dup 0) (match_dup 2))]
|
||||
"")
|
||||
|
@ -18972,7 +18978,8 @@
|
|||
[(set (match_operand:QI 0 "push_operand" "")
|
||||
(match_operand:QI 1 "memory_operand" ""))
|
||||
(match_scratch:QI 2 "q")]
|
||||
"! optimize_size && ! TARGET_PUSH_MEMORY"
|
||||
"!optimize_size && !TARGET_PUSH_MEMORY
|
||||
&& !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
|
||||
[(set (match_dup 2) (match_dup 1))
|
||||
(set (match_dup 0) (match_dup 2))]
|
||||
"")
|
||||
|
|
|
@ -1033,18 +1033,6 @@ macro must evaluate to a value equal to or larger than
|
|||
@code{STACK_BOUNDARY}.
|
||||
@end defmac
|
||||
|
||||
@defmac FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN
|
||||
A C expression that evaluates true if @code{PREFERRED_STACK_BOUNDARY} is
|
||||
not guaranteed by the runtime and we should emit code to align the stack
|
||||
at the beginning of @code{main}.
|
||||
|
||||
@cindex @code{PUSH_ROUNDING}, interaction with @code{PREFERRED_STACK_BOUNDARY}
|
||||
If @code{PUSH_ROUNDING} is not defined, the stack will always be aligned
|
||||
to the specified boundary. If @code{PUSH_ROUNDING} is defined and specifies
|
||||
a less strict alignment than @code{PREFERRED_STACK_BOUNDARY}, the stack may
|
||||
be momentarily unaligned while pushing arguments.
|
||||
@end defmac
|
||||
|
||||
@defmac FUNCTION_BOUNDARY
|
||||
Alignment required for a function entry point, in bits.
|
||||
@end defmac
|
||||
|
|
|
@ -1271,6 +1271,30 @@ clobbers_queued_reg_save (rtx insn)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Entry point for saving the first register into the second. */
|
||||
|
||||
void
|
||||
dwarf2out_reg_save_reg (const char *label, rtx reg, rtx sreg)
|
||||
{
|
||||
size_t i;
|
||||
unsigned int regno, sregno;
|
||||
|
||||
for (i = 0; i < num_regs_saved_in_regs; i++)
|
||||
if (REGNO (regs_saved_in_regs[i].orig_reg) == REGNO (reg))
|
||||
break;
|
||||
if (i == num_regs_saved_in_regs)
|
||||
{
|
||||
gcc_assert (i != ARRAY_SIZE (regs_saved_in_regs));
|
||||
num_regs_saved_in_regs++;
|
||||
}
|
||||
regs_saved_in_regs[i].orig_reg = reg;
|
||||
regs_saved_in_regs[i].saved_in_reg = sreg;
|
||||
|
||||
regno = DWARF_FRAME_REGNUM (REGNO (reg));
|
||||
sregno = DWARF_FRAME_REGNUM (REGNO (sreg));
|
||||
reg_save (label, regno, sregno, 0);
|
||||
}
|
||||
|
||||
/* What register, if any, is currently saved in REG? */
|
||||
|
||||
static rtx
|
||||
|
@ -1659,7 +1683,7 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
|
|||
case UNSPEC_VOLATILE:
|
||||
gcc_assert (targetm.dwarf_handle_frame_unspec);
|
||||
targetm.dwarf_handle_frame_unspec (label, expr, XINT (src, 1));
|
||||
break;
|
||||
return;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
|
|
|
@ -2894,22 +2894,9 @@ assign_parms (tree fndecl)
|
|||
{
|
||||
struct assign_parm_data_all all;
|
||||
tree fnargs, parm;
|
||||
rtx internal_arg_pointer;
|
||||
|
||||
/* If the reg that the virtual arg pointer will be translated into is
|
||||
not a fixed reg or is the stack pointer, make a copy of the virtual
|
||||
arg pointer, and address parms via the copy. The frame pointer is
|
||||
considered fixed even though it is not marked as such.
|
||||
|
||||
The second time through, simply use ap to avoid generating rtx. */
|
||||
|
||||
if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM
|
||||
|| ! (fixed_regs[ARG_POINTER_REGNUM]
|
||||
|| ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM)))
|
||||
internal_arg_pointer = copy_to_reg (virtual_incoming_args_rtx);
|
||||
else
|
||||
internal_arg_pointer = virtual_incoming_args_rtx;
|
||||
current_function_internal_arg_pointer = internal_arg_pointer;
|
||||
current_function_internal_arg_pointer
|
||||
= targetm.calls.internal_arg_pointer ();
|
||||
|
||||
assign_parms_initialize_all (&all);
|
||||
fnargs = assign_parms_augmented_arg_list (&all);
|
||||
|
@ -3916,42 +3903,6 @@ struct tree_opt_pass pass_init_function =
|
|||
void
|
||||
expand_main_function (void)
|
||||
{
|
||||
#ifdef FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN
|
||||
if (FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN)
|
||||
{
|
||||
int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
|
||||
rtx tmp, seq;
|
||||
|
||||
start_sequence ();
|
||||
/* Forcibly align the stack. */
|
||||
#ifdef STACK_GROWS_DOWNWARD
|
||||
tmp = expand_simple_binop (Pmode, AND, stack_pointer_rtx, GEN_INT(-align),
|
||||
stack_pointer_rtx, 1, OPTAB_WIDEN);
|
||||
#else
|
||||
tmp = expand_simple_binop (Pmode, PLUS, stack_pointer_rtx,
|
||||
GEN_INT (align - 1), NULL_RTX, 1, OPTAB_WIDEN);
|
||||
tmp = expand_simple_binop (Pmode, AND, tmp, GEN_INT (-align),
|
||||
stack_pointer_rtx, 1, OPTAB_WIDEN);
|
||||
#endif
|
||||
if (tmp != stack_pointer_rtx)
|
||||
emit_move_insn (stack_pointer_rtx, tmp);
|
||||
|
||||
/* Enlist allocate_dynamic_stack_space to pick up the pieces. */
|
||||
tmp = force_reg (Pmode, const0_rtx);
|
||||
allocate_dynamic_stack_space (tmp, NULL_RTX, BIGGEST_ALIGNMENT);
|
||||
seq = get_insns ();
|
||||
end_sequence ();
|
||||
|
||||
for (tmp = get_last_insn (); tmp; tmp = PREV_INSN (tmp))
|
||||
if (NOTE_P (tmp) && NOTE_LINE_NUMBER (tmp) == NOTE_INSN_FUNCTION_BEG)
|
||||
break;
|
||||
if (tmp)
|
||||
emit_insn_before (seq, tmp);
|
||||
else
|
||||
emit_insn (seq);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(INVOKE__main) \
|
||||
|| (!defined(HAS_INIT_SECTION) \
|
||||
&& !defined(INIT_SECTION_ASM_OP) \
|
||||
|
|
|
@ -445,6 +445,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#define TARGET_ARG_PARTIAL_BYTES hook_int_CUMULATIVE_ARGS_mode_tree_bool_0
|
||||
|
||||
#define TARGET_FUNCTION_VALUE default_function_value
|
||||
#define TARGET_INTERNAL_ARG_POINTER default_internal_arg_pointer
|
||||
|
||||
#define TARGET_CALLS { \
|
||||
TARGET_PROMOTE_FUNCTION_ARGS, \
|
||||
|
@ -463,7 +464,8 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
TARGET_CALLEE_COPIES, \
|
||||
TARGET_ARG_PARTIAL_BYTES, \
|
||||
TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN, \
|
||||
TARGET_FUNCTION_VALUE \
|
||||
TARGET_FUNCTION_VALUE, \
|
||||
TARGET_INTERNAL_ARG_POINTER \
|
||||
}
|
||||
|
||||
#ifndef TARGET_UNWIND_TABLES_DEFAULT
|
||||
|
|
|
@ -613,6 +613,10 @@ struct gcc_target
|
|||
specified by FN_DECL_OR_TYPE with a return type of RET_TYPE. */
|
||||
rtx (*function_value) (tree ret_type, tree fn_decl_or_type,
|
||||
bool outgoing);
|
||||
|
||||
/* Return an rtx for the argument pointer incoming to the
|
||||
current function. */
|
||||
rtx (*internal_arg_pointer) (void);
|
||||
} calls;
|
||||
|
||||
/* Return the diagnostic message string if conversion from FROMTYPE
|
||||
|
|
|
@ -62,6 +62,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
|||
#include "tm_p.h"
|
||||
#include "target-def.h"
|
||||
#include "ggc.h"
|
||||
#include "hard-reg-set.h"
|
||||
|
||||
|
||||
void
|
||||
|
@ -439,4 +440,19 @@ default_function_value (tree ret_type ATTRIBUTE_UNUSED,
|
|||
#endif
|
||||
}
|
||||
|
||||
rtx
|
||||
default_internal_arg_pointer (void)
|
||||
{
|
||||
/* If the reg that the virtual arg pointer will be translated into is
|
||||
not a fixed reg or is the stack pointer, make a copy of the virtual
|
||||
arg pointer, and address parms via the copy. The frame pointer is
|
||||
considered fixed even though it is not marked as such. */
|
||||
if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM
|
||||
|| ! (fixed_regs[ARG_POINTER_REGNUM]
|
||||
|| ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM)))
|
||||
return copy_to_reg (virtual_incoming_args_rtx);
|
||||
else
|
||||
return virtual_incoming_args_rtx;
|
||||
}
|
||||
|
||||
#include "gt-targhooks.h"
|
||||
|
|
|
@ -68,4 +68,4 @@ extern const char *hook_invalid_arg_for_unprototyped_fn
|
|||
(tree, tree, tree);
|
||||
extern bool hook_bool_rtx_commutative_p (rtx, int);
|
||||
extern rtx default_function_value (tree, tree, bool);
|
||||
|
||||
extern rtx default_internal_arg_pointer (void);
|
||||
|
|
|
@ -4119,6 +4119,10 @@ extern void dwarf2out_return_save (const char *, HOST_WIDE_INT);
|
|||
|
||||
extern void dwarf2out_return_reg (const char *, unsigned);
|
||||
|
||||
/* Entry point for saving the first register into the second. */
|
||||
|
||||
extern void dwarf2out_reg_save_reg (const char *, rtx, rtx);
|
||||
|
||||
/* In tree-inline.c */
|
||||
|
||||
/* The type of a set of already-visited pointers. Functions for creating
|
||||
|
|
Loading…
Add table
Reference in a new issue