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]

[tree-ssa] Implement non-call exceptions


Non-call exceptions are pretty much FUBAR on the tree-SSA branch.

We carefully generate EH regions fopr trees, but we don't copy the
information into the RTL we generate.

Also, we don't allow for arithmetic overflow exceptions in
tree_could_trap_p().

Also, we assume that libcalls can't throw.

This patch fixes all these, leaving gcj on the tree-SSA branch in pretty good shape.

Andrew.

	* tree-eh.c (tree_could_trap_p): Add division instructions.
	* calls.c (emit_library_call_value_1): Set ECF_NOTHROW only if
	we're not using flag_non_call_exceptions. 
	* expr.c (expand_expr): Check the EH region of an expression and
	mark all the insns that result from its expansion with the
	appropriate REG_EH_REGION.

Index: calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.229.2.38
diff -p -1 -0 -c -r1.229.2.38 calls.c
*** calls.c	25 Nov 2003 02:09:33 -0000	1.229.2.38
--- calls.c	3 Dec 2003 18:09:47 -0000
*************** emit_library_call_value_1 (int retval, r
*** 3634,3654 ****
      struct locate_and_pad_arg_data locate;
      rtx save_area;
    };
    struct arg *argvec;
    int old_inhibit_defer_pop = inhibit_defer_pop;
    rtx call_fusage = 0;
    rtx mem_value = 0;
    rtx valreg;
    int pcc_struct_value = 0;
    int struct_value_size = 0;
!   int flags;
    int reg_parm_stack_space = 0;
    int needed;
    rtx before_call;
    tree tfom;			/* type_for_mode (outmode, 0) */
  
  #ifdef REG_PARM_STACK_SPACE
    /* Define the boundary of the register parm stack space that needs to be
       save, if any.  */
    int low_to_save, high_to_save;
    rtx save_area = 0;            /* Place that it is saved.  */
--- 3634,3654 ----
      struct locate_and_pad_arg_data locate;
      rtx save_area;
    };
    struct arg *argvec;
    int old_inhibit_defer_pop = inhibit_defer_pop;
    rtx call_fusage = 0;
    rtx mem_value = 0;
    rtx valreg;
    int pcc_struct_value = 0;
    int struct_value_size = 0;
!   int flags = 0;
    int reg_parm_stack_space = 0;
    int needed;
    rtx before_call;
    tree tfom;			/* type_for_mode (outmode, 0) */
  
  #ifdef REG_PARM_STACK_SPACE
    /* Define the boundary of the register parm stack space that needs to be
       save, if any.  */
    int low_to_save, high_to_save;
    rtx save_area = 0;            /* Place that it is saved.  */
