If the DIE for a struct, class, or union contains a nested type, add a
LF_NESTTYPE entry to its field list recording this.

Plus if we use a nested type, make sure that its parent also gets
defined. This may entail adding a forward definition and creating a
deferred type, so we need to call flush_deferred_types in
codeview_debug_finish as well.

gcc/
        * dwarf2codeview.cc (enum cv_leaf_type): Add LF_NESTTYPE.
        (struct codeview_subtype): Add lf_nesttype to union.
        (flush_deferred_types): Add declaration.
        (write_lf_fieldlist): Handle LF_NESTTYPE.
        (codeview_debug_finish): Call flush_deferred_types.
        (add_struct_nested_type): New function.
        (get_type_num_struct): Call add_struct_nested_type, and if nested make
        that parent is added.
---
(This doesn't logically depend on my pending S_INLINESITE patches, but
does if you are attempting to apply this cleanly. I'm getting this out
before the code freeze.)

 gcc/dwarf2codeview.cc | 89 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc
index 08fbe7f5bb6..261fcea6a97 100644
--- a/gcc/dwarf2codeview.cc
+++ b/gcc/dwarf2codeview.cc
@@ -116,6 +116,7 @@ enum cv_leaf_type {
   LF_MEMBER = 0x150d,
   LF_STMEMBER = 0x150e,
   LF_METHOD = 0x150f,
+  LF_NESTTYPE = 0x1510,
   LF_ONEMETHOD = 0x1511,
   LF_FUNC_ID = 0x1601,
   LF_MFUNC_ID = 0x1602,
@@ -1285,6 +1286,11 @@ struct codeview_subtype
       uint32_t base_class_type;
       codeview_integer offset;
     } lf_bclass;
+    struct
+    {
+      uint32_t type;
+      char *name;
+    } lf_nesttype;
   };
 };
 
@@ -1497,6 +1503,7 @@ static uint32_t get_type_num_subroutine_type (dw_die_ref 
type, bool in_struct,
 static void write_cv_padding (size_t padding);
 static uint32_t get_func_id (dw_die_ref die);
 static void write_inlinesite_records (dw_die_ref func, dw_die_ref die);
+static void flush_deferred_types (void);
 
 /* Return the file ID corresponding to a given source filename.  */
 
@@ -4364,6 +4371,40 @@ write_lf_fieldlist (codeview_custom_type *t)
          write_cv_padding (4 - (leaf_len % 4));
          break;
 
+       case LF_NESTTYPE:
+         /* This is lf_nest_type in binutils and lfNestType in Microsoft's
+            cvinfo.h:
+
+           struct lf_nest_type
+           {
+             uint16_t kind;
+             uint16_t padding;
+             uint32_t type;
+             char name[];
+           } ATTRIBUTE_PACKED;
+         */
+
+         fputs (integer_asm_op (2, false), asm_out_file);
+         fprint_whex (asm_out_file, LF_NESTTYPE);
+         putc ('\n', asm_out_file);
+
+         fputs (integer_asm_op (2, 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, v->lf_nesttype.type);
+         putc ('\n', asm_out_file);
+
+         name_len = strlen (v->lf_nesttype.name) + 1;
+         ASM_OUTPUT_ASCII (asm_out_file, v->lf_nesttype.name, name_len);
+
+         leaf_len = 8 + name_len;
+         write_cv_padding (4 - (leaf_len % 4));
+
+         free (v->lf_nesttype.name);
+         break;
+
        default:
          break;
        }
@@ -5137,6 +5178,12 @@ codeview_debug_finish (void)
 
   write_codeview_symbols ();
 
+  /* If we reference a nested struct but not its parent, add_deferred_type
+     gets called if we create a forward reference for this, even though we've
+     already flushed this in codeview_debug_early_finish.  In this case we will
+     need to flush this list again.  */
+  flush_deferred_types ();
+
   if (custom_types)
     write_custom_types ();
 
@@ -6135,6 +6182,32 @@ is_templated_func (dw_die_ref die)
   return false;
 }
 
+/* Create a field list subtype that records that a struct has a nested type
+   contained within it.  */
+
+static void
+add_struct_nested_type (dw_die_ref c, codeview_subtype **el, size_t *el_len)
+{
+  const char *name = get_AT_string (c, DW_AT_name);
+  size_t name_len;
+
+  if (!name)
+    return;
+
+  name_len = strlen (name);
+
+  *el = (codeview_subtype *) xmalloc (sizeof (**el));
+  (*el)->next = NULL;
+  (*el)->kind = LF_NESTTYPE;
+  (*el)->lf_nesttype.type = get_type_num (c, true, false);
+  (*el)->lf_nesttype.name = xstrdup (name);
+
+  *el_len = 9 + name_len;
+
+  if (*el_len % 4)
+    *el_len += 4 - (*el_len % 4);
+}
+
 /* Process a DW_TAG_structure_type, DW_TAG_class_type, or DW_TAG_union_type
    DIE, add an LF_FIELDLIST and an LF_STRUCTURE / LF_CLASS / LF_UNION type,
    and return the number of the latter.  */
@@ -6142,11 +6215,18 @@ is_templated_func (dw_die_ref die)
 static uint32_t
 get_type_num_struct (dw_die_ref type, bool in_struct, bool *is_fwd_ref)
 {
-  dw_die_ref first_child;
+  dw_die_ref parent, first_child;
   codeview_custom_type *ct;
   uint16_t num_members = 0;
   uint32_t last_type = 0;
 
+  parent = dw_get_die_parent(type);
+
+  if (parent && (dw_get_die_tag (parent) == DW_TAG_structure_type
+      || dw_get_die_tag (parent) == DW_TAG_class_type
+      || dw_get_die_tag (parent) == DW_TAG_union_type))
+    get_type_num (parent, true, false);
+
   if ((in_struct && get_AT_string (type, DW_AT_name))
       || get_AT_flag (type, DW_AT_declaration))
     {
@@ -6266,6 +6346,13 @@ get_type_num_struct (dw_die_ref type, bool in_struct, 
bool *is_fwd_ref)
              add_struct_inheritance (c, accessibility, &el, &el_len);
              break;
 
+           case DW_TAG_structure_type:
+           case DW_TAG_class_type:
+           case DW_TAG_union_type:
+           case DW_TAG_enumeration_type:
+             add_struct_nested_type (c, &el, &el_len);
+             break;
+
            default:
              break;
            }
-- 
2.45.2

Reply via email to