This re-writes SSA name parsing to support declarations of anonymous
SSA names (I restricted that to plaine _N thus w/o name for the moment
to cater a bit for the ambiguity).  It also should support non-SSA name
PHI args now (esp. addresses), but no testcase yet as there seem to
be bugs downstream.

Tested on x86_64-unknown-linux-gnu.

Richard.

2016-10-27  Richard Biener  <rguent...@suse.de>

        c/
        * c-parser.c (c_parser_peek_nth_token): Export.
        * c-parser.h (c_parser_peek_nth_token): Declare.
        * gimple-parser.c (c_parser_parse_ssa_names): Remove.
        (c_parser_parse_ssa_name_id): New function parsing a SSA name
        identifier.
        (c_parser_parse_ssa_name): New function parsing a SSA name.
        (c_parser_gimple_postfix_expression): Make SSA name parsing
        stricter, move default-def handling here.
        (c_parser_gimple_declaration): Handle SSA name declarations.
        (c_parser_gimple_expression): Use c_parser_gimple_unary_expression
        for parsing PHI args.

        * gcc.dg/gimplefe-17.c: New testcase.

diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index f69121b..63385fc 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -453,7 +453,7 @@ c_parser_peek_2nd_token (c_parser *parser)
 /* Return a pointer to the Nth token from PARSER, reading it
    in if necessary.  The N-1th token is already read in.  */
 
-static c_token *
+c_token *
 c_parser_peek_nth_token (c_parser *parser, unsigned int n)
 {
   /* N is 1-based, not zero-based.  */
diff --git a/gcc/c/c-parser.h b/gcc/c/c-parser.h
index f36e738..04fa681 100644
--- a/gcc/c/c-parser.h
+++ b/gcc/c/c-parser.h
@@ -133,6 +133,8 @@ enum c_lookahead_kind {
 
 
 extern c_token * c_parser_peek_token (c_parser *parser);
+extern c_token * c_parser_peek_2nd_token (c_parser *parser);
+extern c_token * c_parser_peek_nth_token (c_parser *parser, unsigned int n);
 extern bool c_parser_require (c_parser *parser, enum cpp_ttype type,
                              const char *msgid);
 extern void c_parser_error (c_parser *parser, const char *gmsgid);
@@ -140,7 +142,6 @@ extern void c_parser_consume_token (c_parser *parser);
 extern void c_parser_skip_until_found (c_parser *parser, enum cpp_ttype type,
                                       const char *msgid);
 extern bool c_parser_next_token_starts_declspecs (c_parser *parser);
-extern c_token * c_parser_peek_2nd_token (c_parser *parser);
 bool c_parser_next_tokens_start_declaration (c_parser *parser);
 bool c_token_starts_typename (c_token *token);
 
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 931a61f..7040071 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -72,7 +72,6 @@ static void c_parser_gimple_if_stmt (c_parser *, gimple_seq 
*);
 static void c_parser_gimple_switch_stmt (c_parser *, gimple_seq *);
 static void c_parser_gimple_return_stmt (c_parser *, gimple_seq *);
 static void c_finish_gimple_return (location_t, tree);
-static c_expr c_parser_parse_ssa_names (c_parser *);
 static tree c_parser_gimple_paren_condition (c_parser *);
 static vec<tree, va_gc> *c_parser_gimple_expr_list (c_parser *,
                    vec<tree, va_gc> **, vec<location_t> *);
@@ -343,7 +342,7 @@ c_parser_gimple_expression (c_parser *parser, gimple_seq 
*seq)
            c_parser_consume_token (parser);
          else
            {
-             arg = c_parser_parse_ssa_names (parser).value;
+             arg = c_parser_gimple_unary_expression (parser).value;
              vargs.safe_push (arg);
            }
        }
@@ -633,69 +632,76 @@ c_parser_gimple_unary_expression (c_parser *parser)
     }
 }
 
