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