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]

Committed: patch for dwarf2 eh


This patch removes __builtin_dwarf_reg_size and replaces it with a new
builtin __builtin_init_dwarf_reg_sizes.  This is done to get rid of some
runtime overhead when determining the size of registers in
libgcc2.c:copy_reg, we now use a lookup table to find register sizes.
I stumbled over this area in the code when the old
expand_builtin_dwarf_reg_size code aborted because a port I was working on
overflowed its (arbitrary) limit of 5 ranges.

Approved by Jason Merrill.

Bernd

	* tree.h (enum built_in_function): Rename BUILT_IN_DWARF_REG_SIZE
	to BUILT_IN_INIT_DWARF_REG_SIZES.
	* builtins.c (expand_builtins, case BUILT_IN_INIT_DWARF_REG_SIZES):
	Renamed from BUILT_IN_DWARF_REG_SIZE; call
	expand_builtin_init_dwarf_reg_sizes.
	* c-decl.c (init_decl_processing): Replace __builtin_dwarf_reg_size
	with __builtin_init_dwarf_reg_size_table.
	* dwarf2out.c (struct reg_size_range): Delete.
	(expand_builtin_init_dwarf_reg_sizes): New function.
	(expand_builtin_dwarf_reg_size): Delete.
	* except.h (expand_builtin_init_dwarf_reg_sizes): Declare.
	(expand_builtin_dwarf_reg_size): Don't declare.
	* libgcc2.c (dwarf_reg_size_table_initialized): New.
	(dwarf_reg_size_table): New.
	(init_reg_size_table): New function.
	(copy_reg): Use dwarf_reg_size_table.
	(eh_context_initialize): Make sure dwarf_reg_size_table is initialized
	before use.

Index: builtins.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/builtins.c,v
retrieving revision 1.15
diff -u -p -c -p -d -r1.15 builtins.c
*** builtins.c	1999/09/28 08:15:38	1.15
--- builtins.c	1999/09/29 14:18:36
*************** expand_builtin (exp, target, subtarget, 
*** 2484,2491 ****
  #ifdef DWARF2_UNWIND_INFO
      case BUILT_IN_DWARF_FP_REGNUM:
        return expand_builtin_dwarf_fp_regnum ();
!     case BUILT_IN_DWARF_REG_SIZE:
!       return expand_builtin_dwarf_reg_size (TREE_VALUE (arglist), target);
  #endif
      case BUILT_IN_FROB_RETURN_ADDR:
        return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
--- 2484,2492 ----
  #ifdef DWARF2_UNWIND_INFO
      case BUILT_IN_DWARF_FP_REGNUM:
        return expand_builtin_dwarf_fp_regnum ();
!     case BUILT_IN_INIT_DWARF_REG_SIZES:
!       expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
!       return const0_rtx;
  #endif
      case BUILT_IN_FROB_RETURN_ADDR:
        return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
Index: c-decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-decl.c,v
retrieving revision 1.80
diff -u -p -c -p -d -r1.80 c-decl.c
*** c-decl.c	1999/09/28 13:43:34	1.80
--- c-decl.c	1999/09/29 14:18:38
*************** init_decl_processing ()
*** 3060,3067 ****
    builtin_function ("__builtin_dwarf_fp_regnum",
  		    build_function_type (unsigned_type_node, endlink),
  		    BUILT_IN_DWARF_FP_REGNUM, BUILT_IN_NORMAL, NULL_PTR);
!   builtin_function ("__builtin_dwarf_reg_size", int_ftype_int,
! 		    BUILT_IN_DWARF_REG_SIZE, BUILT_IN_NORMAL, NULL_PTR);		    
    builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
  		    BUILT_IN_FROB_RETURN_ADDR, BUILT_IN_NORMAL, NULL_PTR);
    builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
--- 3060,3067 ----
    builtin_function ("__builtin_dwarf_fp_regnum",
  		    build_function_type (unsigned_type_node, endlink),
  		    BUILT_IN_DWARF_FP_REGNUM, BUILT_IN_NORMAL, NULL_PTR);
!   builtin_function ("__builtin_init_dwarf_reg_size_table", void_ftype_ptr,
! 		    BUILT_IN_INIT_DWARF_REG_SIZES, BUILT_IN_NORMAL, NULL_PTR);
    builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
  		    BUILT_IN_FROB_RETURN_ADDR, BUILT_IN_NORMAL, NULL_PTR);
    builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
Index: dwarf2out.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/dwarf2out.c,v
retrieving revision 1.117
diff -u -p -c -p -d -r1.117 dwarf2out.c
*** dwarf2out.c	1999/09/28 17:11:44	1.117
--- dwarf2out.c	1999/09/29 14:18:41
*************** reg_number (rtl)
*** 560,669 ****
    return regno;
  }
  
