diff mbox

[libiberty] Add demangler support for cloned function symbols (PR 40831)

Message ID AANLkTinzCE6EoYa64KTR688hem0zLx-5XN_4wHv7SGHN@mail.gmail.com
State New
Headers show

Commit Message

Cary Coutant Feb. 23, 2011, 2:06 a.m. UTC
PR 40831 complains that the demangler does not work with the symbols
generated by gcc when it clones a function. This patch adds support
for the ".clone.n" style previously used by gcc, and the ".isra.n",
".constprop.n", and ".part.n" styles currently used. (Are there any
others?)

Comments?

-cary


include/ChangeLog:

        PR 40831
        * demangle.h (enum demangle_component_type): Add
        DEMANGLE_COMPONENT_CLONE, DEMANGLE_COMPONENT_CONSTPROP_CLONE,
        DEMANGLE_COMPONENT_ISRA_CLONE, DEMANGLE_COMPONENT_PART_CLONE.

libiberty/ChangeLog:

        PR 40831
        * cp-demangle.c (struct clone_suffix_list): New type.
        (d_make_comp): Add new component types.
        (cplus_demangle_mangled_name): Check for clone suffixes.
        (d_parmlist): Don't error out if we see '.'.
        (clone_suffixes): New array.
        (d_clone_suffix): New function.
        (d_print_comp): Print info for clone suffixes.
        * testsuite/demangle-expected: Add new testcases.
include/ChangeLog:

	PR 40831
	* demangle.h (enum demangle_component_type): Add
	DEMANGLE_COMPONENT_CLONE, DEMANGLE_COMPONENT_CONSTPROP_CLONE,
	DEMANGLE_COMPONENT_ISRA_CLONE, DEMANGLE_COMPONENT_PART_CLONE.

libiberty/ChangeLog:

	PR 40831
	* cp-demangle.c (struct clone_suffix_list): New type.
	(d_make_comp): Add new component types.
	(cplus_demangle_mangled_name): Check for clone suffixes.
	(d_parmlist): Don't error out if we see '.'.
	(clone_suffixes): New array.
	(d_clone_suffix): New function.
	(d_print_comp): Print info for clone suffixes.
	* testsuite/demangle-expected: Add new testcases.

Comments

Jakub Jelinek Feb. 23, 2011, 8:29 a.m. UTC | #1
On Tue, Feb 22, 2011 at 06:06:11PM -0800, Cary Coutant wrote:
> PR 40831 complains that the demangler does not work with the symbols
> generated by gcc when it clones a function. This patch adds support
> for the ".clone.n" style previously used by gcc, and the ".isra.n",
> ".constprop.n", and ".part.n" styles currently used. (Are there any
> others?)

OpenMP uses ".omp_fn.n" and ".omp_cpyfn.n" suffixes, see e.g.
g++ -fopenmp -S libgomp/testsuite/libgomp.c++/task-3.C
to see both of the types generated by the compiler.
_Zaaaaa.omp_fn.n is the outlined body of a parallel or task region,
_Zaaaaa.omp_cpyfn.n is a function to copy over firstprivate classes
of task regions.

	Jakub
Cary Coutant Feb. 23, 2011, 6:31 p.m. UTC | #2
> OpenMP uses ".omp_fn.n" and ".omp_cpyfn.n" suffixes, see e.g.
> g++ -fopenmp -S libgomp/testsuite/libgomp.c++/task-3.C
> to see both of the types generated by the compiler.
> _Zaaaaa.omp_fn.n is the outlined body of a parallel or task region,
> _Zaaaaa.omp_cpyfn.n is a function to copy over firstprivate classes
> of task regions.

OK, thanks. Dmitry G. also commented that the patch does not work "for
`_Z3fooi.1988' or `_Z3fooi.part.9.165493.constprop.775.31805'."
Apparently, there can be multiple numeric suffixes, and a cloned
function can be cloned again. Is it worth trying to identify the kinds
of cloning in the demangled name, or should I just look for a generic
pattern instead?

-cary
diff mbox

Patch

diff --git a/include/demangle.h b/include/demangle.h
index c062455..dd5191e 100644
--- a/include/demangle.h
+++ b/include/demangle.h
@@ -396,7 +396,15 @@  enum demangle_component_type
   /* An unnamed type.  */
   DEMANGLE_COMPONENT_UNNAMED_TYPE,
   /* A pack expansion.  */
