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.
This commit is contained in:
Florian Weimer 2023-01-02 16:18:02 +01:00
parent 8385088039
commit 3b6cac2b44
5 changed files with 75 additions and 92 deletions

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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})

View file

@ -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,12 +283,55 @@ 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;
table[dcol] = GET_MODE_SIZE (regmode);
}
emit_move_insn (adjust_address (table, slotmode, slotoffset),
gen_int_mode (regsize, slotmode));
/* Fill SIZES with size information for each DWARF register. */
static void
generate_dwarf_reg_sizes (poly_uint16 *sizes)
{
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 (unsigned int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
/* 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. */
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));
if (!span)
init_one_dwarf_reg_size (i, save_mode, sizes, &init_state);
else
{
for (int si = 0; si < XVECLEN (span, 0); si++)
{
rtx reg = XVECEXP (span, 0, si);
init_one_dwarf_reg_size
(REGNO (reg), GET_MODE (reg), sizes, &init_state);
}
}
}
if (!init_state.wrote_return_column)
sizes[DWARF_FRAME_RETURN_COLUMN] = GET_MODE_SIZE (Pmode);
#ifdef DWARF_ALT_FRAME_RETURN_COLUMN
sizes[DWARF_ALT_FRAME_RETURN_COLUMN] = GET_MODE_SIZE (Pmode);
#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
@ -312,52 +340,23 @@ void init_one_dwarf_reg_size (int regno, machine_mode regmode,
void
expand_builtin_init_dwarf_reg_sizes (tree address)
{
unsigned int i;
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);
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 < DWARF_FRAME_REGISTERS; ++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. */
if (init_state.processed_regno[i])
unsigned short value;
if (sizes[i].is_constant (&value) && value == 0)
/* No need to set the value to zero again. */
continue;
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, mem, mode, &init_state);
else
{
for (int si = 0; si < XVECLEN (span, 0); si++)
{
rtx reg = XVECEXP (span, 0, si);
init_one_dwarf_reg_size
(REGNO (reg), GET_MODE (reg), mem, mode, &init_state);
}
}
HOST_WIDE_INT offset = i * GET_MODE_SIZE (mode);
emit_move_insn (adjust_address (mem, mode, offset),
gen_int_mode (sizes[i], mode));
}
if (!init_state.wrote_return_column)
init_return_column_size (mode, mem, DWARF_FRAME_RETURN_COLUMN);
#ifdef DWARF_ALT_FRAME_RETURN_COLUMN
init_return_column_size (mode, mem, DWARF_ALT_FRAME_RETURN_COLUMN);
#endif
targetm.init_dwarf_reg_sizes_extra (address);
}

View file

@ -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