This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Register window support in DWARF-2
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: Richard Henderson <rth at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org,Jason Merrill <jason at redhat dot com>
- Date: Fri, 26 Nov 2004 19:43:31 +0100
- Subject: Re: Register window support in DWARF-2
- References: <200411240022.55423.ebotcazou@libertysurf.fr> <200411251312.45974.ebotcazou@libertysurf.fr> <20041125201913.GA9631@redhat.com>
> I think that you should pass the instruction pattern as well.
> Otherwise you can't distinguish which unspec.
Of course. While I was at it, I also passed the UNSPEC index.
Retested on sparc64-sun-solaris2.9 and sparc-sun-solaris2.8.
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_{inc,dec}rement.
Set RTX_FRAME_RELATED_P on the appropriate insns and members of insns.
(sparc_asm_function_prologue): Do not emit call frame debugging information.
(sparc_expand_epilogue): Adjust calls to emit_stack_pointer_{inc,dec}rement.
(emit_and_preserve): Likewise.
(sparc_dwarf_handle_frame_unspec): New function.
* config/sparc/sparc.md (save_register_window): Remove.
(save_register_windowdi): Rewrite modelled on the call frame debug info.
(save_register_windowsi): Likewise.
--
Eric Botcazou
Index: target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.119
diff -u -p -r1.119 target.h
--- target.h 24 Nov 2004 08:39:31 -0000 1.119
+++ target.h 26 Nov 2004 09:09:00 -0000
@@ -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);
Index: target-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target-def.h,v
retrieving revision 1.107
diff -u -p -r1.107 target-def.h
--- target-def.h 24 Nov 2004 08:39:31 -0000 1.107
+++ target-def.h 26 Nov 2004 09:09:00 -0000
@@ -381,6 +381,8 @@ Foundation, 59 Temple Place - Suite 330,
#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,
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, \
Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2out.c,v
retrieving revision 1.558
diff -u -p -r1.558 dwarf2out.c
--- dwarf2out.c 26 Oct 2004 06:08:38 -0000 1.558
+++ dwarf2out.c 26 Nov 2004 09:09:06 -0000
@@ -1430,7 +1430,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)
@@ -1494,7 +1498,10 @@ dwarf2out_frame_debug_expr (rtx expr, co
{
/* 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;
@@ -1621,6 +1628,13 @@ dwarf2out_frame_debug_expr (rtx expr, co
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 ();
}
Index: config/sparc/sparc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.c,v
retrieving revision 1.346
diff -u -p -r1.346 sparc.c
--- config/sparc/sparc.c 23 Nov 2004 00:35:26 -0000 1.346
+++ config/sparc/sparc.c 26 Nov 2004 09:09:17 -0000
@@ -356,6 +356,7 @@ static tree sparc_gimplify_va_arg (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)
+ return gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx, increment);
+ else
+ 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)
- emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx, decrement));
+ return gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx, decrement);
else
- emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, decrement));
+ 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 decrem
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,
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,
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. */
Index: config/sparc/sparc.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.md,v
retrieving revision 1.222
diff -u -p -r1.222 sparc.md
--- config/sparc/sparc.md 23 Nov 2004 00:35:30 -0000 1.222
+++ config/sparc/sparc.md 26 Nov 2004 09:09:19 -0000
@@ -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")])
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.396
diff -u -p -r1.396 tm.texi
--- doc/tm.texi 24 Nov 2004 08:39:34 -0000 1.396
+++ doc/tm.texi 26 Nov 2004 14:22:08 -0000
@@ -3005,6 +3005,22 @@ someone decided it was a good idea to us
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