[PATCH][GIMPLE FE] Adjust __GIMPLE parsing

Richard Biener rguenther@suse.de
Fri Oct 28 08:09:00 GMT 2016


The following handles __GIMPLE as declspec which better follows other
similar handling.  It also reverts the C FE parts back to rely
on finish_function (that adjusts things like visibility - sth we'll
need in the end).  And it makes the __GIMPLE specs (currently only
startswith) optional.

Tested on x86_64-unknown-linux-gnu.

Given the similarity to attributes I'm not sure if we want to try
re-using the attribute list parsing as well as the storage during
declspec processing (I'd have to experiment with that).  At least
once we add more specs to __GIMPLE this might make things simpler.

Richard.

2016-10-28  Richard Biener  <rguenther@suse.de>

	c/
	* c-parser.c (c_parser_declaration_or_fndef): Move __GIMPLE
	parsing to declspecs parsing.  Rely on finish_function.
	(c_parser_declspecs): Handle RID_GIMPLE.
	* c-tree.h (enum c_declspec_word): Add cdw_gimple.
	(struct c_declspecs): Add gimple_pass member and gimple_p flag.
	* gimple-parser.c (c_parser_gimple_pass_list): Adjust interface,
	make specs optional and consume closing paren.
	* gimple-parser.h (c_parser_gimple_pass_list): Adjust.

	testsuite/
	* gcc.dg/gimplefe-1.c: Drop optional specs for __GIMPLE.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 413d8a7..2997c83 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -436,7 +436,7 @@ const struct c_common_resword c_common_reswords[] =
   { "__volatile",	RID_VOLATILE,	0 },
   { "__volatile__",	RID_VOLATILE,	0 },
   { "__GIMPLE",		RID_GIMPLE,	D_CONLY },
-  { "__PHI",		RID_PHI,	D_CONLY},
+  { "__PHI",		RID_PHI,	D_CONLY },
   { "alignas",		RID_ALIGNAS,	D_CXXONLY | D_CXX11 | D_CXXWARN },
   { "alignof",		RID_ALIGNOF,	D_CXXONLY | D_CXX11 | D_CXXWARN },
   { "asm",		RID_ASM,	D_ASM },
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 63385fc..d21b8e9 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -159,7 +159,7 @@ struct GTY(()) c_parser {
   /* The look-ahead tokens.  */
   c_token * GTY((skip)) tokens;
   /* Buffer for look-ahead tokens.  */
-  c_token GTY(()) tokens_buf[4];
+  c_token tokens_buf[4];
   /* How many look-ahead tokens are available (0 - 4, or
      more if parsing from pre-lexed tokens).  */
   unsigned int tokens_avail;
@@ -1563,8 +1563,6 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
   tree all_prefix_attrs;
   bool diagnosed_no_specs = false;
   location_t here = c_parser_peek_token (parser)->location;
-  bool gimple_body_p = false;
-  char *pass = NULL;
 
   if (static_assert_ok
       && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
@@ -1650,19 +1648,6 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       return;
     }
 
-  if (c_parser_next_token_is (parser, CPP_KEYWORD))
-    {
-      c_token *kw_token = c_parser_peek_token (parser);
-      if (kw_token->keyword == RID_GIMPLE)
-	{
-	  gimple_body_p = true;
-	  c_parser_consume_token (parser);
-	  c_parser_gimple_pass_list (parser, &pass);
-	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-				     "expected %<)%>");
-	}
-    }
-
   finish_declspecs (specs);
   bool auto_type_p = specs->typespec_word == cts_auto_type;
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
@@ -1793,7 +1778,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       struct c_declarator *declarator;
       bool dummy = false;
       timevar_id_t tv;
-      tree fnbody;
+      tree fnbody = NULL_TREE;
       /* Declaring either one or more declarators (in which case we
 	 should diagnose if there were no declaration specifiers) or a
 	 function definition (in which case the diagnostic for
@@ -2076,7 +2061,6 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	c_parser_declaration_or_fndef (parser, false, false, false,
 				       true, false, NULL, vNULL);
       store_parm_decls ();
-
       if (omp_declare_simd_clauses.exists ()
 	  || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
 	c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
@@ -2086,23 +2070,23 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
 	= c_parser_peek_token (parser)->location;
 
-      if (gimple_body_p && flag_gimple)
+      /* If the definition was marked with __GIMPLE then parse the
+         function body as GIMPLE.  */
+      if (specs->gimple_p)
 	{
-	  cfun->pass_startwith = pass;
+	  cfun->pass_startwith = specs->gimple_pass;
 	  bool saved = in_late_binary_op;
 	  in_late_binary_op = true;
 	  c_parser_parse_gimple_body (parser);
 	  in_late_binary_op = saved;
-	  cgraph_node::finalize_function (current_function_decl, false);
-	  set_cfun (NULL);
-	  current_function_decl = NULL;
-	  timevar_pop (tv);
-	  return;
 	}
-
-      fnbody = c_parser_compound_statement (parser);
-      if (flag_cilkplus && contains_array_notation_expr (fnbody))
-	fnbody = expand_array_notation_exprs (fnbody);
+      else
+	{
+	  fnbody = c_parser_compound_statement (parser);
+	  if (flag_cilkplus && contains_array_notation_expr (fnbody))
+	    fnbody = expand_array_notation_exprs (fnbody);
+	}
+      tree fndecl = current_function_decl;
       if (nested)
 	{
 	  tree decl = current_function_decl;
@@ -2118,9 +2102,13 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	}
       else
 	{
-	  add_stmt (fnbody);
+	  if (fnbody)
+	    add_stmt (fnbody);
 	  finish_function ();
 	}
+      /* Get rid of the empty stmt list for GIMPLE.  */
+      if (specs->gimple_p)
+	DECL_SAVED_TREE (fndecl) = NULL_TREE;
 
       timevar_pop (tv);
       break;
@@ -2608,6 +2596,14 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
 	  align = c_parser_alignas_specifier (parser);
 	  declspecs_add_alignas (loc, specs, align);
 	  break;
+	case RID_GIMPLE:
+	  if (! flag_gimple)
+	    error_at (loc, "%<__GIMPLE%> only valid with -fgimple");
+	  c_parser_consume_token (parser);
+	  specs->gimple_p = true;
+	  specs->locations[cdw_gimple] = loc;
+	  specs->gimple_pass = c_parser_gimple_pass_list (parser);
+	  break;
 	default:
 	  goto out;
 	}
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index e8060f8..a8cf353 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -267,6 +267,7 @@ enum c_declspec_word {
   cdw_saturating,
   cdw_alignas,
   cdw_address_space,
+  cdw_gimple,
   cdw_number_of_elements /* This one must always be the last
 			    enumerator.  */
 };