-  DEMANGLE_COMPONENT_PACK_EXPANSION
+  DEMANGLE_COMPONENT_PACK_EXPANSION,
+  /* An old-style constant-propagation clone.  */
+  DEMANGLE_COMPONENT_CLONE,
+  /* A constant-propagation clone.  */
+  DEMANGLE_COMPONENT_CONSTPROP_CLONE,
+  /* An inter-procedural SRA clone.  */
+  DEMANGLE_COMPONENT_ISRA_CLONE,
+  /* A partial inlining clone.  */
+  DEMANGLE_COMPONENT_PART_CLONE
 };
 
 /* Types which are only used internally.  */
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 7e951cc..c48cfc8 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -208,6 +208,19 @@  static void d_init_info (const char *, int, size_t, struct d_info *);
 #define ANONYMOUS_NAMESPACE_PREFIX_LEN \
   (sizeof (ANONYMOUS_NAMESPACE_PREFIX) - 1)
 
+/* Suffixes that may be appended to a mangled name to indicate
+   a cloned function.  */
+
+struct clone_suffix_list
+{
+  /* The suffix.  */
+  const char *suffix;
+  /* The length of the suffix.  */
+  int suffix_len;
+  /* The component type to represent the clone.  */
+  enum demangle_component_type type;
+};
+
 /* Information we keep for the standard substitutions.  */
 
 struct d_standard_sub_info
@@ -419,6 +432,9 @@  static struct demangle_component *d_lambda (struct d_info *);
 
 static struct demangle_component *d_unnamed_type (struct d_info *);
 
+static struct demangle_component *
+d_clone_suffix (struct d_info *, struct demangle_component *);
+
 static int
 d_add_substitution (struct d_info *, struct demangle_component *);
 
@@ -804,6 +820,10 @@  d_make_comp (struct d_info *di, enum demangle_component_type type,
     case DEMANGLE_COMPONENT_LITERAL_NEG:
     case DEMANGLE_COMPONENT_COMPOUND_NAME:
     case DEMANGLE_COMPONENT_VECTOR_TYPE:
+    case DEMANGLE_COMPONENT_CLONE:
+    case DEMANGLE_COMPONENT_CONSTPROP_CLONE:
+    case DEMANGLE_COMPONENT_ISRA_CLONE:
+    case DEMANGLE_COMPONENT_PART_CLONE:
       if (left == NULL || right == NULL)
 	return NULL;
       break;
@@ -1036,7 +1056,7 @@  d_make_sub (struct d_info *di, const char *name, int len)
   return p;
 }
 
-/* <mangled-name> ::= _Z <encoding>
+/* <mangled-name> ::= _Z <encoding> [<clone-suffix>]
 
    TOP_LEVEL is non-zero when called at the top level.  */
 