*************** emit_library_call_value_1 (int retval, r
*** 3662,3682 ****
  
  #ifdef REG_PARM_STACK_SPACE
  #ifdef MAYBE_REG_PARM_STACK_SPACE
    reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
  #else
    reg_parm_stack_space = REG_PARM_STACK_SPACE ((tree) 0);
  #endif
  #endif
  
    /* By default, library functions can not throw.  */
!   flags = ECF_NOTHROW;
  
    switch (fn_type)
      {
      case LCT_NORMAL:
        break;
      case LCT_CONST:
        flags |= ECF_CONST;
        break;
      case LCT_PURE:
        flags |= ECF_PURE;
--- 3662,3683 ----
  
  #ifdef REG_PARM_STACK_SPACE
  #ifdef MAYBE_REG_PARM_STACK_SPACE
    reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
  #else
    reg_parm_stack_space = REG_PARM_STACK_SPACE ((tree) 0);
  #endif
  #endif
  
    /* By default, library functions can not throw.  */
!   if (! flag_non_call_exceptions)
!     flags = ECF_NOTHROW;
  
    switch (fn_type)
      {
      case LCT_NORMAL:
        break;
      case LCT_CONST:
        flags |= ECF_CONST;
        break;
      case LCT_PURE:
        flags |= ECF_PURE;
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.467.2.65
diff -p -1 -0 -c -r1.467.2.65 expr.c
*** expr.c	25 Nov 2003 02:09:43 -0000	1.467.2.65
--- expr.c	3 Dec 2003 18:09:51 -0000
*************** expand_operands (tree exp0, tree exp1, r
*** 6275,6331 ****
     don't want to use TARGET for anything but the final result;
     Intermediate values must go elsewhere.   Additionally, calls to
     emit_block_move will be flagged with BLOCK_OP_CALL_PARM.  */
  
  static rtx expand_expr_1 (tree, rtx, enum machine_mode, enum expand_modifier);
  
  rtx
  expand_expr (tree exp, rtx target, enum machine_mode tmode,
  	     enum expand_modifier modifier)
  {
    /* Handle ERROR_MARK before anybody tries to access its type.  */
    if (TREE_CODE (exp) == ERROR_MARK
        || TREE_CODE (TREE_TYPE (exp)) == ERROR_MARK)
      {
!       rtx ret = CONST0_RTX (tmode);
        return ret ? ret : const0_rtx;
      }
  
    /* If this is an expression of some kind and it has an associated line
       number, then emit the line number before expanding the expression. 
  
       We need to save and restore the file and line information so that
       errors discovered during expansion are emitted with the right
       information.  It would be better of the diagnostic routines 
       used the file/line information embedded in the tree nodes rather
       than globals.  */
    if (cfun && EXPR_LOCUS (exp))
      {
!       location_t saved_location;
!       rtx ret;
! 
!       saved_location = input_location;
        input_location = *EXPR_LOCUS (exp);
        emit_line_note (input_location);
! 
        /* Record where the insns produced belong.  */
        if (cfun->dont_emit_block_notes)
  	record_block_change (TREE_BLOCK (exp));
  
        ret = expand_expr_1 (exp, target, tmode, modifier);
  
        input_location = saved_location;
  
!       return ret;
      }
  
!   return expand_expr_1 (exp, target, tmode, modifier);
  }
  
  static rtx
  expand_expr_1 (tree exp, rtx target, enum machine_mode tmode,
  	       enum expand_modifier modifier)
  {
    rtx op0, op1, temp;
    tree type = TREE_TYPE (exp);
    int unsignedp = TREE_UNSIGNED (type);
    enum machine_mode mode;
--- 6275,6364 ----
     don't want to use TARGET for anything but the final result;
     Intermediate values must go elsewhere.   Additionally, calls to
     emit_block_move will be flagged with BLOCK_OP_CALL_PARM.  */
  
  static rtx expand_expr_1 (tree, rtx, enum machine_mode, enum expand_modifier);
  
  rtx
  expand_expr (tree exp, rtx target, enum machine_mode tmode,
  	     enum expand_modifier modifier)
  {
+   int rn = -1;
+   rtx ret, last;
+ 
    /* Handle ERROR_MARK before anybody tries to access its type.  */
    if (TREE_CODE (exp) == ERROR_MARK
        || TREE_CODE (TREE_TYPE (exp)) == ERROR_MARK)
      {
!       ret = CONST0_RTX (tmode);
        return ret ? ret : const0_rtx;
      }
  
+   if (flag_non_call_exceptions)
+     {
+       rn = lookup_stmt_eh_region (exp);
+       /* If rn < 0, then either (1) tree-ssa not used or (2) doesn't
+ 	 throw.  */
+       if (rn >= 0)
+ 	last = get_last_insn ();
+     }
+ 
    /* If this is an expression of some kind and it has an associated line
       number, then emit the line number before expanding the expression. 
  
       We need to save and restore the file and line information so that
       errors discovered during expansion are emitted with the right
       information.  It would be better of the diagnostic routines 
       used the file/line information embedded in the tree nodes rather
       than globals.  */
    if (cfun && EXPR_LOCUS (exp))
      {
!       location_t saved_location = input_location;
        input_location = *EXPR_LOCUS (exp);
        emit_line_note (input_location);
!       
        /* Record where the insns produced belong.  */
        if (cfun->dont_emit_block_notes)
  	record_block_change (TREE_BLOCK (exp));
  
        ret = expand_expr_1 (exp, target, tmode, modifier);
  
        input_location = saved_location;
+     }
+   else
+     {
+       ret = expand_expr_1 (exp, target, tmode, modifier);
+     }
  
!   /* If using non-call exceptions, mark all insns that may trap.
!      expand_call() will mark CALL_INSNs before we get to this code,
!      but it doesn't handle libcalls, and these may trap.  */
!   if (rn >= 0)
!     {	
!       rtx insn;
!       for (insn = next_real_insn (last); insn; 
! 	   insn = next_real_insn (insn))
! 	{
! 	  if (! find_reg_note (insn, REG_EH_REGION, NULL_RTX)
! 	      /* If we want exceptions for non-call insns, any
! 		 may_trap_p instruction may throw.  */
! 	      && GET_CODE (PATTERN (insn)) != CLOBBER
! 	      && GET_CODE (PATTERN (insn)) != USE
! 	      && (GET_CODE (insn) == CALL_INSN || may_trap_p (PATTERN (insn))))
! 	    {
! 	      REG_NOTES (insn) = alloc_EXPR_LIST (REG_EH_REGION, GEN_INT (rn),
! 						  REG_NOTES (insn));
! 	    }
! 	}
      }
  
!   return ret;
  }
  
  static rtx
  expand_expr_1 (tree exp, rtx target, enum machine_mode tmode,
  	       enum expand_modifier modifier)
  {
    rtx op0, op1, temp;
    tree type = TREE_TYPE (exp);
    int unsignedp = TREE_UNSIGNED (type);
    enum machine_mode mode;
Index: tree-eh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-eh.c,v
retrieving revision 1.1.2.18
diff -p -1 -0 -c -r1.1.2.18 tree-eh.c
*** tree-eh.c	29 Nov 2003 12:43:10 -0000	1.1.2.18
--- tree-eh.c	3 Dec 2003 18:09:52 -0000
*************** make_eh_edges (tree stmt)
*** 1661,1683 ****
  }
  
  
  
  /* Return true if the expr can trap, as in dereferencing an
     invalid pointer location.  */
  
  bool
  tree_could_trap_p (tree expr)
  {
!   return (TREE_CODE (expr) == INDIRECT_REF
! 	  || (TREE_CODE (expr) == COMPONENT_REF
! 	      && (TREE_CODE (TREE_OPERAND (expr, 0)) == INDIRECT_REF)));
  }
  
  
  bool
  tree_could_throw_p (tree t)
  {
    if (!flag_exceptions)
      return false;
    if (TREE_CODE (t) == MODIFY_EXPR)
      {
--- 1661,1701 ----
  }
  
  
  
  /* Return true if the expr can trap, as in dereferencing an
     invalid pointer location.  */
  
  bool
  tree_could_trap_p (tree expr)
  {
!   enum tree_code code = TREE_CODE (expr);
!   if (code == INDIRECT_REF
!       || (code == COMPONENT_REF
! 	  && (TREE_CODE (TREE_OPERAND (expr, 0)) == INDIRECT_REF)))
!     return true;
!   
!   switch (code)
!     {
!     case TRUNC_DIV_EXPR:
!     case CEIL_DIV_EXPR:
!     case FLOOR_DIV_EXPR:
!     case ROUND_DIV_EXPR:
!     case EXACT_DIV_EXPR:
!     case CEIL_MOD_EXPR:
!     case FLOOR_MOD_EXPR:
!     case ROUND_MOD_EXPR:
!     case TRUNC_MOD_EXPR:
!       return true;
!     }
! 
!   return false;
  }
  
  
  bool
  tree_could_throw_p (tree t)
  {
    if (!flag_exceptions)
      return false;
    if (TREE_CODE (t) == MODIFY_EXPR)
      {


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