]> git.ipfire.org Git - thirdparty/gcc.git/commit
dwarf: Multi-register CFI address support.
authorAndrew Stubbs <ams@codesourcery.com>
Thu, 11 Nov 2021 13:43:04 +0000 (13:43 +0000)
committerHafiz Abid Qadeer <abidh@codesourcery.com>
Wed, 8 Dec 2021 09:47:16 +0000 (09:47 +0000)
commit13b6c7639cfdca892a3f02b63596b097e1839f38
treef79c345be55f12d9d6282661bc5e5cc39d033086
parent691f05c2197a7b79cb2d7fdbabe3182e22da320a
dwarf: Multi-register CFI address support.

Add support for architectures such as AMD GCN, in which the pointer size is
larger than the register size.  This allows the CFI information to include
multi-register locations for the stack pointer, frame pointer, and return
address.

This patch was originally posted by Andrew Stubbs in
https://gcc.gnu.org/pipermail/gcc-patches/2020-August/552873.html

It has now been re-worked according to the review comments. It does not use
DW_OP_piece or DW_OP_LLVM_piece_end. Instead it uses
DW_OP_bregx/DW_OP_shl/DW_OP_bregx/DW_OP_plus to build the CFA from multiple
consecutive registers. Here is how .debug_frame looks before and after this
patch:

$ cat factorial.c
int factorial(int n) {
  if (n == 0) return 1;
  return n * factorial (n - 1);
}

$ amdgcn-amdhsa-gcc -g factorial.c -O0 -c -o fac.o
$ llvm-dwarfdump -debug-frame fac.o

*** without this patch (edited for brevity)***

00000000 00000014 ffffffff CIE

  DW_CFA_def_cfa: reg48 +0
  DW_CFA_register: reg16 reg50

00000018 0000002c 00000000 FDE cie=00000000 pc=00000000...000001ac
  DW_CFA_advance_loc4: 96
  DW_CFA_offset: reg46 0
  DW_CFA_offset: reg47 4
  DW_CFA_offset: reg50 8
  DW_CFA_offset: reg51 12
  DW_CFA_offset: reg16 8
  DW_CFA_advance_loc4: 4
  DW_CFA_def_cfa_sf: reg46 -16

*** with this patch (edited for brevity)***

00000000 00000024 ffffffff CIE

  DW_CFA_def_cfa_expression: DW_OP_bregx SGPR49+0, DW_OP_const1u 0x20, DW_OP_shl, DW_OP_bregx SGPR48+0, DW_OP_plus
  DW_CFA_expression: reg16 DW_OP_bregx SGPR51+0, DW_OP_const1u 0x20, DW_OP_shl, DW_OP_bregx SGPR50+0, DW_OP_plus

00000028 0000003c 00000000 FDE cie=00000000 pc=00000000...000001ac
  DW_CFA_advance_loc4: 96
  DW_CFA_offset: reg46 0
  DW_CFA_offset: reg47 4
  DW_CFA_offset: reg50 8
  DW_CFA_offset: reg51 12
  DW_CFA_offset: reg16 8
  DW_CFA_advance_loc4: 4
  DW_CFA_def_cfa_expression: DW_OP_bregx SGPR47+0, DW_OP_const1u 0x20, DW_OP_shl, DW_OP_bregx SGPR46+0, DW_OP_plus, DW_OP_lit16, DW_OP_minus

gcc/ChangeLog:

* dwarf2cfi.c (dw_stack_pointer_regnum): Change type to struct cfa_reg.
(dw_frame_pointer_regnum): Likewise.
(new_cfi_row): Use set_by_dwreg.
(get_cfa_from_loc_descr): Use set_by_dwreg.  Support register spans.
handle DW_OP_bregx with DW_OP_breg{0-31}.  Support DW_OP_lit*,
DW_OP_const*, DW_OP_minus, DW_OP_shl and DW_OP_plus.
(lookup_cfa_1): Use set_by_dwreg.
(def_cfa_0): Update for cfa_reg and support register spans.
(reg_save): Change sreg parameter to struct cfa_reg.  Support register
spans.
(dwf_cfa_reg): New function.
(dwarf2out_flush_queued_reg_saves): Use dwf_cfa_reg instead of
dwf_regno.
(dwarf2out_frame_debug_def_cfa): Likewise.
(dwarf2out_frame_debug_adjust_cfa): Likewise.
(dwarf2out_frame_debug_cfa_offset): Likewise.  Update reg_save usage.
(dwarf2out_frame_debug_cfa_register): Likewise.
(dwarf2out_frame_debug_expr): Likewise.
(create_pseudo_cfg): Use set_by_dwreg.
(initial_return_save): Use set_by_dwreg and dwf_cfa_reg,
(create_cie_data): Use dwf_cfa_reg.
(execute_dwarf2_frame): Use dwf_cfa_reg.
(dump_cfi_row): Use set_by_dwreg.
* dwarf2out.c (build_span_loc, build_breg_loc): New function.
(build_cfa_loc): Support register spans.
(build_cfa_aligned_loc): Update cfa_reg usage.
(convert_cfa_to_fb_loc_list): Use set_by_dwreg.
* dwarf2out.h (struct cfa_reg): New type.
(struct dw_cfa_location): Use struct cfa_reg.
(build_span_loc): New prototype.

co-authored-By: Hafiz Abid Qadeer <abidh@codesourcery.com>
gcc/dwarf2cfi.c
gcc/dwarf2out.c
gcc/dwarf2out.h