[16/24] pdbout: Output definitions of bitfields within structs.

Message ID 20210320162652.23346-16-mark@harmstone.com
State New
Headers show
Series
  • [01/24] Add -gcodeview debugging option
Related show

Commit Message

Mark Harmstone March 20, 2021, 4:26 p.m.
---
 gcc/pdbout.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 gcc/pdbout.h |  8 +++++
 2 files changed, 99 insertions(+), 2 deletions(-)

-- 
2.26.2

Patch

diff --git a/gcc/pdbout.c b/gcc/pdbout.c
index 7d493513e06..d3f251f22d2 100644
--- a/gcc/pdbout.c
+++ b/gcc/pdbout.c
@@ -85,6 +85,7 @@  static struct pdb_type *modifier_types = NULL;
 static struct pdb_type *fieldlist_types = NULL;
 static struct pdb_type *struct_types = NULL, *last_struct_type = NULL;
 static struct pdb_type *enum_types = NULL;
+static struct pdb_type *bitfield_types = NULL;
 static struct pdb_type *array_types = NULL;
 static struct pdb_alias *aliases = NULL;
 static struct pdb_source_file *source_files = NULL, *last_source_file = NULL;
@@ -1312,6 +1313,22 @@  write_modifier (struct pdb_modifier *t)
   fprintf (asm_out_file, "\t.short\t0\n");	// padding
 }
 
+/* Output lfBitfield structure. */
+static void
+write_bitfield (struct pdb_bitfield *t)
+{
+  fprintf (asm_out_file, "\t.short\t0xa\n");
+  fprintf (asm_out_file, "\t.short\t0x%x\n", LF_BITFIELD);
+  fprintf (asm_out_file, "\t.short\t0x%x\n",
+	   t->underlying_type ? t->underlying_type->id : 0);
+  fprintf (asm_out_file, "\t.short\t0\n");	// padding
+  fprintf (asm_out_file, "\t.byte\t0x%x\n", t->size);
+  fprintf (asm_out_file, "\t.byte\t0x%x\n", t->offset);
+
+  fprintf (asm_out_file, "\t.byte\t0xf2\n");	// alignment
+  fprintf (asm_out_file, "\t.byte\t0xf1\n");	// alignment
+}
+
 /* Given a pdb_type, output its definition. */
 static void
 write_type (struct pdb_type *t)
@@ -1357,6 +1374,10 @@  write_type (struct pdb_type *t)
     case LF_MODIFIER:
       write_modifier ((struct pdb_modifier *) t->data);
       break;
+
+    case LF_BITFIELD:
+      write_bitfield ((struct pdb_bitfield *) t->data);
+      break;
     }
 }
 
@@ -1548,6 +1569,57 @@  pdbout_late_global_decl (tree var)
   global_vars = v;
 }
 
+/* Allocate a new pdb_type for a bitfield. */
+static struct pdb_type *
+find_type_bitfield (struct pdb_type *underlying_type, unsigned int size,
+		    unsigned int offset)
+{
+  struct pdb_type *type, *last_entry = NULL;
+  struct pdb_bitfield *bf;
+
+  type = bitfield_types;
+  while (type)
+    {
+      bf = (struct pdb_bitfield *) type->data;
+
+      if (bf->underlying_type == underlying_type && bf->size == size
+	  && bf->offset == offset)
+	return type;
+
+      last_entry = type;
+      type = type->next2;
+    }
+
+  type =
+    (struct pdb_type *) xmalloc (offsetof (struct pdb_type, data) +
+				 sizeof (struct pdb_bitfield));
+
+  type->cv_type = LF_BITFIELD;
+  type->tree = NULL;
+  type->next = type->next2 = NULL;
+  type->id = 0;
+
+  bf = (struct pdb_bitfield *) type->data;
+
+  bf->underlying_type = underlying_type;
+  bf->size = size;
+  bf->offset = offset;
+
+  if (last_entry)
+    last_entry->next2 = type;
+  else
+    bitfield_types = type;
+
+  if (last_type)
+    last_type->next = type;
+  else
+    types = type;
+
+  last_type = type;
+
+  return type;
+}
+
 /* Allocate a pdb_type for a forward declaration for a struct. The debugger
  * will resolve this automatically, by searching for a substantive
  * struct definition with the same name. */
@@ -1844,8 +1916,25 @@  find_type_struct (tree t, bool is_union)
 		  ent->fld_attr = CV_FLDATTR_PUBLIC;
 		  ent->name = xstrdup (IDENTIFIER_POINTER (DECL_NAME (f)));
 
-		  ent->type = find_type (TREE_TYPE (f));
-		  ent->offset = bit_offset / 8;
+		  if (DECL_BIT_FIELD_TYPE (f))
+		    {
+		      struct pdb_type *underlying_type =
+			find_type (DECL_BIT_FIELD_TYPE (f));
+
+		      ent->type =
+			find_type_bitfield (underlying_type,
+					    TREE_INT_CST_ELT (DECL_SIZE (f),
+							      0),
+					    TREE_INT_CST_ELT
+					    (DECL_FIELD_BIT_OFFSET (f), 0));
+		      ent->offset =
+			TREE_INT_CST_ELT (DECL_FIELD_OFFSET (f), 0);
+		    }
+		  else
+		    {
+		      ent->type = find_type (TREE_TYPE (f));
+		      ent->offset = bit_offset / 8;
+		    }
 
 		  ent++;
 		}
diff --git a/gcc/pdbout.h b/gcc/pdbout.h
index 09b3914d650..e12f1cf21a0 100644
--- a/gcc/pdbout.h
+++ b/gcc/pdbout.h
@@ -37,6 +37,7 @@ 
 #define S_DEFRANGE_REGISTER_REL		0x1145
 #define LF_ARGLIST			0x1201
 #define LF_FIELDLIST			0x1203
+#define LF_BITFIELD			0x1205
 #define LF_ENUMERATE			0x1502
 #define LF_ARRAY			0x1503
 #define LF_CLASS			0x1504
@@ -373,6 +374,13 @@  struct pdb_modifier
   uint16_t modifier;
 };
 
+struct pdb_bitfield
+{
+  struct pdb_type *underlying_type;
+  unsigned int size;
+  unsigned int offset;
+};
+
 enum pdb_x86_register
 {
   CV_X86_NONE = 0,