https://gcc.gnu.org/g:340bca65ce50ccb827a2501273f50da77c7d7349

commit r15-1570-g340bca65ce50ccb827a2501273f50da77c7d7349
Author: Mark Harmstone <m...@harmstone.com>
Date:   Sun Jun 23 18:17:39 2024 -0600

    [PATCH 02/11] Handle CodeView base types
    
    Adds a get_type_num function to translate type DIEs into CodeView
    numbers, along with a hash table for this.  For now we just deal with
    the base types (integers, Unicode chars, floats, and bools).
    
    gcc/
            * dwarf2codeview.cc (struct codeview_type): New structure.
            (struct die_hasher): Likewise.
            (types_htab): New variable.
            (codeview_debug_finish): Free types_htab if allocated.
            (get_type_num_base_type, get_type_num): New function.
            (add_variable): Call get_type_num.
            * dwarf2codeview.h (T_CHAR, T_SHORT, T_LONG, T_QUAD): Define.
            (T_UCHAR, T_USHORT, T_ULONG, T_UQUAD, T_BOOL08): Likewise.
            (T_REAL32, T_REAL64, T_REAL80, T_REAL128, T_RCHAR): Likewise.
            (T_WCHAR, T_INT4, T_UINT4, T_CHAR16, T_CHAR32, T_CHAR8): Likewise.

Diff:
---
 gcc/dwarf2codeview.cc | 196 +++++++++++++++++++++++++++++++++++++++++++++++++-
 gcc/dwarf2codeview.h  |  23 ++++++
 2 files changed, 218 insertions(+), 1 deletion(-)

diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc
index 60e84635971..eb7c1270e31 100644
--- a/gcc/dwarf2codeview.cc
+++ b/gcc/dwarf2codeview.cc
@@ -147,6 +147,27 @@ struct codeview_symbol
   };
 };
 
+struct codeview_type
+{
+  dw_die_ref die;
+  uint32_t num;
+};
+
+struct die_hasher : free_ptr_hash <codeview_type>
+{
+  typedef dw_die_ref compare_type;
+
+  static hashval_t hash (const codeview_type *x)
+  {
+    return htab_hash_pointer (x->die);
+  }
+
+  static bool equal (const codeview_type *x, const dw_die_ref y)
+  {
+    return x->die == y;
+  }
+};
+
 static unsigned int line_label_num;
 static unsigned int func_label_num;
 static unsigned int sym_label_num;
@@ -159,6 +180,7 @@ static codeview_function *funcs, *last_func;
 static const char* last_filename;
 static uint32_t last_file_id;
 static codeview_symbol *sym, *last_sym;
+static hash_table<die_hasher> *types_htab;
 
 /* Record new line number against the current function.  */
 
@@ -838,6 +860,178 @@ codeview_debug_finish (void)
   write_source_files ();
   write_line_numbers ();
   write_codeview_symbols ();
