Translate DW_TAG_const_type and DW_TAG_volatile_type DIEs into
LF_MODIFIER symbols.

    gcc/
            * dwarf2codeview.cc
            (struct codeview_custom_type): Add lf_modifier to union.
            (write_cv_padding, write_lf_modifier): New functions.
            (write_custom_types): Call write_lf_modifier.
            (get_type_num_const_type): New function.
            (get_type_num_volatile_type): Likewise.
            (get_type_num): Handle DW_TAG_const_type and
                DW_TAG_volatile_type DIEs.
            * dwarf2codeview.h (MOD_const, MOD_volatile): Define.
            (LF_MODIFIER): Likewise.
---
 gcc/dwarf2codeview.cc | 157 ++++++++++++++++++++++++++++++++++++++++++
 gcc/dwarf2codeview.h  |   5 ++
 2 files changed, 162 insertions(+)

diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc
index 51401f2d5bc..05f5f60997e 100644
--- a/gcc/dwarf2codeview.cc
+++ b/gcc/dwarf2codeview.cc
@@ -183,6 +183,11 @@ struct codeview_custom_type
       uint32_t base_type;
       uint32_t attributes;
     } lf_pointer;
+    struct
+    {
+      uint32_t base_type;
+      uint16_t modifier;
+    } lf_modifier;
   };
 };
 
@@ -903,6 +908,76 @@ write_lf_pointer (codeview_custom_type *t)
   asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
 }
 
+/* All CodeView type definitions have to be aligned to a four-byte boundary,
+   so write some padding bytes if necessary.  These have to be specific values:
+   f3, f2, f1.  */
+
+static void
+write_cv_padding (size_t padding)
+{
+  if (padding == 4 || padding == 0)
+    return;
+
+  if (padding == 3)
+    {
+      fputs (integer_asm_op (1, false), asm_out_file);
+      fprint_whex (asm_out_file, 0xf3);
+      putc ('\n', asm_out_file);
+    }
+
+  if (padding >= 2)
+    {
+      fputs (integer_asm_op (1, false), asm_out_file);
+      fprint_whex (asm_out_file, 0xf2);
+      putc ('\n', asm_out_file);
+    }
+
+  fputs (integer_asm_op (1, false), asm_out_file);
+  fprint_whex (asm_out_file, 0xf1);
+  putc ('\n', asm_out_file);
+}
+
+/* Write an LF_MODIFIER type, representing a const and/or volatile modification
+   of another type.  */
+
+static void
+write_lf_modifier (codeview_custom_type *t)
+{
+  /* This is lf_modifier in binutils and lfModifier in Microsoft's cvinfo.h:
+
+    struct lf_modifier
+    {
+      uint16_t size;
+      uint16_t kind;
+      uint32_t base_type;
+      uint16_t modifier;
+      uint16_t padding;
+    } ATTRIBUTE_PACKED;
+  */
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
+              t->num, t->num);
+
+  asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  fprint_whex (asm_out_file, t->kind);
+  putc ('\n', asm_out_file);
+
+  fputs (integer_asm_op (4, false), asm_out_file);
+  fprint_whex (asm_out_file, t->lf_modifier.base_type);
+  putc ('\n', asm_out_file);
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  fprint_whex (asm_out_file, t->lf_modifier.modifier);
+  putc ('\n', asm_out_file);
+
+  write_cv_padding (2);
+
+  asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
+}
+
 /* Write the .debug$T section, which contains all of our custom type
    definitions.  */
 
@@ -924,6 +999,10 @@ write_custom_types (void)
        case LF_POINTER:
          write_lf_pointer (custom_types);
          break;
+
+       case LF_MODIFIER:
+         write_lf_modifier (custom_types);
+         break;
        }
 
       free (custom_types);
@@ -1159,6 +1238,76 @@ get_type_num_pointer_type (dw_die_ref type)
   return ct->num;
 }
 
+/* Process a DW_TAG_const_type DIE, adding an LF_MODIFIER type and returning
+   its number.  */
+
+static uint32_t
+get_type_num_const_type (dw_die_ref type)
+{
+  dw_die_ref base_type;
+  uint32_t base_type_num;
+  codeview_custom_type *ct;
+  bool is_volatile = false;
+
+  base_type = get_AT_ref (type, DW_AT_type);
+  if (!base_type)
+    return 0;
+
+  /* Handle case when this is a const volatile type - we only need one
+     LF_MODIFIER for this.  */
+  if (dw_get_die_tag (base_type) == DW_TAG_volatile_type)
+    {
+      is_volatile = true;
+
+      base_type = get_AT_ref (base_type, DW_AT_type);
+      if (!base_type)
+       return 0;
+    }
+
+  base_type_num = get_type_num (base_type);
+  if (base_type_num == 0)
+    return 0;
+
+  ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
+
+  ct->next = NULL;
+  ct->kind = LF_MODIFIER;
+  ct->lf_modifier.base_type = base_type_num;
+  ct->lf_modifier.modifier = MOD_const;
+
+  if (is_volatile)
+    ct->lf_modifier.modifier |= MOD_volatile;
+
+  add_custom_type (ct);
+
+  return ct->num;
+}
+
+/* Process a DW_TAG_volatile_type DIE, adding an LF_MODIFIER type and
+   returning its number.  */
+
+static uint32_t
+get_type_num_volatile_type (dw_die_ref type)
+{
+  uint32_t base_type_num;
+  codeview_custom_type *ct;
+
+  base_type_num = get_type_num (get_AT_ref (type, DW_AT_type));
+  if (base_type_num == 0)
+    return 0;
+
+  ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
+
+  ct->next = NULL;
+  ct->kind = LF_MODIFIER;
+  ct->lf_modifier.base_type = base_type_num;
+  ct->lf_modifier.modifier = MOD_volatile;
+
+  add_custom_type (ct);
+
+  return ct->num;
+}
+
 /* Process a DIE representing a type definition, add a CodeView type if
    necessary, 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
@@ -1201,6 +1350,14 @@ get_type_num (dw_die_ref type)
       t->num = get_type_num_pointer_type (type);
       break;
 
+    case DW_TAG_const_type:
+      t->num = get_type_num_const_type (type);
+      break;
+
+    case DW_TAG_volatile_type:
+      t->num = get_type_num_volatile_type (type);
+      break;
+
     default:
       t->num = 0;
       break;
diff --git a/gcc/dwarf2codeview.h b/gcc/dwarf2codeview.h
index 0af4c98250f..d48cfbebc32 100644
--- a/gcc/dwarf2codeview.h
+++ b/gcc/dwarf2codeview.h
@@ -56,7 +56,12 @@ along with GCC; see the file COPYING3.  If not see
 #define CV_PTR_NEAR32          0x0a
 #define CV_PTR_64              0x0c
 
+/* LF_MODIFIER values.  */
+#define MOD_const              0x1
+#define MOD_volatile           0x2
+
 /* Constants for type definitions.  */
+#define LF_MODIFIER            0x1001
 #define LF_POINTER             0x1002
 
 /* Debug Format Interface.  Used in dwarf2out.cc.  */
-- 
2.44.2

Reply via email to