diff options
author | Jason Merrill <jason@yorick.cygnus.com> | 1997-09-27 18:16:15 +0000 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 1997-09-27 14:16:15 -0400 |
commit | 2f3ca9e7f4bc29c645df8a51023ece6ece8faf9d (patch) | |
tree | a5a4bcb347df37e58a470806a1587b469f81d6af /gcc/dwarf2out.c | |
parent | faf199a62194ffea2487c131c0ef8efc2c6127f5 (diff) | |
download | gcc-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.c | 77 |
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 * |