---
 gcc/pdbout.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++---
 gcc/pdbout.h |  36 ++++++++++++++
 2 files changed, 161 insertions(+), 6 deletions(-)

diff --git a/gcc/pdbout.c b/gcc/pdbout.c
index 64f7c1d71bc..08bb14364e5 100644
--- a/gcc/pdbout.c
+++ b/gcc/pdbout.c
@@ -76,6 +76,7 @@ static struct pdb_block *cur_block = NULL;
 static struct pdb_global_var *global_vars = NULL;
 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_source_file *source_files = NULL, *last_source_file = NULL;
 static uint32_t source_file_string_offset = 1;
@@ -803,6 +804,17 @@ free_type (struct pdb_type *t)
   free (t);
 }
 
+/* Output a lfPointer structure. */
+static void
+write_pointer (struct pdb_pointer *ptr)
+{
+  fprintf (asm_out_file, "\t.short\t0xa\n");
+  fprintf (asm_out_file, "\t.short\t0x%x\n", LF_POINTER);
+  fprintf (asm_out_file, "\t.short\t0x%x\n", ptr->type ? ptr->type->id : 0);
+  fprintf (asm_out_file, "\t.short\t0\n");     // padding
+  fprintf (asm_out_file, "\t.long\t0x%x\n", ptr->attr.num);
+}
+
 /* Output a lfArgList structure, describing the arguments that a
  * procedure expects. */
 static void
@@ -857,6 +869,13 @@ write_type (struct pdb_type *t)
 {
   switch (t->cv_type)
     {
+    case LF_POINTER:
+      if (t->id < FIRST_TYPE_NUM)      // pointer to builtin
+       return;
+
+      write_pointer ((struct pdb_pointer *) t->data);
+      break;
+
     case LF_ARGLIST:
       write_arglist ((struct pdb_arglist *) t->data);
       break;
@@ -910,13 +929,38 @@ number_types (void)
          continue;
        }
 
-      t->id = type_num;
-      type_num++;
-
-      if (type_num == 0)       // overflow
+      switch (t->cv_type)
        {
-         fprintf (stderr, "too many CodeView types\n");
-         xexit (1);
+       case LF_POINTER:
+         {
+           struct pdb_pointer *ptr = (struct pdb_pointer *) t->data;
+
+           // pointers to builtins have their own constants
+           if (ptr->type && ptr->type->id != 0 && ptr->type->id < 0x100)
+             {
+               if (ptr->attr.s.ptrtype == CV_PTR_NEAR32)
+                 {
+                   t->id = (CV_TM_NPTR32 << 8) | ptr->type->id;
+                   break;
+                 }
+               else if (ptr->attr.s.ptrtype == CV_PTR_64)
+                 {
+                   t->id = (CV_TM_NPTR64 << 8) | ptr->type->id;
+                   break;
+                 }
+             }
+           [[fallthrough]];
+         }
+
+       default:
+         t->id = type_num;
+         type_num++;
+
+         if (type_num == 0)    // overflow
+           {
+             fprintf (stderr, "too many CodeView types\n");
+             xexit (1);
+           }
        }
 
       t = t->next;
@@ -1072,6 +1116,77 @@ add_arglist_type (struct pdb_type *t)
   return t;
 }
 
