---
 gcc/pdbout.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/pdbout.h |  15 ++++++
 2 files changed, 148 insertions(+)

diff --git a/gcc/pdbout.c b/gcc/pdbout.c
index fa3b1fb0312..8376b0e762c 100644
--- a/gcc/pdbout.c
+++ b/gcc/pdbout.c
@@ -79,6 +79,7 @@ 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_type *array_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;
@@ -816,6 +817,71 @@ write_pointer (struct pdb_pointer *ptr)
   fprintf (asm_out_file, "\t.long\t0x%x\n", ptr->attr.num);
 }
 
+/* Output a lfArray structure. */
+static void
+write_array (struct pdb_array *arr)
+{
+  uint16_t len = 15, align;
+
+  if (arr->length >= 0x8000)
+    {
+      if (arr->length <= 0xffff)
+       len += 2;               // LF_USHORT
+      else if (arr->length <= 0xffffffff)
+       len += 4;               // LF_ULONG
+      else
+       len += 8;               // LF_UQUADWORD
+    }
+
+  align = 4 - (len % 4);
+
+  if (align != 4)
+    len += align;
+
+  fprintf (asm_out_file, "\t.short\t0x%lx\n", len - sizeof (uint16_t));
+  fprintf (asm_out_file, "\t.short\t0x%x\n", LF_ARRAY);
+
+  fprintf (asm_out_file, "\t.short\t0x%x\n", arr->type ? arr->type->id : 0);
+  fprintf (asm_out_file, "\t.short\t0\n");     // padding
+  fprintf (asm_out_file, "\t.short\t0x%x\n",
+          arr->index_type ? arr->index_type->id : 0);
+  fprintf (asm_out_file, "\t.short\t0\n");     // padding
+
+  if (arr->length >= 0x8000)
+    {
+      if (arr->length <= 0xffff)
+       {
+         fprintf (asm_out_file, "\t.short\t0x%x\n", LF_USHORT);
+         fprintf (asm_out_file, "\t.short\t0x%x\n", (uint16_t) arr->length);
+       }
+      else if (arr->length <= 0xffffffff)
+       {
+         fprintf (asm_out_file, "\t.short\t0x%x\n", LF_ULONG);
+         fprintf (asm_out_file, "\t.long\t0x%x\n", (uint32_t) arr->length);
+       }
+      else
+       {
+         fprintf (asm_out_file, "\t.short\t0x%x\n", LF_UQUADWORD);
+         fprintf (asm_out_file, "\t.quad\t0x%" PRIx64 "\n", arr->length);
+       }
+    }
+  else
+    fprintf (asm_out_file, "\t.short\t0x%x\n", (uint32_t) arr->length);
+
+  fprintf (asm_out_file, "\t.byte\t0\n");      // empty string
+
+  if (align != 4)
+    {
+      if (align == 3)
+       fprintf (asm_out_file, "\t.byte\t0xf3\n");
+
+      if (align >= 2)
+       fprintf (asm_out_file, "\t.byte\t0xf2\n");
+
+      fprintf (asm_out_file, "\t.byte\t0xf1\n");
+    }
+}
+
 /* Output a lfArgList structure, describing the arguments that a
  * procedure expects. */
 static void
@@ -890,6 +956,10 @@ write_type (struct pdb_type *t)
       write_pointer ((struct pdb_pointer *) t->data);
       break;
 
+    case LF_ARRAY:
+      write_array ((struct pdb_array *) t->data);
+      break;
+
     case LF_ARGLIST:
       write_arglist ((struct pdb_arglist *) t->data);
       break;
@@ -1074,6 +1144,66 @@ pdbout_late_global_decl (tree var)
   global_vars = v;
 }
 
+/* Given an array type t, allocate a new pdb_type and add it to the
+ * type list. */
+static struct pdb_type *
+find_type_array (tree t)
+{
+  struct pdb_type *arrtype, *last_entry = NULL, *type;
+  struct pdb_array *arr;
+  uint64_t length =
+    TYPE_SIZE (t) ? (TREE_INT_CST_ELT (TYPE_SIZE (t), 0) / 8) : 0;
+  struct pdb_type **slot;
+
+  type = find_type (TREE_TYPE (t));
+
+  if (!type)
+    return NULL;
+
+  arrtype = array_types;
+  while (arrtype)
+    {
+      arr = (struct pdb_array *) arrtype->data;
+
+      if (arr->type == type && arr->length == length)
+       return arrtype;
+
+      last_entry = arrtype;
+      arrtype = arrtype->next2;
+    }
+
+  arrtype =
+    (struct pdb_type *) xmalloc (offsetof (struct pdb_type, data) +
+                                sizeof (struct pdb_array));
+  arrtype->cv_type = LF_ARRAY;
+  arrtype->tree = t;
+  arrtype->next = arrtype->next2 = NULL;
+  arrtype->id = 0;
+
+  arr = (struct pdb_array *) arrtype->data;
+  arr->type = type;
+  arr->index_type = ulong_type;
+  arr->length = length;
+
+  if (last_entry)
+    last_entry->next2 = arrtype;
+  else
+    array_types = arrtype;
+
+  if (last_type)
+    last_type->next = arrtype;
+  else
+    types = arrtype;
+
+  last_type = arrtype;
+
+  slot =
+    tree_hash_table.find_slot_with_hash (t, htab_hash_pointer (t), INSERT);
+  *slot = arrtype;
+
+  return arrtype;
+}
+
 /* Add an argument list type. */
 static pdb_type *
 add_arglist_type (struct pdb_type *t)
@@ -1682,6 +1812,9 @@ find_type (tree t)
     case REFERENCE_TYPE:
       return find_type_pointer (t);
 
+    case ARRAY_TYPE:
+      return find_type_array (t);
+
     case FUNCTION_TYPE:
     case METHOD_TYPE:
       return find_type_function (t);
diff --git a/gcc/pdbout.h b/gcc/pdbout.h
index 1fa2b1ab2fa..412378a63ac 100644
--- a/gcc/pdbout.h
+++ b/gcc/pdbout.h
@@ -36,6 +36,14 @@
 #define S_DEFRANGE_REGISTER            0x1141
 #define S_DEFRANGE_REGISTER_REL                0x1145
 #define LF_ARGLIST                     0x1201
+#define LF_ARRAY                       0x1503
+#define LF_CHAR                                0x8000
+#define LF_SHORT                       0x8001
+#define LF_USHORT                      0x8002
+#define LF_LONG                                0x8003
+#define LF_ULONG                       0x8004
+#define LF_QUADWORD                    0x8009
+#define LF_UQUADWORD                   0x800a
 
 /* Format version as of MSVC 7 */
 #define CV_SIGNATURE_C13       4
@@ -161,6 +169,13 @@ struct pdb_pointer
   } attr;
 };
 
+struct pdb_array
+{
+  struct pdb_type *type;
+  struct pdb_type *index_type;
+  uint64_t length;
+};
+
 struct pdb_arglist
 {
   unsigned int count;
-- 
2.26.2

Reply via email to