---
 gcc/pdbout.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/pdbout.h | 11 +++++++
 2 files changed, 96 insertions(+)

diff --git a/gcc/pdbout.c b/gcc/pdbout.c
index 08bb14364e5..fa3b1fb0312 100644
--- a/gcc/pdbout.c
+++ b/gcc/pdbout.c
@@ -78,6 +78,7 @@ static struct pdb_type *types = NULL, *last_type = NULL;
 static struct pdb_type *arglist_types = NULL;
 static struct pdb_type *pointer_types = NULL;
 static struct pdb_type *proc_types = NULL;
+static struct pdb_type *modifier_types = NULL;
 static struct pdb_source_file *source_files = NULL, *last_source_file = NULL;
 static uint32_t source_file_string_offset = 1;
 static unsigned int num_line_number_entries = 0;
@@ -863,6 +864,19 @@ write_procedure (struct pdb_proc *proc)
   fprintf (asm_out_file, "\t.short\t0\n");     // padding
 }
 
+/* Output lfModifier structure, representing a const or volatile version
+ * of an existing type. */
+static void
+write_modifier (struct pdb_modifier *t)
+{
+  fprintf (asm_out_file, "\t.short\t0xa\n");
+  fprintf (asm_out_file, "\t.short\t0x%x\n", LF_MODIFIER);
+  fprintf (asm_out_file, "\t.short\t0x%x\n", t->type ? t->type->id : 0);
+  fprintf (asm_out_file, "\t.short\t0\n");     // padding
+  fprintf (asm_out_file, "\t.short\t0x%x\n", t->modifier);
+  fprintf (asm_out_file, "\t.short\t0\n");     // padding
+}
+
 /* Given a pdb_type, output its definition. */
 static void
 write_type (struct pdb_type *t)
@@ -883,6 +897,10 @@ write_type (struct pdb_type *t)
     case LF_PROCEDURE:
       write_procedure ((struct pdb_proc *) t->data);
       break;
+
+    case LF_MODIFIER:
+      write_modifier ((struct pdb_modifier *) t->data);
+      break;
     }
 }
 
@@ -1318,6 +1336,68 @@ find_type_function (tree t)
   return proctype;
 }
 
+/* Given a CV-modified type t, allocate a new pdb_type modifying
+ * the base type, and add it to the type list. */
+static struct pdb_type *
+find_type_modifier (tree t)
+{
+  struct pdb_type *type, *last_entry = NULL, *base_type;
+  struct pdb_modifier *mod;
+  uint16_t modifier = 0;
+  struct pdb_type **slot;
+
+  base_type = find_type (TYPE_MAIN_VARIANT (t));
+
+  if (TYPE_READONLY (t))
+    modifier |= CV_MODIFIER_CONST;
+
+  if (TYPE_VOLATILE (t))
+    modifier |= CV_MODIFIER_VOLATILE;
+
+  type = modifier_types;
+  while (type)
+    {
+      mod = (struct pdb_modifier *) type->data;
+
+      if (mod->type == base_type && mod->modifier == modifier)
+       return type;
+
+      last_entry = type;
+      type = type->next2;
+    }
+
+  type =
+    (struct pdb_type *) xmalloc (offsetof (struct pdb_type, data) +
+                                sizeof (struct pdb_modifier));
+  type->cv_type = LF_MODIFIER;
+  type->tree = t;
+  type->next = type->next2 = NULL;
+  type->id = 0;
+
+  mod = (struct pdb_modifier *) type->data;
+
+  mod->type = base_type;
+  mod->modifier = modifier;
+
+  if (last_entry)
+    last_entry->next2 = type;
+  else
+    modifier_types = type;
+
+  if (last_type)
+    last_type->next = type;
+  else
+    types = type;
+
+  last_type = type;
+
+  slot =
+    tree_hash_table.find_slot_with_hash (t, htab_hash_pointer (t), INSERT);
+  *slot = type;
+
+  return type;
+}
+
 inline hashval_t
 pdb_type_tree_hasher::hash (pdb_type_tree_hasher::compare_type tree)
 {
@@ -1439,6 +1519,11 @@ find_type (tree t)
   if (type)
     return type;
 
+  // add modifier type if const or volatile
+
+  if (TYPE_READONLY (t) || TYPE_VOLATILE (t))
+    return find_type_modifier (t);
+
   switch (TREE_CODE (t))
     {
     case INTEGER_TYPE:
diff --git a/gcc/pdbout.h b/gcc/pdbout.h
index a660728158e..1fa2b1ab2fa 100644
--- a/gcc/pdbout.h
+++ b/gcc/pdbout.h
@@ -21,6 +21,7 @@
 #define GCC_PDBOUT_H 1
 
 #define S_END                          0x0006
+#define LF_MODIFIER                    0x1001
 #define LF_POINTER                     0x1002
 #define LF_PROCEDURE                   0x1008
 #define S_BLOCK32                      0x1103
@@ -262,6 +263,16 @@ struct pdb_source_file
   char name[1];
 };
 
+#define CV_MODIFIER_CONST      0x1
+#define CV_MODIFIER_VOLATILE   0x2
+#define CV_MODIFIER_UNALIGNED  0x4
+
+struct pdb_modifier
+{
+  struct pdb_type *type;
+  uint16_t modifier;
+};
+
 enum pdb_x86_register
 {
   CV_X86_NONE = 0,
-- 
2.26.2

Reply via email to