]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
dwarf: Multi-register CFI address support
authorAndrew Stubbs <ams@codesourcery.com>
Mon, 27 Jul 2020 09:55:22 +0000 (10:55 +0100)
committerKwok Cheung Yeung <kcy@codesourcery.com>
Tue, 21 Jun 2022 13:11:29 +0000 (14:11 +0100)
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.

Note that this uses a newly proposed DWARF operator DW_OP_LLVM_piece_end,
which is currently only recognized by the ROCGDB debugger from AMD.  The exact
name and encoding for this operator is subject to change if and when the DWARF
standard accepts it.

gcc/ChangeLog:

* dwarf2cfi.cc (get_cfa_from_loc_descr): Support register spans
with DW_OP_piece and DW_OP_LLVM_piece_end.
* dwarf2out.cc (build_cfa_loc): Support register spans.

include/ChangeLog:

* dwarf2.def (DW_OP_LLVM_piece_end): New extension operator.

gcc/ChangeLog.omp
gcc/dwarf2cfi.cc
gcc/dwarf2out.cc
include/ChangeLog.omp
include/dwarf2.def

index bc3360e053ccca0704216026a53e668d984eac18..862c5c2dd31e8fa81bc8df00833866a02da68c1f 100644 (file)
@@ -1,3 +1,9 @@
+2020-07-27  Andrew Stubbs  <ams@codesourcery.com>
+
+       * dwarf2cfi.cc (get_cfa_from_loc_descr): Support register spans
+       with DW_OP_piece and DW_OP_LLVM_piece_end.
+       * dwarf2out.cc (build_cfa_loc): Support register spans.
+
 2020-08-19  Sandra Loosemore  <sandra@codesourcery.com>
 
        Add a "combined" flag for "acc kernels loop" etc directives.
index ab7c5cc5b27b5fb48b0f63ee2240fda8054c7a33..8d52622a4cbc6b14d7af5777386bfe81363ce7ee 100644 (file)
@@ -540,6 +540,10 @@ get_cfa_from_loc_descr (dw_cfa_location *cfa, struct dw_loc_descr_node *loc)
   cfa->indirect = 0;
   cfa->reg.set_by_dwreg (INVALID_REGNUM);
 
+  /* Record previous register pieces here.  */
+  struct cfa_reg span;
+  span.set_by_dwreg (INVALID_REGNUM);
+
   for (ptr = loc; ptr != NULL; ptr = ptr->dw_loc_next)
     {
       enum dwarf_location_atom op = ptr->dw_loc_opc;
@@ -622,7 +626,9 @@ get_cfa_from_loc_descr (dw_cfa_location *cfa, struct dw_loc_descr_node *loc)
                = (op == DW_OP_bregx
                   ? ptr->dw_loc_oprnd1.v.val_int : op - DW_OP_breg0);
              cfa->reg.set_by_dwreg (regno);
-             cfa->base_offset = ptr->dw_loc_oprnd1.v.val_int;
+             cfa->base_offset = (DW_OP_bregx
+                                 ? ptr->dw_loc_oprnd2.v.val_int
+                                 : ptr->dw_loc_oprnd1.v.val_int);
            }
          else
            {
@@ -647,6 +653,24 @@ get_cfa_from_loc_descr (dw_cfa_location *cfa, struct dw_loc_descr_node *loc)
              cfa->offset = 0;
            }
          break;
+       case DW_OP_piece:
+         if (span.reg != INVALID_REGNUM)
+           {
+             /* We only support contiguous pieces, for now.  */
+             gcc_assert (cfa->reg.reg == span.reg + span.span);
+             gcc_assert (known_eq (ptr->dw_loc_oprnd1.v.val_int,
+                                   span.span_width));
+             span.span++;
+             cfa->reg = span;
+           }
+         else
+           {
+             cfa->reg.span_width = ptr->dw_loc_oprnd1.v.val_int;
+             span = cfa->reg;
+           }
+         break;
+       case DW_OP_LLVM_piece_end:
+         break;
        case DW_OP_deref:
          cfa->indirect = 1;
          break;
@@ -705,6 +729,7 @@ get_cfa_from_loc_descr (dw_cfa_location *cfa, struct dw_loc_descr_node *loc)
          /* The offset is already in place.  */
          break;
        case DW_OP_plus_uconst:
+         gcc_assert (known_eq (cfa->offset, 0));
          cfa->offset = ptr->dw_loc_oprnd1.v.val_unsigned;
          break;
        default:
index 5681b01749add28c52666b41e44cbbc239f7204a..d7a39944424b9f4eed7e042d6835acea1394b95f 100644 (file)
@@ -2833,7 +2833,11 @@ build_cfa_loc (dw_cfa_location *cfa, poly_int64 offset)
       head = build_span_loc (cfa->reg);
 
       if (maybe_ne (offset, 0))
+       {
+         add_loc_descr (&head, new_loc_descr (DW_OP_LLVM_piece_end, 0, 0));
+         add_loc_descr (&head, new_loc_descr (DW_OP_deref, 0, 0));
          loc_descr_plus_const (&head, offset);
+       }
     }
   else if (cfa->indirect)
     {
index a460e639d22993f14fc7831c85d70eb3051751a9..8290e4ea28673bf2f24f45bd2e3ed1e32d64178b 100644 (file)
@@ -1,3 +1,7 @@
+2020-07-27  Andrew Stubbs  <ams@codesourcery.com>
+
+       * dwarf2.def (DW_OP_LLVM_piece_end): New extension operator.
+
 2018-10-04  Cesar Philippidis  <cesar@codesourcery.com>
             Julian Brown  <julian@codesourcery.com>
 
index 4214c80907a09ca32342870f0127d49c6a811bd9..a3625a619bf1ea9997116f8ddb4ddc87474f36d7 100644 (file)
@@ -704,6 +704,12 @@ DW_OP (DW_OP_PGI_omp_thread_num, 0xf8)
    to 0 except explicitly documented for one action.  Please refer AArch64 DWARF
    ABI documentation for details.  */
 DW_OP (DW_OP_AARCH64_operation, 0xea)
+
+/* AMD GCN extensions (originally for LLVM).  See
+   http://llvm.org/docs/AMDGPUDwarfExtensionsForHeterogeneousDebugging.html  */
+// This clashes with DW_OP_AARCH64_operation, so use an alias instead
+// DW_OP (DW_OP_LLVM_piece_end, 0xea)
+#define DW_OP_LLVM_piece_end DW_OP_AARCH64_operation
 DW_END_OP
 
 DW_FIRST_ATE (DW_ATE_void, 0x0)