+
+  if (types_htab)
+    delete types_htab;
+}
+
+/* Translate a DWARF base type (DW_TAG_base_type) into its CodeView
+   equivalent.  */
+
+static uint32_t
+get_type_num_base_type (dw_die_ref type)
+{
+  unsigned int size = get_AT_unsigned (type, DW_AT_byte_size);
+
+  switch (get_AT_unsigned (type, DW_AT_encoding))
+    {
+    case DW_ATE_signed_char:
+      {
+       const char *name = get_AT_string (type, DW_AT_name);
+
+       if (size != 1)
+         return 0;
+
+       if (name && !strcmp (name, "signed char"))
+         return T_CHAR;
+       else
+         return T_RCHAR;
+      }
+
+    case DW_ATE_unsigned_char:
+      if (size != 1)
+       return 0;
+
+      return T_UCHAR;
+
+    case DW_ATE_signed:
+      switch (size)
+       {
+       case 2:
+         return T_SHORT;
+
+       case 4:
+         {
+           const char *name = get_AT_string (type, DW_AT_name);
+
+           if (name && !strcmp (name, "int"))
+             return T_INT4;
+           else
+             return T_LONG;
+         }
+
+       case 8:
+         return T_QUAD;
+
+       default:
+         return 0;
+       }
+
+    case DW_ATE_unsigned:
+      switch (size)
+       {
+       case 2:
+         {
+           const char *name = get_AT_string (type, DW_AT_name);
+
+           if (name && !strcmp (name, "wchar_t"))
+             return T_WCHAR;
+           else
+             return T_USHORT;
+         }
+
+       case 4:
+         {
+           const char *name = get_AT_string (type, DW_AT_name);
+
+           if (name && !strcmp (name, "unsigned int"))
+             return T_UINT4;
+           else
+             return T_ULONG;
+         }
+
+       case 8:
+         return T_UQUAD;
+
+       default:
+         return 0;
+       }
+
+    case DW_ATE_UTF:
+      switch (size)
+       {
+       case 1:
+         return T_CHAR8;
+
+       case 2:
+         return T_CHAR16;
+
+       case 4:
+         return T_CHAR32;
+
+       default:
+         return 0;
+       }
+
+    case DW_ATE_float:
+      switch (size)
+       {
+       case 4:
+         return T_REAL32;
+
+       case 8:
+         return T_REAL64;
+
+       case 12:
+         return T_REAL80;
+
+       case 16:
+         return T_REAL128;
+
+       default:
+         return 0;
+       }
+
+    case DW_ATE_boolean:
+      if (size == 1)
+       return T_BOOL08;
+      else
+       return 0;
+
+    default:
+      return 0;
+    }
+}
+
+/* Process a DIE representing a type definition and return its number.  If
+   it's something we can't handle, return 0.  We keep a hash table so that
+   we're not adding the same type multiple times - though if we do it's not
+   disastrous, as ld will deduplicate everything for us.  */
+
+static uint32_t
+get_type_num (dw_die_ref type)
+{
+  codeview_type **slot, *t;
+
+  if (!type)
+    return 0;
+
+  if (!types_htab)
+    types_htab = new hash_table<die_hasher> (10);
+
+  slot = types_htab->find_slot_with_hash (type, htab_hash_pointer (type),
+                                         INSERT);
+
+  if (*slot)
+    return (*slot)->num;
+
+  t = (codeview_type *) xmalloc (sizeof (codeview_type));
+  t->die = type;
+
+  switch (dw_get_die_tag (type))
+    {
+    case DW_TAG_base_type:
+      t->num = get_type_num_base_type (type);
+      break;
+
+    default:
+      t->num = 0;
+      break;
+    }
+
+  *slot = t;
+
+  return t->num;
 }
 
 /* Process a DW_TAG_variable DIE, and add an S_GDATA32 or S_LDATA32 symbol for
@@ -857,7 +1051,7 @@ add_variable (dw_die_ref die)
 
   s->next = NULL;
   s->kind = get_AT (die, DW_AT_external) ? S_GDATA32 : S_LDATA32;
-  s->data_symbol.type = 0;
+  s->data_symbol.type = get_type_num (get_AT_ref (die, DW_AT_type));
   s->data_symbol.name = xstrdup (name);
   s->data_symbol.die = die;
 
diff --git a/gcc/dwarf2codeview.h b/gcc/dwarf2codeview.h
index ac4c2fd21c2..7d8a4c161f4 100644
--- a/gcc/dwarf2codeview.h
+++ b/gcc/dwarf2codeview.h
@@ -23,6 +23,29 @@ along with GCC; see the file COPYING3.  If not see
 #include "dwarf2out.h"
 #include "flags.h"
 
+/* Constants for in-built types.  */
+
+#define T_CHAR                 0x0010
+#define T_SHORT                        0x0011
+#define T_LONG                 0x0012
+#define T_QUAD                 0x0013
+#define T_UCHAR                        0x0020
+#define T_USHORT               0x0021
+#define T_ULONG                        0x0022
+#define T_UQUAD                        0x0023
+#define T_BOOL08               0x0030
+#define T_REAL32               0x0040
+#define T_REAL64               0x0041
+#define T_REAL80               0x0042
+#define T_REAL128              0x0043
+#define T_RCHAR                        0x0070
+#define T_WCHAR                        0x0071
+#define T_INT4                 0x0074
+#define T_UINT4                        0x0075
+#define T_CHAR16               0x007a
+#define T_CHAR32               0x007b
+#define T_CHAR8                        0x007c
+
 /* Debug Format Interface.  Used in dwarf2out.cc.  */
 
 extern void codeview_debug_finish (void);

Reply via email to