Commit e54c7471 by Eric Botcazou Committed by Eric Botcazou

target.h (struct gcc_target): New field 'dwarf_handle_frame_unspec'.

	* target.h (struct gcc_target): New field 'dwarf_handle_frame_unspec'.
	* target_def.h (TARGET_DWARF_HANDLE_FRAME_UNSPEC): Define to 0.
	(TARGET_INITIALIZER): Add TARGET_DWARF_HANDLE_FRAME_UNSPEC.
	* dwarf2out.c (dwarf2out_frame_debug_expr): Allow REG->REG move
	to a fixed reg if the source is the Return Address register.
	Implement new Rule 15.
	* doc/tm.texi (Frame Layout): Document TARGET_DWARF_HANDLE_FRAME_UNSPEC.
	* config/sparc/sparc.c (TARGET_DWARF_HANDLE_FRAME_UNSPEC): Define to
	sparc_dwarf_handle_frame_unspec.
	(gen_save_register_window): New function.
	(emit_stack_pointer_increment): Rename into gen_stack_pointer_inc.
	(emit_stack_pointer_decrement): Rename into gen_stack_pointer_dec.
	(expand_prologue): Adjust calls to emit_stack_pointer_{in,de}crement.
	Set RTX_FRAME_RELATED_P on the appropriate insns and members of insns.
	(sparc_asm_function_prologue): Do not emit call frame debugging info.
	(emit_and_preserve): Adjust calls to emit_stack_pointer_{in,de}crement.
	(sparc_expand_epilogue): Likewise.
	(sparc_dwarf_handle_frame_unspec): New function.
	* config/sparc/sparc.md (save_register_window): Remove.
	(save_register_windowdi): Rewrite modelled on the callframe debug info.
	(save_register_windowsi): Likewise.