! struct reg_size_range
! {
!   int beg;
!   int end;
!   int size;
! };
! 
! /* Given a register number in REG_TREE, return an rtx for its size in bytes.
!    We do this in kind of a roundabout way, by building up a list of
!    register size ranges and seeing where our register falls in one of those
!    ranges.  We need to do it this way because REG_TREE is not a constant,
!    and the target macros were not designed to make this task easy.  */
  
! rtx
! expand_builtin_dwarf_reg_size (reg_tree, target)
!      tree reg_tree;
!      rtx target;
  {
!   enum machine_mode mode;
!   int size;
!   struct reg_size_range ranges[5];
!   tree t, t2;
! 
!   int i = 0;
!   int n_ranges = 0;
!   int last_size = -1;
  
!   for (; i < FIRST_PSEUDO_REGISTER; ++i)
      {
!       /* The return address is out of order on the MIPS, and we don't use
! 	 copy_reg for it anyway, so we don't care here how large it is.  */
!       if (DWARF_FRAME_REGNUM (i) == DWARF_FRAME_RETURN_COLUMN)
! 	continue;
! 
!       mode = reg_raw_mode[i];
! 
!       /* CCmode is arbitrarily given a size of 4 bytes.  It is more useful
! 	 to use the same size as word_mode, since that reduces the number
! 	 of ranges we need.  It should not matter, since the result should
! 	 never be used for a condition code register anyways.  */
!       if (GET_MODE_CLASS (mode) == MODE_CC)
! 	mode = word_mode;
! 
!       size = GET_MODE_SIZE (mode);
! 
!       /* If this register is not valid in the specified mode and
! 	 we have a previous size, use that for the size of this
! 	 register to avoid making junk tiny ranges.  */
!       if (! HARD_REGNO_MODE_OK (i, mode) && last_size != -1)
! 	size = last_size;
! 
!       if (size != last_size)
! 	{
! 	  ranges[n_ranges].beg = i;
! 	  ranges[n_ranges].size = last_size = size;
! 	  ++n_ranges;
! 	  if (n_ranges >= 5)
! 	    abort ();
! 	}
!       ranges[n_ranges-1].end = i;
!     }
  
!   /* The usual case: fp regs surrounded by general regs.  */
!   if (n_ranges == 3 && ranges[0].size == ranges[2].size)
!     {
!       if ((DWARF_FRAME_REGNUM (ranges[1].end)
! 	   - DWARF_FRAME_REGNUM (ranges[1].beg))
! 	  != ranges[1].end - ranges[1].beg)
! 	abort ();
!       t  = fold (build (GE_EXPR, integer_type_node, reg_tree,
! 			build_int_2 (DWARF_FRAME_REGNUM (ranges[1].beg), 0)));
!       t2 = fold (build (LE_EXPR, integer_type_node, reg_tree,
! 			build_int_2 (DWARF_FRAME_REGNUM (ranges[1].end), 0)));
!       t = fold (build (TRUTH_ANDIF_EXPR, integer_type_node, t, t2));
!       t = fold (build (COND_EXPR, integer_type_node, t,
! 		       build_int_2 (ranges[1].size, 0),
! 		       build_int_2 (ranges[0].size, 0)));
!     }
!   else
!     {
!       /* Initialize last_end to be larger than any possible
! 	 DWARF_FRAME_REGNUM.  */
!       int last_end = 0x7fffffff;
!       --n_ranges;
!       t = build_int_2 (ranges[n_ranges].size, 0);
!       do
! 	{
! 	  int beg = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
! 	  int end = DWARF_FRAME_REGNUM (ranges[n_ranges].end);
! 	  if (beg < 0)
! 	    continue;
! 	  if (end >= last_end)
! 	    abort ();
! 	  last_end = end;
! 	  if (end - beg != ranges[n_ranges].end - ranges[n_ranges].beg)
! 	    abort ();
! 	  t2 = fold (build (LE_EXPR, integer_type_node, reg_tree,
! 			    build_int_2 (end, 0)));
! 	  t = fold (build (COND_EXPR, integer_type_node, t2,
! 			   build_int_2 (ranges[n_ranges].size, 0), t));
! 	}
!       while (--n_ranges >= 0);
      }
-   return expand_expr (t, target, Pmode, 0);
  }
  
  /* Convert a DWARF call frame info. operation to its string name */
--- 560,585 ----
    return regno;
  }
  
! /* Generate code to initialize the register size table.  */
  
! void
! expand_builtin_init_dwarf_reg_sizes (address)
!      tree address;
  {
!   int i;
!   enum machine_mode mode = TYPE_MODE (char_type_node);
!   rtx addr = expand_expr (address, NULL_RTX, VOIDmode, 0);
!   rtx mem = gen_rtx_MEM (mode, addr);
  
!   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
      {
!       int offset = i * GET_MODE_SIZE (mode);
!       int size = GET_MODE_SIZE (reg_raw_mode[i]);
  
!       emit_move_insn (change_address (mem, mode,
! 				      plus_constant (addr, offset)),
! 		      GEN_INT (size));
      }
  }
  
  /* Convert a DWARF call frame info. operation to its string name */
