This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Register window support in DWARF-2


[Moved to gcc-patches]

> That, or a magic attribute, such that
>
> #ifdef HAVE_ATTR_window_save
> 	if (RTX_FRAME_RELATED_P (insn)
> 	    && get_attr_window_save (insn))
> 	 ...
> #endif

Thanks for the suggestion.  This would have been more elegant, but it turned 
out that this didn't fit in very well with low-level ordering constraints.  So 
I went for the target hook, which is set to dwarf2out_window_save.

Bootstrapped/regtested on sparc64-sun-solaris2.9 and sparc-sun-solaris2.8.
Does it look correct to you?


2004-11-25  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
	hook_void_constcharptr.
	(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. (TARGET_DWARF_HANDLE_FRAME_UNSPEC): Define to
	dwarf2out_window_save.
	(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.
	* config/sparc/sparc.md (save_register_window): Invoke the gen_* functions of
	the following 2 patterns.
	(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	24 Nov 2004 20:26:11 -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 *);
+
   /* 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	24 Nov 2004 20:26:12 -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 hook_void_constcharptr
+
 #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	24 Nov 2004 20:26:17 -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);
+	  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	25 Nov 2004 10:41:31 -0000
@@ -480,6 +480,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 dwarf2out_window_save
+
 #ifdef SUBTARGET_INSERT_ATTRIBUTES
 #undef TARGET_INSERT_ATTRIBUTES
 #define TARGET_INSERT_ATTRIBUTES SUBTARGET_INSERT_ATTRIBUTES
@@ -4478,26 +4481,26 @@ 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 an increment for the stack pointer.  */
 
-static void
-emit_stack_pointer_increment (rtx increment)
+static rtx
+gen_stack_pointer_inc (rtx increment)
 {
   if (TARGET_ARCH64)
-    emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx, increment));
+    return gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx, increment);
   else
-    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, increment));
+    return gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, increment);
 }
 
-/* Emit a decrement for the stack pointer.  */
+/* Generate a decrement for the stack pointer.  */
 
-static void
-emit_stack_pointer_decrement (rtx decrement)
+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 +4510,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 +4562,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 +4616,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 +4631,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 +4647,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 +8882,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
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	24 Nov 2004 20:26:23 -0000
@@ -7717,35 +7717,38 @@
   [(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));
+  if (TARGET_ARCH64)
+    emit_insn (gen_save_register_windowdi (operands[0]));
+  else
+    emit_insn (gen_save_register_windowsi (operands[0]));
   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 -r1.396 tm.texi
--- doc/tm.texi	24 Nov 2004 08:39:34 -0000	1.396
+++ doc/tm.texi	24 Nov 2004 22:58:05 -0000
@@ -3005,6 +3005,20 @@
 terminate the stack backtrace.  New ports should avoid this.
 @end defmac
 
+@deftypefn {Target Hook} void TARGET_DWARF_HANDLE_FRAME_UNSPEC (const char *@var{label})
+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
+@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.
+@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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]