diff mbox series

[11/24] pdbout: Output array types.

Message ID 20210320162652.23346-11-mark@harmstone.com
State New
Headers show
Series [01/24] Add -gcodeview debugging option | expand

Commit Message

Mark Harmstone March 20, 2021, 4:26 p.m. UTC
---
 gcc/pdbout.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/pdbout.h |  15 ++++++
 2 files changed, 148 insertions(+)
diff mbox series

Patch

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;