summaryrefslogtreecommitdiff
path: root/gcc/dwarf2out.c
diff options
context:
space:
mode:
authorJason Merrill <jason@yorick.cygnus.com>1997-09-27 18:16:15 +0000
committerJason Merrill <jason@gcc.gnu.org>1997-09-27 14:16:15 -0400
commit2f3ca9e7f4bc29c645df8a51023ece6ece8faf9d (patch)
treea5a4bcb347df37e58a470806a1587b469f81d6af /gcc/dwarf2out.c
parentfaf199a62194ffea2487c131c0ef8efc2c6127f5 (diff)
downloadgcc-2f3ca9e7f4bc29c645df8a51023ece6ece8faf9d.tar.gz
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
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r--gcc/dwarf2out.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 56ce82b8e01..6ad1c1b0ae9 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -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 *