---
 gcc/pdbout.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 gcc/pdbout.h |  8 +++++
 2 files changed, 99 insertions(+), 2 deletions(-)

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,
-- 
2.26.2

Reply via email to