Index: except.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/except.h,v
retrieving revision 1.30
diff -u -p -c -p -d -r1.30 except.h
*** except.h	1999/08/10 16:19:14	1.30
--- except.h	1999/09/29 14:18:41
*************** rtx expand_builtin_dwarf_fp_regnum	PROTO
*** 473,479 ****
  #ifdef TREE_CODE
  rtx expand_builtin_frob_return_addr	PROTO((tree));
  rtx expand_builtin_extract_return_addr	PROTO((tree));
! rtx expand_builtin_dwarf_reg_size	PROTO((tree, rtx));
  void expand_builtin_eh_return		PROTO((tree, tree, tree));
  #endif
  void expand_eh_return			PROTO((void));
--- 473,479 ----
  #ifdef TREE_CODE
  rtx expand_builtin_frob_return_addr	PROTO((tree));
  rtx expand_builtin_extract_return_addr	PROTO((tree));
! void expand_builtin_init_dwarf_reg_sizes	PROTO((tree));
  void expand_builtin_eh_return		PROTO((tree, tree, tree));
  #endif
  void expand_eh_return			PROTO((void));
Index: libgcc2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/libgcc2.c,v
retrieving revision 1.70
diff -u -p -c -p -d -r1.70 libgcc2.c
*** libgcc2.c	1999/09/23 13:37:49	1.70
--- libgcc2.c	1999/09/29 14:18:43
*************** __get_eh_info ()
*** 3120,3125 ****
--- 3120,3137 ----
    return &eh->info;
  }
  
+ #ifdef DWARF2_UNWIND_INFO
+ static int dwarf_reg_size_table_initialized = 0;
+ static char dwarf_reg_size_table[FIRST_PSEUDO_REGISTER];
+ 
+ static void
+ init_reg_size_table ()
+ {
+   __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
+   dwarf_reg_size_table_initialized = 1;
+ }
+ #endif
+ 
  #if __GTHREADS
  static void
  eh_threads_initialize ()
*************** eh_context_initialize ()
*** 3152,3163 ****
--- 3164,3187 ----
        /* Use static version of EH context. */
        get_eh_context = &eh_context_static;
      }
+ #ifdef DWARF2_UNWIND_INFO
+   {
+     static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
+     if (__gthread_once (&once_regsizes, init_reg_size_table) != 0
+ 	|| ! dwarf_reg_size_table_initialized)
+       init_reg_size_table ();
+   }
+ #endif
  
  #else /* no __GTHREADS */
  
    /* Use static version of EH context. */
    get_eh_context = &eh_context_static;
  
+ #ifdef DWARF2_UNWIND_INFO
+   init_reg_size_table ();
+ #endif
+ 
  #endif /* no __GTHREADS */
  
    return (*get_eh_context) ();
*************** EH_TABLE_LOOKUP
*** 3395,3401 ****
  
  #ifdef DWARF2_UNWIND_INFO
  
- 
  /* Return the table version of an exception descriptor */
  
  short 
--- 3419,3424 ----
*************** copy_reg (unsigned reg, frame_state *uda
*** 3620,3626 ****
    word_type *preg = get_reg_addr (reg, udata, NULL);
    word_type *ptreg = get_reg_addr (reg, target_udata, NULL);
  
!   memcpy (ptreg, preg, __builtin_dwarf_reg_size (reg));
  }
  
  /* Retrieve the return address for frame UDATA.  */
--- 3643,3649 ----
    word_type *preg = get_reg_addr (reg, udata, NULL);
    word_type *ptreg = get_reg_addr (reg, target_udata, NULL);
  
!   memcpy (ptreg, preg, dwarf_reg_size_table [reg]);
  }
  
  /* Retrieve the return address for frame UDATA.  */
Index: tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/tree.h,v
retrieving revision 1.94
diff -u -p -c -p -d -r1.94 tree.h
*** tree.h	1999/09/28 06:18:11	1.94
--- tree.h	1999/09/29 14:18:46
*************** enum built_in_function
*** 120,126 ****
    BUILT_IN_UNWIND_INIT,
    BUILT_IN_DWARF_CFA,
    BUILT_IN_DWARF_FP_REGNUM,
!   BUILT_IN_DWARF_REG_SIZE,
    BUILT_IN_FROB_RETURN_ADDR,
    BUILT_IN_EXTRACT_RETURN_ADDR,
    BUILT_IN_EH_RETURN,
--- 120,126 ----
    BUILT_IN_UNWIND_INIT,
    BUILT_IN_DWARF_CFA,
    BUILT_IN_DWARF_FP_REGNUM,
!   BUILT_IN_INIT_DWARF_REG_SIZES,
    BUILT_IN_FROB_RETURN_ADDR,
    BUILT_IN_EXTRACT_RETURN_ADDR,
    BUILT_IN_EH_RETURN,


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