-/* Parse gimple ssa names.  */
+/* Decompose ID into base name (ID until ver_offset) and VERSION.  Return
+   true if ID matches a SSA name.  */
 
-static c_expr
-c_parser_parse_ssa_names (c_parser *parser)
+static bool
+c_parser_parse_ssa_name_id (tree id, unsigned *version, unsigned *ver_offset)
 {
-  tree id = NULL_TREE;
-  c_expr ret;
-  char *var_name = NULL, *var_version = NULL, *token = NULL;
-  ret.original_code = ERROR_MARK;
-  ret.original_type = NULL;
+  const char *token = IDENTIFIER_POINTER (id);
+  const char *var_version = strrchr (token, '_');
+  if (! var_version)
+    return false;
 
-  /* SSA token string.  */
-  const char *ssa_token
-    = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-  token = new char [strlen (ssa_token) + 1];
-  strcpy (token, ssa_token);
+  *ver_offset = var_version - token;
+  for (const char *p = var_version + 1; *p; ++p)
+    if (! ISDIGIT (*p))
+      return false;
+  *version = atoi (var_version + 1);
+  return *version > 0;
+}
 
-  /* Separate var name and version.  */
-  var_version = strrchr (token, '_');
-  if (var_version)
-    {
-      var_name = new char[var_version - token + 1];
-      memcpy (var_name, token, var_version - token);
-      var_name[var_version - token] = '\0';
-      id = get_identifier (var_name);
+/* Get at the actual SSA name ID with VERSION starting at VER_OFFSET.
+   TYPE is the type if the SSA name is being declared.  */
 
-      /* lookup for parent decl.  */
-      if (lookup_name (id))
+static tree 
+c_parser_parse_ssa_name (c_parser *parser,
+                        tree id, tree type, unsigned version,
+                        unsigned ver_offset)
+{
+  tree name = NULL_TREE;
+  const char *token = IDENTIFIER_POINTER (id);
+
+  if (ver_offset == 0)
+    {
+      /* Anonymous unnamed SSA name.  */
+      if (version < num_ssa_names)
+       name = ssa_name (version);
+      if (! name)
        {
-         var_version++;
-         unsigned int version;
-         version = atoi (var_version);
-         if (var_version && version)
+         if (! type)
            {
-             ret.value = NULL_TREE;
-             if (version < num_ssa_names)
-               ret.value = ssa_name (version);
-             if (! ret.value)
-               ret.value = make_ssa_name_fn (cfun, lookup_name (id),
-                                             gimple_build_nop (), version);
-             c_parser_consume_token (parser);
+             c_parser_error (parser, "SSA name not declared"); 
+             return error_mark_node;
            }
+         name = make_ssa_name_fn (cfun, type, NULL, version);
        }
     }
-
-  /* For default definition SSA names.  */
-  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+  else
     {
-      c_parser_consume_token (parser);
-      ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-      if (! strcmp ("D", ssa_token))
+      if (version < num_ssa_names)
+       name = ssa_name (version);
+      if (! name)
        {
-         set_ssa_default_def (cfun, lookup_name (id), ret.value);
-         c_parser_consume_token (parser);
+         /* Separate var name from version.  */
+         char *var_name = XNEWVEC (char, ver_offset + 1);
+         memcpy (var_name, token, ver_offset);
+         var_name[ver_offset] = '\0';
+         /* lookup for parent decl.  */
+         id = get_identifier (var_name);
+         tree parent = lookup_name (id);
+         XDELETEVEC (var_name);
+         if (! parent)
+           {
+             c_parser_error (parser, "base variable or SSA name not 
declared"); 
+             return error_mark_node;
+           }
+         name = make_ssa_name_fn (cfun, parent,
+                                  gimple_build_nop (), version);
        }
-      if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
-       goto out;
     }
 
-  out:
-  free (var_name);
-  free (token);
-  return ret;
+  return name;
 }
 
 /* Parse gimple postfix expression.
@@ -756,8 +762,32 @@ c_parser_gimple_postfix_expression (c_parser *parser)
       if (c_parser_peek_token (parser)->id_kind == C_ID_ID)
        {
          tree id = c_parser_peek_token (parser)->value;
-         if (! lookup_name (id))
-           expr = c_parser_parse_ssa_names (parser);
+         unsigned version, ver_offset;
+         if (! lookup_name (id)
+             && c_parser_parse_ssa_name_id (id, &version, &ver_offset))
+           {
+             c_parser_consume_token (parser);
+             expr.value = c_parser_parse_ssa_name (parser, id, NULL_TREE,
+                                                   version, ver_offset);
+             /* For default definition SSA names.  */
+             if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+                 && c_parser_peek_2nd_token (parser)->type == CPP_NAME
+                 && strcmp ("D",
+                            IDENTIFIER_POINTER
+                              (c_parser_peek_2nd_token (parser)->value)) == 0
+                 && c_parser_peek_nth_token (parser, 3)->type == 
CPP_CLOSE_PAREN)
+               {
+                 c_parser_consume_token (parser);
+                 c_parser_consume_token (parser);
+                 c_parser_consume_token (parser);
+                 if (! SSA_NAME_IS_DEFAULT_DEF (expr.value))
+                   {
+                     set_ssa_default_def (cfun, SSA_NAME_VAR (expr.value),
+                                          expr.value);
+                     SSA_NAME_DEF_STMT (expr.value) = gimple_build_nop ();
+                   }
+               }
+           }
          else
            {
              c_parser_consume_token (parser);
@@ -1125,13 +1155,30 @@ c_parser_gimple_declaration (c_parser *parser)
 
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
-      tree postfix_attrs = NULL_TREE;
-      tree all_prefix_attrs = specs->attrs;
-      specs->attrs = NULL;
-      tree decl = start_decl (declarator, specs, false,
-                        chainon (postfix_attrs, all_prefix_attrs));
-      if (decl)
-       finish_decl (decl, UNKNOWN_LOCATION, NULL_TREE, NULL_TREE, NULL_TREE);
+      /* Handle SSA name decls specially, they do not go into the identifier
+         table but we simply build the SSA name for later lookup.  */
+      unsigned version, ver_offset;
+      if (declarator->kind == cdk_id
+         && is_gimple_reg_type (specs->type)
+         && c_parser_parse_ssa_name_id (declarator->u.id,
+                                        &version, &ver_offset)
+         /* The following restricts it to unnamed anonymous SSA names
+            which fails parsing of named ones in dumps (we could
+            decide to not dump their name for -gimple).  */
+         && ver_offset == 0)
+       c_parser_parse_ssa_name (parser, declarator->u.id, specs->type,
+                                version, ver_offset);
+      else
+       {
+         tree postfix_attrs = NULL_TREE;
+         tree all_prefix_attrs = specs->attrs;
+         specs->attrs = NULL;
+         tree decl = start_decl (declarator, specs, false,
+                                 chainon (postfix_attrs, all_prefix_attrs));
+         if (decl)
+           finish_decl (decl, UNKNOWN_LOCATION, NULL_TREE, NULL_TREE,
+                        NULL_TREE);
+       }
     }
   else
     {
diff --git a/gcc/testsuite/gcc.dg/gimplefe-17.c 
b/gcc/testsuite/gcc.dg/gimplefe-17.c
new file mode 100644
index 0000000..c5633ee
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-17.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -fdump-tree-ssa" } */
+
+int 
+__GIMPLE () *
+foo ()
+{
+  int _1;
+  int j;
+  int *b;
+  _1 = 1;
+bb1:
+  if (_1)
+    goto bb3;
+  else
+    goto bb2;
+
+bb2:
+  b_2 = (int *)0;
+
+bb3:
+  b_4 = __PHI (bb1: b_3(D), bb2: b_2);
+  return b_4;
+}
+
+/* { dg-final { scan-tree-dump-not "_1_" "ssa" } } */

Reply via email to