mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-21 23:30:59 +08:00
Use lookup table to get register sizes in dwarf2 eh
From-SVN: r29730
This commit is contained in:
parent
a89e95f9fb
commit
d9d5c9de1c
@ -1,3 +1,24 @@
|
||||
Thu Sep 30 14:39:17 1999 Bernd Schmidt <bernds@cygnus.co.uk>
|
||||
|
||||
* 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.
|
||||
|
||||
Thu Sep 30 05:40:34 1999 Richard Earnshaw <rearnsha@arm.com>
|
||||
|
||||
* c-lang.c (finish_file case ndef ASM_OUTPUT_{CON,DE}STRUCTOR):
|
||||
|
@ -2484,8 +2484,9 @@ expand_builtin (exp, target, subtarget, mode, ignore)
|
||||
#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);
|
||||
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));
|
||||
|
@ -3068,8 +3068,8 @@ init_decl_processing ()
|
||||
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_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,
|
||||
|
114
gcc/dwarf2out.c
114
gcc/dwarf2out.c
@ -560,110 +560,26 @@ reg_number (rtl)
|
||||
return regno;
|
||||
}
|
||||
|
||||
struct reg_size_range
|
||||
/* Generate code to initialize the register size table. */
|
||||
|
||||
void
|
||||
expand_builtin_init_dwarf_reg_sizes (address)
|
||||
tree address;
|
||||
{
|
||||
int beg;
|
||||
int end;
|
||||
int size;
|
||||
};
|
||||
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);
|
||||
|
||||
/* 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)
|
||||
for (i = 0; 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;
|
||||
int offset = i * GET_MODE_SIZE (mode);
|
||||
int size = GET_MODE_SIZE (reg_raw_mode[i]);
|
||||
|
||||
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;
|
||||
emit_move_insn (change_address (mem, mode,
|
||||
plus_constant (addr, offset)),
|
||||
GEN_INT (size));
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
@ -473,7 +473,7 @@ rtx expand_builtin_dwarf_fp_regnum PROTO((void));
|
||||
#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_init_dwarf_reg_sizes PROTO((tree));
|
||||
void expand_builtin_eh_return PROTO((tree, tree, tree));
|
||||
#endif
|
||||
void expand_eh_return PROTO((void));
|
||||
|
@ -3120,6 +3120,18 @@ __get_eh_info ()
|
||||
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 ()
|
||||
@ -3152,12 +3164,24 @@ eh_context_initialize ()
|
||||
/* 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) ();
|
||||
@ -3395,7 +3419,6 @@ EH_TABLE_LOOKUP
|
||||
|
||||
#ifdef DWARF2_UNWIND_INFO
|
||||
|
||||
|
||||
/* Return the table version of an exception descriptor */
|
||||
|
||||
short
|
||||
@ -3620,7 +3643,7 @@ copy_reg (unsigned reg, frame_state *udata, frame_state *target_udata)
|
||||
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));
|
||||
memcpy (ptreg, preg, dwarf_reg_size_table [reg]);
|
||||
}
|
||||
|
||||
/* Retrieve the return address for frame UDATA. */
|
||||
|
@ -120,7 +120,7 @@ enum built_in_function
|
||||
BUILT_IN_UNWIND_INIT,
|
||||
BUILT_IN_DWARF_CFA,
|
||||
BUILT_IN_DWARF_FP_REGNUM,
|
||||
BUILT_IN_DWARF_REG_SIZE,
|
||||
BUILT_IN_INIT_DWARF_REG_SIZES,
|
||||
BUILT_IN_FROB_RETURN_ADDR,
|
||||
BUILT_IN_EXTRACT_RETURN_ADDR,
|
||||
BUILT_IN_EH_RETURN,
|
||||
|
Loading…
x
Reference in New Issue
Block a user