This is the mail archive of the 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]

RFC / RFA: dwarf2 unwinding for targets with call-part-clobbered registers

There have been numerous problems in gcc and ld that prevent exception
handling to work for sh64, but now I've got a set of patches that
works - at least for the eh/filter1.C test.
Although most of the patches are target-specific, some changes to
target-independent code are necessary.

dwarf2out.c:expand_builtin_init_dwarf_reg_sizes uses reg_raw_mode to
determine the size of the memory locations where registers are saved.
This is not correct for machines with call-part-clobbered registers.
reg_raw_mode is a mode suitable to do caller-saves so that the register
can hold any mode over a call.  You can use call_used_regs and
HARD_REGNO_CALL_PART_CLOBBERED to find out where the mode is not
appropriate, but using it to find one that fits requires the logic
in choose_hard_reg_mode, and then some.
So the only clean way to do this is to add another parameter to
choose_hard_reg_mode that makes it return the largest mode that is not
partially clobbered.
Or should we add a new target hook instead?

There is also a problem with unwind-dw2.c assuming that the return
address and stack/frame pointer are stored in word_mode; I have
attached a patch for this.

And I have some questions on the use of RETURN_ADDR_OFFSET:
This macro is not documented.  Is it save to use?  Should we add
documentation for it?
gets confused by SHmedia addresses, which have the least significant bit
set.  It subtracts one and expects to get an address that is lower than
the address of that instruction in the table, but the addresses in the
table are aligned.  I was able to fix / work around this problem (?)
by defining RETURN_ADDR_OFFSET to -1 for TARGET_SH5.
Or is the bug that "info.Start + cs_start" / "info.Start + cs_start + cs_len"
should work out as possible program counter values, rather than as
instruction addresses?

SuperH (UK) Ltd.
2410 Aztec West / Almondsbury / BRISTOL / BS32 4QX
T:+44 1454 465658
unwind-dw2.c:uw_update_context_1 assumes that the registers that
hold the cfa and the return address are saved in word mode.  That
is not true for SHmedia32, which has 64 bit words, but saves the
frame pointer and return address as 32 bit.
The result is that unwinding doesn't work at all.
I could use __builtin_init_dwarf_reg_size_table and play games with memcpy
and endianness translations, but that would likely slow down exception
handling noticably.
So instead of hard-coding _Unwind_Word, I use __UNWIND_CFA_TYPE__ and
__UNWIND_RA_TYPE__ and define them to _Unwind_Word if they are not
already defined.
I'm not sure where this stuff should be documented.  Or does it require no
special documentation?

2003-06-30  J"orn Rennecke <>

	* unwind-dw2.c (uw_update_context_1, uw_init_context_1): Use
	__UNWIND_CFA_TYPE__, if defined.
	(uw_update_context): Use __UNWIND_RA_TYPE__, if defined.
	* config/sh/sh.h (TARGET_CPU_CPP_BUILTINS): Provide

Index: unwind-dw2.c
RCS file: /cvs/gcc/gcc/gcc/unwind-dw2.c,v
retrieving revision 1.32
diff -p -u -r1.32 unwind-dw2.c
--- unwind-dw2.c	13 May 2003 06:49:46 -0000	1.32
+++ unwind-dw2.c	30 Jun 2003 22:05:39 -0000
@@ -1095,7 +1095,11 @@ uw_update_context_1 (struct _Unwind_Cont
      Always zap the saved stack pointer value for the next frame; carrying
      the value over from one frame to another doesn't make sense.  */
-  _Unwind_Word tmp_sp;
+#ifndef __UNWIND_CFA_TYPE__
+#define __UNWIND_CFA_TYPE__ _Unwind_Word
+  __UNWIND_CFA_TYPE__ tmp_sp;
   if (!_Unwind_GetGRPtr (&orig_context, __builtin_dwarf_sp_column ()))
@@ -1109,7 +1113,9 @@ uw_update_context_1 (struct _Unwind_Cont
   switch (fs->cfa_how)
     case CFA_REG_OFFSET:
-      cfa = (void *) (_Unwind_Ptr) _Unwind_GetGR (&orig_context, fs->cfa_reg);
+      cfa = (void *) (_Unwind_Ptr) *(__UNWIND_CFA_TYPE__ *) (_Unwind_GetGRPtr
+							     (&orig_context,
+							      fs->cfa_reg));
       cfa += fs->cfa_offset;
@@ -1162,6 +1168,10 @@ uw_update_context_1 (struct _Unwind_Cont
+#ifndef __UNWIND_RA_TYPE__
+#define __UNWIND_RA_TYPE__ _Unwind_Word
 /* CONTEXT describes the unwind state for a frame, and FS describes the FDE
    of its caller.  Update CONTEXT to refer to the caller as well.  Note
    that the args_size and lsda members are not updated here, but later in
@@ -1175,7 +1185,9 @@ uw_update_context (struct _Unwind_Contex
   /* Compute the return address now, since the return address column
      can change from frame to frame.  */
   context->ra = __builtin_extract_return_addr
-    ((void *) (_Unwind_Ptr) _Unwind_GetGR (context, fs->retaddr_column));
+    ((void *) (_Unwind_Ptr) *(__UNWIND_RA_TYPE__*) (_Unwind_GetGRPtr
+						    (context,
+						     fs->retaddr_column)));
 /* Fill in CONTEXT for top-of-stack.  The only valid registers at this
@@ -1198,7 +1210,7 @@ uw_init_context_1 (struct _Unwind_Contex
   void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
   _Unwind_FrameState fs;
-  _Unwind_Word sp_slot;
+  __UNWIND_CFA_TYPE__ sp_slot;
   memset (context, 0, sizeof (struct _Unwind_Context));
   context->ra = ra;
Index: config/sh/sh.h
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.h,v
retrieving revision 1.215
diff -p -u -r1.215 sh.h
--- config/sh/sh.h	24 Jun 2003 17:22:05 -0000	1.215
+++ config/sh/sh.h	30 Jun 2003 22:05:40 -0000
@@ -66,6 +66,11 @@ do { \
 				   TARGET_SHMEDIA64 ? "64" : "32", 0); \
 	builtin_define_with_value ("__SHMEDIA__", \
 				   TARGET_SHMEDIA ? "1" : "0", 0); \
+	  { \
+	    builtin_define_with_value ("__UNWIND_CFA_TYPE__", "long", 0); \
+	    builtin_define_with_value ("__UNWIND_RA_TYPE__", "long", 0); \
+	  } \
 	  builtin_define ("__SH4_NOFPU__"); \
       } \

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