When I was researching to write my blogpost about vtables:
https://peter0x44.github.io/posts/vtables-itanium-abi/

I noticed a few improvements I could make to -fdump-lang-class's output

-fdump-lang-class prepended "0x" to HOST_WIDE_INT_PRINT_HEX outputs, but the
macro already includes that prefix, producing "0x0x..." in dumps.

Some vtable entries hold signed values e.g. vcall offsets, vbase offsets,
 offset-to-top.  When expr_as_string prints those INTEGER_CSTs,
negative offsets appear as large (unsigned) values.  Print integer vtable
entries as signed values, and keep expr_as_string for all other entries.

gcc/cp/ChangeLog:

        * class.cc (dump_vtable_entry): New function.
        (dump_array): Use it.
        (dump_class_hierarchy_r): Drop redundant literal 0x from
        HOST_WIDE_INT_PRINT_HEX formatting.
        (dump_vtable): Likewise.
---
 gcc/cp/class.cc | 31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 6e4dc3cb093..2ea90f6f8bf 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -167,6 +167,7 @@ static int maybe_indent_hierarchy (FILE *, int, int);
 static tree dump_class_hierarchy_r (FILE *, dump_flags_t, tree, tree, int);
 static void dump_class_hierarchy (tree);
 static void dump_class_hierarchy_1 (FILE *, dump_flags_t, tree);
+static void dump_vtable_entry (FILE *, tree);
 static void dump_array (FILE *, tree);
 static void dump_vtable (tree, tree, tree);
 static void dump_vtt (tree, tree);
@@ -9762,7 +9763,7 @@ dump_class_hierarchy_r (FILE *stream,
   tree base_binfo;
   int i;
 
-  fprintf (stream, "%s (0x" HOST_WIDE_INT_PRINT_HEX ") ",
+  fprintf (stream, "%s (" HOST_WIDE_INT_PRINT_HEX ") ",
           type_as_string (BINFO_TYPE (binfo), TFF_PLAIN_IDENTIFIER),
           (HOST_WIDE_INT) (uintptr_t) binfo);
   if (binfo != igo)
@@ -9785,7 +9786,7 @@ dump_class_hierarchy_r (FILE *stream,
   if (BINFO_PRIMARY_P (binfo))
     {
       indented = maybe_indent_hierarchy (stream, indent + 3, indented);
-      fprintf (stream, " primary-for %s (0x" HOST_WIDE_INT_PRINT_HEX ")",
+      fprintf (stream, " primary-for %s (" HOST_WIDE_INT_PRINT_HEX ")",
               type_as_string (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)),
                               TFF_PLAIN_IDENTIFIER),
               (HOST_WIDE_INT) (uintptr_t) BINFO_INHERITANCE_CHAIN (binfo));
@@ -9878,6 +9879,23 @@ dump_class_hierarchy (tree t)
     }
 }
 
+/* Dump VALUE, a vtable entry, to STREAM.  Print integer offsets as signed
+   values.  */
+
+static void
+dump_vtable_entry (FILE *stream, tree value)
+{
+  /* Vtable offset entries are stored in the pointer-sized vtable entry
+     type, but should be displayed as signed ptrdiff_t values.  */
+  tree cst = value;
+  STRIP_NOPS (cst);
+
+  if (TREE_CODE (cst) == INTEGER_CST)
+    print_decs (wi::to_wide (cst), stream);
+  else
+    fprintf (stream, "%s", expr_as_string (value, TFF_PLAIN_IDENTIFIER));
+}
+
 static void
 dump_array (FILE * stream, tree decl)
 {
@@ -9896,8 +9914,11 @@ dump_array (FILE * stream, tree decl)
 
   FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)),
                              ix, value)
-    fprintf (stream, "%-4ld  %s\n", (long)(ix * elt),
-            expr_as_string (value, TFF_PLAIN_IDENTIFIER));
+    {
+      fprintf (stream, "%-4ld  ", (long)(ix * elt));
+      dump_vtable_entry (stream, value);
+      fprintf (stream, "\n");
+    }
 }
 
 static void
@@ -9919,7 +9940,7 @@ dump_vtable (tree t, tree binfo, tree vtable)
       if (ctor_vtbl_p)
        {
          if (!BINFO_VIRTUAL_P (binfo))
-           fprintf (stream, " (0x" HOST_WIDE_INT_PRINT_HEX " instance)",
+           fprintf (stream, " (" HOST_WIDE_INT_PRINT_HEX " instance)",
                     (HOST_WIDE_INT) (uintptr_t) binfo);
          fprintf (stream, " in %s", type_as_string (t, TFF_PLAIN_IDENTIFIER));
        }
-- 
2.54.0

Reply via email to