diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-11-03 01:40:33 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-11-03 01:40:33 +0000 |
commit | 567925e3b55e2cc7285b116f6460365f12e530ed (patch) | |
tree | 6cea9b2ad7c60bdcd1ca27428519046f1cb9729f | |
parent | e8fe69c33b9164dabea5d77c80c03090a58e8ced (diff) | |
download | gcc-567925e3b55e2cc7285b116f6460365f12e530ed.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@106420 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 33 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 115 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 1 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 23 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 12 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 26 | ||||
-rw-r--r-- | gcc/function.c | 53 | ||||
-rw-r--r-- | gcc/target-def.h | 4 | ||||
-rw-r--r-- | gcc/target.h | 4 | ||||
-rw-r--r-- | gcc/targhooks.c | 16 | ||||
-rw-r--r-- | gcc/targhooks.h | 2 | ||||
-rw-r--r-- | gcc/tree.h | 4 |
12 files changed, 216 insertions, 77 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index afca62bfa1a..a2e518a14f5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 7b3f8887996..26f0299b52b 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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; diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index a00e0e043ab..256c0e49e20 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -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]; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 19d874bce84..b739e500497 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -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))] "") diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 46d24b6b789..b339c4ccdc0 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -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 diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index d780914fe1e..314652b1547 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -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 (); diff --git a/gcc/function.c b/gcc/function.c index 941021edc66..9e36af74d72 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -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) \ diff --git a/gcc/target-def.h b/gcc/target-def.h index 6dd121d952f..7e8837451f3 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -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 diff --git a/gcc/target.h b/gcc/target.h index cd850d1a4b5..0f775f1de15 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -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 diff --git a/gcc/targhooks.c b/gcc/targhooks.c index c0c42019a04..94469a76b0f 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -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" diff --git a/gcc/targhooks.h b/gcc/targhooks.h index a39d27df337..24e3b6d38be 100644 --- a/gcc/targhooks.h +++ b/gcc/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); diff --git a/gcc/tree.h b/gcc/tree.h index f54f6d34977..4705bb12b83 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -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 |