As-applied. From: https://gcc.gnu.org/ml/gcc-patches/2014-09/msg02625.html Linked from bug62231 comment 4 there --- gcc/defaults.h | 5 +++ gcc/dwarf2cfi.c | 76 +++++++++++++++++++++++++++++++++++----------------- libgcc/unwind-dw2.c | 4 -- 3 files changed, 57 insertions(+), 28 deletions(-) --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -438,6 +438,11 @@ #define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG) #endif +/* The mapping from dwarf CFA reg number to internal dwarf reg numbers. */ +#ifndef DWARF_REG_TO_UNWIND_COLUMN +#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO) +#endif + /* Map register numbers held in the call frame info that gcc has collected using DWARF_FRAME_REGNUM to those that should be output in .debug_frame and .eh_frame. */ --- a/gcc/dwarf2cfi.c +++ b/gcc/dwarf2cfi.c @@ -252,7 +252,44 @@ gen_int_mode (size, mode)); } -/* Generate code to initialize the register size table. */ +/* Helper for expand_builtin_init_dwarf_reg_sizes. Generate code to + initialize the dwarf register size table entry corresponding to register + REGNO in REGMODE. TABLE is the table base address, SLOTMODE is the mode + to use for the size entry to initialize, and WROTE_RETURN_COLUMN needs to + be set to true if the dwarf register number for REGNO is the dwarf return + column number. */ + +static +void init_one_dwarf_reg_size (int regno, enum machine_mode regmode, + rtx table, enum machine_mode slotmode, + bool *wrote_return_column) +{ + 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); + + const HOST_WIDE_INT slotoffset = dcol * GET_MODE_SIZE (slotmode); + const HOST_WIDE_INT regsize = GET_MODE_SIZE (regmode); + + if (rnum >= DWARF_FRAME_REGISTERS) + return; + + if (dnum == DWARF_FRAME_RETURN_COLUMN) + { + if (regmode == VOIDmode) + return; + *wrote_return_column = true; + } + + if (slotoffset < 0) + return; + + emit_move_insn (adjust_address (table, slotmode, slotoffset), + gen_int_mode (regsize, slotmode)); +} + +/* Generate code to initialize the dwarf register size table located + at the provided ADDRESS. */ void expand_builtin_init_dwarf_reg_sizes (tree address) @@ -265,30 +302,21 @@ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { - unsigned int dnum = DWARF_FRAME_REGNUM (i); - unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1); + enum machine_mode save_mode = reg_raw_mode[i]; + rtx span; - if (rnum < DWARF_FRAME_REGISTERS) - { - HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (mode); - enum machine_mode save_mode = reg_raw_mode[i]; - HOST_WIDE_INT size; - - if (HARD_REGNO_CALL_PART_CLOBBERED (i, save_mode)) - save_mode = choose_hard_reg_mode (i, 1, true); - if (dnum == DWARF_FRAME_RETURN_COLUMN) - { - if (save_mode == VOIDmode) - continue; - wrote_return_column = true; - } - size = GET_MODE_SIZE (save_mode); - if (offset < 0) - continue; - - emit_move_insn (adjust_address (mem, mode, offset), - gen_int_mode (size, mode)); - } + span = targetm.dwarf_register_span (gen_rtx_REG (save_mode, i)); + if (!span) + init_one_dwarf_reg_size (i, save_mode, mem, mode, &wrote_return_column); + 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, &wrote_return_column); + } + } } if (!wrote_return_column) --- a/libgcc/unwind-dw2.c +++ b/libgcc/unwind-dw2.c @@ -55,10 +55,6 @@ #define PRE_GCC3_DWARF_FRAME_REGISTERS DWARF_FRAME_REGISTERS #endif -#ifndef DWARF_REG_TO_UNWIND_COLUMN -#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO) -#endif - /* ??? For the public function interfaces, we tend to gcc_assert that the column numbers are in range. For the dwarf2 unwind info this does happen, although so far in a case that doesn't actually matter.