+/* Given a pointer type t, allocate a new pdb_type and add it to the
+ * type list. */
+static struct pdb_type *
+find_type_pointer (tree t)
+{
+  struct pdb_type *ptrtype, *t2, *last_entry = NULL, *type;
+  struct pdb_pointer *ptr, v;
+  unsigned int size = TREE_INT_CST_ELT (TYPE_SIZE (t), 0) / 8;
+  struct pdb_type **slot;
+
+  type = find_type (TREE_TYPE (t));
+
+  if (!type)
+    return NULL;
+
+  v.attr.num = 0;
+
+  v.attr.s.size = size;
+
+  if (size == 8)
+    v.attr.s.ptrtype = CV_PTR_64;
+  else if (size == 4)
+    v.attr.s.ptrtype = CV_PTR_NEAR32;
+
+  if (TREE_CODE (t) == REFERENCE_TYPE)
+    v.attr.s.ptrmode =
+      TYPE_REF_IS_RVALUE (t) ? CV_PTR_MODE_RVREF : CV_PTR_MODE_LVREF;
+
+  t2 = pointer_types;
+  while (t2)
+    {
+      ptr = (struct pdb_pointer *) t2->data;
+
+      if (ptr->type == type && ptr->attr.num == v.attr.num)
+       return t2;
+
+      last_entry = t2;
+      t2 = t2->next2;
+    }
+
+  ptrtype =
+    (struct pdb_type *) xmalloc (offsetof (struct pdb_type, data) +
+                                sizeof (struct pdb_pointer));
+  ptrtype->cv_type = LF_POINTER;
+  ptrtype->tree = t;
+  ptrtype->next = ptrtype->next2 = NULL;
+  ptrtype->id = 0;
+
+  ptr = (struct pdb_pointer *) ptrtype->data;
+  ptr->type = type;
+  ptr->attr.num = v.attr.num;
+
+  if (last_entry)
+    last_entry->next2 = ptrtype;
+  else
+    pointer_types = ptrtype;
+
+  if (last_type)
+    last_type->next = ptrtype;
+  else
+    types = ptrtype;
+
+  last_type = ptrtype;
+
+  slot =
+    tree_hash_table.find_slot_with_hash (t, htab_hash_pointer (t), INSERT);
+  *slot = ptrtype;
+
+  return ptrtype;
+}
+
 /* Given a function type t, allocate a new pdb_type and add it to the
  * type list. */
 static struct pdb_type *
@@ -1478,6 +1593,10 @@ find_type (tree t)
 
   switch (TREE_CODE (t))
     {
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      return find_type_pointer (t);
+
     case FUNCTION_TYPE:
     case METHOD_TYPE:
       return find_type_function (t);
diff --git a/gcc/pdbout.h b/gcc/pdbout.h
index b9e56a66069..a660728158e 100644
--- a/gcc/pdbout.h
+++ b/gcc/pdbout.h
@@ -21,6 +21,7 @@
 #define GCC_PDBOUT_H 1
 
 #define S_END                          0x0006
+#define LF_POINTER                     0x1002
 #define LF_PROCEDURE                   0x1008
 #define S_BLOCK32                      0x1103
 #define S_REGISTER                     0x1106
@@ -124,6 +125,41 @@ struct pdb_global_var
   struct pdb_type *type;
 };
 
+// from CV_ptrtype_e in cvdump
+#define CV_PTR_NEAR32          0x0a
+#define CV_PTR_64              0x0c
+
+// from CV_ptrmode_e in cvdump
+#define CV_PTR_MODE_PTR                0x0
+#define CV_PTR_MODE_LVREF      0x1
+#define CV_PTR_MODE_PMEM       0x2
+#define CV_PTR_MODE_PMFUNC     0x3
+#define CV_PTR_MODE_RVREF      0x4
+
+struct pdb_pointer
+{
+  struct pdb_type *type;
+  union
+  {
+    struct
+    {
+      uint32_t ptrtype:5;
+      uint32_t ptrmode:3;
+      uint32_t isflat32:1;
+      uint32_t isvolatile:1;
+      uint32_t isconst:1;
+      uint32_t isunaligned:1;
+      uint32_t isrestrict:1;
+      uint32_t size:6;
+      uint32_t ismocom:1;
+      uint32_t islref:1;
+      uint32_t isrref:1;
+      uint32_t unused:10;
+    } s;
+    uint32_t num;
+  } attr;
+};
+
 struct pdb_arglist
 {
   unsigned int count;
-- 
2.26.2

Reply via email to