970917 EH problem in sparc with -O
Jason Merrill
jason@cygnus.com
Thu Sep 18 14:27:00 GMT 1997
>>>>> Teemu Torma <tot@trema.com> writes:
> If the following program is compiled with optimization turned on,
> throwing an exception will cause an infinite loop to exceptions.
> The compiler has Jason's `--pc' patch installed.
Thanks for the testcase. You'll need this, too:
Thu Sep 18 14:22:22 1997 Jason Merrill <jason@yorick.cygnus.com>
* final.c (final_scan_insn): Hand BARRIERs off to the dwarf2 code.
* dwarf2out.c (dwarf2out_frame_debug): Pass the whole insn along.
(dwarf2out_stack_adjust): A BARRIER resets the args space to 0.
* except.c (end_eh_unwinder): Subtract 1 from return address.
* libgcc2.c (__throw): Likewise.
(find_exception_handler): Don't change PC here. Compare end with >.
Index: final.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/final.c,v
retrieving revision 1.120
diff -c -r1.120 final.c
*** final.c 1997/09/15 23:37:56 1.120
--- final.c 1997/09/18 20:51:44
***************
*** 1592,1597 ****
--- 1592,1603 ----
if (NEXT_INSN (insn))
ASM_OUTPUT_ALIGN_CODE (file);
#endif
+ #if defined (DWARF2_UNWIND_INFO) && !defined (ACCUMULATE_OUTGOING_ARGS)
+ /* If we push arguments, we need to check all insns for stack
+ adjustments. */
+ if (dwarf2out_do_frame ())
+ dwarf2out_frame_debug (insn);
+ #endif
break;
case CODE_LABEL:
Index: dwarf2out.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/dwarf2out.c,v
retrieving revision 1.64
diff -c -r1.64 dwarf2out.c
*** dwarf2out.c 1997/09/15 23:37:46 1.64
--- dwarf2out.c 1997/09/18 21:21:48
***************
*** 915,958 ****
dwarf2out_stack_adjust (insn)
rtx insn;
{
- rtx src, dest;
- enum rtx_code code;
long offset;
char *label;
! if (GET_CODE (insn) != SET)
! return;
!
! src = SET_SRC (insn);
! dest = SET_DEST (insn);
! if (dest == stack_pointer_rtx)
{
! /* (set (reg sp) (plus (reg sp) (const_int))) */
! code = GET_CODE (src);
! if (! (code == PLUS || code == MINUS)
! || XEXP (src, 0) != stack_pointer_rtx
! || GET_CODE (XEXP (src, 1)) != CONST_INT)
! return;
!
! offset = INTVAL (XEXP (src, 1));
}
! else if (GET_CODE (dest) == MEM)
{
! /* (set (mem (pre_dec (reg sp))) (foo)) */
! src = XEXP (dest, 0);
! code = GET_CODE (src);
! if (! (code == PRE_DEC || code == PRE_INC)
! || XEXP (src, 0) != stack_pointer_rtx)
return;
! offset = GET_MODE_SIZE (GET_MODE (dest));
}
else
return;
! if (code == PLUS || code == PRE_INC)
! offset = -offset;
if (cfa_reg == STACK_POINTER_REGNUM)
cfa_offset += offset;
--- 915,978 ----
dwarf2out_stack_adjust (insn)
rtx insn;
{
long offset;
char *label;
! if (GET_CODE (insn) == BARRIER)
{
! /* When we see a BARRIER, we know to reset args_size to 0. Usually
! the compiler will have already emitted a stack adjustment, but
! doesn't bother for calls to noreturn functions. */
! #ifdef STACK_GROWS_DOWNWARD
! offset = -args_size;
! #else
! offset = args_size;
! #endif
}
! else if (GET_CODE (PATTERN (insn)) == SET)
{
! rtx src, dest;
! enum rtx_code code;
! insn = PATTERN (insn);
! src = SET_SRC (insn);
! dest = SET_DEST (insn);
!
! if (dest == stack_pointer_rtx)
! {
! /* (set (reg sp) (plus (reg sp) (const_int))) */
! code = GET_CODE (src);
! if (! (code == PLUS || code == MINUS)
! || XEXP (src, 0) != stack_pointer_rtx
! || GET_CODE (XEXP (src, 1)) != CONST_INT)
! return;
!
! offset = INTVAL (XEXP (src, 1));
! }
! else if (GET_CODE (dest) == MEM)
! {
! /* (set (mem (pre_dec (reg sp))) (foo)) */
! src = XEXP (dest, 0);
! code = GET_CODE (src);
!
! if (! (code == PRE_DEC || code == PRE_INC)
! || XEXP (src, 0) != stack_pointer_rtx)
! return;
!
! offset = GET_MODE_SIZE (GET_MODE (dest));
! }
! else
return;
! if (code == PLUS || code == PRE_INC)
! offset = -offset;
}
else
return;
! if (offset == 0)
! return;
!
if (cfa_reg == STACK_POINTER_REGNUM)
cfa_offset += offset;
***************
*** 999,1005 ****
if (! RTX_FRAME_RELATED_P (insn))
{
! dwarf2out_stack_adjust (PATTERN (insn));
return;
}
--- 1019,1025 ----
if (! RTX_FRAME_RELATED_P (insn))
{
! dwarf2out_stack_adjust (insn);
return;
}
Index: except.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/except.c,v
retrieving revision 1.23
diff -c -r1.23 except.c
*** except.c 1997/09/18 01:24:15 1.23
--- except.c 1997/09/18 19:51:51
***************
*** 1668,1673 ****
--- 1668,1675 ----
/* Get the address we need to use to determine what exception
handler should be invoked, and store it in __eh_pc. */
return_val_rtx = eh_outer_context (return_val_rtx);
+ return_val_rtx = expand_binop (Pmode, sub_optab, return_val_rtx, GEN_INT (1),
+ NULL_RTX, 0, OPTAB_LIB_WIDEN);
emit_move_insn (eh_saved_pc_rtx, return_val_rtx);
/* Either set things up so we do a return directly to __throw, or
Index: libgcc2.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/libgcc2.c,v
retrieving revision 1.140
diff -c -r1.140 libgcc2.c
*** libgcc2.c 1997/09/18 01:24:13 1.140
--- libgcc2.c 1997/09/18 20:11:59
***************
*** 3353,3367 ****
int pos;
int best = -1;
- /* We subtract 1 from PC to avoid hitting the beginning of the next
- region. */
- --pc;
-
/* We can't do a binary search because the table isn't guaranteed
to be sorted from function to function. */
for (pos = 0; table[pos].exception_handler != (void *) -1; ++pos)
{
! if (table[pos].start <= pc && table[pos].end >= pc)
{
/* This can apply. Make sure it is at least as small as
the previous best. */
--- 3353,3363 ----
int pos;
int best = -1;
/* We can't do a binary search because the table isn't guaranteed
to be sorted from function to function. */
for (pos = 0; table[pos].exception_handler != (void *) -1; ++pos)
{
! if (table[pos].start <= pc && table[pos].end > pc)
{
/* This can apply. Make sure it is at least as small as
the previous best. */
***************
*** 3370,3376 ****
best = pos;
}
/* But it is sorted by starting PC within a function. */
! else if (best && table[pos].start > pc)
break;
}
if (best != -1)
--- 3366,3372 ----
best = pos;
}
/* But it is sorted by starting PC within a function. */
! else if (best >= 0 && table[pos].start > pc)
break;
}
if (best != -1)
***************
*** 3702,3709 ****
break;
}
! /* Otherwise, we continue searching. */
! pc = get_return_addr (udata, sub_udata);
}
/* If we haven't found a handler by now, this is an unhandled
--- 3698,3706 ----
break;
}
! /* Otherwise, we continue searching. We subtract 1 from PC to avoid
! hitting the beginning of the next region. */
! pc = get_return_addr (udata, sub_udata) - 1;
}
/* If we haven't found a handler by now, this is an unhandled
***************
*** 3752,3758 ****
put_reg (i, val, my_udata);
}
! pc = get_return_addr (udata, sub_udata);
}
#ifdef INCOMING_REGNO
--- 3749,3755 ----
put_reg (i, val, my_udata);
}
! pc = get_return_addr (udata, sub_udata) - 1;
}
#ifdef INCOMING_REGNO
More information about the Gcc
mailing list