[18/24] pdbout: Append template information to struct or function name.

Message ID 20210320162652.23346-18-mark@harmstone.com
State New
Headers show
Series
  • [01/24] Add -gcodeview debugging option
Related show

Commit Message

Mark Harmstone March 20, 2021, 4:26 p.m.
---
 gcc/pdbout.c | 346 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 344 insertions(+), 2 deletions(-)

-- 
2.26.2

Patch

diff --git a/gcc/pdbout.c b/gcc/pdbout.c
index fb40f066bd9..0cae4d33469 100644
--- a/gcc/pdbout.c
+++ b/gcc/pdbout.c
@@ -73,6 +73,7 @@  static void pdbout_end_block (unsigned int line ATTRIBUTE_UNUSED,
 			      unsigned int blocknum);
 
 static struct pdb_type *find_type (tree t);
+static char *get_tree_name (tree t);
 
 static struct pdb_func *funcs = NULL, *cur_func = NULL;
 static struct pdb_block *cur_block = NULL;
@@ -1484,13 +1485,264 @@  pdbout_finish (const char *filename ATTRIBUTE_UNUSED)
   write_pdb_type_section ();
 }
 
+/* Reallocate the string n, adding the type name of arg and the character
+ * suffix.
+ * We can't use the C++ pretty printer for this as this file gets
+ * compiled into libbackend.a. */
+static void
+append_template_element (char **n, size_t *len, tree arg, char suffix)
+{
+  char *tmp;
+  char *name = *n;
+
+  switch (TREE_CODE (arg))
+    {
+    case RECORD_TYPE:
+    case UNION_TYPE:
+      {
+	char *s = get_tree_name (arg);
+
+	if (s)
+	  {
+	    size_t s_len = strlen (s);
+
+	    tmp = (char *) xmalloc (*len + s_len + 2);
+	    memcpy (tmp, name, *len);
+	    free (name);
+	    name = tmp;
+
+	    memcpy (&name[*len], s, s_len);
+	    name[*len + s_len] = suffix;
+	    name[*len + s_len + 1] = 0;
+	    *len += s_len + 1;
+
+	    free (s);
+	  }
+	else
+	  {
+	    tmp = (char *) xmalloc (*len + 3);
+	    memcpy (tmp, name, *len);
+	    free (name);
+	    name = tmp;
+
+	    name[*len] = '?';
+	    name[*len + 1] = suffix;
+	    name[*len + 2] = 0;
+	    *len += 2;
+	  }
+
+	break;
+      }
+
+    case INTEGER_TYPE:
+    case BOOLEAN_TYPE:
+    case REAL_TYPE:
+    case VOID_TYPE:
+    case NULLPTR_TYPE:
+    case ENUMERAL_TYPE:
+      {
+	const char *s;
+	size_t s_len;
+
+	if (TREE_CODE (arg) == NULLPTR_TYPE)
+	  s = "std::nullptr_t";
+	else
+	  s = IDENTIFIER_POINTER (TYPE_IDENTIFIER (arg));
+
+	s_len = strlen (s);
+
+	tmp = (char *) xmalloc (*len + s_len + 2);
+	memcpy (tmp, name, *len);
+	free (name);
+	name = tmp;
+
+	memcpy (&name[*len], s, s_len);
+	name[*len + s_len] = suffix;
+	name[*len + s_len + 1] = 0;
+	*len += s_len + 1;
+
+	break;
+      }
+
+    case POINTER_TYPE:
+      {
+	append_template_element (&name, len, TREE_TYPE (arg), '*');
+
+	tmp = (char *) xmalloc (*len + 2);
+	memcpy (tmp, name, *len);
+	free (name);
+	name = tmp;
+
+	name[*len] = suffix;
+	name[*len + 1] = 0;
+	(*len)++;
+
+	break;
+      }
+
+    case INTEGER_CST:
+      if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
+	{
+	  if (TREE_INT_CST_ELT_CHECK (arg, 0) == 0)
+	    {
+	      static const char str[] = "false";
+
+	      tmp = (char *) xmalloc (*len + sizeof (str) + 2);
+	      memcpy (tmp, name, *len);
+	      free (name);
+	      name = tmp;
+
+	      memcpy (&name[*len], str, sizeof (str) - 1);
+	      name[*len + sizeof (str) - 1] = suffix;
+	      name[*len + sizeof (str)] = 0;
+	      *len += sizeof (str);
+	    }
+	  else
+	    {
+	      static const char str[] = "true";
+
+	      tmp = (char *) xmalloc (*len + sizeof (str) + 2);
+	      memcpy (tmp, name, *len);
+	      free (name);
+	      name = tmp;
+
+	      memcpy (&name[*len], str, sizeof (str) - 1);
+	      name[*len + sizeof (str) - 1] = suffix;
+	      name[*len + sizeof (str)] = 0;
+	      *len += sizeof (str);
+	    }
+	}
+      else
+	{
+	  char s[50];
+	  size_t s_len;
+
+	  if (TYPE_UNSIGNED (arg))
+	    sprintf (s, "%lu", TREE_INT_CST_ELT_CHECK (arg, 0));
+	  else
+	    sprintf (s, "%li", TREE_INT_CST_ELT_CHECK (arg, 0));
+
+	  s_len = strlen (s);
+
+	  tmp = (char *) xmalloc (*len + s_len + 2);
+	  memcpy (tmp, name, *len);
+	  free (name);
+	  name = tmp;
+
+	  memcpy (&name[*len], s, s_len);
+	  name[*len + s_len] = suffix;
+	  name[*len + s_len + 1] = 0;
+	  *len += s_len + 1;
+	}
+      break;
+
+    case REFERENCE_TYPE:
+      {
+	append_template_element (&name, len, TREE_TYPE (arg), '&');
+
+	tmp = (char *) xmalloc (*len + 2);
+	memcpy (tmp, name, *len);
+	free (name);
+	name = tmp;
+
+	name[*len] = suffix;
+	name[*len + 1] = 0;
+	(*len)++;
+
+	break;
+      }
+
+    case TYPE_ARGUMENT_PACK:
+      {
+	static const char str[] = "...";
+
+	tmp = (char *) xmalloc (*len + sizeof (str) + 2);
+	memcpy (tmp, name, *len);
+	free (name);
+	name = tmp;
+
+	memcpy (&name[*len], str, sizeof (str) - 1);
+	name[*len + sizeof (str) - 1] = suffix;
+	name[*len + sizeof (str)] = 0;
+	*len += sizeof (str);
+
+	break;
+      }
+
+    case FUNCTION_TYPE:
+      {
+	tree param = TYPE_ARG_TYPES (arg);
+
+	append_template_element (&name, len, TREE_TYPE (arg), '(');
+
+	if (!param || TREE_CODE (TREE_VALUE (param)) == VOID_TYPE)
+	  {
+	    tmp = (char *) xmalloc (*len + 3);
+	    memcpy (tmp, name, *len);
+	    free (name);
+	    name = tmp;
+
+	    name[*len] = ')';
+	    name[*len + 1] = suffix;
+	    name[*len + 2] = 0;
+
+	    *len += 2;
+	  }
+	else
+	  {
+	    while (param)
+	      {
+		if (TREE_CODE (TREE_VALUE (param)) == VOID_TYPE)
+		  break;
+
+		append_template_element (&name, len, TREE_VALUE (param),
+					 TREE_CHAIN (param)
+					 &&
+					 TREE_CODE (TREE_VALUE
+						    (TREE_CHAIN (param))) !=
+					 VOID_TYPE ? ',' : ')');
+
+		param = TREE_CHAIN (param);
+	      }
+
+	    tmp = (char *) xmalloc (*len + 2);
+	    memcpy (tmp, name, *len);
+	    free (name);
+	    name = tmp;
+
+	    name[*len] = suffix;
+	    name[*len + 1] = 0;
+
+	    (*len)++;
+	  }
+
+	break;
+      }
+
+    default:
+      tmp = (char *) xmalloc (*len + 3);
+      memcpy (tmp, name, *len);
+      free (name);
+      name = tmp;
+
+      name[*len] = '?';
+      name[*len + 1] = suffix;
+      name[*len + 2] = 0;
+      *len += 2;
+
+      break;
+    }
+
+  *n = name;
+}
+
 /* For a tree t, construct the name - namespaces, plus the
- * base name of the tree. */
+ * base name of the tree, plus the template information. */
 static char *
 get_tree_name (tree t)
 {
   char *name;
-  tree ns;
+  tree ns, tmpl, args;
 
   static const char anon_ns[] = "<anonymous>";
 
@@ -1591,6 +1843,96 @@  get_tree_name (tree t)
 	}
     }
 
