https://gcc.gnu.org/g:5297795e5b9e86fd2085a8f739f43fc28fb5e522

commit r15-5826-g5297795e5b9e86fd2085a8f739f43fc28fb5e522
Author: Mark Harmstone <m...@harmstone.com>
Date:   Wed Nov 6 05:25:00 2024 +0000

    Write S_INLINESITE CodeView symbols
    
    Translate DW_TAG_inlined_subroutine DIEs into S_INLINESITE CodeView
    symbols, marking inlined functions.
    
    gcc/
            * dwarf2codeview.cc (enum cv_sym_type): Add S_INLINESITE and
            S_INLINESITE_END.
            (get_func_id): Add declaration.
            (write_s_inlinesite): New function.
            (write_inlinesite_records): New function.
            (write_function): Call write_inlinesite_records.

Diff:
---
 gcc/dwarf2codeview.cc | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc
index 18a75135352c..a0809d893430 100644
--- a/gcc/dwarf2codeview.cc
+++ b/gcc/dwarf2codeview.cc
@@ -86,6 +86,8 @@ enum cv_sym_type {
   S_DEFRANGE_REGISTER_REL = 0x1145,
   S_LPROC32_ID = 0x1146,
   S_GPROC32_ID = 0x1147,
+  S_INLINESITE = 0x114d,
+  S_INLINESITE_END = 0x114e,
   S_PROC_ID_END = 0x114f
 };
 
@@ -1468,6 +1470,8 @@ static uint32_t get_type_num_subroutine_type (dw_die_ref 
type, bool in_struct,
                                              int32_t this_adjustment);
 static void write_cv_padding (size_t padding);
 static void flush_deferred_types (void);
+static uint32_t get_func_id (dw_die_ref die);
+static void write_inlinesite_records (dw_die_ref func, dw_die_ref die);
 
 /* Return the file ID corresponding to a given source filename.  */
 
@@ -3324,6 +3328,124 @@ write_optimized_static_local_vars (dw_die_ref die)
   while (c != first_child);
 }
 
+/* Write an S_INLINESITE symbol, to record that a function has been inlined
+   inside another function.  */
+
+static void
+write_s_inlinesite (dw_die_ref parent_func, dw_die_ref die)
+{
+  unsigned int label_num = ++sym_label_num;
+  dw_die_ref func;
+  uint32_t func_id;
+
+  func = get_AT_ref (die, DW_AT_abstract_origin);
+  if (!func)
+    return;
+
+  func_id = get_func_id (func);
+  if (func_id == 0)
+    return;
+
+  /* This is struct inline_site in binutils and INLINESITESYM in Microsoft's
+     cvinfo.h:
+
+      struct inline_site
+      {
+       uint16_t size;
+       uint16_t kind;
+       uint32_t parent;
+       uint32_t end;
+       uint32_t inlinee;
+       uint8_t binary_annotations[];
+      } ATTRIBUTE_PACKED;
+  */
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  asm_fprintf (asm_out_file,
+              "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
+              label_num, label_num);
+
+  targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  fprint_whex (asm_out_file, S_INLINESITE);
+  putc ('\n', asm_out_file);
+
+  /* parent, filled in by linker */
+  fputs (integer_asm_op (4, false), asm_out_file);
+  fprint_whex (asm_out_file, 0);
+  putc ('\n', asm_out_file);
+
+  /* end, filled in by linker */
+  fputs (integer_asm_op (4, false), asm_out_file);
+  fprint_whex (asm_out_file, 0);
+  putc ('\n', asm_out_file);
+
+  fputs (integer_asm_op (4, false), asm_out_file);
+  fprint_whex (asm_out_file, func_id);
+  putc ('\n', asm_out_file);
+
+  /* FIXME: there now should follow some "binary annotations", recording how
+           offsets in the function map to line numbers in the inlined function,
+           but these require support in GAS.  */
+
+  targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
+
+  write_inlinesite_records (parent_func, die);
+
+  /* Write S_INLINESITE_END symbol.  */
+
+  label_num = ++sym_label_num;
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  asm_fprintf (asm_out_file,
+              "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
+              label_num, label_num);
+
+  targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  fprint_whex (asm_out_file, S_INLINESITE_END);
+  putc ('\n', asm_out_file);
+
+  targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
+}
+
+/* Loop through a function, and translate its DW_TAG_inlined_subroutine DIEs
+   into CodeView S_INLINESITE symbols.  */
+
+static void
+write_inlinesite_records (dw_die_ref func, dw_die_ref die)
+{
+  dw_die_ref first_child, c;
+
+  first_child = dw_get_die_child (die);
+
+  if (!first_child)
+    return;
+
+  c = first_child;
+  do
+    {
+      c = dw_get_die_sib (c);
+
+      switch (dw_get_die_tag (c))
+       {
+       case DW_TAG_lexical_block:
+         write_inlinesite_records (func, c);
+         break;
+
+       case DW_TAG_inlined_subroutine:
+         write_s_inlinesite (func, c);
+         break;
+
+       default:
+         break;
+       }
+    }
+  while (c != first_child);
+}
+
 /* Write an S_GPROC32_ID symbol, representing a global function, or an
    S_LPROC32_ID symbol, for a static function.  */
 
@@ -3450,6 +3572,8 @@ write_function (codeview_symbol *s)
 
   targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
 
+  write_inlinesite_records (s->function.die, s->function.die);
+
   frame_base = get_AT (s->function.die, DW_AT_frame_base);
 
   if (frame_base && frame_base->dw_attr_val.val_class == dw_val_class_loc)

Reply via email to