backport unwind fixes to 3.3
Richard Henderson
rth@redhat.com
Fri Jun 6 08:52:00 GMT 2003
This is a backport of your mainline EH cleanups to 3.3.
Can you give this a try on s390? The change in how the
stack pointer is handled is rather desirable for various
odd-ball cases like signal trampoline unwind info.
r~
Index: except.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/except.c,v
retrieving revision 1.233.2.5
diff -c -p -d -r1.233.2.5 except.c
*** except.c 2 May 2003 21:01:15 -0000 1.233.2.5
--- except.c 6 Jun 2003 08:44:20 -0000
*************** Software Foundation, 59 Temple Place - S
*** 74,85 ****
/* Provide defaults for stuff that may not be defined when using
sjlj exceptions. */
- #ifndef EH_RETURN_STACKADJ_RTX
- #define EH_RETURN_STACKADJ_RTX 0
- #endif
- #ifndef EH_RETURN_HANDLER_RTX
- #define EH_RETURN_HANDLER_RTX 0
- #endif
#ifndef EH_RETURN_DATA_REGNO
#define EH_RETURN_DATA_REGNO(N) INVALID_REGNUM
#endif
--- 74,79 ----
*************** expand_builtin_frob_return_addr (addr_tr
*** 3075,3151 ****
void
expand_builtin_eh_return (stackadj_tree, handler_tree)
! tree stackadj_tree, handler_tree;
{
! rtx stackadj, handler;
!
! stackadj = expand_expr (stackadj_tree, cfun->eh->ehr_stackadj, VOIDmode, 0);
! handler = expand_expr (handler_tree, cfun->eh->ehr_handler, VOIDmode, 0);
#ifdef POINTERS_EXTEND_UNSIGNED
! if (GET_MODE (stackadj) != Pmode)
! stackadj = convert_memory_address (Pmode, stackadj);
!
! if (GET_MODE (handler) != Pmode)
! handler = convert_memory_address (Pmode, handler);
#endif
! if (! cfun->eh->ehr_label)
! {
! cfun->eh->ehr_stackadj = copy_to_reg (stackadj);
! cfun->eh->ehr_handler = copy_to_reg (handler);
! cfun->eh->ehr_label = gen_label_rtx ();
! }
! else
! {
! if (stackadj != cfun->eh->ehr_stackadj)
! emit_move_insn (cfun->eh->ehr_stackadj, stackadj);
! if (handler != cfun->eh->ehr_handler)
! emit_move_insn (cfun->eh->ehr_handler, handler);
! }
emit_jump (cfun->eh->ehr_label);
}
void
expand_eh_return ()
{
! rtx sa, ra, around_label;
if (! cfun->eh->ehr_label)
return;
- sa = EH_RETURN_STACKADJ_RTX;
- if (! sa)
- {
- error ("__builtin_eh_return not supported on this target");
- return;
- }
-
current_function_calls_eh_return = 1;
around_label = gen_label_rtx ();
- emit_move_insn (sa, const0_rtx);
emit_jump (around_label);
emit_label (cfun->eh->ehr_label);
clobber_return_register ();
#ifdef HAVE_eh_return
if (HAVE_eh_return)
! emit_insn (gen_eh_return (cfun->eh->ehr_stackadj, cfun->eh->ehr_handler));
else
#endif
{
! ra = EH_RETURN_HANDLER_RTX;
! if (! ra)
! {
! error ("__builtin_eh_return not supported on this target");
! ra = gen_reg_rtx (Pmode);
! }
!
! emit_move_insn (sa, cfun->eh->ehr_stackadj);
! emit_move_insn (ra, cfun->eh->ehr_handler);
}
emit_label (around_label);
--- 3069,3141 ----
void
expand_builtin_eh_return (stackadj_tree, handler_tree)
! tree stackadj_tree ATTRIBUTE_UNUSED;
! tree handler_tree;
{
! rtx tmp;
+ #ifdef EH_RETURN_STACKADJ_RTX
+ tmp = expand_expr (stackadj_tree, cfun->eh->ehr_stackadj, VOIDmode, 0);
#ifdef POINTERS_EXTEND_UNSIGNED
! if (GET_MODE (tmp) != Pmode)
! tmp = convert_memory_address (Pmode, tmp);
! #endif
! if (!cfun->eh->ehr_stackadj)
! cfun->eh->ehr_stackadj = copy_to_reg (tmp);
! else if (tmp != cfun->eh->ehr_stackadj)
! emit_move_insn (cfun->eh->ehr_stackadj, tmp);
#endif
! tmp = expand_expr (handler_tree, cfun->eh->ehr_handler, VOIDmode, 0);
! #ifdef POINTERS_EXTEND_UNSIGNED
! if (GET_MODE (tmp) != Pmode)
! tmp = convert_memory_address (Pmode, tmp);
! #endif
! if (!cfun->eh->ehr_handler)
! cfun->eh->ehr_handler = copy_to_reg (tmp);
! else if (tmp != cfun->eh->ehr_handler)
! emit_move_insn (cfun->eh->ehr_handler, tmp);
+ if (!cfun->eh->ehr_label)
+ cfun->eh->ehr_label = gen_label_rtx ();
emit_jump (cfun->eh->ehr_label);
}
void
expand_eh_return ()
{
! rtx around_label;
if (! cfun->eh->ehr_label)
return;
current_function_calls_eh_return = 1;
+ #ifdef EH_RETURN_STACKADJ_RTX
+ emit_move_insn (EH_RETURN_STACKADJ_RTX, const0_rtx);
+ #endif
+
around_label = gen_label_rtx ();
emit_jump (around_label);
emit_label (cfun->eh->ehr_label);
clobber_return_register ();
+ #ifdef EH_RETURN_STACKADJ_RTX
+ emit_move_insn (EH_RETURN_STACKADJ_RTX, cfun->eh->ehr_stackadj);
+ #endif
+
#ifdef HAVE_eh_return
if (HAVE_eh_return)
! emit_insn (gen_eh_return (cfun->eh->ehr_handler));
else
#endif
{
! #ifdef EH_RETURN_HANDLER_RTX
! emit_move_insn (EH_RETURN_HANDLER_RTX, cfun->eh->ehr_handler);
! #else
! error ("__builtin_eh_return not supported on this target");
! #endif
}
emit_label (around_label);
Index: except.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/except.h,v
retrieving revision 1.65.8.2
diff -c -p -d -r1.65.8.2 except.h
*** except.h 5 May 2003 16:59:21 -0000 1.65.8.2
--- except.h 6 Jun 2003 08:44:20 -0000
*************** extern tree (*lang_eh_runtime_type) PARA
*** 155,161 ****
#if ! (defined (EH_RETURN_DATA_REGNO) \
&& (defined (IA64_UNWIND_INFO) \
|| (DWARF2_UNWIND_INFO \
- && defined (EH_RETURN_STACKADJ_RTX) \
&& (defined (EH_RETURN_HANDLER_RTX) \
|| defined (HAVE_eh_return)))))
#define MUST_USE_SJLJ_EXCEPTIONS 1
--- 155,160 ----
*************** extern tree (*lang_eh_runtime_type) PARA
*** 171,179 ****
# define USING_SJLJ_EXCEPTIONS 0
# ifndef EH_RETURN_DATA_REGNO
#error "EH_RETURN_DATA_REGNO required"
- # endif
- # ifndef EH_RETURN_STACKADJ_RTX
- #error "EH_RETURN_STACKADJ_RTX required"
# endif
# if !defined(EH_RETURN_HANDLER_RTX) && !defined(HAVE_eh_return)
#error "EH_RETURN_HANDLER_RTX or eh_return required"
--- 170,175 ----
Index: unwind-dw2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/unwind-dw2.c,v
retrieving revision 1.22.2.5
diff -c -p -d -r1.22.2.5 unwind-dw2.c
*** unwind-dw2.c 7 May 2003 19:32:36 -0000 1.22.2.5
--- unwind-dw2.c 6 Jun 2003 08:44:20 -0000
*************** static void
*** 1046,1055 ****
uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
{
struct _Unwind_Context orig_context = *context;
- _Unwind_Word tmp_sp;
void *cfa;
long i;
/* Special handling here: Many machines do not use a frame pointer,
and track the CFA only through offsets from the stack pointer from
one frame to the next. In this case, the stack pointer is never
--- 1046,1055 ----
uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
{
struct _Unwind_Context orig_context = *context;
void *cfa;
long i;
+ #ifdef EH_RETURN_STACKADJ_RTX
/* Special handling here: Many machines do not use a frame pointer,
and track the CFA only through offsets from the stack pointer from
one frame to the next. In this case, the stack pointer is never
*************** uw_update_context_1 (struct _Unwind_Cont
*** 1059,1070 ****
In very special situations (such as unwind info for signal return),
there may be location expressions that use the stack pointer as well.
! Given that other unwind mechanisms generally won't work if you try
! to represent stack pointer saves and restores directly, we don't
! bother conditionalizing this at all. */
! #ifndef __s390__
! tmp_sp = (_Unwind_Ptr) context->cfa;
! orig_context.reg[__builtin_dwarf_sp_column ()] = &tmp_sp;
#endif
/* Compute this frame's CFA. */
--- 1059,1078 ----
In very special situations (such as unwind info for signal return),
there may be location expressions that use the stack pointer as well.
! Do this conditionally for one frame. This allows the unwind info
! for one frame to save a copy of the stack pointer from the previous
! frame, and be able to use much easier CFA mechanisms to do it.
! 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;
!
! if (!orig_context.reg[__builtin_dwarf_sp_column ()])
! {
! tmp_sp = (_Unwind_Ptr) context->cfa;
! orig_context.reg[__builtin_dwarf_sp_column ()] = &tmp_sp;
! }
! context->reg[__builtin_dwarf_sp_column ()] = NULL;
#endif
/* Compute this frame's CFA. */
*************** uw_init_context_1 (struct _Unwind_Contex
*** 1157,1162 ****
--- 1165,1171 ----
{
void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
_Unwind_FrameState fs;
+ _Unwind_Word sp_slot;
memset (context, 0, sizeof (struct _Unwind_Context));
context->ra = ra;
*************** uw_init_context_1 (struct _Unwind_Contex
*** 1165,1174 ****
abort ();
/* Force the frame state to use the known cfa value. */
! context->cfa = outer_cfa;
! #ifdef __s390__
! context->reg[__builtin_dwarf_sp_column ()] = &outer_cfa;
! #endif
fs.cfa_how = CFA_REG_OFFSET;
fs.cfa_reg = __builtin_dwarf_sp_column ();
fs.cfa_offset = 0;
--- 1174,1181 ----
abort ();
/* Force the frame state to use the known cfa value. */
! sp_slot = (_Unwind_Ptr) outer_cfa;
! context->reg[__builtin_dwarf_sp_column ()] = &sp_slot;
fs.cfa_how = CFA_REG_OFFSET;
fs.cfa_reg = __builtin_dwarf_sp_column ();
fs.cfa_offset = 0;
*************** uw_install_context_1 (struct _Unwind_Con
*** 1227,1237 ****
memcpy (c, t, dwarf_reg_size_table[i]);
}
! /* We adjust SP by the difference between CURRENT and TARGET's CFA. */
! if (STACK_GROWS_DOWNWARD)
! return target->cfa - current->cfa + target->args_size;
! else
! return current->cfa - target->cfa - target->args_size;
}
static inline _Unwind_Ptr
--- 1234,1259 ----
memcpy (c, t, dwarf_reg_size_table[i]);
}
! #ifdef EH_RETURN_STACKADJ_RTX
! {
! void *target_cfa;
!
! /* If the last frame records a saved stack pointer, use it. */
! if (target->reg[__builtin_dwarf_sp_column ()])
! target_cfa = (void *)(_Unwind_Ptr)
! _Unwind_GetGR (target, __builtin_dwarf_sp_column ());
! else
! target_cfa = target->cfa;
!
! /* We adjust SP by the difference between CURRENT and TARGET's CFA. */
! if (STACK_GROWS_DOWNWARD)
! return target_cfa - current->cfa + target->args_size;
! else
! return current->cfa - target_cfa - target->args_size;
! }
! #else
! return 0;
! #endif
}
static inline _Unwind_Ptr
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.404.2.16
diff -c -p -d -r1.404.2.16 i386.md
*** config/i386/i386.md 1 Jun 2003 16:15:09 -0000 1.404.2.16
--- config/i386/i386.md 6 Jun 2003 08:44:21 -0000
***************
*** 13607,13617 ****
"ix86_expand_epilogue (0); DONE;")
(define_expand "eh_return"
! [(use (match_operand 0 "register_operand" ""))
! (use (match_operand 1 "register_operand" ""))]
""
{
! rtx tmp, sa = operands[0], ra = operands[1];
/* Tricky bit: we write the address of the handler to which we will
be returning into someone else's stack frame, one word below the
--- 13607,13616 ----
"ix86_expand_epilogue (0); DONE;")
(define_expand "eh_return"
! [(use (match_operand 0 "register_operand" ""))]
""
{
! rtx tmp, sa = EH_RETURN_STACKADJ_RTX, ra = operands[0];
/* Tricky bit: we write the address of the handler to which we will
be returning into someone else's stack frame, one word below the
Index: config/mips/mips.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.md,v
retrieving revision 1.153.2.2
diff -c -p -d -r1.153.2.2 mips.md
*** config/mips/mips.md 28 Feb 2003 15:02:22 -0000 1.153.2.2
--- config/mips/mips.md 6 Jun 2003 08:44:21 -0000
*************** ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n
*** 10069,10089 ****
;; This is used in compiling the unwind routines.
(define_expand "eh_return"
! [(use (match_operand 0 "general_operand" ""))
! (use (match_operand 1 "general_operand" ""))]
""
"
{
enum machine_mode gpr_mode = TARGET_64BIT ? DImode : SImode;
! if (GET_MODE (operands[1]) != gpr_mode)
! operands[1] = convert_to_mode (gpr_mode, operands[1], 0);
if (TARGET_64BIT)
! emit_insn (gen_eh_set_lr_di (operands[1]));
else
! emit_insn (gen_eh_set_lr_si (operands[1]));
- emit_move_insn (EH_RETURN_STACKADJ_RTX, operands[0]);
DONE;
}")
--- 10069,10087 ----
;; This is used in compiling the unwind routines.
(define_expand "eh_return"
! [(use (match_operand 0 "general_operand" ""))]
""
"
{
enum machine_mode gpr_mode = TARGET_64BIT ? DImode : SImode;
! if (GET_MODE (operands[0]) != gpr_mode)
! operands[0] = convert_to_mode (gpr_mode, operands[0], 0);
if (TARGET_64BIT)
! emit_insn (gen_eh_set_lr_di (operands[0]));
else
! emit_insn (gen_eh_set_lr_si (operands[0]));
DONE;
}")
Index: config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.224.2.3
diff -c -p -d -r1.224.2.3 rs6000.md
*** config/rs6000/rs6000.md 6 Apr 2003 02:02:21 -0000 1.224.2.3
--- config/rs6000/rs6000.md 6 Jun 2003 08:44:21 -0000
***************
*** 14875,14893 ****
; This is used in compiling the unwind routines.
(define_expand "eh_return"
! [(use (match_operand 0 "general_operand" ""))
! (use (match_operand 1 "general_operand" ""))]
""
"
{
#if TARGET_AIX
! rs6000_emit_eh_toc_restore (operands[0]);
#endif
if (TARGET_32BIT)
! emit_insn (gen_eh_set_lr_si (operands[1]));
else
! emit_insn (gen_eh_set_lr_di (operands[1]));
! emit_move_insn (EH_RETURN_STACKADJ_RTX, operands[0]);
DONE;
}")
--- 14875,14891 ----
; This is used in compiling the unwind routines.
(define_expand "eh_return"
! [(use (match_operand 0 "general_operand" ""))]
""
"
{
#if TARGET_AIX
! rs6000_emit_eh_toc_restore (EH_RETURN_STACKADJ_RTX);
#endif
if (TARGET_32BIT)
! emit_insn (gen_eh_set_lr_si (operands[0]));
else
! emit_insn (gen_eh_set_lr_di (operands[0]));
DONE;
}")
Index: config/s390/s390.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.h,v
retrieving revision 1.53.2.6
diff -c -p -d -r1.53.2.6 s390.h
*** config/s390/s390.h 29 Apr 2003 14:31:53 -0000 1.53.2.6
--- config/s390/s390.h 6 Jun 2003 08:44:21 -0000
*************** extern int current_function_outgoing_arg
*** 510,516 ****
/* Describe how we implement __builtin_eh_return. */
#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 6 : INVALID_REGNUM)
- #define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 10)
#define EH_RETURN_HANDLER_RTX \
gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, \
TARGET_64BIT? -48 : -40))
--- 510,515 ----
More information about the Gcc-patches
mailing list