+  /* Append template information */
+
+  if (TREE_CODE (t) == RECORD_TYPE && TYPE_LANG_SPECIFIC (t)
+      && CLASSTYPE_USE_TEMPLATE (t) && CLASSTYPE_TEMPLATE_INFO (t))
+    tmpl = CLASSTYPE_TEMPLATE_INFO (t);
+  else if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t)
+	   && DECL_TEMPLATE_INFO (t))
+    tmpl = DECL_TEMPLATE_INFO (t);
+  else
+    tmpl = NULL;
+
+  if (!tmpl || !PRIMARY_TEMPLATE_P (TI_TEMPLATE (tmpl)))
+    return name;
+
+  args = TI_ARGS (tmpl);
+
+  if (args)
+    {
+      size_t len = strlen (name);
+      char *tmp;
+      tree pack = NULL;
+
+      // If both scope and final part are templated, we're only interested
+      // in the final TREE_VEC.
+
+      if (TREE_VEC_LENGTH (args) > 0
+	  && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+	args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
+
+      // If first element is a TYPE_ARGUMENT_PACK, extract the
+      // TREE_VEC from it.
+
+      if (TREE_VEC_LENGTH (args) > 0
+	  && TREE_CODE (TREE_VEC_ELT (args, 0)) == TYPE_ARGUMENT_PACK)
+	args = TREE_TYPE (TREE_VEC_ELT (args, 0));
+
+      if (TREE_VEC_LENGTH (args) == 0)
+	{
+	  tmp = (char *) xmalloc (len + 3);
+	  memcpy (tmp, name, len);
+	  free (name);
+
+	  tmp[len] = '<';
+	  tmp[len + 1] = '>';
+	  tmp[len + 2] = 0;
+
+	  return tmp;
+	}
+
+      tmp = (char *) xmalloc (len + 2);
+      memcpy (tmp, name, len);
+      free (name);
+      name = tmp;
+
+      name[len] = '<';
+      name[len + 1] = 0;
+      len++;
+
+      for (int i = 0; i < TREE_VEC_LENGTH (args); i++)
+	{
+	  if (TREE_CODE (TREE_VEC_ELT (args, i)) == TYPE_ARGUMENT_PACK)
+	    {
+	      pack = TREE_VEC_ELT (args, i);
+	      break;
+	    }
+
+	  append_template_element (&name, &len, TREE_VEC_ELT (args, i),
+				   ((int) i <
+				    TREE_VEC_LENGTH (args) - 1) ? ',' : '>');
+	}
+
+      if (pack)
+	{
+	  args = TREE_TYPE (pack);
+
+	  // If TYPE_ARGUMENT_PACK is last element but empty,
+	  // get rid of trailing comma
+	  if (TREE_VEC_LENGTH (args) == 0)
+	    name[strlen (name) - 1] = '>';
+
+	  for (int i = 0; i < TREE_VEC_LENGTH (args); i++)
+	    {
+	      append_template_element (&name, &len, TREE_VEC_ELT (args, i),
+				       ((int) i <
+					TREE_VEC_LENGTH (args) -
+					1) ? ',' : '>');
+	    }
+	}
+    }
+
   return name;
 }