aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2023-01-02 16:18:02 +0100
committerFlorian Weimer <fweimer@redhat.com>2023-01-02 16:18:02 +0100
commit3b6cac2b44b384cd2091eaeaebeb3478c253a25d (patch)
tree0c7eaab6bb102eca8829b40fef1e9d531f10eb7d
parent8385088039f58a1d403cbb0792105236d240de85 (diff)
downloadgcc-3b6cac2b44b384cd2091eaeaebeb3478c253a25d.zip
gcc-3b6cac2b44b384cd2091eaeaebeb3478c253a25d.tar.gz
gcc-3b6cac2b44b384cd2091eaeaebeb3478c253a25d.tar.bz2
Compute a table of DWARF register sizes at compile
The sizes are compile-time constants. Create a vector with them, so that they can be inspected at compile time. gcc/ * dwarf2cfi.cc (init_return_column_size): Remove. (init_one_dwarf_reg_size): Adjust. (generate_dwarf_reg_sizes): New function. Extracted from expand_builtin_init_dwarf_reg_sizes. (expand_builtin_init_dwarf_reg_sizes): Call generate_dwarf_reg_sizes. * target.def (init_dwarf_reg_sizes_extra): Adjust hook signature. * config/msp430/msp430.cc (msp430_init_dwarf_reg_sizes_extra): Adjust. * config/rs6000/rs6000.cc (rs6000_init_dwarf_reg_sizes_extra): Likewise. * doc/tm.texi: Update.
-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, 58 insertions, 75 deletions
diff --git a/gcc/config/msp430/msp430.cc b/gcc/config/msp430/msp430.cc
index 6c15780..dbea8d7 100644
--- a/gcc/config/msp430/msp430.cc
+++ b/gcc/config/msp430/msp430.cc
@@ -3202,11 +3202,9 @@ 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 (tree address)
+msp430_init_dwarf_reg_sizes_extra (poly_uint16 *sizes)
{
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)
@@ -3218,12 +3216,7 @@ msp430_init_dwarf_reg_sizes_extra (tree address)
unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1);
if (rnum < DWARF_FRAME_REGISTERS)
- {
- HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (QImode);
-
- emit_move_insn (adjust_address (mem, QImode, offset),
- gen_int_mode (4, QImode));
- }
+ sizes[rnum] = 4;
}
}
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 6ac3adc..875684a 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -23860,27 +23860,17 @@ rs6000_initial_elimination_offset (int from, int to)
/* Fill in sizes of registers used by unwinder. */
static void
-rs6000_init_dwarf_reg_sizes_extra (tree address)
+rs6000_init_dwarf_reg_sizes_extra (poly_uint16 *sizes)
{
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++)
- {
- 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);
- }
+ sizes[i] = 16;
}
}
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 8fe49c2..b6d7900 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -9840,13 +9840,14 @@ 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 (tree @var{address})
+@deftypefn {Target Hook} void TARGET_INIT_DWARF_REG_SIZES_EXTRA (poly_uint16 *@var{sizes})
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{expand_builtin_init_dwarf_reg_sizes} after
+It will be called by @code{generate_dwarf_reg_sizes} after
filling in a single size corresponding to each hard register;
-@var{address} is the address of the table.
+@var{sizes} is the address of the table. It will contain
+@code{DWARF_FRAME_REGISTERS} elements when this hook is called.
@end deftypefn
@deftypefn {Target Hook} bool TARGET_ASM_TTYPE (rtx @var{sym})
diff --git a/gcc/dwarf2cfi.cc b/gcc/dwarf2cfi.cc
index 1c70bd8..4d2bd86 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" /* init_return_column_size */
+#include "expr.h" /* expand_normal, emit_move_insn */
#include "output.h" /* asm_out_file */
#include "debug.h" /* dwarf2out_do_frame, dwarf2out_do_cfi_asm */
#include "flags.h" /* dwarf_debuginfo_p */
@@ -241,18 +241,6 @@ 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. */
@@ -274,17 +262,14 @@ 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,
- rtx table, machine_mode slotmode,
- init_one_dwarf_reg_state *init_state)
+static void
+init_one_dwarf_reg_size (int regno, machine_mode regmode,
+ poly_uint16 *table,
+ 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;
@@ -298,34 +283,22 @@ void init_one_dwarf_reg_size (int regno, machine_mode regmode,
init_state->wrote_return_column = true;
}
- /* ??? 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));
+ table[dcol] = GET_MODE_SIZE (regmode);
}
-/* Generate code to initialize the dwarf register size table located
- at the provided ADDRESS. */
+/* Fill SIZES with size information for each DWARF register. */
-void
-expand_builtin_init_dwarf_reg_sizes (tree address)
+static void
+generate_dwarf_reg_sizes (poly_uint16 *sizes)
{
- 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;
+ for (unsigned int i = 0; i < DWARF_FRAME_REGISTERS; i++)
+ sizes[i] = poly_uint16{};
+ init_one_dwarf_reg_state init_state{};
memset ((char *)&init_state, 0, sizeof (init_state));
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ for (unsigned int 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. */
@@ -333,11 +306,11 @@ expand_builtin_init_dwarf_reg_sizes (tree address)
if (init_state.processed_regno[i])
continue;
- save_mode = targetm.dwarf_frame_reg_mode (i);
- span = targetm.dwarf_register_span (gen_rtx_REG (save_mode, i));
+ machine_mode save_mode = targetm.dwarf_frame_reg_mode (i);
+ rtx span = targetm.dwarf_register_span (gen_rtx_REG (save_mode, i));
if (!span)
- init_one_dwarf_reg_size (i, save_mode, mem, mode, &init_state);
+ init_one_dwarf_reg_size (i, save_mode, sizes, &init_state);
else
{
for (int si = 0; si < XVECLEN (span, 0); si++)
@@ -345,19 +318,45 @@ expand_builtin_init_dwarf_reg_sizes (tree address)
rtx reg = XVECEXP (span, 0, si);
init_one_dwarf_reg_size
- (REGNO (reg), GET_MODE (reg), mem, mode, &init_state);
+ (REGNO (reg), GET_MODE (reg), sizes, &init_state);
}
}
}
if (!init_state.wrote_return_column)
- init_return_column_size (mode, mem, DWARF_FRAME_RETURN_COLUMN);
+ sizes[DWARF_FRAME_RETURN_COLUMN] = GET_MODE_SIZE (Pmode);
#ifdef DWARF_ALT_FRAME_RETURN_COLUMN
- init_return_column_size (mode, mem, DWARF_ALT_FRAME_RETURN_COLUMN);
+ sizes[DWARF_ALT_FRAME_RETURN_COLUMN] = GET_MODE_SIZE (Pmode);
#endif
- targetm.init_dwarf_reg_sizes_extra (address);
+ 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));
+ }
}
diff --git a/gcc/target.def b/gcc/target.def
index db8af0c..da5dd31 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{expand_builtin_init_dwarf_reg_sizes} after\n\
+It will be called by @code{generate_dwarf_reg_sizes} after\n\
filling in a single size corresponding to each hard register;\n\
-@var{address} is the address of the table.",
- void, (tree address),
- hook_void_tree)
+@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)
/* Fetch the fixed register(s) which hold condition codes, for
targets where it makes sense to look for duplicate assignments to