@@ -290,6 +291,8 @@ struct c_declspecs {
      NULL; attributes (possibly from multiple lists) will be passed
      separately.  */
   tree attrs;
+  /* The pass to start compiling a __GIMPLE function with.  */
+  char *gimple_pass;
   /* The base-2 log of the greatest alignment required by an _Alignas
      specifier, in bytes, or -1 if no such specifiers with nonzero
      alignment.  */
@@ -362,6 +365,8 @@ struct c_declspecs {
   /* Whether any alignment specifier (even with zero alignment) was
      specified.  */
   BOOL_BITFIELD alignas_p : 1;
+  /* Whether any __GIMPLE specifier was specified.  */
+  BOOL_BITFIELD gimple_p : 1;
   /* The address space that the declaration belongs to.  */
   addr_space_t address_space;
 };
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 7040071..392f6b0 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -1046,14 +1046,15 @@ c_parser_gimple_label (c_parser *parser, gimple_seq *seq)
      startwith("pass-name")
  */
 
-void
-c_parser_gimple_pass_list (c_parser *parser, char **pass)
+char *
+c_parser_gimple_pass_list (c_parser *parser)
 {
-  if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    return;
+  char *pass = NULL;
 
-  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-    return;
+  /* Accept __GIMPLE.  */
+  if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
+    return NULL;
+  c_parser_consume_token (parser);
 
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
@@ -1062,33 +1063,31 @@ c_parser_gimple_pass_list (c_parser *parser, char **pass)
       if (! strcmp (op, "startwith"))
 	{
 	  if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-	    return;
+	    return NULL;
 	  if (c_parser_next_token_is_not (parser, CPP_STRING))
 	    {
 	      error_at (c_parser_peek_token (parser)->location,
 			"expected pass name");
-	      return;
+	      return NULL;
 	    }
-	  *pass = xstrdup (TREE_STRING_POINTER
+	  pass = xstrdup (TREE_STRING_POINTER
 				(c_parser_peek_token (parser)->value));
 	  c_parser_consume_token (parser);
 	  if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
-	    return;
+	    return NULL;
 	}
       else
 	{
 	  error_at (c_parser_peek_token (parser)->location,
 		    "invalid operation");
-	  return;
+	  return NULL;
 	}
     }
-  else if (c_parser_next_token_is (parser, CPP_EOF))
-    {
-      c_parser_error (parser, "expected parameters");
-      return;
-    }
 
-  return;
+  if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+    return NULL;
+
+  return pass;
 }
 
 /* Parse gimple local declaration.
diff --git a/gcc/c/gimple-parser.h b/gcc/c/gimple-parser.h
index 860695b..f72b626 100644
--- a/gcc/c/gimple-parser.h
+++ b/gcc/c/gimple-parser.h
@@ -22,6 +22,6 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Gimple parsing functions.  */
 extern void c_parser_parse_gimple_body (c_parser *);
-extern void c_parser_gimple_pass_list (c_parser *, char **);
+extern char *c_parser_gimple_pass_list (c_parser *);
 
 #endif
diff --git a/gcc/testsuite/gcc.dg/gimplefe-1.c b/gcc/testsuite/gcc.dg/gimplefe-1.c
index 0786d47..a81ed1f 100644
--- a/gcc/testsuite/gcc.dg/gimplefe-1.c
+++ b/gcc/testsuite/gcc.dg/gimplefe-1.c
@@ -2,7 +2,7 @@
 /* { dg-options "-fgimple" } */
 
 int i;
-void __GIMPLE () foo()
+void __GIMPLE foo()
 {
   i = 1;
 }



More information about the Gcc-patches mailing list