aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/config/msp430/msp430.cc11
-rw-r--r--gcc/config/rs6000/rs6000.cc14
-rw-r--r--gcc/doc/tm.texi7
-rw-r--r--gcc/dwarf2cfi.cc93
-rw-r--r--gcc/target.def8
5 files changed, 75 insertions, 58 deletions
diff --git a/gcc/config/msp430/msp430.cc b/gcc/config/msp430/msp430.cc
index dbea8d7..6c15780 100644
--- a/gcc/config/msp430/msp430.cc
+++ b/gcc/config/msp430/msp430.cc
@@ -3202,9 +3202,11 @@ msp430_expand_eh_return (rtx eh_handler)
#undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
#define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
void
-msp430_init_dwarf_reg_sizes_extra (poly_uint16 *sizes)
+msp430_init_dwarf_reg_sizes_extra (tree address)
{
int i;
+ rtx addr = expand_normal (address);
+ rtx mem = gen_rtx_MEM (BLKmode, addr);
/* This needs to match msp430_unwind_word_mode (above). */
if (!msp430x)
@@ -3216,7 +3218,12 @@ msp430_init_dwarf_reg_sizes_extra (poly_uint16 *sizes)
unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1);
if (rnum < DWARF_FRAME_REGISTERS)
- sizes[rnum] = 4;
+ {
+ HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (QImode);
+
+ emit_move_insn (adjust_address (mem, QImode, offset),
+ gen_int_mode (4, QImode));
+ }
}
}
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 875684a..6ac3adc 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -23860,17 +23860,27 @@ rs6000_initial_elimination_offset (int from, int to)
/* Fill in sizes of registers used by unwinder. */
static void
-rs6000_init_dwarf_reg_sizes_extra (poly_uint16 *sizes)
+rs6000_init_dwarf_reg_sizes_extra (tree address)
{
if (TARGET_MACHO && ! TARGET_ALTIVEC)
{
int i;
+ machine_mode mode = TYPE_MODE (char_type_node);
+ rtx addr = expand_expr (address, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ rtx mem = gen_rtx_MEM (BLKmode, addr);
+ rtx value = gen_int_mode (16, mode);
/* On Darwin, libgcc may be built to run on both G3 and G4/5.
The unwinder still needs to know the size of Altivec registers. */
for (i = FIRST_ALTIVEC_REGNO; i < LAST_ALTIVEC_REGNO+1; i++)
- sizes[i] = 16;
+ {
+ int column = DWARF_REG_TO_UNWIND_COLUMN
+ (DWARF2_FRAME_REG_OUT (DWARF_FRAME_REGNUM (i), true));
+ HOST_WIDE_INT offset = column * GET_MODE_SIZE (mode);
+
+ emit_move_insn (adjust_address (mem, mode, offset), value);
+ }
}
}
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index b6d7900..8fe49c2 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -9840,14 +9840,13 @@ used to return a smaller mode than the raw mode to prevent call
clobbered parts of a register altering the frame register size
@end deftypefn
-@deftypefn {Target Hook} void TARGET_INIT_DWARF_REG_SIZES_EXTRA (poly_uint16 *@var{sizes})
+@deftypefn {Target Hook} void TARGET_INIT_DWARF_REG_SIZES_EXTRA (tree @var{address})
If some registers are represented in Dwarf-2 unwind information in
multiple pieces, define this hook to fill in information about the
sizes of those pieces in the table used by the unwinder at runtime.
-It will be called by @code{generate_dwarf_reg_sizes} after
+It will be called by @code{expand_builtin_init_dwarf_reg_sizes} after
filling in a single size corresponding to each hard register;
-@var{sizes} is the address of the table. It will contain
-@code{DWARF_FRAME_REGISTERS} elements when this hook is called.
+@var{address} is the address of the table.
@end deftypefn
@deftypefn {Target Hook} bool TARGET_ASM_TTYPE (rtx @var{sym})
diff --git a/gcc/dwarf2cfi.cc b/gcc/dwarf2cfi.cc
index 4d2bd86..1c70bd8 100644
--- a/gcc/dwarf2cfi.cc
+++ b/gcc/dwarf2cfi.cc
@@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. If not see
#include "except.h" /* expand_builtin_dwarf_sp_column */
#include "profile-count.h" /* For expr.h */
-#include "expr.h" /* expand_normal, emit_move_insn */
+#include "expr.h" /* init_return_column_size */
#include "output.h" /* asm_out_file */
#include "debug.h" /* dwarf2out_do_frame, dwarf2out_do_cfi_asm */
#include "flags.h" /* dwarf_debuginfo_p */
@@ -241,6 +241,18 @@ expand_builtin_dwarf_sp_column (void)
return GEN_INT (DWARF2_FRAME_REG_OUT (dwarf_regnum, 1));
}
+/* MEM is a memory reference for the register size table, each element of
+ which has mode MODE. Initialize column C as a return address column. */
+
+static void
+init_return_column_size (scalar_int_mode mode, rtx mem, unsigned int c)
+{
+ HOST_WIDE_INT offset = c * GET_MODE_SIZE (mode);
+ HOST_WIDE_INT size = GET_MODE_SIZE (Pmode);
+ emit_move_insn (adjust_address (mem, mode, offset),
+ gen_int_mode (size, mode));
+}
+
/* Datastructure used by expand_builtin_init_dwarf_reg_sizes and
init_one_dwarf_reg_size to communicate on what has been done by the
latter. */
@@ -262,14 +274,17 @@ struct init_one_dwarf_reg_state
use for the size entry to initialize, and INIT_STATE is the communication
datastructure conveying what we're doing to our caller. */
-static void
-init_one_dwarf_reg_size (int regno, machine_mode regmode,
- poly_uint16 *table,
- init_one_dwarf_reg_state *init_state)
+static
+void init_one_dwarf_reg_size (int regno, machine_mode regmode,
+ rtx table, machine_mode slotmode,
+ init_one_dwarf_reg_state *init_state)
{
const unsigned int dnum = DWARF_FRAME_REGNUM (regno);
const unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1);
const unsigned int dcol = DWARF_REG_TO_UNWIND_COLUMN (rnum);
+
+ poly_int64 slotoffset = dcol * GET_MODE_SIZE (slotmode);
+ poly_int64 regsize = GET_MODE_SIZE (regmode);
init_state->processed_regno[regno] = true;
@@ -283,22 +298,34 @@ init_one_dwarf_reg_size (int regno, machine_mode regmode,
init_state->wrote_return_column = true;
}
- table[dcol] = GET_MODE_SIZE (regmode);
+ /* ??? When is this true? Should it be a test based on DCOL instead? */
+ if (maybe_lt (slotoffset, 0))
+ return;
+
+ emit_move_insn (adjust_address (table, slotmode, slotoffset),
+ gen_int_mode (regsize, slotmode));
}
-/* Fill SIZES with size information for each DWARF register. */
+/* Generate code to initialize the dwarf register size table located
+ at the provided ADDRESS. */
-static void
-generate_dwarf_reg_sizes (poly_uint16 *sizes)
+void
+expand_builtin_init_dwarf_reg_sizes (tree address)
{
- for (unsigned int i = 0; i < DWARF_FRAME_REGISTERS; i++)
- sizes[i] = poly_uint16{};
+ unsigned int i;
+ scalar_int_mode mode = SCALAR_INT_TYPE_MODE (char_type_node);
+ rtx addr = expand_normal (address);
+ rtx mem = gen_rtx_MEM (BLKmode, addr);
+
+ init_one_dwarf_reg_state init_state;
- init_one_dwarf_reg_state init_state{};
memset ((char *)&init_state, 0, sizeof (init_state));
- for (unsigned int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
+ machine_mode save_mode;
+ rtx span;
+
/* No point in processing a register multiple times. This could happen
with register spans, e.g. when a reg is first processed as a piece of
a span, then as a register on its own later on. */
@@ -306,11 +333,11 @@ generate_dwarf_reg_sizes (poly_uint16 *sizes)
if (init_state.processed_regno[i])
continue;
- machine_mode save_mode = targetm.dwarf_frame_reg_mode (i);
- rtx span = targetm.dwarf_register_span (gen_rtx_REG (save_mode, i));
+ save_mode = targetm.dwarf_frame_reg_mode (i);
+ span = targetm.dwarf_register_span (gen_rtx_REG (save_mode, i));
if (!span)
- init_one_dwarf_reg_size (i, save_mode, sizes, &init_state);
+ init_one_dwarf_reg_size (i, save_mode, mem, mode, &init_state);
else
{
for (int si = 0; si < XVECLEN (span, 0); si++)
@@ -318,45 +345,19 @@ generate_dwarf_reg_sizes (poly_uint16 *sizes)
rtx reg = XVECEXP (span, 0, si);
init_one_dwarf_reg_size
- (REGNO (reg), GET_MODE (reg), sizes, &init_state);
+ (REGNO (reg), GET_MODE (reg), mem, mode, &init_state);
}
}
}
if (!init_state.wrote_return_column)
- sizes[DWARF_FRAME_RETURN_COLUMN] = GET_MODE_SIZE (Pmode);
+ init_return_column_size (mode, mem, DWARF_FRAME_RETURN_COLUMN);
#ifdef DWARF_ALT_FRAME_RETURN_COLUMN
- sizes[DWARF_ALT_FRAME_RETURN_COLUMN] = GET_MODE_SIZE (Pmode);
+ init_return_column_size (mode, mem, DWARF_ALT_FRAME_RETURN_COLUMN);
#endif
- if (targetm.init_dwarf_reg_sizes_extra != nullptr)
- targetm.init_dwarf_reg_sizes_extra (sizes);
-}
-
-/* Generate code to initialize the dwarf register size table located
- at the provided ADDRESS. */
-
-void
-expand_builtin_init_dwarf_reg_sizes (tree address)
-{
- poly_uint16 *sizes = XALLOCAVEC (poly_uint16, DWARF_FRAME_REGISTERS);
- generate_dwarf_reg_sizes (sizes);
-
- scalar_int_mode mode = SCALAR_INT_TYPE_MODE (char_type_node);
- rtx addr = expand_normal (address);
- rtx mem = gen_rtx_MEM (BLKmode, addr);
- for (unsigned int i = 0; i < DWARF_FRAME_REGISTERS; ++i)
- {
- unsigned short value;
- if (sizes[i].is_constant (&value) && value == 0)
- /* No need to set the value to zero again. */
- continue;
-
- HOST_WIDE_INT offset = i * GET_MODE_SIZE (mode);
- emit_move_insn (adjust_address (mem, mode, offset),
- gen_int_mode (sizes[i], mode));
- }
+ targetm.init_dwarf_reg_sizes_extra (address);
}
diff --git a/gcc/target.def b/gcc/target.def
index da5dd31..db8af0c 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -4039,11 +4039,11 @@ DEFHOOK
"If some registers are represented in Dwarf-2 unwind information in\n\
multiple pieces, define this hook to fill in information about the\n\
sizes of those pieces in the table used by the unwinder at runtime.\n\
-It will be called by @code{generate_dwarf_reg_sizes} after\n\
+It will be called by @code{expand_builtin_init_dwarf_reg_sizes} after\n\
filling in a single size corresponding to each hard register;\n\
-@var{sizes} is the address of the table. It will contain\n\
-@code{DWARF_FRAME_REGISTERS} elements when this hook is called.",
- void, (poly_uint16 *sizes), nullptr)
+@var{address} is the address of the table.",
+ void, (tree address),
+ hook_void_tree)
/* Fetch the fixed register(s) which hold condition codes, for
targets where it makes sense to look for duplicate assignments to