@@ -1044,6 +1064,8 @@  CP_STATIC_IF_GLIBCPP_V3
 struct demangle_component *
 cplus_demangle_mangled_name (struct d_info *di, int top_level)
 {
+  struct demangle_component *p;
+
   if (! d_check_char (di, '_')
       /* Allow missing _ if not at toplevel to work around a
 	 bug in G++ abi-version=2 mangling; see the comment in
@@ -1052,7 +1074,16 @@  cplus_demangle_mangled_name (struct d_info *di, int top_level)
     return NULL;
   if (! d_check_char (di, 'Z'))
     return NULL;
-  return d_encoding (di, top_level);
+  p = d_encoding (di, top_level);
+
+  /* If at top level and parsing parameters, check for a clone
+     suffix.  */
+  if (top_level &&
+      ((di->options & DMGL_PARAMS) != 0)
+      && d_peek_char (di) == '.')
+    p = d_clone_suffix (di, p);
+
+  return p;
 }
 
 /* Return whether a function should have a return type.  The argument
@@ -2346,7 +2377,7 @@  d_parmlist (struct d_info *di)
       struct demangle_component *type;
 
       char peek = d_peek_char (di);
-      if (peek == '\0' || peek == 'E')
+      if (peek == '\0' || peek == 'E' || peek == '.')
 	break;
       type = cplus_demangle_type (di);
       if (type == NULL)
@@ -3066,6 +3097,47 @@  d_unnamed_type (struct d_info *di)
   return ret;
 }
 
+/* <clone-suffix> ::= .clone. <nonnegative number>
+		  ::= .constprop. <nonnegative number>
+		  ::= .isra. <nonnegative number>
+		  ::= .part. <nonnegative number>
+*/
+
+static const struct clone_suffix_list clone_suffixes[] =
+{
+  { NL (".clone."),     DEMANGLE_COMPONENT_CLONE },
+  { NL (".constprop."), DEMANGLE_COMPONENT_CONSTPROP_CLONE },
+  { NL (".isra."),      DEMANGLE_COMPONENT_ISRA_CLONE },
+  { NL (".part."),      DEMANGLE_COMPONENT_PART_CLONE },
+};
+
+static struct demangle_component *
+d_clone_suffix (struct d_info *di, struct demangle_component *encoding)
+{
+  const char *suffix;
+  const struct clone_suffix_list *p;
+  const struct clone_suffix_list *pend;
+
+  suffix = d_str (di);
+  pend = (&clone_suffixes[0]
+	  + sizeof clone_suffixes / sizeof clone_suffixes[0]);
+  for (p = &clone_suffixes[0]; p < pend; ++p)
+    {
+      if (strncmp (suffix, p->suffix, p->suffix_len) == 0)
+        {
+	  struct demangle_component *n;
+
+	  if (! IS_DIGIT (suffix[p->suffix_len]))
+	    return encoding;
+	  d_advance (di, p->suffix_len);
+	  n = d_number_component (di);
+	  return d_make_comp (di, p->type, encoding, n);
+	}
+    }
+
+  return encoding;
+}
+
 /* Add a new substitution.  */
 
 static int
@@ -4343,6 +4415,34 @@  d_print_comp (struct d_print_info *dpi,
       d_append_char (dpi, '}');
       return;
 
+    case DEMANGLE_COMPONENT_CLONE:
+      d_print_comp (dpi, d_left (dc));
+      d_append_string (dpi, " [clone #");
+      d_print_comp (dpi, d_right (dc));
+      d_append_char (dpi, ']');
+      return;
+
+    case DEMANGLE_COMPONENT_CONSTPROP_CLONE:
+      d_print_comp (dpi, d_left (dc));
+      d_append_string (dpi, " [CP clone #");
+      d_print_comp (dpi, d_right (dc));
+      d_append_char (dpi, ']');
+      return;
+
+    case DEMANGLE_COMPONENT_ISRA_CLONE:
+      d_print_comp (dpi, d_left (dc));
+      d_append_string (dpi, " [ISRA clone #");
+      d_print_comp (dpi, d_right (dc));
+      d_append_char (dpi, ']');
+      return;
+
+    case DEMANGLE_COMPONENT_PART_CLONE:
+      d_print_comp (dpi, d_left (dc));
+      d_append_string (dpi, " [partial inlining clone #");
+      d_print_comp (dpi, d_right (dc));
+      d_append_char (dpi, ']');
+      return;
+
     default:
       d_print_error (dpi);
       return;
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 5ce0377..d493766 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -4092,3 +4092,30 @@  DFA
 --format=auto
 _ZN3Psi7VariantIIcPKcEE5visitIIRZN11VariantTest9TestVisit11test_methodEvEUlS2_E0_RZNS6_11test_methodEvEUlcE1_RZNS6_11test_methodEvEUlNS_4NoneEE_EEENS_13VariantDetail19SelectVisitorResultIIDpT_EE4typeEDpOSG_
 Psi::VariantDetail::SelectVisitorResult<VariantTest::TestVisit::test_method()::{lambda(char const*)#2}&, VariantTest::TestVisit::test_method()::{lambda(char)#3}&, VariantTest::TestVisit::test_method()::{lambda(Psi::None)#1}&>::type Psi::Variant<char, char const*>::visit<VariantTest::TestVisit::test_method()::{lambda(char const*)#2}&, VariantTest::TestVisit::test_method()::{lambda(char)#3}&, VariantTest::TestVisit::test_method()::{lambda(Psi::None)#1}&>((VariantTest::TestVisit::test_method()::{lambda(Psi::None)#1}&&&)...)
+#
+# Clone suffix tests
+#
+--format=gnu-v3 --no-params
+_Z3fo5n.clone.1
+fo5(__int128) [clone #1]
+fo5
+#
+--format=gnu-v3 --no-params
+_Z3fo5n.constprop.2
+fo5(__int128) [CP clone #2]
+fo5
+#
+--format=gnu-v3 --no-params
+_Z3fo5n.isra.3
+fo5(__int128) [ISRA clone #3]
+fo5
+#
+--format=gnu-v3 --no-params
+_Z3fo5n.part.4
+fo5(__int128) [partial inlining clone #4]
+fo5
+#
+--format=gnu-v3 --no-params
+_Z12to_be_clonediPv.clone.0
+to_be_cloned(int, void*) [clone #0]
+to_be_cloned