From-SVN: r91346
parent 077094ac
2004-11-26 Eric Botcazou <ebotcazou@libertysurf.fr>
* target.h (struct gcc_target): New field 'dwarf_handle_frame_unspec'.
* target_def.h (TARGET_DWARF_HANDLE_FRAME_UNSPEC): Define to 0.
(TARGET_INITIALIZER): Add TARGET_DWARF_HANDLE_FRAME_UNSPEC.
* dwarf2out.c (dwarf2out_frame_debug_expr): Allow REG->REG move
to a fixed reg if the source is the Return Address register.
Implement new Rule 15.
* doc/tm.texi (Frame Layout): Document TARGET_DWARF_HANDLE_FRAME_UNSPEC.
* config/sparc/sparc.c (TARGET_DWARF_HANDLE_FRAME_UNSPEC): Define to
sparc_dwarf_handle_frame_unspec.
(gen_save_register_window): New function.
(emit_stack_pointer_increment): Rename into gen_stack_pointer_inc.
(emit_stack_pointer_decrement): Rename into gen_stack_pointer_dec.
(expand_prologue): Adjust calls to emit_stack_pointer_{in,de}crement.
Set RTX_FRAME_RELATED_P on the appropriate insns and members of insns.
(sparc_asm_function_prologue): Do not emit call frame debugging info.
(emit_and_preserve): Adjust calls to emit_stack_pointer_{in,de}crement.
(sparc_expand_epilogue): Likewise.
(sparc_dwarf_handle_frame_unspec): New function.
* config/sparc/sparc.md (save_register_window): Remove.
(save_register_windowdi): Rewrite modelled on the callframe debug info.
(save_register_windowsi): Likewise.
2004-11-26 Alexandre Oliva <aoliva@redhat.com>
* config/frv/frv-protos.h: Guard ifcvt functions declarations with
......
......@@ -356,6 +356,7 @@ static tree sparc_gimplify_va_arg (tree, tree, tree *, tree *);
static bool sparc_vector_mode_supported_p (enum machine_mode);
static bool sparc_pass_by_reference (CUMULATIVE_ARGS *,
enum machine_mode, tree, bool);
static void sparc_dwarf_handle_frame_unspec (const char *, rtx, int);
#ifdef SUBTARGET_ATTRIBUTE_TABLE
const struct attribute_spec sparc_attribute_table[];
#endif
......@@ -480,6 +481,9 @@ enum processor_type sparc_cpu;
#undef TARGET_VECTOR_MODE_SUPPORTED_P
#define TARGET_VECTOR_MODE_SUPPORTED_P sparc_vector_mode_supported_p
#undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
#define TARGET_DWARF_HANDLE_FRAME_UNSPEC sparc_dwarf_handle_frame_unspec
#ifdef SUBTARGET_INSERT_ATTRIBUTES
#undef TARGET_INSERT_ATTRIBUTES
#define TARGET_INSERT_ATTRIBUTES SUBTARGET_INSERT_ATTRIBUTES
......@@ -4478,26 +4482,37 @@ emit_restore_regs (void)
save_or_restore_regs (32, TARGET_V9 ? 96 : 64, base, offset, SORR_RESTORE);
}
/* Emit an increment for the stack pointer. */
/* Generate a save_register_window insn. */
static void
emit_stack_pointer_increment (rtx increment)
static rtx
gen_save_register_window (rtx increment)
{
if (TARGET_ARCH64)
emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx, increment));
return gen_save_register_windowdi (increment);
else
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, increment));
return gen_save_register_windowsi (increment);
}
/* Emit a decrement for the stack pointer. */
/* Generate an increment for the stack pointer. */
static void
emit_stack_pointer_decrement (rtx decrement)
static rtx
gen_stack_pointer_inc (rtx increment)
{
if (TARGET_ARCH64)
emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx, decrement));
return gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx, increment);
else
emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, decrement));
return gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, increment);
}
/* Generate a decrement for the stack pointer. */
static rtx
gen_stack_pointer_dec (rtx decrement)
{
if (TARGET_ARCH64)
return gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx, decrement);
else
return gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, decrement);
}
/* Expand the function prologue. The prologue is responsible for reserving
......@@ -4507,6 +4522,9 @@ emit_stack_pointer_decrement (rtx decrement)
void
sparc_expand_prologue (void)
{
rtx insn;
int i;
/* Compute a snapshot of current_function_uses_only_leaf_regs. Relying
on the final value of the flag means deferring the prologue/epilogue
expansion until just before the second scheduling pass, which is too
......@@ -4556,34 +4574,48 @@ sparc_expand_prologue (void)
else if (sparc_leaf_function_p)
{
if (actual_fsize <= 4096)
emit_stack_pointer_increment (GEN_INT (- actual_fsize));
insn = emit_insn (gen_stack_pointer_inc (GEN_INT (-actual_fsize)));
else if (actual_fsize <= 8192)
{
emit_stack_pointer_increment (GEN_INT (-4096));
emit_stack_pointer_increment (GEN_INT (4096 - actual_fsize));
insn = emit_insn (gen_stack_pointer_inc (GEN_INT (-4096)));
/* %sp is still the CFA register. */
RTX_FRAME_RELATED_P (insn) = 1;
insn
= emit_insn (gen_stack_pointer_inc (GEN_INT (4096-actual_fsize)));
}
else
{
rtx reg = gen_rtx_REG (Pmode, 1);
emit_move_insn (reg, GEN_INT (-actual_fsize));
emit_stack_pointer_increment (reg);
insn = emit_insn (gen_stack_pointer_inc (reg));
REG_NOTES (insn) =
gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
PATTERN (gen_stack_pointer_inc (GEN_INT (-actual_fsize))),
REG_NOTES (insn));
}
RTX_FRAME_RELATED_P (insn) = 1;
}
else
{
if (actual_fsize <= 4096)
emit_insn (gen_save_register_window (GEN_INT (-actual_fsize)));
insn = emit_insn (gen_save_register_window (GEN_INT (-actual_fsize)));
else if (actual_fsize <= 8192)
{
emit_insn (gen_save_register_window (GEN_INT (-4096)));
emit_stack_pointer_increment (GEN_INT (4096 - actual_fsize));
insn = emit_insn (gen_save_register_window (GEN_INT (-4096)));
/* %sp is not the CFA register anymore. */
emit_insn (gen_stack_pointer_inc (GEN_INT (4096-actual_fsize)));
}
else
{
rtx reg = gen_rtx_REG (Pmode, 1);
emit_move_insn (reg, GEN_INT (-actual_fsize));
emit_insn (gen_save_register_window (reg));
insn = emit_insn (gen_save_register_window (reg));
}
RTX_FRAME_RELATED_P (insn) = 1;
for (i=0; i < XVECLEN (PATTERN (insn), 0); i++)
RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, i)) = 1;
}
/* Call-saved registers are saved just above the outgoing argument area. */
......@@ -4596,8 +4628,7 @@ sparc_expand_prologue (void)
}
/* This function generates the assembly code for function entry, which boils
down to emitting the necessary .register directives. It also informs the
DWARF-2 back-end on the layout of the frame.
down to emitting the necessary .register directives.
??? Historical cruft: "On SPARC, move-double insns between fpu and cpu need
an 8-byte block of memory. If any fpu reg is used in the function, we
......@@ -4612,29 +4643,6 @@ sparc_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
abort();
sparc_output_scratch_registers (file);
if (dwarf2out_do_frame () && actual_fsize)
{
char *label = dwarf2out_cfi_label ();
/* The canonical frame address refers to the top of the frame. */
dwarf2out_def_cfa (label,
sparc_leaf_function_p
? STACK_POINTER_REGNUM
: HARD_FRAME_POINTER_REGNUM,
frame_base_offset);
if (! sparc_leaf_function_p)
{
/* Note the register window save. This tells the unwinder that
it needs to restore the window registers from the previous
frame's window save area at 0(cfa). */
dwarf2out_window_save (label);
/* The return address (-8) is now in %i7. */
dwarf2out_return_reg (label, 31);
}
}
}
/* Expand the function epilogue, either normal or part of a sibcall.
......@@ -4651,17 +4659,17 @@ sparc_expand_epilogue (void)
else if (sparc_leaf_function_p)
{
if (actual_fsize <= 4096)
emit_stack_pointer_decrement (GEN_INT (- actual_fsize));
emit_insn (gen_stack_pointer_dec (GEN_INT (- actual_fsize)));
else if (actual_fsize <= 8192)
{
emit_stack_pointer_decrement (GEN_INT (-4096));
emit_stack_pointer_decrement (GEN_INT (4096 - actual_fsize));
emit_insn (gen_stack_pointer_dec (GEN_INT (-4096)));
emit_insn (gen_stack_pointer_dec (GEN_INT (4096 - actual_fsize)));
}
else
{
rtx reg = gen_rtx_REG (Pmode, 1);
emit_move_insn (reg, GEN_INT (-actual_fsize));
emit_stack_pointer_decrement (reg);
emit_insn (gen_stack_pointer_dec (reg));
}
}
}
......@@ -8886,11 +8894,11 @@ emit_and_preserve (rtx seq, rtx reg)
rtx slot = gen_rtx_MEM (word_mode,
plus_constant (stack_pointer_rtx, SPARC_STACK_BIAS));
emit_stack_pointer_decrement (GEN_INT (STACK_BOUNDARY/BITS_PER_UNIT));
emit_insn (gen_stack_pointer_dec (GEN_INT (STACK_BOUNDARY/BITS_PER_UNIT)));
emit_insn (gen_rtx_SET (VOIDmode, slot, reg));
emit_insn (seq);
emit_insn (gen_rtx_SET (VOIDmode, reg, slot));
emit_stack_pointer_increment (GEN_INT (STACK_BOUNDARY/BITS_PER_UNIT));
emit_insn (gen_stack_pointer_inc (GEN_INT (STACK_BOUNDARY/BITS_PER_UNIT)));
}
/* Output the assembler code for a thunk function. THUNK_DECL is the
......@@ -9153,6 +9161,18 @@ get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
return 0;
}
/* 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
sparc_dwarf_handle_frame_unspec (const char *label,
rtx pattern ATTRIBUTE_UNUSED,
int index ATTRIBUTE_UNUSED)
{
gcc_assert (index == UNSPECV_SAVEW);
dwarf2out_window_save (label);
}
/* This is called from dwarf2out.c via ASM_OUTPUT_DWARF_DTPREL.
We need to emit DTP-relative relocations. */
......
......@@ -7713,39 +7713,31 @@
DONE;
})
(define_expand "save_register_window"
[(use (match_operand 0 "arith_operand" ""))]
""
{
rtvec vec;
vec = gen_rtvec (2,
gen_rtx_SET (VOIDmode,
stack_pointer_rtx,
gen_rtx_PLUS (Pmode,
hard_frame_pointer_rtx,
operands[0])),
gen_rtx_UNSPEC_VOLATILE (VOIDmode,
gen_rtvec (1, const0_rtx),
UNSPECV_SAVEW));
emit_insn (gen_rtx_PARALLEL (VOIDmode, vec));
DONE;
})
(define_insn "*save_register_windowsi"
[(set (reg:SI 14) (plus:SI (reg:SI 30)
(match_operand:SI 0 "arith_operand" "rI")))
(unspec_volatile [(const_int 0)] UNSPECV_SAVEW)]
"! TARGET_ARCH64"
;; The "save register window" insn is modelled as follows so that the DWARF-2
;; backend automatically emits the required call frame debugging information
;; while it is parsing it. Therefore, the pattern should not be modified
;; without first studying the impact of the changes on the debug info.
;; [(set (%fp) (%sp))
;; (set (%sp) (unspec_volatile [(%sp) (-frame_size)] UNSPECV_SAVEW))
;; (set (%i7) (%o7))]
(define_insn "save_register_windowdi"
[(set (reg:DI 30) (reg:DI 14))
(set (reg:DI 14) (unspec_volatile [(reg:DI 14)
(match_operand:DI 0 "arith_operand" "rI")]
UNSPECV_SAVEW))
(set (reg:DI 31) (reg:DI 15))]
"TARGET_ARCH64"
"save\t%%sp, %0, %%sp"
[(set_attr "type" "savew")])
(define_insn "*save_register_windowdi"
[(set (reg:DI 14) (plus:DI (reg:DI 30)
(match_operand:DI 0 "arith_operand" "rI")))
(unspec_volatile [(const_int 0)] UNSPECV_SAVEW)]
"TARGET_ARCH64"
(define_insn "save_register_windowsi"
[(set (reg:SI 30) (reg:SI 14))
(set (reg:SI 14) (unspec_volatile [(reg:SI 14)
(match_operand:SI 0 "arith_operand" "rI")]
UNSPECV_SAVEW))
(set (reg:SI 31) (reg:SI 15))]
"!TARGET_ARCH64"
"save\t%%sp, %0, %%sp"
[(set_attr "type" "savew")])
......
......@@ -3005,6 +3005,22 @@ someone decided it was a good idea to use that register number to
terminate the stack backtrace. New ports should avoid this.
@end defmac
@deftypefn {Target Hook} void TARGET_DWARF_HANDLE_FRAME_UNSPEC (const char *@var{label}, rtx @var{pattern}, int @var{index})
This target hook allows the backend to emit frame-related insns that
contain UNSPECs or UNSPEC_VOLATILEs. The DWARF 2 call frame debugging
info engine will invoke it on insns of the form
@smallexample
(set (reg) (unspec [...] UNSPEC_INDEX))
@end smallexample
and
@smallexample
(set (reg) (unspec_volatile [...] UNSPECV_INDEX)).
@end smallexample
to let the backend emit the call frame instructions. @var{label} is
the CFI label attached to the insn, @var{pattern} is the pattern of
the insn and @var{index} is @code{UNSPEC_INDEX} or @code{UNSPECV_INDEX}.
@end deftypefn
@defmac INCOMING_FRAME_SP_OFFSET
A C expression whose value is an integer giving the offset, in bytes,
from the value of the stack pointer register to the top of the stack
......
......@@ -1441,7 +1441,11 @@ static dw_cfa_location cfa_temp;
(set (mem (postinc <reg1>:cfa_temp <const_int>)) <reg2>)
effects: cfa.reg = <reg1>
cfa.base_offset = -cfa_temp.offset
cfa_temp.offset -= mode_size(mem) */
cfa_temp.offset -= mode_size(mem)
  Rule 15:
  (set <reg> {unspec, unspec_volatile})
  effects: target-dependent */
static void
dwarf2out_frame_debug_expr (rtx expr, const char *label)
......@@ -1505,7 +1509,10 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
{
/* Saving a register in a register. */
gcc_assert (call_used_regs [REGNO (dest)]
&& !fixed_regs [REGNO (dest)]);
&& (!fixed_regs [REGNO (dest)]
/* For the SPARC and its register window. */
|| DWARF_FRAME_REGNUM (REGNO (src))
== DWARF_FRAME_RETURN_COLUMN));
queue_reg_save (label, src, dest, 0);
}
break;
......@@ -1632,6 +1639,13 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
case HIGH:
break;
/* Rule 15 */
case UNSPEC:
case UNSPEC_VOLATILE:
gcc_assert (targetm.dwarf_handle_frame_unspec);
targetm.dwarf_handle_frame_unspec (label, expr, XINT (src, 1));
break;
default:
gcc_unreachable ();
}
......
......@@ -381,6 +381,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define TARGET_DWARF_CALLING_CONVENTION hook_int_tree_0
#define TARGET_DWARF_HANDLE_FRAME_UNSPEC 0
#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_false
#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_false
#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_false
......@@ -525,6 +527,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
TARGET_BUILTIN_SETJMP_FRAME_VALUE, \
TARGET_MD_ASM_CLOBBERS, \
TARGET_DWARF_CALLING_CONVENTION, \
TARGET_DWARF_HANDLE_FRAME_UNSPEC, \
TARGET_CALLS, \
TARGET_CXX, \
TARGET_HAVE_NAMED_SECTIONS, \
......
......@@ -495,6 +495,15 @@ struct gcc_target
the function is being declared as an int. */
int (* dwarf_calling_convention) (tree);
/* This target hook allows the backend to emit frame-related insns that
contain UNSPECs or UNSPEC_VOLATILEs. The call frame debugging info
engine will invoke it on insns of the form
(set (reg) (unspec [...] UNSPEC_INDEX))
and
(set (reg) (unspec_volatile [...] UNSPECV_INDEX))
to let the backend emit the call frame instructions. */
void (* dwarf_handle_frame_unspec) (const char *, rtx, int);
/* Functions relating to calls - argument passing, returns, etc. */
struct calls {
bool (*promote_function_args) (tree fntype);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment