c-decl.c (init_decl_processing): Add __builtin_dwarf_reg_size.

* c-decl.c (init_decl_processing): Add __builtin_dwarf_reg_size.
	* tree.h (built_in_function): Likewise.
	* expr.c (expand_builtin): Likewise.
	* except.h: Likewise.
	* dwarf2out.c (expand_builtin_dwarf_reg_size): New fn.
	* libgcc2.c (copy_reg): New fn.
	(__throw): Use it.

From-SVN: r15750
This commit is contained in:
Jason Merrill 1997-09-27 18:16:15 +00:00 committed by Jason Merrill
parent faf199a621
commit 2f3ca9e7f4
7 changed files with 111 additions and 6 deletions

View File

@ -1,3 +1,13 @@
Sat Sep 27 11:02:38 1997 Jason Merrill <jason@yorick.cygnus.com>
* c-decl.c (init_decl_processing): Add __builtin_dwarf_reg_size.
* tree.h (built_in_function): Likewise.
* expr.c (expand_builtin): Likewise.
* except.h: Likewise.
* dwarf2out.c (expand_builtin_dwarf_reg_size): New fn.
* libgcc2.c (copy_reg): New fn.
(__throw): Use it.
Fri Sep 26 08:54:59 1997 Paul Eggert <eggert@twinsun.com>
* c-typeck.c (build_binary_op): Warn about comparing signed vs

View File

@ -3200,6 +3200,8 @@ init_decl_processing ()
builtin_function ("__builtin_dwarf_fp_regnum",
build_function_type (unsigned_type_node, endlink),
BUILT_IN_DWARF_FP_REGNUM, NULL_PTR);
builtin_function ("__builtin_dwarf_reg_size", int_ftype_int,
BUILT_IN_DWARF_REG_SIZE, NULL_PTR);
builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
BUILT_IN_FROB_RETURN_ADDR, NULL_PTR);
builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,

View File

@ -502,6 +502,83 @@ reg_number (rtl)
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;
{
int i, n_ranges, size;
struct reg_size_range ranges[5];
tree t, t2;
ranges[0].beg = 0;
ranges[0].size = GET_MODE_SIZE (reg_raw_mode[0]);
n_ranges = 1;
for (i = 1; i < FIRST_PSEUDO_REGISTER; ++i)
{
size = GET_MODE_SIZE (reg_raw_mode[i]);
if (size != ranges[n_ranges-1].size)
{
ranges[n_ranges-1].end = i-1;
ranges[n_ranges].beg = i;
ranges[n_ranges].size = GET_MODE_SIZE (reg_raw_mode[i]);
++n_ranges;
assert (n_ranges < 5);
}
}
ranges[n_ranges-1].end = i-1;
/* The usual case: fp regs surrounded by general regs. */
if (n_ranges == 3 && ranges[0].size == ranges[2].size)
{
assert ((DWARF_FRAME_REGNUM (ranges[1].end)
- DWARF_FRAME_REGNUM (ranges[1].beg))
== ranges[1].end - ranges[1].beg);
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
{
--n_ranges;
t = build_int_2 (ranges[n_ranges].size, 0);
size = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
for (; n_ranges--; )
{
assert ((DWARF_FRAME_REGNUM (ranges[n_ranges].end)
- DWARF_FRAME_REGNUM (ranges[n_ranges].beg))
== ranges[n_ranges].end - ranges[n_ranges].beg);
assert (DWARF_FRAME_REGNUM (ranges[n_ranges].beg) < size);
size = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
t2 = fold (build (LE_EXPR, integer_type_node, reg_tree,
build_int_2 (DWARF_FRAME_REGNUM
(ranges[n_ranges].end), 0)));
t = fold (build (COND_EXPR, integer_type_node, t2,
build_int_2 (ranges[n_ranges].size, 0), t));
}
}
return expand_expr (t, target, Pmode, 0);
}
/* Convert a DWARF call frame info. operation to its string name */
static char *

View File

@ -292,4 +292,5 @@ rtx expand_builtin_frob_return_addr PROTO((tree));
rtx expand_builtin_extract_return_addr PROTO((tree));
void expand_builtin_set_return_addr_reg PROTO((tree));
void expand_builtin_set_eh_regs PROTO((tree, tree));
rtx expand_builtin_dwarf_reg_size PROTO((tree, rtx));
#endif

View File

@ -9159,6 +9159,8 @@ 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);
#endif
case BUILT_IN_FROB_RETURN_ADDR:
return expand_builtin_frob_return_addr (TREE_VALUE (arglist));

View File

@ -3556,6 +3556,22 @@ put_reg (unsigned reg, void *val, frame_state *udata)
abort ();
}
/* Copy the saved value for register REG from frame UDATA to frame
TARGET_UDATA. Unlike the previous two functions, this can handle
registers that are not one word large. */
static void
copy_reg (unsigned reg, frame_state *udata, frame_state *target_udata)
{
if (udata->saved[reg] == REG_SAVED_OFFSET
&& target_udata->saved[reg] == REG_SAVED_OFFSET)
memcpy (target_udata->cfa + target_udata->reg_or_offset[reg],
udata->cfa + udata->reg_or_offset[reg],
__builtin_dwarf_reg_size (reg));
else
abort ();
}
/* Retrieve the return address for frame UDATA, where SUB_UDATA is a
frame called by UDATA or 0. */
@ -3729,8 +3745,7 @@ label:
&& udata->reg_or_offset[udata->retaddr_column] == i)
continue;
#endif
val = get_reg (i, udata, sub_udata);
put_reg (i, val, my_udata);
copy_reg (i, udata, my_udata);
}
pc = get_return_addr (udata, sub_udata) - 1;
@ -3744,10 +3759,7 @@ label:
{
i = udata->reg_or_offset[udata->retaddr_column];
if (in_reg_window (i, udata))
{
val = get_reg (i, udata, sub_udata);
put_reg (i, val, my_udata);
}
copy_reg (i, udata, sub_udata);
}
#endif
}

View File

@ -105,6 +105,7 @@ enum built_in_function
BUILT_IN_FP, BUILT_IN_SP,
BUILT_IN_UNWIND_INIT,
BUILT_IN_DWARF_FP_REGNUM,
BUILT_IN_DWARF_REG_SIZE,
BUILT_IN_FROB_RETURN_ADDR,
BUILT_IN_EXTRACT_RETURN_ADDR,
BUILT_IN_SET_RETURN_ADDR_REG,