public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] [gsoc] [gimplefe] GIMPLE FE Project
@ 2016-08-21 17:05 Prasad Ghangal
  2016-08-22 11:17 ` Trevor Saunders
  0 siblings, 1 reply; 24+ messages in thread
From: Prasad Ghangal @ 2016-08-21 17:05 UTC (permalink / raw)
  To: gcc-patches, Richard Biener

[-- Attachment #1: Type: text/plain, Size: 1002 bytes --]

Hi all,

As a part of my gsoc project. I have completed the following tasks:

* Parsed gimple-expression
* Parsed gimple-labels
* Parsed local declaration
* Parsed gimple-goto statement
* Parsed gimple-if-else statement
* Parsed gimple-switch statement
* Parsed gimple-return statement
* Parsed gimple-PHI function
* Parsed gimple ssa-names along with default def
* Parsed gimple-call

* Hacked pass manager to add support for startwith (pass-name) to skip
early opt passes
* Modified gimple dump for making it parsable

I am willing to continue work on the project, some TODOs for the projects are:

* Error handling
* Parse more gimple syntax
* Add startwith support for IPA passes

The complete code of gimple fe project can be found at
https://github.com/PrasadG193/gcc_gimple_fe


PFA patch for complete project (rebased for latest trunk revision).
I have successfully bootstrapped and tested on x86_64-pc-linux-gnu.
Some testcases failed due to modified gimple dump as expected.


Thanks,
Prasad

[-- Attachment #2: ChangeLog.patch --]
[-- Type: application/octet-stream, Size: 5458 bytes --]

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1929ba8..cded23f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,55 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+	
+	* cgraphunit.c (cgraph_node::assemble_thunks_and_aliases): New variable.
+	(cgraph_node::expand): Add new argument to function.
+	execute_pass_list, guard gcc_assert (TREE_ASM_WRITTEN (decl)) with 
+	condition.
+	* coretypes.h (tree_node *const_tree): New decl, add headers, new
+	variables.
+	* function.h (struct GTY()) function): Add new member to store
+	startwith pass also add new member as a flag.
+	* gimple-pretty-print.c (dump_gimple_switch): Change dumping formats.
+	(dump_gimple_label): Remove condition for DECL_NONLOCAL, flags & 
+	TDF_EH, EH_LANDING_PAD_NR. Change dumping format.
+	(dump_ssaname_info_to_file): Change passing arguments of dump_gimple_phi
+	(dump_gimple_phi): Remove condition for comment, change format of
+	dumping PHI and PHI arguments.
+	(pp_gimple_stmt_1): Remove argument of dump_gimple_phi function.
+	(dump_gimple_bb_header): Change format of dumping gimple basic block
+	header.
+	(dump_phi_nodes): Remove argument of dump_gimple_phi function.
+	(pp_cfg_jump): Remove stmt, remove condition for GIMPLE_LABEL, change 
+	dumping format of gimple basic block header.
+	(gimple_dump_bb_for_graph): Change format of dumping gimple basic block
+	* gimplify.c (gimplify_function_tree): Add condition for presence of
+	gimple body in the cfun.
+	* internal-fn.c (expand_PHI): New function.
+	* internal-fn.h (expand_PHI): Declared here.
+	* internal-fn.def: New defination for PHI.
+	* passes.c (do_per_function_toporder): Add new argument flag, add new
+	argument in callback function call.
+	(execute_one_pass): Add new function argument, add condition for 
+	skipping passes until startwith pass.
+	(execute_pass_list_1): Add new function argument, add condition to 
+	check starwith flag.
+	(execute_ipa_pass_list): New variable, add condition to check and skip
+	passes for startwith pass, pass new argument to function 
+	do_per_function_toporder.
+	* tree-pass.h (execute_one_pass): Add new argument to the function.
+	(execute_pass_list): Likewise.
+	* tree-cfg.c (lower_phi_internal_fn): New function.
+	(verify_gimple_call): Condition for passing label as arg in internal
+	function PHI.
+	(dump_function_to_file): Change format of gimple dump.
+	* tree-into-ssa.c (rewrite_add_phi_arguments): New variable, add 
+	condition for avoiding ssa name versions.
+	* tree-pretty-print.c (dump_decl_name): Change format of dumping gimple
+	labels.
+	(dump_function_header): Change format of gimple dump header
+	* tree-ssanames.c (make_ssa_name_fn): New argument, check for version
+	and assign proper version for parsed ssa names.
+	* tree-ssanames.h (make_ssa_name_fn): Add new argument to the function.
+
 2016-08-20  Kugan Vivekanandarajah  <kuganv@linaro.org>
 
 	* Makefile.in: Add tree-vrp.h to GTFILES.
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index bec37cf..a8c0ab1 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+	
+	* c-common.h (c_common_resword): Add RID_GIMPLE, RID_PHI types.
+	* c-common.h (enum rid): Add RID_GIMPLE, RID_PHI.
+	* c.opt (fgimple): New option.
+
 2016-08-19  Joseph Myers  <joseph@codesourcery.com>
 
 	PR c/32187
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 8d9d4aa..71e78f3 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,29 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+	
+	* c_parser.c: Add headers.
+	(c_parser_parse_gimple_body): New function.
+	(c_parser_gimple_compound_statement): Likewise.
+	(c_parser_gimple_label): Likewise.
+	(c_parser_gimple_expression): Likewise
+	(c_parser_gimple_binary_expression): Likewise.
+	(c_parser_gimple_unary_expression): Likewise.
+	(c_parser_gimple_postfix_expression): Likewise.
+	(c_parser_gimple_postfix_expression_after_primary): Likewise.
+	(c_parser_gimple_pass_list): Likewise.
+	(c_parser_gimple_pass_list_params): Likewise.
+	(c_parser_gimple_declaration): Likewise.
+	(c_parser_gimple_goto_stmt): Likewise.
+	(c_parser_gimple_if_stmt): Likewise.
+	(c_parser_gimple_switch_stmt): Likewise.
+	(c_parser_gimple_return_stmt): Likewise.
+	(c_finish_gimple_return): Likewise.
+	(c_parser_parse_ssa_names): Likewise.
+	(c_parser_gimple_paren_condition): Likewise.
+	(c_parser_gimple_expr_list): Likewise.
+	(c_parser_declaration_or_fndef): New decls. Call function.
+	c_parser_gimple_pass_list, set startwith passes, call
+	c_parser_parse_gimple_body.
+
 2016-08-19  Joseph Myers  <joseph@codesourcery.com>
 
 	PR c/32187
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6201e0c..3da6354 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,19 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+
+	* gcc.dg/gimplefe-1.c: New testcase.
+	* gcc.dg/gimplefe-2.c: Likewise.
+	* gcc.dg/gimplefe-3.c: Likewise.
+	* gcc.dg/gimplefe-4.c: Likewise.
+	* gcc.dg/gimplefe-5.c: Likewise.
+	* gcc.dg/gimplefe-6.c: Likewise.
+	* gcc.dg/gimplefe-7.c: Likewise.
+	* gcc.dg/gimplefe-8.c: Likewise.
+	* gcc.dg/gimplefe-9.c: Likewise.
+	* gcc.dg/gimplefe-10.c: Likewise.
+	* gcc.dg/gimplefe-11.c: Likewise.
+	* gcc.dg/gimplefe-12.c: Likewise.
+	* gcc.dg/gimplefe-13.c: Likewise.
+
 2016-08-20  Kugan Vivekanandarajah  <kuganv@linaro.org>
 
 	PR tree-optimization/61839


[-- Attachment #3: gimplefe.patch --]
[-- Type: application/octet-stream, Size: 72061 bytes --]

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 32468ca..5b43016 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -522,6 +522,8 @@ const struct c_common_resword c_common_reswords[] =
   { "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY },
   { "__volatile",	RID_VOLATILE,	0 },
   { "__volatile__",	RID_VOLATILE,	0 },
+  { "__GIMPLE",		RID_GIMPLE,	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-family/c-common.h b/gcc/c-family/c-common.h
index bc22baa..17dc91e 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -118,6 +118,12 @@ enum rid
 
   RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN,
 
+  /* "__GIMPLE", for the GIMPLE-parsing extension to the C frontend. */
+  RID_GIMPLE,
+
+  /* "__PHI", for parsing PHI function in GIMPLE FE.  */
+  RID_PHI,
+
   /* C11 */
   RID_ALIGNAS, RID_GENERIC,
 
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index a5358ed..3c4d2cc 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -200,6 +200,10 @@ F
 Driver C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -F <dir>	Add <dir> to the end of the main framework include path.
 
+fgimple
+C Var(flag_gimple) Init(0)
+Enable parsing GIMPLE
+
 H
 C ObjC C++ ObjC++
 Print the name of header files as they are used.
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index fe0c95f..56c641e 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -59,6 +59,18 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-expr.h"
 #include "context.h"
 #include "gcc-rich-location.h"
+#include "tree-vrp.h"
+#include "tree-pass.h"
+#include "tree-pretty-print.h"
+#include "tree.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-pretty-print.h"
+#include "tree-ssa.h"
+#include "pass_manager.h"
+#include "tree-ssanames.h"
+#include "gimple-ssa.h"
+#include "tree-dfa.h"
 
 /* We need to walk over decls with incomplete struct/union/enum types
    after parsing the whole translation unit.
@@ -1416,6 +1428,29 @@ static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context);
 static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
 static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool);
 static void c_parser_cilk_grainsize (c_parser *, bool *);
+static void c_parser_parse_gimple_body (c_parser *);
+static bool c_parser_gimple_compound_statement (c_parser *, gimple_seq *);
+static void c_parser_gimple_label (c_parser *, gimple_seq *);
+static void c_parser_gimple_expression (c_parser *, gimple_seq *);
+static struct c_expr c_parser_gimple_binary_expression (c_parser *, enum tree_code *);
+static struct c_expr c_parser_gimple_unary_expression (c_parser *);
+static struct c_expr c_parser_gimple_postfix_expression (c_parser *);
+static struct c_expr c_parser_gimple_postfix_expression_after_primary (c_parser *,
+								       location_t,
+								       struct c_expr);
+static void c_parser_gimple_pass_list (c_parser *, opt_pass **, bool *);
+static opt_pass *c_parser_gimple_pass_list_params (c_parser *, opt_pass **);
+static void c_parser_gimple_declaration (c_parser *);
+static void c_parser_gimple_goto_stmt (location_t, tree, gimple_seq *);
+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 *, bool,
+		    vec<tree, va_gc> **, location_t *, tree *,
+		    vec<location_t> *, unsigned int *);
 
 /* Parse a translation unit (C90 6.7, C99 6.9).
 
@@ -1659,6 +1694,9 @@ 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;
+  opt_pass *pass = NULL;
+  bool startwith_p = false;
 
   if (static_assert_ok
       && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
@@ -1743,6 +1781,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       c_parser_skip_to_end_of_block_or_statement (parser);
       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, &startwith_p);
+	  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))
@@ -2144,6 +2196,13 @@ 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 (pass)
+	{
+	  cfun->pass_startwith = pass;
+	  cfun->startwith = startwith_p;
+	}
+
       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,
@@ -2152,6 +2211,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
 	= c_parser_peek_token (parser)->location;
+
+      if (gimple_body_p && flag_gimple)
+	{
+	  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);
@@ -18194,4 +18267,1532 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
   return value_tree;
 }
 
+/* Parse the body of a function declaration marked with "__GIMPLE".  */
+
+void
+c_parser_parse_gimple_body (c_parser *parser)
+{
+  bool return_p = false;
+  gimple_seq seq;
+  gimple_seq body;
+  tree stmt = push_stmt_list ();
+  push_scope ();
+  location_t loc1 = c_parser_peek_token (parser)->location;
+  seq = NULL;
+  body = NULL;
+  init_tree_ssa (cfun);
+  return_p = c_parser_gimple_compound_statement (parser, &seq);
+
+  if (!return_p)
+    {
+      gimple *ret;
+      ret = gimple_build_return (NULL);
+      gimple_seq_add_stmt (&seq, ret);
+    }
+
+  tree block = NULL;
+  block = pop_scope ();
+  stmt = pop_stmt_list (stmt);
+  stmt = c_build_bind_expr (loc1, block, stmt);
+
+  block = DECL_INITIAL (current_function_decl);
+  BLOCK_SUBBLOCKS (block) = NULL_TREE;
+  BLOCK_CHAIN (block) = NULL_TREE;
+  TREE_ASM_WRITTEN (block) = 1;
+
+  gbind *bind_stmt = gimple_build_bind (BIND_EXPR_VARS (stmt), NULL,
+					BIND_EXPR_BLOCK (stmt));
+  gimple_bind_set_body (bind_stmt, seq);
+  gimple_seq_add_stmt (&body, bind_stmt);
+  gimple_set_body (current_function_decl, body);
+  cfun->curr_properties = PROP_gimple_any;
+
+  return;
+}
+
+/* Parse a compound statement in gimple function body.
+
+   gimple-statement:
+     gimple-statement
+     gimple-declaration-statement
+     gimple-if-statement
+     gimple-switch-statement
+     gimple-labeled-statement
+     gimple-expression-statement
+     gimple-goto-statement
+     gimple-phi-statement
+     gimple-return-statement
+*/
+
+static bool
+c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
+{
+  bool return_p = false;
+
+  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+      return return_p;
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      c_parser_consume_token (parser);
+      goto out;
+    }
+
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      c_parser_error (parser, "expected declaration or statement");
+      c_parser_consume_token (parser);
+      goto out;
+    }
+
+  while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+    {
+
+      if (parser->error)
+	{
+	  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
+	  goto out;
+	}
+
+      if (c_parser_next_token_is (parser, CPP_NAME)
+	  && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+	  c_parser_gimple_label (parser, seq);
+
+      else if (c_parser_next_tokens_start_declaration (parser))
+	  c_parser_gimple_declaration (parser);
+
+      else if (c_parser_next_token_is (parser, CPP_EOF))
+	{
+	  c_parser_error (parser, "expected declaration or statement");
+	  goto out;
+	}
+
+      else
+	{
+	  switch (c_parser_peek_token (parser)->type)
+	    {
+	    case CPP_KEYWORD:
+	      switch (c_parser_peek_token (parser)->keyword)
+		{
+		case RID_IF:
+		  c_parser_gimple_if_stmt (parser, seq);
+		  break;
+		case RID_SWITCH:
+		  c_parser_gimple_switch_stmt (parser, seq);
+		  break;
+		case RID_GOTO:
+		    {
+		      location_t loc = c_parser_peek_token (parser)->location;
+		      c_parser_consume_token (parser);
+		      if (c_parser_next_token_is (parser, CPP_NAME))
+			{
+			  c_parser_gimple_goto_stmt (loc,
+						     c_parser_peek_token (parser)->value,
+						     seq);
+			  c_parser_consume_token (parser);
+			  if (!c_parser_require (parser, CPP_SEMICOLON,
+						 "expected %<;%>"))
+			    goto out;
+			}
+		    }
+		  break;
+		case RID_RETURN:
+		  return_p = true;
+		  c_parser_gimple_return_stmt (parser, seq);
+		  if (!c_parser_require (parser, CPP_SEMICOLON,
+					 "expected %<;%>"))
+		    goto out;
+		  break;
+		default:
+		  goto expr_stmt;
+		}
+	      break;
+	    case CPP_SEMICOLON:
+	      c_parser_consume_token (parser);
+	      break;
+	    default:
+	    expr_stmt:
+	      c_parser_gimple_expression (parser, seq);
+	      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+		goto out;
+	    }
+	}
+    }
+  c_parser_consume_token (parser);
+
+  out:
+  return return_p;
+}
+
+/* Parse a gimple expression.
+
+   gimple-expression:
+     gimple-unary-expression
+     gimple-call-statement
+     gimple-binary-expression
+     gimple-assign-expression
+     gimple-cast-expression
+
+*/
+
+static void
+c_parser_gimple_expression (c_parser *parser, gimple_seq *seq)
+{
+  c_expr lhs, rhs;
+  gimple *assign;
+  enum tree_code subcode = NOP_EXPR;
+  tree save_expr;
+  location_t loc, exp_location;
+
+  lhs = c_parser_gimple_unary_expression (parser);
+
+  if (c_parser_next_token_is (parser, CPP_EQ))
+    {
+      c_parser_consume_token (parser);
+    }
+
+  loc = EXPR_LOCATION (lhs.value);
+
+  /* gimple call expression. */
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON) &&
+      TREE_CODE (lhs.value) == CALL_EXPR)
+    {
+      gimple *call;
+      call = gimple_build_call_from_tree (lhs.value);
+      gimple_seq_add_stmt (seq, call);
+      gimple_set_location (call, loc);
+      return;
+    }
+
+  /* cast expression.  */
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+    {
+      rhs = c_parser_cast_expression (parser, NULL);	  //TODO: have a gimple_cast_expr function
+      if (lhs.value != error_mark_node &&
+	  rhs.value != error_mark_node)
+	{
+	  assign = gimple_build_assign (lhs.value, rhs.value);
+	  gimple_seq_add_stmt (seq, assign);
+	  gimple_set_location (assign, loc);
+	  return;
+	}
+    }
+
+  if (POINTER_TYPE_P (TREE_TYPE (lhs.value)))
+    {
+      STRIP_USELESS_TYPE_CONVERSION (rhs.value);
+      if (!useless_type_conversion_p (TREE_TYPE (lhs.value),
+				      TREE_TYPE (rhs.value)))
+	rhs.value = fold_convert_loc (loc, TREE_TYPE (lhs.value), rhs.value);
+    }
+
+  /* pointer expression.  */
+  if (TREE_CODE (lhs.value) == INDIRECT_REF)
+    {
+      save_expr = lhs.value;
+      bool volatilep = TREE_THIS_VOLATILE (lhs.value);
+      bool notrap = TREE_THIS_NOTRAP (lhs.value);
+      tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (lhs.value, 0));
+
+      lhs.value = fold_indirect_ref_loc (loc, lhs.value);
+      if (lhs.value == save_expr)
+	{
+	  lhs.value = fold_build2_loc (input_location, MEM_REF,
+				       TREE_TYPE (lhs.value),
+				       TREE_OPERAND (lhs.value, 0),
+				       build_int_cst (saved_ptr_type, 0));
+	  TREE_THIS_VOLATILE (lhs.value) = volatilep;
+	  TREE_THIS_NOTRAP (lhs.value) = notrap;
+	}
+    }
+
+  if (c_parser_next_token_is (parser, CPP_AND) ||
+      c_parser_next_token_is (parser, CPP_MULT) ||
+      c_parser_next_token_is (parser, CPP_PLUS) ||
+      c_parser_next_token_is (parser, CPP_MINUS) ||
+      c_parser_next_token_is (parser, CPP_COMPL) ||
+      c_parser_next_token_is (parser, CPP_NOT))
+    {
+      rhs = c_parser_gimple_unary_expression (parser);
+      assign = gimple_build_assign (lhs.value, rhs.value);
+      gimple_set_location (assign, loc);
+      gimple_seq_add_stmt (seq, assign);
+      return;
+    }
+
+  /* gimple PHI expression.  */
+  if (c_parser_next_token_is_keyword (parser, RID_PHI))
+    {
+      c_parser_consume_token (parser);
+
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+	{
+	  return;
+	}
+
+      gcall *call_stmt;
+      tree arg = NULL_TREE;
+      vec<tree> vargs = vNULL;
+
+      if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+	c_parser_consume_token (parser);
+
+      while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+	{
+	  if (c_parser_next_token_is (parser, CPP_NAME) &&
+	      c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+	    {
+	      arg = lookup_label_for_goto (loc,
+					   c_parser_peek_token (parser)->value);
+	      c_parser_consume_token (parser);
+
+	      if (c_parser_next_token_is (parser, CPP_COLON))
+		c_parser_consume_token (parser);
+	      vargs.safe_push (arg);
+	    }
+	  else if (c_parser_next_token_is (parser, CPP_COMMA))
+	    {
+	      c_parser_consume_token (parser);
+	    }
+	  else
+	    {
+	      arg = c_parser_parse_ssa_names (parser).value;
+	      vargs.safe_push (arg);
+	    }
+	}
+
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+				 "expected %<)%>");
+
+      /* build internal function for PHI. */
+      call_stmt = gimple_build_call_internal_vec (IFN_PHI, vargs);
+      gimple_call_set_lhs (call_stmt, lhs.value);
+      gimple_set_location (call_stmt, UNKNOWN_LOCATION);
+      gimple_seq_add_stmt (seq, call_stmt);
+      return;
+    }
+
+  /* gimple call with lhs. */
+  if (c_parser_next_token_is (parser, CPP_NAME) &&
+      c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN &&
+      lookup_name (c_parser_peek_token (parser)->value))
+    {
+      gimple *call;
+      rhs = c_parser_gimple_unary_expression (parser);
+      call = gimple_build_call_from_tree (rhs.value);
+      gimple_call_set_lhs (call, lhs.value);
+      gimple_seq_add_stmt (seq, call);
+      gimple_set_location (call, loc);
+      return;
+    }
+
+  exp_location = c_parser_peek_token (parser)->location;
+  rhs = c_parser_gimple_binary_expression (parser, &subcode);
+  rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true);
+
+  if (lhs.value != error_mark_node &&
+      rhs.value != error_mark_node)
+    {
+      if (subcode == NOP_EXPR)
+	assign = gimple_build_assign (lhs.value, rhs.value);
+      else
+	assign = gimple_build_assign (lhs.value, subcode,
+				      TREE_OPERAND (rhs.value, 0),
+				      TREE_OPERAND (rhs.value, 1));
+      gimple_seq_add_stmt (seq, assign);
+      gimple_set_location (assign, loc);
+    }
+  return;
+}
+
+/* Parse gimple binary expr.
+
+   gimple-multiplicative-expression:
+     gimple-unary-expression * gimple-unary-expression
+     gimple-unary-expression / gimple-unary-expression
+     gimple-unary-expression % gimple-unary-expression
+
+   gimple-additive-expression:
+     gimple-unary-expression + gimple-unary-expression
+     gimple-unary-expression - gimple-unary-expression
+
+   gimple-shift-expression:
+     gimple-unary-expression << gimple-unary-expression
+     gimple-unary-expression >> gimple-unary-expression
+
+   gimple-relational-expression:
+     gimple-unary-expression < gimple-unary-expression
+     gimple-unary-expression > gimple-unary-expression
+     gimple-unary-expression <= gimple-unary-expression
+     gimple-unary-expression >= gimple-unary-expression
+
+   gimple-equality-expression:
+     gimple-unary-expression == gimple-unary-expression
+     gimple-unary-expression != gimple-unary-expression
+
+   gimple-AND-expression:
+     gimple-unary-expression & gimple-unary-expression
+
+   gimple-exclusive-OR-expression:
+     gimple-unary-expression ^ gimple-unary-expression
+
+   gimple-inclusive-OR-expression:
+     gimple-unary-expression | gimple-unary-expression
+
+   gimple-logical-AND-expression:
+     gimple-unary-expression && gimple-unary-expression
+
+   gimple-logical-OR-expression:
+     gimple-unary-expression || gimple-unary-expression
+
+*/
+
+static c_expr
+c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)
+{
+  tree omp_atomic_lhs = NULL;
+  struct {
+    /* The expression at this stack level.  */
+    struct c_expr expr;
+    /* The precedence of the operator on its left, PREC_NONE at the
+       bottom of the stack.  */
+    enum c_parser_prec prec;
+    /* The operation on its left.  */
+    enum tree_code op;
+    /* The source location of this operation.  */
+    location_t loc;
+  } stack[2];
+  int sp;
+  /* Location of the binary operator.  */
+  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
+#define POP								      \
+  do {									      \
+    switch (stack[sp].op)						      \
+      {									      \
+      case TRUTH_ANDIF_EXPR:						      \
+	c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value	      \
+					  == truthvalue_false_node);	      \
+	break;								      \
+      case TRUTH_ORIF_EXPR:						      \
+	c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value	      \
+					  == truthvalue_true_node);	      \
+	break;								      \
+      default:								      \
+	break;								      \
+      }									      \
+    stack[sp - 1].expr							      \
+      = convert_lvalue_to_rvalue (stack[sp - 1].loc,			      \
+				  stack[sp - 1].expr, true, true);	      \
+    stack[sp].expr							      \
+      = convert_lvalue_to_rvalue (stack[sp].loc,			      \
+				  stack[sp].expr, true, true);		      \
+    if (__builtin_expect (omp_atomic_lhs != NULL_TREE, 0) && sp == 1	      \
+	&& c_parser_peek_token (parser)->type == CPP_SEMICOLON		      \
+	&& ((1 << stack[sp].prec)					      \
+	    & ((1 << PREC_BITOR) | (1 << PREC_BITXOR) | (1 << PREC_BITAND)    \
+	       | (1 << PREC_SHIFT) | (1 << PREC_ADD) | (1 << PREC_MULT)))     \
+	&& stack[sp].op != TRUNC_MOD_EXPR				      \
+	&& stack[0].expr.value != error_mark_node			      \
+	&& stack[1].expr.value != error_mark_node			      \
+	&& (c_tree_equal (stack[0].expr.value, omp_atomic_lhs)		      \
+	    || c_tree_equal (stack[1].expr.value, omp_atomic_lhs)))	      \
+      stack[0].expr.value						      \
+	= build2 (stack[1].op, TREE_TYPE (stack[0].expr.value),		      \
+		  stack[0].expr.value, stack[1].expr.value);		      \
+    else								      \
+      stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,	      \
+						   stack[sp].op,	      \
+						   stack[sp - 1].expr,	      \
+						   stack[sp].expr);	      \
+    sp--;								      \
+  } while (0)
+  stack[0].loc = c_parser_peek_token (parser)->location;
+  stack[0].expr = c_parser_gimple_unary_expression (parser);
+  stack[0].prec = PREC_NONE;
+  sp = 0;
+  enum c_parser_prec oprec;
+  source_range src_range;
+  if (parser->error)
+    goto out;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_MULT:
+      oprec = PREC_MULT;
+      *subcode = MULT_EXPR;
+      break;
+    case CPP_DIV:
+      oprec = PREC_MULT;
+      *subcode = TRUNC_DIV_EXPR;
+      break;
+    case CPP_MOD:
+      oprec = PREC_MULT;
+      *subcode = TRUNC_MOD_EXPR;
+      break;
+    case CPP_PLUS:
+      oprec = PREC_ADD;
+      *subcode = PLUS_EXPR;
+      break;
+    case CPP_MINUS:
+      oprec = PREC_ADD;
+      *subcode = MINUS_EXPR;
+      break;
+    case CPP_LSHIFT:
+      oprec = PREC_SHIFT;
+      *subcode = LSHIFT_EXPR;
+      break;
+    case CPP_RSHIFT:
+      oprec = PREC_SHIFT;
+      *subcode = RSHIFT_EXPR;
+      break;
+    case CPP_LESS:
+      oprec = PREC_REL;
+      *subcode = LT_EXPR;
+      break;
+    case CPP_GREATER:
+      oprec = PREC_REL;
+      *subcode = GT_EXPR;
+      break;
+    case CPP_LESS_EQ:
+      oprec = PREC_REL;
+      *subcode = LE_EXPR;
+      break;
+    case CPP_GREATER_EQ:
+      oprec = PREC_REL;
+      *subcode = GE_EXPR;
+      break;
+    case CPP_EQ_EQ:
+      oprec = PREC_EQ;
+      *subcode = EQ_EXPR;
+      break;
+    case CPP_NOT_EQ:
+      oprec = PREC_EQ;
+      *subcode = NE_EXPR;
+      break;
+    case CPP_AND:
+      oprec = PREC_BITAND;
+      *subcode = BIT_AND_EXPR;
+      break;
+    case CPP_XOR:
+      oprec = PREC_BITXOR;
+      *subcode = BIT_XOR_EXPR;
+      break;
+    case CPP_OR:
+      oprec = PREC_BITOR;
+      *subcode = BIT_IOR_EXPR;
+      break;
+    case CPP_AND_AND:
+      oprec = PREC_LOGAND;
+      *subcode = TRUTH_ANDIF_EXPR;
+      break;
+    case CPP_OR_OR:
+      oprec = PREC_LOGOR;
+      *subcode = TRUTH_ORIF_EXPR;
+      break;
+    default:
+      /* Not a binary operator, so end of the binary
+	 expression.  */
+      *subcode = NOP_EXPR;
+      goto out;
+    }
+  binary_loc = c_parser_peek_token (parser)->location;
+  while (oprec <= stack[sp].prec)
+    POP;
+  c_parser_consume_token (parser);
+  switch (*subcode)
+    {
+    case TRUTH_ANDIF_EXPR:
+      src_range = stack[sp].expr.src_range;
+      stack[sp].expr
+	= convert_lvalue_to_rvalue (stack[sp].loc,
+				    stack[sp].expr, true, true);
+      stack[sp].expr.value = c_objc_common_truthvalue_conversion
+	(stack[sp].loc, default_conversion (stack[sp].expr.value));
+      c_inhibit_evaluation_warnings += (stack[sp].expr.value
+					== truthvalue_false_node);
+      set_c_expr_source_range (&stack[sp].expr, src_range);
+      break;
+    case TRUTH_ORIF_EXPR:
+      src_range = stack[sp].expr.src_range;
+      stack[sp].expr
+	= convert_lvalue_to_rvalue (stack[sp].loc,
+				    stack[sp].expr, true, true);
+      stack[sp].expr.value = c_objc_common_truthvalue_conversion
+	(stack[sp].loc, default_conversion (stack[sp].expr.value));
+      c_inhibit_evaluation_warnings += (stack[sp].expr.value
+					== truthvalue_true_node);
+      set_c_expr_source_range (&stack[sp].expr, src_range);
+      break;
+    default:
+      break;
+    }
+  sp++;
+  stack[sp].loc = binary_loc;
+  stack[sp].expr = c_parser_gimple_unary_expression (parser);
+  stack[sp].prec = oprec;
+  stack[sp].op = *subcode;
+out:
+  while (sp > 0)
+    POP;
+  return stack[0].expr;
+#undef POP
+
+}
+
+/* Parse gimple unary expression.
+
+   gimple-unary-expression:
+     gimple-postfix-expression
+     unary-operator cast-expression
+
+   unary-operator: one of
+     & * + - ~ !
+*/
+
+static c_expr
+c_parser_gimple_unary_expression (c_parser *parser)
+{
+  struct c_expr ret, op;
+  if (c_parser_peek_token (parser)->value
+      && TREE_CODE (c_parser_peek_token (parser)->value) == IDENTIFIER_NODE
+      && !lookup_name (c_parser_peek_token (parser)->value))
+    return c_parser_parse_ssa_names (parser);
+
+  location_t op_loc = c_parser_peek_token (parser)->location;
+  location_t exp_loc;
+  location_t finish;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_AND:
+      c_parser_consume_token (parser);
+      op = c_parser_cast_expression (parser, NULL);
+      mark_exp_read (op.value);
+      return parser_build_unary_op (op_loc, ADDR_EXPR, op);
+    case CPP_MULT:
+      {
+	c_parser_consume_token (parser);
+	exp_loc = c_parser_peek_token (parser)->location;
+	op = c_parser_cast_expression (parser, NULL);
+	finish = op.get_finish ();
+	op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
+	location_t combined_loc = make_location (op_loc, op_loc, finish);
+	ret.value = build_indirect_ref (combined_loc, op.value,
+					RO_UNARY_STAR);
+	ret.src_range.m_start = op_loc;
+	ret.src_range.m_finish = finish;
+	return ret;
+      }
+    case CPP_PLUS:
+      if (!c_dialect_objc () && !in_system_header_at (input_location))
+	warning_at (op_loc,
+		    OPT_Wtraditional,
+		    "traditional C rejects the unary plus operator");
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
+      return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
+    case CPP_MINUS:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
+      return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
+    case CPP_COMPL:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
+      return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
+    case CPP_NOT:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
+      return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
+    default:
+      return c_parser_gimple_postfix_expression (parser);
+    }
+}
+
+/* Parse gimple ssa names.  */
+
+static c_expr
+c_parser_parse_ssa_names (c_parser *parser)
+{
+  tree id = NULL_TREE;
+  c_expr ret;
+  char *var_name, *var_version, *token;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
+
+  /* ssa token string.  */
+  const char *ssa_token = NULL;
+  ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+  token = new char [strlen (ssa_token)];
+  strcpy (token, ssa_token);
+
+  /* seperate 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);
+
+      /* lookup for parent decl.  */
+      if (lookup_name (id))
+	{
+	  var_version++;
+	  unsigned int version;
+	  version = atoi (var_version);
+	  if (var_version && version)
+	    {
+	      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);
+	    }
+	}
+    }
+
+  /* for default defination ssa names.  */
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      c_parser_consume_token (parser);
+      ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (!strcmp ("D", ssa_token))
+	{
+	  set_ssa_default_def (cfun, lookup_name (id), ret.value);
+	  c_parser_consume_token (parser);
+	}
+      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+	return ret;
+    }
+  return ret;
+}
+
+/* Parse gimple postfix expression.
+
+   gimple-postfix-expression:
+     gimple-primary-expression
+     gimple-primary-xpression [ gimple-primary-expression ]
+     gimple-primary-expression ( gimple-argument-expression-list[opt] )
+
+   gimple-argument-expression-list:
+     gimple-unary-expression
+     gimple-argument-expression-list , gimple-unary-expression
+
+   gimple-primary-expression:
+     identifier
+     constant
+     string-literal
+
+*/
+
+static struct c_expr
+c_parser_gimple_postfix_expression (c_parser *parser)
+{
+  struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;;
+  source_range tok_range = c_parser_peek_token (parser)->get_range ();
+  expr.original_code = ERROR_MARK;
+  expr.original_type = NULL;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_NUMBER:
+      expr.value = c_parser_peek_token (parser)->value;
+      set_c_expr_source_range (&expr, tok_range);
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      if (TREE_CODE (expr.value) == FIXED_CST
+	  && !targetm.fixed_point_supported_p ())
+	{
+	  error_at (loc, "fixed-point types not supported for this target");
+	  expr.value = error_mark_node;
+	}
+      break;
+    case CPP_CHAR:
+    case CPP_CHAR16:
+    case CPP_CHAR32:
+    case CPP_WCHAR:
+      expr.value = c_parser_peek_token (parser)->value;
+      set_c_expr_source_range (&expr, tok_range);
+      c_parser_consume_token (parser);
+      break;
+    case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
+    case CPP_WSTRING:
+    case CPP_UTF8STRING:
+      expr.value = c_parser_peek_token (parser)->value;
+      set_c_expr_source_range (&expr, tok_range);
+      expr.original_code = STRING_CST;
+      c_parser_consume_token (parser);
+      break;
+    case CPP_OBJC_STRING:
+      gcc_assert (c_dialect_objc ());
+      expr.value
+	= objc_build_string_object (c_parser_peek_token (parser)->value);
+      set_c_expr_source_range (&expr, tok_range);
+      c_parser_consume_token (parser);
+      break;
+    case CPP_NAME:
+      if (c_parser_peek_token (parser)->id_kind == C_ID_ID)
+	{
+	  tree id = c_parser_peek_token (parser)->value;
+	  c_parser_consume_token (parser);
+	  expr.value = build_external_ref (loc, id,
+					   (c_parser_peek_token (parser)->type
+					    == CPP_OPEN_PAREN),
+					   &expr.original_type);
+	  set_c_expr_source_range (&expr, tok_range);
+	  break;
+	}
+      else
+	{
+	  c_parser_error (parser, "expected expression");
+	  expr.set_error ();
+	  break;
+	}
+      break;
+    default:
+      c_parser_error (parser, "expected expression");
+      expr.set_error ();
+      break;
+    }
+  return c_parser_gimple_postfix_expression_after_primary
+    (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
+}
+
+/* Parse a gimple postfix expression after the initial primary or compound
+   literal.  */
+
+static struct c_expr
+c_parser_gimple_postfix_expression_after_primary (c_parser *parser,
+						  location_t expr_loc,
+						  struct c_expr expr)
+{
+  struct c_expr orig_expr;
+  tree idx;
+  location_t sizeof_arg_loc[3];
+  tree sizeof_arg[3];
+  unsigned int literal_zero_mask;
+  unsigned int i;
+  vec<tree, va_gc> *exprlist;
+  vec<tree, va_gc> *origtypes = NULL;
+  vec<location_t> arg_loc = vNULL;
+  location_t start;
+  location_t finish;
+
+  location_t op_loc = c_parser_peek_token (parser)->location;
+
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_OPEN_SQUARE:
+	{
+	  c_parser_consume_token (parser);
+	  idx = c_parser_gimple_unary_expression (parser).value;
+
+	  if (!c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>"))
+	    break;
+
+	  start = expr.get_start ();
+	  finish = parser->tokens_buf[0].location;
+	  expr.value = build_array_ref (op_loc, expr.value, idx);
+	  set_c_expr_source_range (&expr, start, finish);
+
+	  expr.original_code = ERROR_MARK;
+	  expr.original_type = NULL;
+	  break;
+	}
+    case CPP_OPEN_PAREN:
+	{
+	  /* Function call */
+	  c_parser_consume_token (parser);
+	  for (i = 0; i < 3; i++)
+	    {
+	      sizeof_arg[i] = NULL_TREE;
+	      sizeof_arg_loc[i] = UNKNOWN_LOCATION;
+	    }
+	  literal_zero_mask = 0;
+	  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+	    exprlist = NULL;
+	  else
+	    exprlist = c_parser_gimple_expr_list (parser, true, &origtypes,
+					   sizeof_arg_loc, sizeof_arg,
+					   &arg_loc, &literal_zero_mask);
+	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+				     "expected %<)%>");
+	  orig_expr = expr;
+	  mark_exp_read (expr.value);
+	  if (warn_sizeof_pointer_memaccess)
+	    sizeof_pointer_memaccess_warning (sizeof_arg_loc,
+					      expr.value, exprlist,
+					      sizeof_arg,
+					      sizeof_ptr_memacc_comptypes);
+	  if (TREE_CODE (expr.value) == FUNCTION_DECL
+	      && DECL_BUILT_IN_CLASS (expr.value) == BUILT_IN_NORMAL
+	      && DECL_FUNCTION_CODE (expr.value) == BUILT_IN_MEMSET
+	      && vec_safe_length (exprlist) == 3)
+	    {
+	      tree arg0 = (*exprlist)[0];
+	      tree arg2 = (*exprlist)[2];
+	      warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
+	    }
+
+	  start = expr.get_start ();
+	  finish = parser->tokens_buf[0].get_finish ();
+	  expr.value
+	    = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
+					 exprlist, origtypes);
+	  set_c_expr_source_range (&expr, start, finish);
+
+	  expr.original_code = ERROR_MARK;
+	  if (TREE_CODE (expr.value) == INTEGER_CST
+	      && TREE_CODE (orig_expr.value) == FUNCTION_DECL
+	      && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
+	      && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
+	    expr.original_code = C_MAYBE_CONST_EXPR;
+	  expr.original_type = NULL;
+	  if (exprlist)
+	    {
+	      release_tree_vector (exprlist);
+	      release_tree_vector (origtypes);
+	    }
+	  arg_loc.release ();
+	  break;
+	default:
+	  return expr;
+
+	}
+    }
+  return expr;
+}
+
+/* Parse expression list.
+
+   gimple-expr-list:
+     gimple-unary-expression
+     gimple-expr-list , gimple-unary-expression
+
+ */
+
+static vec<tree, va_gc> *
+c_parser_gimple_expr_list (c_parser *parser, bool convert_p,
+		    vec<tree, va_gc> **p_orig_types,
+		    location_t *sizeof_arg_loc, tree *sizeof_arg,
+		    vec<location_t> *locations,
+		    unsigned int *literal_zero_mask)
+{
+  vec<tree, va_gc> *ret;
+  vec<tree, va_gc> *orig_types;
+  struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
+  location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION;
+  unsigned int idx = 0;
+
+  ret = make_tree_vector ();
+  if (p_orig_types == NULL)
+    orig_types = NULL;
+  else
+    orig_types = make_tree_vector ();
+
+  if (sizeof_arg != NULL
+      && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
+    cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
+  if (literal_zero_mask)
+    c_parser_check_literal_zero (parser, literal_zero_mask, 0);
+  expr = c_parser_gimple_unary_expression (parser);
+  if (convert_p)
+    expr = convert_lvalue_to_rvalue (loc, expr, true, true);
+  ret->quick_push (expr.value);
+  if (orig_types)
+    orig_types->quick_push (expr.original_type);
+  if (locations)
+    locations->safe_push (loc);
+  if (sizeof_arg != NULL
+      && cur_sizeof_arg_loc != UNKNOWN_LOCATION
+      && expr.original_code == SIZEOF_EXPR)
+    {
+      sizeof_arg[0] = c_last_sizeof_arg;
+      sizeof_arg_loc[0] = cur_sizeof_arg_loc;
+    }
+  while (c_parser_next_token_is (parser, CPP_COMMA))
+    {
+      c_parser_consume_token (parser);
+      loc = c_parser_peek_token (parser)->location;
+      if (sizeof_arg != NULL
+	  && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
+	cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
+      else
+	cur_sizeof_arg_loc = UNKNOWN_LOCATION;
+      if (literal_zero_mask)
+	c_parser_check_literal_zero (parser, literal_zero_mask, idx + 1);
+      expr = c_parser_gimple_unary_expression (parser);
+      if (convert_p)
+	expr = convert_lvalue_to_rvalue (loc, expr, true, true);
+      vec_safe_push (ret, expr.value);
+      if (orig_types)
+	vec_safe_push (orig_types, expr.original_type);
+      if (locations)
+	locations->safe_push (loc);
+      if (++idx < 3
+	  && sizeof_arg != NULL
+	  && cur_sizeof_arg_loc != UNKNOWN_LOCATION
+	  && expr.original_code == SIZEOF_EXPR)
+	{
+	  sizeof_arg[idx] = c_last_sizeof_arg;
+	  sizeof_arg_loc[idx] = cur_sizeof_arg_loc;
+	}
+    }
+  if (orig_types)
+    *p_orig_types = orig_types;
+  return ret;
+}
+
+/* Parse gimple label.
+
+   gimple-label:
+     identifier :
+     case constant-expression :
+     default :
+
+*/
+
+static void
+c_parser_gimple_label (c_parser *parser, gimple_seq *seq)
+{
+  tree label;
+  tree name = c_parser_peek_token (parser)->value;
+  location_t loc1 = c_parser_peek_token (parser)->location;
+  gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
+  c_parser_consume_token (parser);
+  gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
+  c_parser_consume_token (parser);
+  label = define_label (loc1, name);
+  gimple_seq_add_stmt (seq, gimple_build_label (label));
+  return;
+}
+
+/* Parse gimple pass list.
+
+   gimple-pass-list:
+     startwith("pass-name")
+ */
+
+static void
+c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass,
+			   bool *startwith_p)
+{
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      return;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      return;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *op = NULL;
+      op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      c_parser_consume_token (parser);
+      if (!strcmp (op, "startwith"))
+	{
+	  *pass = c_parser_gimple_pass_list_params (parser, pass);
+	  if (!(*pass))
+	    return;
+
+	  *startwith_p = true;
+	  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+	    return;
+	}
+      else
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "invalid operation");
+	  return;
+	}
+    }
+  else if (c_parser_next_token_is (parser, CPP_EOF))
+    {
+      c_parser_error (parser, "expected parameters");
+      return;
+    }
+
+  return;
+}
+
+/* Support function for c_parser_gimple_pass_list.  */
+
+static opt_pass *
+c_parser_gimple_pass_list_params (c_parser *parser, opt_pass **pass)
+{
+  opt_pass *pass_start = NULL, *new_pass;
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      return NULL;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      return NULL;
+    }
+
+  while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+    {
+      if (c_parser_next_token_is (parser, CPP_EOF))
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "expected pass names");
+	  return NULL;
+	}
+
+      if (c_parser_next_token_is (parser, CPP_STRING))
+	{
+	  const char *name = NULL;
+	  name = TREE_STRING_POINTER (c_parser_peek_token (parser)->value);
+	  c_parser_consume_token (parser);
+	  new_pass = g->get_passes ()->get_pass_by_name (name);
+
+	  if (!new_pass)
+	    {
+	      error_at (c_parser_peek_token (parser)->location,
+			"invalid pass name");
+	      parser->error = true;
+	      c_parser_consume_token (parser);
+	      return NULL;
+	    }
+	  if (*pass)
+	    {
+	      (*pass)->next = new_pass;
+	      (*pass) = (*pass)->next;
+	    }
+	  else
+	    {
+	      *pass = new_pass;
+	      pass_start = *pass;
+	    }
+	}
+      else if (c_parser_next_token_is (parser, CPP_COMMA))
+	c_parser_consume_token (parser);
+      else
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "invalid pass name");
+	  c_parser_consume_token (parser);
+	  return NULL;
+	}
+    }
+  return pass_start;
+}
+
+/* Parse gimple local declaration.
+
+   declaration-specifiers:
+     storage-class-specifier declaration-specifiers[opt]
+     type-specifier declaration-specifiers[opt]
+     type-qualifier declaration-specifiers[opt]
+     function-specifier declaration-specifiers[opt]
+     alignment-specifier declaration-specifiers[opt]
+
+   storage-class-specifier:
+     typedef
+     extern
+     static
+     auto
+     register
+
+   type-specifier:
+     void
+     char
+     short
+     int
+     long
+     float
+     double
+     signed
+     unsigned
+     _Bool
+     _Complex
+
+   type-qualifier:
+     const
+     restrict
+     volatile
+     address-space-qualifier
+     _Atomic
+
+ */
+
+static void
+c_parser_gimple_declaration (c_parser *parser)
+{
+  struct c_declspecs *specs;
+  struct c_declarator *declarator;
+  specs = build_null_declspecs ();
+  c_parser_declspecs (parser, specs, true, true, true,
+		      true, true, cla_nonabstract_decl);
+  finish_declspecs (specs);
+  bool auto_type_p = specs->typespec_word == cts_auto_type;
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      if (auto_type_p)
+	error_at (c_parser_peek_token (parser)->location,
+		  "%<__auto_type%> in empty declaration");
+      c_parser_consume_token (parser);
+      return;
+    }
+
+  /* Provide better error recovery.  Note that a type name here is usually
+     better diagnosed as a redeclaration.  */
+  if (specs->typespec_kind == ctsk_tagdef
+      && c_parser_next_token_starts_declspecs (parser)
+      && !c_parser_next_token_is (parser, CPP_NAME))
+    {
+      c_parser_error (parser, "expected %<;%>");
+      parser->error = false;
+      shadow_tag_warned (specs, 1);
+      return;
+    }
+
+  bool dummy = false;
+  declarator = c_parser_declarator (parser,
+				    specs->typespec_kind != ctsk_none,
+				    C_DTR_NORMAL, &dummy);
+
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      tree decl;
+      tree postfix_attrs = NULL_TREE;
+      tree all_prefix_attrs = specs->attrs;
+      specs->attrs = NULL;
+      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
+    {
+      c_parser_error (parser, "expected %<;%>");
+      return;
+    }
+}
+
+/* Parse gimple goto statement.  */
+
+static void
+c_parser_gimple_goto_stmt (location_t loc, tree label, gimple_seq *seq)
+{
+  tree decl;
+  decl = lookup_label_for_goto (loc, label);
+  gimple_seq_add_stmt (seq, gimple_build_goto (decl));
+  return;
+}
+
+/* Parse a parenthesized condition.
+   gimple-condition:
+     ( gimple-binary-expression )    */
+
+static tree
+c_parser_gimple_paren_condition (c_parser *parser)
+{
+  tree cond;
+  enum tree_code subcode = NOP_EXPR;
+  location_t loc = c_parser_peek_token (parser)->location;
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return error_mark_node;
+  cond = c_parser_gimple_binary_expression (parser, &subcode).value;
+  cond = c_objc_common_truthvalue_conversion (loc, cond);
+  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+    return error_mark_node;
+  return cond;
+}
+
+/* Parse gimple if-else statement.
+
+   if-statement:
+     if ( gimple-binary-expression ) gimple-goto-statement
+     if ( gimple-binary-expression ) gimple-goto-statement \
+					else gimple-goto-statement
+ */
+
+static void
+c_parser_gimple_if_stmt (c_parser *parser, gimple_seq *seq)
+{
+  tree cond, t_label, f_label, label;
+  location_t loc;
+  c_parser_consume_token (parser);
+  cond = c_parser_gimple_paren_condition (parser);
+
+  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+    {
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      label = c_parser_peek_token (parser)->value;
+      t_label = lookup_label_for_goto (loc, label);
+      c_parser_consume_token (parser);
+      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+	return;
+    }
+  else
+    {
+      c_parser_error (parser, "expected goto expression");
+      return;
+    }
+
+  if (c_parser_next_token_is_keyword (parser, RID_ELSE))
+    c_parser_consume_token (parser);
+  else
+    {
+      c_parser_error (parser, "expected else statement");
+      return;
+    }
+
+  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+    {
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      label = c_parser_peek_token (parser)->value;
+      f_label = lookup_label_for_goto (loc, label);
+      c_parser_consume_token (parser);
+      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+	return;
+    }
+  else
+    {
+      c_parser_error (parser, "expected goto expression");
+      return;
+    }
+
+  gimple_seq_add_stmt (seq, gimple_build_cond_from_tree (cond, t_label,
+							 f_label));
+}
+
+/* Parse gimple switch-statement.
+
+   gimple-switch-statement:
+     switch (gimple-unary-expression) gimple-case-statement
+
+   gimple-case-statement:
+     gimple-case-statement
+     gimple-label-statement : gimple-goto-statment
+*/
+
+static void
+c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
+{
+  c_expr cond_expr;
+  tree case_label, label;
+  vec<tree> labels = vNULL;
+  tree default_label = NULL_TREE;
+  gimple_seq switch_body = NULL;
+  location_t loc;
+  c_parser_consume_token (parser);
+
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      cond_expr = c_parser_gimple_unary_expression (parser);
+      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+	return;
+    }
+
+  if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+    {
+      while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+	{
+	  if (c_parser_next_token_is (parser, CPP_EOF))
+	    {
+	      c_parser_error (parser, "expected statement");
+	      return;
+	    }
+
+	  switch (c_parser_peek_token (parser)->keyword)
+	    {
+	    case RID_CASE:
+		{
+		  c_expr exp1;
+		  loc = c_parser_peek_token (parser)->location;
+		  c_parser_consume_token (parser);
+
+		  if (c_parser_next_token_is (parser, CPP_NAME) ||
+		      c_parser_peek_token (parser)->type == CPP_NUMBER)
+		    exp1 = c_parser_gimple_unary_expression (parser);
+		  else
+		    c_parser_error (parser, "expected expression");
+
+		  if (c_parser_next_token_is (parser, CPP_COLON))
+		    {
+		      c_parser_consume_token (parser);
+		      label = create_artificial_label (loc);
+		      case_label = build_case_label (exp1.value, NULL_TREE,
+						     label);
+		      labels.safe_push (case_label);
+		      gimple_seq_add_stmt (&switch_body,
+					   gimple_build_label
+					   (CASE_LABEL (case_label)));
+		    }
+		  else
+		    {
+		      if (!c_parser_require (parser, CPP_SEMICOLON,
+					     "expected %<:%>"))
+			return;
+		    }
+		}
+	      break;
+	    case RID_DEFAULT:
+		{
+		  c_parser_consume_token (parser);
+		  if (c_parser_next_token_is (parser, CPP_COLON))
+		    {
+		      c_parser_consume_token (parser);
+		      default_label = build_case_label (NULL_TREE, NULL_TREE,
+							create_artificial_label
+							(UNKNOWN_LOCATION));
+		      gimple_seq_add_stmt (&switch_body,
+					   gimple_build_label
+					   (CASE_LABEL (default_label)));
+		    }
+		  else
+		    {
+		      if (!c_parser_require (parser, CPP_SEMICOLON,
+					     "expected %<:%>"))
+			return;
+		    }
+		}
+	      break;
+	    case RID_GOTO:
+		{
+		  location_t loc = c_parser_peek_token (parser)->location;
+		  c_parser_consume_token (parser);
+		  if (c_parser_next_token_is (parser, CPP_NAME))
+		    {
+		      c_parser_gimple_goto_stmt (loc,
+						 c_parser_peek_token (parser)->value,
+						 &switch_body);
+		      c_parser_consume_token (parser);
+		      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+			c_parser_consume_token (parser);
+		      else
+			{
+			  c_parser_error (parser, "expected semicolon");
+			  return;
+			}
+		    }
+		  else
+		    {
+		      if (!c_parser_require (parser, CPP_NAME,
+					     "expected label"))
+			return;
+		    }
+		}
+	      break;
+	    default:
+	      c_parser_error (parser, "expected case label or goto statement");
+	      return;
+	    }
+
+	}
+    }
+  if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
+    return;
+  gimple_seq_add_stmt (seq, gimple_build_switch (cond_expr.value,
+						 default_label, labels));
+  gimple_seq_add_seq (seq, switch_body);
+  labels.release();
+}
+
+/* Parse gimple return statement.  */
+
+static void
+c_parser_gimple_return_stmt (c_parser *parser, gimple_seq *seq)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  gimple *ret;
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      c_finish_gimple_return (loc, NULL_TREE);
+      ret = gimple_build_return (NULL);
+      gimple_seq_add_stmt (seq, ret);
+    }
+  else
+    {
+      location_t xloc = c_parser_peek_token (parser)->location;
+      c_expr expr = c_parser_gimple_unary_expression (parser);
+      c_finish_gimple_return (xloc, expr.value);
+      ret = gimple_build_return (expr.value);
+      gimple_seq_add_stmt (seq, ret);
+    }
+}
+
+/* Support function for c_parser_gimple_return_stmt.  */
+
+static void
+c_finish_gimple_return (location_t loc, tree retval)
+{
+  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
+
+  /* Use the expansion point to handle cases such as returning NULL
+     in a function returning void.  */
+  source_location xloc = expansion_point_location_if_in_system_header (loc);
+
+  if (TREE_THIS_VOLATILE (current_function_decl))
+    warning_at (xloc, 0,
+		"function declared %<noreturn%> has a %<return%> statement");
+
+  if (!retval)
+    {
+      current_function_returns_null = 1;
+      if ((warn_return_type || flag_isoc99)
+	  && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
+	{
+	  bool warned_here;
+	  if (flag_isoc99)
+	    warned_here = pedwarn
+	      (loc, 0,
+	       "%<return%> with no value, in function returning non-void");
+	  else
+	    warned_here = warning_at
+	      (loc, OPT_Wreturn_type,
+	       "%<return%> with no value, in function returning non-void");
+	  if (warned_here)
+	    inform (DECL_SOURCE_LOCATION (current_function_decl),
+		    "declared here");
+	}
+    }
+  else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
+    {
+      current_function_returns_null = 1;
+      if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
+	{
+	  error_at
+	    (xloc, "%<return%> with a value, in function returning void");
+	  inform (DECL_SOURCE_LOCATION (current_function_decl),
+		  "declared here");
+	}
+    }
+  else if (TREE_CODE (valtype) != TREE_CODE (TREE_TYPE (retval)))
+    {
+      error_at
+	(xloc, "invalid conversion in return statement");
+      inform (DECL_SOURCE_LOCATION (current_function_decl),
+	      "declared here");
+    }
+  return;
+}
+
 #include "gt-c-c-parser.h"
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 6a1d126..cf6728f 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1944,6 +1944,7 @@ cgraph_node::assemble_thunks_and_aliases (void)
 void
 cgraph_node::expand (void)
 {
+  bool startwith_p = true;
   location_t saved_loc;
 
   /* We ought to not compile any inline clones.  */
@@ -1982,7 +1983,7 @@ cgraph_node::expand (void)
   /* Signal the start of passes.  */
   invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
 
-  execute_pass_list (cfun, g->get_passes ()->all_passes);
+  execute_pass_list (cfun, g->get_passes ()->all_passes, &startwith_p);
 
   /* Signal the end of passes.  */
   invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
@@ -2035,7 +2036,9 @@ cgraph_node::expand (void)
   timevar_pop (TV_REST_OF_COMPILATION);
 
   /* Make sure that BE didn't give up on compiling.  */
-  gcc_assert (TREE_ASM_WRITTEN (decl));
+  if (!(flag_gimple && cfun->pass_startwith))  /* FIXME : for gimplefe custom_pass_list */
+    gcc_assert (TREE_ASM_WRITTEN (decl));
+
   if (cfun)
     pop_cfun ();
 
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index fe1e984..ad6e5ac 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -85,6 +85,7 @@ typedef const union tree_node *const_tree;
 struct gimple;
 typedef gimple *gimple_seq;
 struct gimple_stmt_iterator;
+class opt_pass;
 
 /* Forward decls for leaf gimple subclasses (for individual gimple codes).
    Keep this in the same order as the corresponding codes in gimple.def.  */
@@ -405,6 +406,8 @@ typedef unsigned char uchar;
 #include "input.h"
 #include "is-a.h"
 #include "memory-block.h"
+#include "pass_manager.h"
+#include "tree-pass.h"
 #endif /* GENERATOR_FILE && !USED_FOR_TARGET */
 
 #endif /* coretypes.h */
diff --git a/gcc/function.h b/gcc/function.h
index 501ef68..0adbd68 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -228,6 +228,12 @@ struct GTY(()) function {
   /* GIMPLE body for this function.  */
   gimple_seq gimple_body;
 
+  /* GIMPLEFE pass to start with */
+  opt_pass *pass_startwith = NULL;
+
+  /* Startwith flag */
+  bool startwith;
+
   /* SSA and dataflow information.  */
   struct gimple_df *gimple_df;
 
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 12d9a9c..e4416a5 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -838,7 +838,7 @@ dump_gimple_switch (pretty_printer *buffer, gswitch *gs, int spc,
     {
       pp_string (buffer, "switch (");
       dump_generic_node (buffer, gimple_switch_index (gs), spc, flags, true);
-      pp_string (buffer, ") <");
+      pp_string (buffer, ") {");
     }
 
   for (i = 0; i < gimple_switch_num_labels (gs); i++)
@@ -849,9 +849,9 @@ dump_gimple_switch (pretty_printer *buffer, gswitch *gs, int spc,
       pp_space (buffer);
       dump_generic_node (buffer, CASE_LABEL (case_label), spc, flags, false);
       if (i < gimple_switch_num_labels (gs) - 1)
-        pp_string (buffer, ", ");
+        pp_string (buffer, "; ");
     }
-  pp_greater (buffer);
+  pp_string (buffer, "}");
 }
 
 
@@ -907,16 +907,11 @@ dump_gimple_label (pretty_printer *buffer, glabel *gs, int spc, int flags)
 {
   tree label = gimple_label_label (gs);
   if (flags & TDF_RAW)
-      dump_gimple_fmt (buffer, spc, flags, "%G <%T>", gs, label);
+    dump_gimple_fmt (buffer, spc, flags, "%T", label);
   else
-    {
-      dump_generic_node (buffer, label, spc, flags, false);
-      pp_colon (buffer);
-    }
-  if (DECL_NONLOCAL (label))
-    pp_string (buffer, " [non-local]");
-  if ((flags & TDF_EH) && EH_LANDING_PAD_NR (label))
-    pp_printf (buffer, " [LP %d]", EH_LANDING_PAD_NR (label));
+    dump_generic_node (buffer, label, spc, flags, false);
+
+  pp_colon (buffer);
 }
 
 /* Dump a GIMPLE_GOTO tuple on the pretty_printer BUFFER, SPC
@@ -1966,8 +1961,7 @@ dump_ssaname_info_to_file (FILE *file, tree node, int spc)
    pretty printer.  If COMMENT is true, print this after #.  */
 
 static void
-dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, bool comment,
-		 int flags)
+dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, int flags)
 {
   size_t i;
   tree lhs = gimple_phi_result (phi);
@@ -1975,30 +1969,27 @@ dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, bool comment,
   if (flags & TDF_ALIAS)
     dump_ssaname_info (buffer, lhs, spc);
 
-  if (comment)
-    pp_string (buffer, "# ");
-
   if (flags & TDF_RAW)
     dump_gimple_fmt (buffer, spc, flags, "%G <%T, ", phi,
 		     gimple_phi_result (phi));
   else
     {
       dump_generic_node (buffer, lhs, spc, flags, false);
-      pp_string (buffer, " = PHI <");
+      pp_string (buffer, " = __PHI (");
     }
   for (i = 0; i < gimple_phi_num_args (phi); i++)
     {
       if ((flags & TDF_LINENO) && gimple_phi_arg_has_location (phi, i))
 	dump_location (buffer, gimple_phi_arg_location (phi, i));
+      pp_string (buffer, "bb_");
+      pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index);
+      pp_string (buffer, ": ");
       dump_generic_node (buffer, gimple_phi_arg_def (phi, i), spc, flags,
 			 false);
-      pp_left_paren (buffer);
-      pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index);
-      pp_right_paren (buffer);
       if (i < gimple_phi_num_args (phi) - 1)
 	pp_string (buffer, ", ");
     }
-  pp_greater (buffer);
+  pp_right_paren (buffer);
 }
 
 
@@ -2286,7 +2277,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple *gs, int spc, int flags)
       break;
 
     case GIMPLE_PHI:
-      dump_gimple_phi (buffer, as_a <gphi *> (gs), spc, false, flags);
+      dump_gimple_phi (buffer, as_a <gphi *> (gs), spc, flags);
       break;
 
     case GIMPLE_OMP_PARALLEL:
@@ -2447,7 +2438,7 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, int indent, int flags)
     {
       gimple *stmt = first_stmt (bb);
       if (!stmt || gimple_code (stmt) != GIMPLE_LABEL)
-	fprintf (outf, "%*s<bb %d>:\n", indent, "", bb->index);
+	fprintf (outf, "%*sbb_%d:\n", indent, "", bb->index);
     }
 }
 
@@ -2480,7 +2471,7 @@ dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags)
       if (!virtual_operand_p (gimple_phi_result (phi)) || (flags & TDF_VOPS))
         {
           INDENT (indent);
-	  dump_gimple_phi (buffer, phi, indent, true, flags);
+	  dump_gimple_phi (buffer, phi, indent, flags);
           pp_newline (buffer);
         }
     }
@@ -2493,24 +2484,9 @@ dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags)
 static void
 pp_cfg_jump (pretty_printer *buffer, basic_block bb)
 {
-  gimple *stmt;
-
-  stmt = first_stmt (bb);
-
-  pp_string (buffer, "goto <bb ");
+  pp_string (buffer, "goto bb_");
   pp_decimal_int (buffer, bb->index);
-  pp_greater (buffer);
-  if (stmt && gimple_code (stmt) == GIMPLE_LABEL)
-    {
-      pp_string (buffer, " (");
-      dump_generic_node (buffer,
-			 gimple_label_label (as_a <glabel *> (stmt)),
-			 0, 0, false);
-      pp_right_paren (buffer);
-      pp_semicolon (buffer);
-    }
-  else
-    pp_semicolon (buffer);
+  pp_semicolon (buffer);
 }
 
 
@@ -2627,7 +2603,7 @@ gimple_dump_bb (FILE *file, basic_block bb, int indent, int flags)
 void
 gimple_dump_bb_for_graph (pretty_printer *pp, basic_block bb)
 {
-  pp_printf (pp, "<bb %d>:\n", bb->index);
+  pp_printf (pp, "bb_%d:\n", bb->index);
   pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
 
   for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 4715332..12b9ec9 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -11848,7 +11848,22 @@ gimplify_function_tree (tree fndecl)
       && !needs_to_live_in_memory (ret))
     DECL_GIMPLE_REG_P (ret) = 1;
 
-  bind = gimplify_body (fndecl, true);
+  if (!cfun->gimple_body)
+    bind = gimplify_body (fndecl, true);
+  else
+    {
+      gimple_seq seq;
+      gimple *outer_stmt;
+      seq = cfun->gimple_body;
+      outer_stmt = gimple_seq_first_stmt (seq);
+      if (gimple_code (outer_stmt) == GIMPLE_BIND
+	  && gimple_seq_first (seq) == gimple_seq_last (seq))
+	bind = as_a <gbind *> (outer_stmt);
+      else
+	bind = gimple_build_bind (NULL_TREE, seq, NULL);
+
+      DECL_SAVED_TREE (fndecl) = NULL_TREE;
+    }
 
   /* The tree body of the function is no longer needed, replace it
      with the new GIMPLE body.  */
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index cd4b625..3824fb7 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2412,3 +2412,9 @@ expand_internal_call (gcall *stmt)
 {
   expand_internal_call (gimple_call_internal_fn (stmt), stmt);
 }
+
+void
+expand_PHI (internal_fn, gcall *)
+{
+    gcc_unreachable ();
+}
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 6701cd9..a5dd23e 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -169,6 +169,7 @@ DEF_INTERNAL_FN (VA_ARG, ECF_NOTHROW | ECF_LEAF, NULL)
    other such optimizations.  The first argument distinguishes
    between uses.  See internal-fn.h for usage.  */
 DEF_INTERNAL_FN (UNIQUE, ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (PHI, 0, NULL)
 
 /* DIM_SIZE and DIM_POS return the size of a particular compute
    dimension and the executing thread's position within that
diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
index bb31465..9c39dd67 100644
--- a/gcc/internal-fn.h
+++ b/gcc/internal-fn.h
@@ -174,5 +174,6 @@ extern bool set_edom_supported_p (void);
 
 extern void expand_internal_call (gcall *);
 extern void expand_internal_call (internal_fn, gcall *);
+extern void expand_PHI (internal_fn, gcall *);
 
 #endif
diff --git a/gcc/passes.c b/gcc/passes.c
index c7d7dbe..04caf39 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -1685,12 +1685,13 @@ remove_cgraph_node_from_order (cgraph_node *node, void *data)
    call CALLBACK on the current function.
    This function is global so that plugins can use it.  */
 void
-do_per_function_toporder (void (*callback) (function *, void *data), void *data)
+do_per_function_toporder (void (*callback) (function *, void *data, void *flag),
+			  void *data, void *flag)
 {
   int i;
 
   if (current_function_decl)
-    callback (cfun, data);
+    callback (cfun, data, flag);
   else
     {
       cgraph_node_hook_list *hook;
@@ -1725,7 +1726,7 @@ do_per_function_toporder (void (*callback) (function *, void *data), void *data)
 	    {
 	      struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
 	      push_cfun (fn);
-	      callback (fn, data);
+	      callback (fn, data, flag);
 	      pop_cfun ();
 	    }
 	}
@@ -2276,8 +2277,18 @@ override_gate_status (opt_pass *pass, tree func, bool gate_status)
 /* Execute PASS. */
 
 bool
-execute_one_pass (opt_pass *pass)
+execute_one_pass (opt_pass *pass, bool startwith_p)
 {
+  /* For skipping passes until startwith pass */
+  if (cfun && startwith_p && cfun->startwith)
+    {
+      if (!strcmp (pass->name, cfun->pass_startwith->name)
+	  || !strcmp (pass->name, "*clean_state"))
+	cfun->startwith = false;
+      else
+	return true;
+    }
+
   unsigned int todo_after = 0;
 
   bool gate_status;
@@ -2417,7 +2428,7 @@ execute_one_pass (opt_pass *pass)
 }
 
 static void
-execute_pass_list_1 (opt_pass *pass)
+execute_pass_list_1 (opt_pass *pass, bool startwith_p)
 {
   do
     {
@@ -2426,18 +2437,23 @@ execute_pass_list_1 (opt_pass *pass)
 
       if (cfun == NULL)
 	return;
-      if (execute_one_pass (pass) && pass->sub)
-        execute_pass_list_1 (pass->sub);
+      if (execute_one_pass (pass, startwith_p) && pass->sub)
+	execute_pass_list_1 (pass->sub, startwith_p);
       pass = pass->next;
     }
   while (pass);
 }
 
 void
-execute_pass_list (function *fn, opt_pass *pass)
+execute_pass_list (function *fn, opt_pass *pass, bool *startwith_p)
 {
   gcc_assert (fn == cfun);
-  execute_pass_list_1 (pass);
+
+  if (startwith_p)
+    execute_pass_list_1 (pass, *startwith_p);
+  else
+    execute_pass_list_1 (pass, false);
+
   if (cfun && fn->cfg)
     {
       free_dominance_info (CDI_DOMINATORS);
@@ -2767,19 +2783,22 @@ ipa_read_optimization_summaries (void)
 void
 execute_ipa_pass_list (opt_pass *pass)
 {
+  bool startwith_p = false;
   do
     {
       gcc_assert (!current_function_decl);
       gcc_assert (!cfun);
       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
-      if (execute_one_pass (pass) && pass->sub)
+      if (!strcmp (pass->name, "opt_local_passes"))
+	startwith_p = true;
+      if (execute_one_pass (pass, startwith_p) && pass->sub)
 	{
 	  if (pass->sub->type == GIMPLE_PASS)
 	    {
 	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL);
-	      do_per_function_toporder ((void (*)(function *, void *))
+	      do_per_function_toporder ((void (*)(function *, void *, void *))
 					  execute_pass_list,
-					pass->sub);
+					pass->sub, &startwith_p);
 	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL);
 	    }
 	  else if (pass->sub->type == SIMPLE_IPA_PASS
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 57c8410..7fe994e 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -170,6 +170,7 @@ static edge find_taken_edge_computed_goto (basic_block, tree);
 static edge find_taken_edge_cond_expr (basic_block, tree);
 static edge find_taken_edge_switch_expr (gswitch *, basic_block, tree);
 static tree find_case_label_for_value (gswitch *, tree);
+static void lower_phi_internal_fn ();
 
 void
 init_empty_tree_cfg_for_function (struct function *fn)
@@ -244,6 +245,7 @@ build_gimple_cfg (gimple_seq seq)
   discriminator_per_locus = new hash_table<locus_discrim_hasher> (13);
   make_edges ();
   assign_discriminators ();
+  lower_phi_internal_fn ();
   cleanup_dead_labels ();
   delete discriminator_per_locus;
   discriminator_per_locus = NULL;
@@ -345,6 +347,50 @@ replace_loop_annotate (void)
     }
 }
 
+/* Lower internal PHI function from GIMPLE FE.  */
+
+static void
+lower_phi_internal_fn ()
+{
+  basic_block bb, pred = NULL;
+  gimple_stmt_iterator gsi;
+  tree lhs;
+  gphi *phi_node;
+  gimple *stmt;
+
+  /* After edge creation, handle __PHI function from GIMPLE FE.  */
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	{
+	  stmt = gsi_stmt (gsi);
+	  if (gimple_code (stmt) != GIMPLE_CALL)
+	    continue;
+
+	  if (gimple_call_internal_p (stmt) &&
+	      gimple_call_internal_fn (stmt) == IFN_PHI)
+	    {
+	      gsi_remove (&gsi, true);
+	      unsigned int i;
+	      lhs = gimple_call_lhs (stmt);
+	      phi_node = create_phi_node (lhs, bb);
+
+	      /* Add arguments to the PHI node.  */
+	      for (i = 0; i < gimple_call_num_args (stmt); ++i)
+		{
+		  tree arg = gimple_call_arg (stmt, i);
+		  if (TREE_CODE (arg) == LABEL_DECL)
+		    pred = label_to_block (arg);
+		  else
+		    {
+		      edge e = find_edge (pred, bb);
+		      add_phi_arg (phi_node, arg, e, UNKNOWN_LOCATION);
+		    }
+		}
+	    }
+	}
+    }
+}
 
 static unsigned int
 execute_build_cfg (void)
@@ -3340,6 +3386,11 @@ verify_gimple_call (gcall *stmt)
 	  debug_generic_stmt (fn);
 	  return true;
 	}
+      /* FIXME : for passing label as arg in internal fn PHI from GIMPLE FE*/
+      else if (gimple_call_internal_fn (stmt) == IFN_PHI)
+	{
+	  return false;
+	}
     }
   else
     {
@@ -7504,7 +7555,8 @@ dump_function_to_file (tree fndecl, FILE *file, int flags)
     }
 
   current_function_decl = fndecl;
-  fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
+  print_generic_expr (file, TREE_TYPE (TREE_TYPE (fndecl)), dump_flags);
+  fprintf (file, "\n%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
 
   arg = DECL_ARGUMENTS (fndecl);
   while (arg)
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index ceafa68..ba3dc05 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -1379,12 +1379,19 @@ rewrite_add_phi_arguments (basic_block bb)
       for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi);
 	   gsi_next (&gsi))
 	{
-	  tree currdef, res;
+	  tree currdef, res, argvar;
 	  location_t loc;
 
 	  phi = gsi.phi ();
 	  res = gimple_phi_result (phi);
-	  currdef = get_reaching_def (SSA_NAME_VAR (res));
+	  /* If we have pre-existing PHI its args may be different
+	     vars than existing vars */
+	  argvar = gimple_phi_arg_def (phi, e->dest_idx);
+	  if (argvar && TREE_CODE (argvar) == SSA_NAME)
+	    continue;
+	  if (!argvar)
+	    argvar = SSA_NAME_VAR (res);
+	  currdef = get_reaching_def (argvar);
 	  /* Virtual operand PHI args do not need a location.  */
 	  if (virtual_operand_p (res))
 	    loc = UNKNOWN_LOCATION;
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index c0059de..213070b 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -617,8 +617,9 @@ extern gimple_opt_pass *make_pass_lower_vaarg (gcc::context *ctxt);
 /* Current optimization pass.  */
 extern opt_pass *current_pass;
 
-extern bool execute_one_pass (opt_pass *);
-extern void execute_pass_list (function *, opt_pass *);
+extern bool execute_one_pass (opt_pass *, bool startwith_p = false);
+extern void execute_pass_list (function *, opt_pass *,
+			       bool *startwith_p = NULL);
 extern void execute_ipa_pass_list (opt_pass *);
 extern void execute_ipa_summary_passes (ipa_opt_pass_d *);
 extern void execute_all_ipa_transforms (void);
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 734ecda..aa53bd2 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -260,7 +260,7 @@ dump_decl_name (pretty_printer *pp, tree node, int flags)
   if ((flags & TDF_UID) || DECL_NAME (node) == NULL_TREE)
     {
       if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1)
-	pp_printf (pp, "L.%d", (int) LABEL_DECL_UID (node));
+	pp_printf (pp, "L_%d", (int) LABEL_DECL_UID (node));
       else if (TREE_CODE (node) == DEBUG_EXPR_DECL)
 	{
 	  if (flags & TDF_NOUID)
@@ -274,7 +274,7 @@ dump_decl_name (pretty_printer *pp, tree node, int flags)
 	  if (flags & TDF_NOUID)
 	    pp_printf (pp, "%c.xxxx", c);
 	  else
-	    pp_printf (pp, "%c.%u", c, DECL_UID (node));
+	    pp_printf (pp, "%c_%u", c, DECL_UID (node));
 	}
     }
   if ((flags & TDF_ALIAS) && DECL_PT_UID (node) != DECL_UID (node))
@@ -3965,14 +3965,14 @@ dump_function_header (FILE *dump_file, tree fdecl, int flags)
   else
     aname = "<unset-asm-name>";
 
-  fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d",
+  fprintf (dump_file, "\n/* Function %s (%s, funcdef_no=%d",
 	   dname, aname, fun->funcdef_no);
   if (!(flags & TDF_NOUID))
     fprintf (dump_file, ", decl_uid=%d", DECL_UID (fdecl));
   if (node)
     {
       fprintf (dump_file, ", cgraph_uid=%d", node->uid);
-      fprintf (dump_file, ", symbol_order=%d)%s\n\n", node->order,
+      fprintf (dump_file, ", symbol_order=%d)%s", node->order,
                node->frequency == NODE_FREQUENCY_HOT
                ? " (hot)"
                : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
@@ -3982,7 +3982,8 @@ dump_function_header (FILE *dump_file, tree fdecl, int flags)
                : "");
     }
   else
-    fprintf (dump_file, ")\n\n");
+    fprintf (dump_file, ")");
+  fprintf (dump_file, "*/\n\n");
 }
 
 /* Dump double_int D to pretty_printer PP.  UNS is true
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 91a8f97..8b8863b 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -255,7 +255,8 @@ flush_ssaname_freelist (void)
    used without a preceding definition).  */
 
 tree
-make_ssa_name_fn (struct function *fn, tree var, gimple *stmt)
+make_ssa_name_fn (struct function *fn, tree var, gimple *stmt,
+		  unsigned int version)
 {
   tree t;
   use_operand_p imm;
@@ -265,8 +266,19 @@ make_ssa_name_fn (struct function *fn, tree var, gimple *stmt)
 	      || TREE_CODE (var) == RESULT_DECL
 	      || (TYPE_P (var) && is_gimple_reg_type (var)));
 
+  /* parsing ssa names with versions.	*/
+  if (version != 0)
+    {
+      t = make_node (SSA_NAME);
+      SSA_NAME_VERSION (t) = version;
+      if (version >= SSANAMES (fn)->length ())
+	vec_safe_grow_cleared (SSANAMES (fn), version + 1);
+      gcc_assert ((*SSANAMES (fn))[version] == NULL);
+      (*SSANAMES (fn))[version] = t;
+      ssa_name_nodes_created++;
+    }
   /* If our free list has an element, then use it.  */
-  if (!vec_safe_is_empty (FREE_SSANAMES (fn)))
+  else if (!vec_safe_is_empty (FREE_SSANAMES (fn)))
     {
       t = FREE_SSANAMES (fn)->pop ();
       ssa_name_nodes_reused++;
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index 8e66ce6..3ce9327 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -74,7 +74,8 @@ extern bool ssa_name_has_boolean_range (tree);
 extern void init_ssanames (struct function *, int);
 extern void fini_ssanames (struct function *);
 extern void ssanames_print_statistics (void);
-extern tree make_ssa_name_fn (struct function *, tree, gimple *);
+extern tree make_ssa_name_fn (struct function *, tree, gimple *,
+			      unsigned int version = 0);
 extern void release_ssa_name_fn (struct function *, tree);
 extern bool get_ptr_info_alignment (struct ptr_info_def *, unsigned int *,
 				    unsigned int *);

[-- Attachment #4: testcases.patch --]
[-- Type: application/octet-stream, Size: 5193 bytes --]

diff --git a/gcc/testsuite/gcc.dg/gimplefe-1.c b/gcc/testsuite/gcc.dg/gimplefe-1.c
new file mode 100644
index 0000000..0786d47
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int i;
+void __GIMPLE () foo()
+{
+  i = 1;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-10.c b/gcc/testsuite/gcc.dg/gimplefe-10.c
new file mode 100644
index 0000000..7f63c58
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-10.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE() bar(int a, int b, int c)
+{
+  a = 1;
+  b = a + 1;
+  c = b * 4;
+  return b;
+}
+
+void __GIMPLE() foo()
+{
+  int a;
+  int b;
+  int c;
+  b = bar(a, b, c);
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-11.c b/gcc/testsuite/gcc.dg/gimplefe-11.c
new file mode 100644
index 0000000..e1483f4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-11.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE() bar(int a, int b, int c)
+{
+  a = 1;
+  b = a + 1;
+  c = b * 4;
+  return;
+}
+
+void __GIMPLE() foo()
+{
+  int a;
+  int b;
+  int c;
+  bar(a, b, c);
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-12.c b/gcc/testsuite/gcc.dg/gimplefe-12.c
new file mode 100644
index 0000000..cbaf8a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-12.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE (startwith ("tree-ccp1")) foo ()
+{
+  int a;
+  int b;
+  a = b + 2;
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-13.c b/gcc/testsuite/gcc.dg/gimplefe-13.c
new file mode 100644
index 0000000..c0da9fa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-13.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE (startwith ("tree-dse1")) foo ()
+{
+  int a;
+
+bb_2:
+  if (a > 4)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_3:
+  a_2 = 10;
+  goto bb_5;
+
+bb_4:
+  a_3 = 20;
+
+bb_5:
+  a_1 = __PHI (bb_3: a_2, bb_4: a_3);
+  a_4 = a_1 + 4;
+
+return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-2.c b/gcc/testsuite/gcc.dg/gimplefe-2.c
new file mode 100644
index 0000000..e3a23cf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile }*/
+/* { dg-options "-fgimple" } */
+
+int a;
+void __GIMPLE () foo ()
+{
+  int b;
+  b = a;
+  b = b + 1;
+  a = b;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-3.c b/gcc/testsuite/gcc.dg/gimplefe-3.c
new file mode 100644
index 0000000..595365e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-3.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int *b;
+  *b = 1;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-4.c b/gcc/testsuite/gcc.dg/gimplefe-4.c
new file mode 100644
index 0000000..3600c7c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-4.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int a;
+  char b;
+  a = (int) b;
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-5.c b/gcc/testsuite/gcc.dg/gimplefe-5.c
new file mode 100644
index 0000000..1dab4af
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-5.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int a;
+void __GIMPLE () foo ()
+{
+  int b;
+  int c;
+
+bb_2:
+  b = a;
+  if (b > 3)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_3:
+  b = c + 4;
+  goto bb_5;
+
+bb_4:
+  b = b + 1;
+  goto bb_5;
+
+bb_5:
+  a = b;
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-6.c b/gcc/testsuite/gcc.dg/gimplefe-6.c
new file mode 100644
index 0000000..242e08f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-6.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int a;
+  int b;
+  int c;
+  int d;
+
+bb_2:
+  a = ~b;
+  b = a << c;
+  c = a & b;
+  d = b | c;
+
+bb_3:
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-7.c b/gcc/testsuite/gcc.dg/gimplefe-7.c
new file mode 100644
index 0000000..6125541
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-7.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int a;
+
+bb_2:
+  if (a > 4)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_3:
+  a_2 = 10;
+  goto bb_5;
+
+bb_4:
+  a_3 = 20;
+
+bb_5:
+  a_1 = __PHI (bb_3: a_2, bb_4: a_3);
+  a_4 = a_1 + 4;
+
+return;
+}
+
diff --git a/gcc/testsuite/gcc.dg/gimplefe-8.c b/gcc/testsuite/gcc.dg/gimplefe-8.c
new file mode 100644
index 0000000..4936bec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-8.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE () foo ()
+{
+  int a;
+  int b;
+
+bb_2:
+  b = a_1(D) + 1;
+bb_3:
+  return b;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-9.c b/gcc/testsuite/gcc.dg/gimplefe-9.c
new file mode 100644
index 0000000..a24be273
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-9.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE() bar()
+{
+  int a;
+  a = a + 1;
+  return a;
+}
+
+void __GIMPLE() foo()
+{
+  int b;
+  b = bar();
+}


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-21 17:05 [patch] [gsoc] [gimplefe] GIMPLE FE Project Prasad Ghangal
@ 2016-08-22 11:17 ` Trevor Saunders
  2016-08-22 18:40   ` Prasad Ghangal
  0 siblings, 1 reply; 24+ messages in thread
From: Trevor Saunders @ 2016-08-22 11:17 UTC (permalink / raw)
  To: Prasad Ghangal; +Cc: gcc-patches, Richard Biener

On Sun, Aug 21, 2016 at 10:35:17PM +0530, Prasad Ghangal wrote:
> Hi all,
> 
> As a part of my gsoc project. I have completed the following tasks:
> 
> * Parsed gimple-expression
> * Parsed gimple-labels
> * Parsed local declaration
> * Parsed gimple-goto statement
> * Parsed gimple-if-else statement
> * Parsed gimple-switch statement
> * Parsed gimple-return statement
> * Parsed gimple-PHI function
> * Parsed gimple ssa-names along with default def
> * Parsed gimple-call
> 
> * Hacked pass manager to add support for startwith (pass-name) to skip
> early opt passes
> * Modified gimple dump for making it parsable
> 
> I am willing to continue work on the project, some TODOs for the projects are:
> 
> * Error handling
> * Parse more gimple syntax
> * Add startwith support for IPA passes
> 
> The complete code of gimple fe project can be found at
> https://github.com/PrasadG193/gcc_gimple_fe
> 
> 
> PFA patch for complete project (rebased for latest trunk revision).
> I have successfully bootstrapped and tested on x86_64-pc-linux-gnu.
> Some testcases failed due to modified gimple dump as expected.
> 
> 
> Thanks,
> Prasad

only some rather minor comments


+++ b/gcc/c/c-parser.c
@@ -59,6 +59,18 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-expr.h"
 #include "context.h"
 #include "gcc-rich-location.h"
+#include "tree-vrp.h"

given that you need these headers it might be better to put most of the
gimple parsing in its own file so only what actually needs to know about
this part of the compiler does now about it.

+void
+c_parser_parse_gimple_body (c_parser *parser)
+{
+  bool return_p = false;
+  gimple_seq seq;
+  gimple_seq body;
+  tree stmt = push_stmt_list ();

it would be nice to move the declarations down to their first use.

+      gimple *ret;
+      ret = gimple_build_return (NULL);

there's no reason for a separate declaration and assignment ;)

+  tree block = NULL;
+  block = pop_scope ();

same here, and a number of other places.

+c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
+{
+  bool return_p = false;
+
+  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+      return return_p;

return false would work fine.

+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      c_parser_consume_token (parser);
+      goto out;

I don't see the need for the gotos, there's no cleanup in this function.

+  /* gimple PHI expression.  */
+  if (c_parser_next_token_is_keyword (parser, RID_PHI))
+    {
+      c_parser_consume_token (parser);
+
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+	{
+	  return;
+	}
+
+      gcall *call_stmt;
+      tree arg = NULL_TREE;
+      vec<tree> vargs = vNULL;

I think you can use auto_vec here, as is I think this leaks the vectors
storage.

+c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)

you can skip the explicit 'enum' keyword.

+  struct {
+    /* The expression at this stack level.  */
+    struct c_expr expr;

similar with struct here.

+    /* The precedence of the operator on its left, PREC_NONE at the
+       bottom of the stack.  */
+    enum c_parser_prec prec;
+    /* The operation on its left.  */
+    enum tree_code op;
+    /* The source location of this operation.  */
+    location_t loc;
+  } stack[2];
+  int sp;
+  /* Location of the binary operator.  */
+  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
+#define POP								      \

it seems like it would be nicer to name the type, and then make this a
function.

+					RO_UNARY_STAR);
+	ret.src_range.m_start = op_loc;
+	ret.src_range.m_finish = finish;
+	return ret;
+      }
+    case CPP_PLUS:
+      if (!c_dialect_objc () && !in_system_header_at (input_location))
+	warning_at (op_loc,
+		    OPT_Wtraditional,
+		    "traditional C rejects the unary plus operator");

does it really make sense to warn about C issues when compiling gimple?

+c_parser_parse_ssa_names (c_parser *parser)
+{
+  tree id = NULL_TREE;
+  c_expr ret;
+  char *var_name, *var_version, *token;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
+
+  /* ssa token string.  */
+  const char *ssa_token = NULL;
+  ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+  token = new char [strlen (ssa_token)];

I'm not sure I see why you need this copy, and getting rid of it would
mean you don't need to free it.

+  strcpy (token, ssa_token);
+
+  /* seperate var name and version.  */
+  var_version = strrchr (token, '_');
+  if (var_version)
+    {
+      var_name = new char[var_version - token + 1];

you should free this when done with it.

+c_parser_gimple_postfix_expression (c_parser *parser)
+{
+  struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;;

extra ;

+    case CPP_OBJC_STRING:
+      gcc_assert (c_dialect_objc ());
+      expr.value
+	= objc_build_string_object (c_parser_peek_token (parser)->value);
+      set_c_expr_source_range (&expr, tok_range);
+      c_parser_consume_token (parser);
+      break;

is there a reason to support objc stuff in gimple?

+c_parser_gimple_expr_list (c_parser *parser, bool convert_p,
+		    vec<tree, va_gc> **p_orig_types,
+		    location_t *sizeof_arg_loc, tree *sizeof_arg,
+		    vec<location_t> *locations,
+		    unsigned int *literal_zero_mask)
+{
+  vec<tree, va_gc> *ret;
+  vec<tree, va_gc> *orig_types;
+  struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
+  location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION;
+  unsigned int idx = 0;
+
+  ret = make_tree_vector ();
+  if (p_orig_types == NULL)
+    orig_types = NULL;
+  else
+    orig_types = make_tree_vector ();
+
+  if (sizeof_arg != NULL
+      && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
+    cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
+  if (literal_zero_mask)
+    c_parser_check_literal_zero (parser, literal_zero_mask, 0);
+  expr = c_parser_gimple_unary_expression (parser);
+  if (convert_p)
+    expr = convert_lvalue_to_rvalue (loc, expr, true, true);
+  ret->quick_push (expr.value);

 That kind of relies on the details of make_tree_vector (), so it seems
 somewhat safer to use vec_safe_push.

+  if (orig_types)
+    orig_types->quick_push (expr.original_type);

same

+c_parser_gimple_declaration (c_parser *parser)
+{
+  struct c_declspecs *specs;
+  struct c_declarator *declarator;
+  specs = build_null_declspecs ();
+  c_parser_declspecs (parser, specs, true, true, true,
+		      true, true, cla_nonabstract_decl);
+  finish_declspecs (specs);
+  bool auto_type_p = specs->typespec_word == cts_auto_type;

is it useful to support auto here in gimple?

+c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
+{
+  c_expr cond_expr;
+  tree case_label, label;
+  vec<tree> labels = vNULL;

auto_vec?

+static void
+c_finish_gimple_return (location_t loc, tree retval)
+{
+  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
+
+  /* Use the expansion point to handle cases such as returning NULL
+     in a function returning void.  */
+  source_location xloc = expansion_point_location_if_in_system_header (loc);
+
+  if (TREE_THIS_VOLATILE (current_function_decl))
+    warning_at (xloc, 0,
+		"function declared %<noreturn%> has a %<return%> statement");
+
+  if (!retval)
+    {
+      current_function_returns_null = 1;
+      if ((warn_return_type || flag_isoc99)

I'm not sure what to do about warnings, but checking the language we are
compiling as seems kind of wrong when we're compiling gimple?

@@ -228,6 +228,12 @@ struct GTY(()) function {
   /* GIMPLE body for this function.  */
   gimple_seq gimple_body;
 
+  /* GIMPLEFE pass to start with */
+  opt_pass *pass_startwith = NULL;

I'm guessing you've only compiled in C++11 mode? because I'm pretty sure
you are using a C++11 feature here (the default member value you
assign).

Thanks!

Trev

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-22 11:17 ` Trevor Saunders
@ 2016-08-22 18:40   ` Prasad Ghangal
  2016-08-22 21:20     ` Trevor Saunders
                       ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: Prasad Ghangal @ 2016-08-22 18:40 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: gcc-patches, Richard Biener

[-- Attachment #1: Type: text/plain, Size: 9185 bytes --]

On 22 August 2016 at 16:55, Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
> On Sun, Aug 21, 2016 at 10:35:17PM +0530, Prasad Ghangal wrote:
>> Hi all,
>>
>> As a part of my gsoc project. I have completed the following tasks:
>>
>> * Parsed gimple-expression
>> * Parsed gimple-labels
>> * Parsed local declaration
>> * Parsed gimple-goto statement
>> * Parsed gimple-if-else statement
>> * Parsed gimple-switch statement
>> * Parsed gimple-return statement
>> * Parsed gimple-PHI function
>> * Parsed gimple ssa-names along with default def
>> * Parsed gimple-call
>>
>> * Hacked pass manager to add support for startwith (pass-name) to skip
>> early opt passes
>> * Modified gimple dump for making it parsable
>>
>> I am willing to continue work on the project, some TODOs for the projects are:
>>
>> * Error handling
>> * Parse more gimple syntax
>> * Add startwith support for IPA passes
>>
>> The complete code of gimple fe project can be found at
>> https://github.com/PrasadG193/gcc_gimple_fe
>>
>>
>> PFA patch for complete project (rebased for latest trunk revision).
>> I have successfully bootstrapped and tested on x86_64-pc-linux-gnu.
>> Some testcases failed due to modified gimple dump as expected.
>>
>>
>> Thanks,
>> Prasad
>
> only some rather minor comments
>
>
> +++ b/gcc/c/c-parser.c
> @@ -59,6 +59,18 @@ along with GCC; see the file COPYING3.  If not see
>  #include "gimple-expr.h"
>  #include "context.h"
>  #include "gcc-rich-location.h"
> +#include "tree-vrp.h"
>
> given that you need these headers it might be better to put most of the
> gimple parsing in its own file so only what actually needs to know about
> this part of the compiler does now about it.
>
> +void
> +c_parser_parse_gimple_body (c_parser *parser)
> +{
> +  bool return_p = false;
> +  gimple_seq seq;
> +  gimple_seq body;
> +  tree stmt = push_stmt_list ();
>
> it would be nice to move the declarations down to their first use.
>
> +      gimple *ret;
> +      ret = gimple_build_return (NULL);
>
> there's no reason for a separate declaration and assignment ;)
>
> +  tree block = NULL;
> +  block = pop_scope ();
>
> same here, and a number of other places.
>
> +c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
> +{
> +  bool return_p = false;
> +
> +  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
> +      return return_p;
>
> return false would work fine.
>
> +
> +  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
> +    {
> +      c_parser_consume_token (parser);
> +      goto out;
>
> I don't see the need for the gotos, there's no cleanup in this function.
>
> +  /* gimple PHI expression.  */
> +  if (c_parser_next_token_is_keyword (parser, RID_PHI))
> +    {
> +      c_parser_consume_token (parser);
> +
> +      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
> +       {
> +         return;
> +       }
> +
> +      gcall *call_stmt;
> +      tree arg = NULL_TREE;
> +      vec<tree> vargs = vNULL;
>
> I think you can use auto_vec here, as is I think this leaks the vectors
> storage.
>
> +c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)
>
> you can skip the explicit 'enum' keyword.
>
> +  struct {
> +    /* The expression at this stack level.  */
> +    struct c_expr expr;
>
> similar with struct here.
>
> +    /* The precedence of the operator on its left, PREC_NONE at the
> +       bottom of the stack.  */
> +    enum c_parser_prec prec;
> +    /* The operation on its left.  */
> +    enum tree_code op;
> +    /* The source location of this operation.  */
> +    location_t loc;
> +  } stack[2];
> +  int sp;
> +  /* Location of the binary operator.  */
> +  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
> +#define POP                                                                  \
>
> it seems like it would be nicer to name the type, and then make this a
> function.
>
> +                                       RO_UNARY_STAR);
> +       ret.src_range.m_start = op_loc;
> +       ret.src_range.m_finish = finish;
> +       return ret;
> +      }
> +    case CPP_PLUS:
> +      if (!c_dialect_objc () && !in_system_header_at (input_location))
> +       warning_at (op_loc,
> +                   OPT_Wtraditional,
> +                   "traditional C rejects the unary plus operator");
>
> does it really make sense to warn about C issues when compiling gimple?
>
> +c_parser_parse_ssa_names (c_parser *parser)
> +{
> +  tree id = NULL_TREE;
> +  c_expr ret;
> +  char *var_name, *var_version, *token;
> +  ret.original_code = ERROR_MARK;
> +  ret.original_type = NULL;
> +
> +  /* ssa token string.  */
> +  const char *ssa_token = NULL;
> +  ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
> +  token = new char [strlen (ssa_token)];
>
> I'm not sure I see why you need this copy, and getting rid of it would
> mean you don't need to free it.
>
> +  strcpy (token, ssa_token);
> +
> +  /* seperate var name and version.  */
> +  var_version = strrchr (token, '_');
> +  if (var_version)
> +    {
> +      var_name = new char[var_version - token + 1];
>
> you should free this when done with it.
>
> +c_parser_gimple_postfix_expression (c_parser *parser)
> +{
> +  struct c_expr expr;
> +  location_t loc = c_parser_peek_token (parser)->location;;
>
> extra ;
>
> +    case CPP_OBJC_STRING:
> +      gcc_assert (c_dialect_objc ());
> +      expr.value
> +       = objc_build_string_object (c_parser_peek_token (parser)->value);
> +      set_c_expr_source_range (&expr, tok_range);
> +      c_parser_consume_token (parser);
> +      break;
>
> is there a reason to support objc stuff in gimple?
>
> +c_parser_gimple_expr_list (c_parser *parser, bool convert_p,
> +                   vec<tree, va_gc> **p_orig_types,
> +                   location_t *sizeof_arg_loc, tree *sizeof_arg,
> +                   vec<location_t> *locations,
> +                   unsigned int *literal_zero_mask)
> +{
> +  vec<tree, va_gc> *ret;
> +  vec<tree, va_gc> *orig_types;
> +  struct c_expr expr;
> +  location_t loc = c_parser_peek_token (parser)->location;
> +  location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION;
> +  unsigned int idx = 0;
> +
> +  ret = make_tree_vector ();
> +  if (p_orig_types == NULL)
> +    orig_types = NULL;
> +  else
> +    orig_types = make_tree_vector ();
> +
> +  if (sizeof_arg != NULL
> +      && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
> +    cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
> +  if (literal_zero_mask)
> +    c_parser_check_literal_zero (parser, literal_zero_mask, 0);
> +  expr = c_parser_gimple_unary_expression (parser);
> +  if (convert_p)
> +    expr = convert_lvalue_to_rvalue (loc, expr, true, true);
> +  ret->quick_push (expr.value);
>
>  That kind of relies on the details of make_tree_vector (), so it seems
>  somewhat safer to use vec_safe_push.
>
> +  if (orig_types)
> +    orig_types->quick_push (expr.original_type);
>
> same
>
> +c_parser_gimple_declaration (c_parser *parser)
> +{
> +  struct c_declspecs *specs;
> +  struct c_declarator *declarator;
> +  specs = build_null_declspecs ();
> +  c_parser_declspecs (parser, specs, true, true, true,
> +                     true, true, cla_nonabstract_decl);
> +  finish_declspecs (specs);
> +  bool auto_type_p = specs->typespec_word == cts_auto_type;
>
> is it useful to support auto here in gimple?
>
> +c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
> +{
> +  c_expr cond_expr;
> +  tree case_label, label;
> +  vec<tree> labels = vNULL;
>
> auto_vec?
>
> +static void
> +c_finish_gimple_return (location_t loc, tree retval)
> +{
> +  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
> +
> +  /* Use the expansion point to handle cases such as returning NULL
> +     in a function returning void.  */
> +  source_location xloc = expansion_point_location_if_in_system_header (loc);
> +
> +  if (TREE_THIS_VOLATILE (current_function_decl))
> +    warning_at (xloc, 0,
> +               "function declared %<noreturn%> has a %<return%> statement");
> +
> +  if (!retval)
> +    {
> +      current_function_returns_null = 1;
> +      if ((warn_return_type || flag_isoc99)
>
> I'm not sure what to do about warnings, but checking the language we are
> compiling as seems kind of wrong when we're compiling gimple?
>
> @@ -228,6 +228,12 @@ struct GTY(()) function {
>    /* GIMPLE body for this function.  */
>    gimple_seq gimple_body;
>
> +  /* GIMPLEFE pass to start with */
> +  opt_pass *pass_startwith = NULL;
>
> I'm guessing you've only compiled in C++11 mode? because I'm pretty sure
> you are using a C++11 feature here (the default member value you
> assign).
>
> Thanks!
>
> Trev
>

Hi Trevor,

Thanks for your feedback. I had missed removing some unwanted code
while code cleanup. I have updated the patch.
I am not sure if we should move all gimple parsing related functions
to the new file (?)

I am not getting what did you mean by C++11 mode (I am not explicitly
giving any option while configure or make). I also have successfully
bootstrapped and tested the project on another system. Is there any
way to check that ?


Thanks,
Prasad

[-- Attachment #2: ChangeLog.patch --]
[-- Type: text/x-diff, Size: 5458 bytes --]

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1929ba8..cded23f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,55 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+	
+	* cgraphunit.c (cgraph_node::assemble_thunks_and_aliases): New variable.
+	(cgraph_node::expand): Add new argument to function.
+	execute_pass_list, guard gcc_assert (TREE_ASM_WRITTEN (decl)) with 
+	condition.
+	* coretypes.h (tree_node *const_tree): New decl, add headers, new
+	variables.
+	* function.h (struct GTY()) function): Add new member to store
+	startwith pass also add new member as a flag.
+	* gimple-pretty-print.c (dump_gimple_switch): Change dumping formats.
+	(dump_gimple_label): Remove condition for DECL_NONLOCAL, flags & 
+	TDF_EH, EH_LANDING_PAD_NR. Change dumping format.
+	(dump_ssaname_info_to_file): Change passing arguments of dump_gimple_phi
+	(dump_gimple_phi): Remove condition for comment, change format of
+	dumping PHI and PHI arguments.
+	(pp_gimple_stmt_1): Remove argument of dump_gimple_phi function.
+	(dump_gimple_bb_header): Change format of dumping gimple basic block
+	header.
+	(dump_phi_nodes): Remove argument of dump_gimple_phi function.
+	(pp_cfg_jump): Remove stmt, remove condition for GIMPLE_LABEL, change 
+	dumping format of gimple basic block header.
+	(gimple_dump_bb_for_graph): Change format of dumping gimple basic block
+	* gimplify.c (gimplify_function_tree): Add condition for presence of
+	gimple body in the cfun.
+	* internal-fn.c (expand_PHI): New function.
+	* internal-fn.h (expand_PHI): Declared here.
+	* internal-fn.def: New defination for PHI.
+	* passes.c (do_per_function_toporder): Add new argument flag, add new
+	argument in callback function call.
+	(execute_one_pass): Add new function argument, add condition for 
+	skipping passes until startwith pass.
+	(execute_pass_list_1): Add new function argument, add condition to 
+	check starwith flag.
+	(execute_ipa_pass_list): New variable, add condition to check and skip
+	passes for startwith pass, pass new argument to function 
+	do_per_function_toporder.
+	* tree-pass.h (execute_one_pass): Add new argument to the function.
+	(execute_pass_list): Likewise.
+	* tree-cfg.c (lower_phi_internal_fn): New function.
+	(verify_gimple_call): Condition for passing label as arg in internal
+	function PHI.
+	(dump_function_to_file): Change format of gimple dump.
+	* tree-into-ssa.c (rewrite_add_phi_arguments): New variable, add 
+	condition for avoiding ssa name versions.
+	* tree-pretty-print.c (dump_decl_name): Change format of dumping gimple
+	labels.
+	(dump_function_header): Change format of gimple dump header
+	* tree-ssanames.c (make_ssa_name_fn): New argument, check for version
+	and assign proper version for parsed ssa names.
+	* tree-ssanames.h (make_ssa_name_fn): Add new argument to the function.
+
 2016-08-20  Kugan Vivekanandarajah  <kuganv@linaro.org>
 
 	* Makefile.in: Add tree-vrp.h to GTFILES.
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index bec37cf..a8c0ab1 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+	
+	* c-common.h (c_common_resword): Add RID_GIMPLE, RID_PHI types.
+	* c-common.h (enum rid): Add RID_GIMPLE, RID_PHI.
+	* c.opt (fgimple): New option.
+
 2016-08-19  Joseph Myers  <joseph@codesourcery.com>
 
 	PR c/32187
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 8d9d4aa..71e78f3 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,29 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+	
+	* c_parser.c: Add headers.
+	(c_parser_parse_gimple_body): New function.
+	(c_parser_gimple_compound_statement): Likewise.
+	(c_parser_gimple_label): Likewise.
+	(c_parser_gimple_expression): Likewise
+	(c_parser_gimple_binary_expression): Likewise.
+	(c_parser_gimple_unary_expression): Likewise.
+	(c_parser_gimple_postfix_expression): Likewise.
+	(c_parser_gimple_postfix_expression_after_primary): Likewise.
+	(c_parser_gimple_pass_list): Likewise.
+	(c_parser_gimple_pass_list_params): Likewise.
+	(c_parser_gimple_declaration): Likewise.
+	(c_parser_gimple_goto_stmt): Likewise.
+	(c_parser_gimple_if_stmt): Likewise.
+	(c_parser_gimple_switch_stmt): Likewise.
+	(c_parser_gimple_return_stmt): Likewise.
+	(c_finish_gimple_return): Likewise.
+	(c_parser_parse_ssa_names): Likewise.
+	(c_parser_gimple_paren_condition): Likewise.
+	(c_parser_gimple_expr_list): Likewise.
+	(c_parser_declaration_or_fndef): New decls. Call function.
+	c_parser_gimple_pass_list, set startwith passes, call
+	c_parser_parse_gimple_body.
+
 2016-08-19  Joseph Myers  <joseph@codesourcery.com>
 
 	PR c/32187
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6201e0c..3da6354 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,19 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+
+	* gcc.dg/gimplefe-1.c: New testcase.
+	* gcc.dg/gimplefe-2.c: Likewise.
+	* gcc.dg/gimplefe-3.c: Likewise.
+	* gcc.dg/gimplefe-4.c: Likewise.
+	* gcc.dg/gimplefe-5.c: Likewise.
+	* gcc.dg/gimplefe-6.c: Likewise.
+	* gcc.dg/gimplefe-7.c: Likewise.
+	* gcc.dg/gimplefe-8.c: Likewise.
+	* gcc.dg/gimplefe-9.c: Likewise.
+	* gcc.dg/gimplefe-10.c: Likewise.
+	* gcc.dg/gimplefe-11.c: Likewise.
+	* gcc.dg/gimplefe-12.c: Likewise.
+	* gcc.dg/gimplefe-13.c: Likewise.
+
 2016-08-20  Kugan Vivekanandarajah  <kuganv@linaro.org>
 
 	PR tree-optimization/61839


[-- Attachment #3: gimplefe.patch --]
[-- Type: text/x-diff, Size: 69972 bytes --]

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 32468ca..5b43016 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -522,6 +522,8 @@ const struct c_common_resword c_common_reswords[] =
   { "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY },
   { "__volatile",	RID_VOLATILE,	0 },
   { "__volatile__",	RID_VOLATILE,	0 },
+  { "__GIMPLE",		RID_GIMPLE,	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-family/c-common.h b/gcc/c-family/c-common.h
index bc22baa..17dc91e 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -118,6 +118,12 @@ enum rid
 
   RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN,
 
+  /* "__GIMPLE", for the GIMPLE-parsing extension to the C frontend. */
+  RID_GIMPLE,
+
+  /* "__PHI", for parsing PHI function in GIMPLE FE.  */
+  RID_PHI,
+
   /* C11 */
   RID_ALIGNAS, RID_GENERIC,
 
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index a5358ed..3c4d2cc 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -200,6 +200,10 @@ F
 Driver C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -F <dir>	Add <dir> to the end of the main framework include path.
 
+fgimple
+C Var(flag_gimple) Init(0)
+Enable parsing GIMPLE
+
 H
 C ObjC C++ ObjC++
 Print the name of header files as they are used.
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index fe0c95f..6ce817a 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -59,6 +59,18 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-expr.h"
 #include "context.h"
 #include "gcc-rich-location.h"
+#include "tree-vrp.h"
+#include "tree-pass.h"
+#include "tree-pretty-print.h"
+#include "tree.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-pretty-print.h"
+#include "tree-ssa.h"
+#include "pass_manager.h"
+#include "tree-ssanames.h"
+#include "gimple-ssa.h"
+#include "tree-dfa.h"
 
 /* We need to walk over decls with incomplete struct/union/enum types
    after parsing the whole translation unit.
@@ -1416,6 +1428,29 @@ static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context);
 static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
 static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool);
 static void c_parser_cilk_grainsize (c_parser *, bool *);
+static void c_parser_parse_gimple_body (c_parser *);
+static bool c_parser_gimple_compound_statement (c_parser *, gimple_seq *);
+static void c_parser_gimple_label (c_parser *, gimple_seq *);
+static void c_parser_gimple_expression (c_parser *, gimple_seq *);
+static struct c_expr c_parser_gimple_binary_expression (c_parser *, enum tree_code *);
+static struct c_expr c_parser_gimple_unary_expression (c_parser *);
+static struct c_expr c_parser_gimple_postfix_expression (c_parser *);
+static struct c_expr c_parser_gimple_postfix_expression_after_primary (c_parser *,
+								       location_t,
+								       struct c_expr);
+static void c_parser_gimple_pass_list (c_parser *, opt_pass **, bool *);
+static opt_pass *c_parser_gimple_pass_list_params (c_parser *, opt_pass **);
+static void c_parser_gimple_declaration (c_parser *);
+static void c_parser_gimple_goto_stmt (location_t, tree, gimple_seq *);
+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 *, bool,
+		    vec<tree, va_gc> **, location_t *, tree *,
+		    vec<location_t> *, unsigned int *);
 
 /* Parse a translation unit (C90 6.7, C99 6.9).
 
@@ -1659,6 +1694,9 @@ 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;
+  opt_pass *pass = NULL;
+  bool startwith_p = false;
 
   if (static_assert_ok
       && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
@@ -1743,6 +1781,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       c_parser_skip_to_end_of_block_or_statement (parser);
       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, &startwith_p);
+	  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))
@@ -2144,6 +2196,13 @@ 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 (pass)
+	{
+	  cfun->pass_startwith = pass;
+	  cfun->startwith = startwith_p;
+	}
+
       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,
@@ -2152,6 +2211,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
 	= c_parser_peek_token (parser)->location;
+
+      if (gimple_body_p && flag_gimple)
+	{
+	  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);
@@ -18194,4 +18267,1460 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
   return value_tree;
 }
 
+/* Parse the body of a function declaration marked with "__GIMPLE".  */
+
+void
+c_parser_parse_gimple_body (c_parser *parser)
+{
+  gimple_seq seq = NULL;
+  gimple_seq body = NULL;
+  tree stmt = push_stmt_list ();
+  push_scope ();
+  location_t loc1 = c_parser_peek_token (parser)->location;
+
+  init_tree_ssa (cfun);
+
+  if(!c_parser_gimple_compound_statement (parser, &seq))
+    {
+      gimple *ret = gimple_build_return (NULL);
+      gimple_seq_add_stmt (&seq, ret);
+    }
+
+  tree block = pop_scope ();
+  stmt = pop_stmt_list (stmt);
+  stmt = c_build_bind_expr (loc1, block, stmt);
+
+  block = DECL_INITIAL (current_function_decl);
+  BLOCK_SUBBLOCKS (block) = NULL_TREE;
+  BLOCK_CHAIN (block) = NULL_TREE;
+  TREE_ASM_WRITTEN (block) = 1;
+
+  gbind *bind_stmt = gimple_build_bind (BIND_EXPR_VARS (stmt), NULL,
+					BIND_EXPR_BLOCK (stmt));
+  gimple_bind_set_body (bind_stmt, seq);
+  gimple_seq_add_stmt (&body, bind_stmt);
+  gimple_set_body (current_function_decl, body);
+  cfun->curr_properties = PROP_gimple_any;
+
+  return;
+}
+
+/* Parse a compound statement in gimple function body.
+
+   gimple-statement:
+     gimple-statement
+     gimple-declaration-statement
+     gimple-if-statement
+     gimple-switch-statement
+     gimple-labeled-statement
+     gimple-expression-statement
+     gimple-goto-statement
+     gimple-phi-statement
+     gimple-return-statement
+*/
+
+static bool
+c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
+{
+  bool return_p = false;
+
+  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+    return false;
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      c_parser_consume_token (parser);
+      return false;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      c_parser_error (parser, "expected declaration or statement");
+      c_parser_consume_token (parser);
+      return false;
+    }
+
+  while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+    {
+
+      if (parser->error)
+	{
+	  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
+	  return return_p;
+	}
+
+      if (c_parser_next_token_is (parser, CPP_NAME)
+	  && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+	c_parser_gimple_label (parser, seq);
+
+      else if (c_parser_next_tokens_start_declaration (parser))
+	c_parser_gimple_declaration (parser);
+
+      else if (c_parser_next_token_is (parser, CPP_EOF))
+	{
+	  c_parser_error (parser, "expected declaration or statement");
+	  return return_p;
+	}
+
+      else
+	{
+	  switch (c_parser_peek_token (parser)->type)
+	    {
+	    case CPP_KEYWORD:
+	      switch (c_parser_peek_token (parser)->keyword)
+		{
+		case RID_IF:
+		  c_parser_gimple_if_stmt (parser, seq);
+		  break;
+		case RID_SWITCH:
+		  c_parser_gimple_switch_stmt (parser, seq);
+		  break;
+		case RID_GOTO:
+		    {
+		      location_t loc = c_parser_peek_token (parser)->location;
+		      c_parser_consume_token (parser);
+		      if (c_parser_next_token_is (parser, CPP_NAME))
+			{
+			  c_parser_gimple_goto_stmt (loc,
+						     c_parser_peek_token (parser)->value,
+						     seq);
+			  c_parser_consume_token (parser);
+			  if (!c_parser_require (parser, CPP_SEMICOLON,
+						 "expected %<;%>"))
+			    return return_p;
+			}
+		    }
+		  break;
+		case RID_RETURN:
+		  return_p = true;
+		  c_parser_gimple_return_stmt (parser, seq);
+		  if (!c_parser_require (parser, CPP_SEMICOLON,
+					 "expected %<;%>"))
+		    return return_p;
+		  break;
+		default:
+		  goto expr_stmt;
+		}
+	      break;
+	    case CPP_SEMICOLON:
+	      c_parser_consume_token (parser);
+	      break;
+	    default:
+	    expr_stmt:
+	      c_parser_gimple_expression (parser, seq);
+	      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+		return return_p;
+	    }
+	}
+    }
+  c_parser_consume_token (parser);
+  return return_p; 
+}
+
+/* Parse a gimple expression.
+
+   gimple-expression:
+     gimple-unary-expression
+     gimple-call-statement
+     gimple-binary-expression
+     gimple-assign-expression
+     gimple-cast-expression
+
+*/
+
+static void
+c_parser_gimple_expression (c_parser *parser, gimple_seq *seq)
+{
+  c_expr lhs, rhs;
+  gimple *assign = NULL;
+  enum tree_code subcode = NOP_EXPR;
+  location_t loc;
+  tree arg = NULL_TREE;
+  auto_vec<tree> vargs;
+
+
+  lhs = c_parser_gimple_unary_expression (parser);
+
+  if (c_parser_next_token_is (parser, CPP_EQ))
+    {
+      c_parser_consume_token (parser);
+    }
+
+  loc = EXPR_LOCATION (lhs.value);
+
+  /* gimple call expression. */
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON) &&
+      TREE_CODE (lhs.value) == CALL_EXPR)
+    {
+      gimple *call;
+      call = gimple_build_call_from_tree (lhs.value);
+      gimple_seq_add_stmt (seq, call);
+      gimple_set_location (call, loc);
+      return;
+    }
+
+  /* cast expression.  */
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+    {
+      rhs = c_parser_cast_expression (parser, NULL);	  //TODO: have a gimple_cast_expr function
+      if (lhs.value != error_mark_node &&
+	  rhs.value != error_mark_node)
+	{
+	  assign = gimple_build_assign (lhs.value, rhs.value);
+	  gimple_seq_add_stmt (seq, assign);
+	  gimple_set_location (assign, loc);
+	  return;
+	}
+    }
+
+  if (POINTER_TYPE_P (TREE_TYPE (lhs.value)))
+    {
+      STRIP_USELESS_TYPE_CONVERSION (rhs.value);
+      if (!useless_type_conversion_p (TREE_TYPE (lhs.value),
+				      TREE_TYPE (rhs.value)))
+	rhs.value = fold_convert_loc (loc, TREE_TYPE (lhs.value), rhs.value);
+    }
+
+  /* pointer expression.  */
+  if (TREE_CODE (lhs.value) == INDIRECT_REF)
+    {
+      tree save_expr = lhs.value;
+      bool volatilep = TREE_THIS_VOLATILE (lhs.value);
+      bool notrap = TREE_THIS_NOTRAP (lhs.value);
+      tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (lhs.value, 0));
+
+      lhs.value = fold_indirect_ref_loc (loc, lhs.value);
+      if (lhs.value == save_expr)
+	{
+	  lhs.value = fold_build2_loc (input_location, MEM_REF,
+				       TREE_TYPE (lhs.value),
+				       TREE_OPERAND (lhs.value, 0),
+				       build_int_cst (saved_ptr_type, 0));
+	  TREE_THIS_VOLATILE (lhs.value) = volatilep;
+	  TREE_THIS_NOTRAP (lhs.value) = notrap;
+	}
+    }
+
+  if (c_parser_next_token_is (parser, CPP_AND) ||
+      c_parser_next_token_is (parser, CPP_MULT) ||
+      c_parser_next_token_is (parser, CPP_PLUS) ||
+      c_parser_next_token_is (parser, CPP_MINUS) ||
+      c_parser_next_token_is (parser, CPP_COMPL) ||
+      c_parser_next_token_is (parser, CPP_NOT))
+    {
+      rhs = c_parser_gimple_unary_expression (parser);
+      assign = gimple_build_assign (lhs.value, rhs.value);
+      gimple_set_location (assign, loc);
+      gimple_seq_add_stmt (seq, assign);
+      return;
+    }
+
+  /* gimple PHI expression.  */
+  if (c_parser_next_token_is_keyword (parser, RID_PHI))
+    {
+      c_parser_consume_token (parser);
+
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+	{
+	  return;
+	}
+
+      if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+	c_parser_consume_token (parser);
+
+      while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+	{
+	  if (c_parser_next_token_is (parser, CPP_NAME) &&
+	      c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+	    {
+	      arg = lookup_label_for_goto (loc,
+					   c_parser_peek_token (parser)->value);
+	      c_parser_consume_token (parser);
+
+	      if (c_parser_next_token_is (parser, CPP_COLON))
+		c_parser_consume_token (parser);
+	      vargs.safe_push (arg);
+	    }
+	  else if (c_parser_next_token_is (parser, CPP_COMMA))
+	    {
+	      c_parser_consume_token (parser);
+	    }
+	  else
+	    {
+	      arg = c_parser_parse_ssa_names (parser).value;
+	      vargs.safe_push (arg);
+	    }
+	}
+
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+				 "expected %<)%>");
+
+      /* build internal function for PHI. */
+      gcall *call_stmt = gimple_build_call_internal_vec (IFN_PHI, vargs);
+      gimple_call_set_lhs (call_stmt, lhs.value);
+      gimple_set_location (call_stmt, UNKNOWN_LOCATION);
+      gimple_seq_add_stmt (seq, call_stmt);
+      return;
+    }
+
+  /* gimple call with lhs. */
+  if (c_parser_next_token_is (parser, CPP_NAME) &&
+      c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN &&
+      lookup_name (c_parser_peek_token (parser)->value))
+    {
+      rhs = c_parser_gimple_unary_expression (parser);
+      gimple *call = gimple_build_call_from_tree (rhs.value);
+      gimple_call_set_lhs (call, lhs.value);
+      gimple_seq_add_stmt (seq, call);
+      gimple_set_location (call, loc);
+      return;
+    }
+
+  location_t exp_location = c_parser_peek_token (parser)->location;
+  rhs = c_parser_gimple_binary_expression (parser, &subcode);
+  rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true);
+
+  if (lhs.value != error_mark_node &&
+      rhs.value != error_mark_node)
+    {
+      if (subcode == NOP_EXPR)
+	assign = gimple_build_assign (lhs.value, rhs.value);
+      else
+	assign = gimple_build_assign (lhs.value, subcode,
+				      TREE_OPERAND (rhs.value, 0),
+				      TREE_OPERAND (rhs.value, 1));
+      gimple_seq_add_stmt (seq, assign);
+      gimple_set_location (assign, loc);
+    }
+  return;
+}
+
+/* Parse gimple binary expr.
+
+   gimple-multiplicative-expression:
+     gimple-unary-expression * gimple-unary-expression
+     gimple-unary-expression / gimple-unary-expression
+     gimple-unary-expression % gimple-unary-expression
+
+   gimple-additive-expression:
+     gimple-unary-expression + gimple-unary-expression
+     gimple-unary-expression - gimple-unary-expression
+
+   gimple-shift-expression:
+     gimple-unary-expression << gimple-unary-expression
+     gimple-unary-expression >> gimple-unary-expression
+
+   gimple-relational-expression:
+     gimple-unary-expression < gimple-unary-expression
+     gimple-unary-expression > gimple-unary-expression
+     gimple-unary-expression <= gimple-unary-expression
+     gimple-unary-expression >= gimple-unary-expression
+
+   gimple-equality-expression:
+     gimple-unary-expression == gimple-unary-expression
+     gimple-unary-expression != gimple-unary-expression
+
+   gimple-AND-expression:
+     gimple-unary-expression & gimple-unary-expression
+
+   gimple-exclusive-OR-expression:
+     gimple-unary-expression ^ gimple-unary-expression
+
+   gimple-inclusive-OR-expression:
+     gimple-unary-expression | gimple-unary-expression
+
+   gimple-logical-AND-expression:
+     gimple-unary-expression && gimple-unary-expression
+
+   gimple-logical-OR-expression:
+     gimple-unary-expression || gimple-unary-expression
+
+*/
+
+static c_expr
+c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)
+{
+  struct {
+    /* The expression at this stack level.  */
+    struct c_expr expr;
+    /* The operation on its left.  */
+    enum tree_code op;
+    /* The source location of this operation.  */
+    location_t loc;
+  } stack[2];
+  int sp;
+  /* Location of the binary operator.  */
+  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
+#define POP								      \
+  do {									      \
+    switch (stack[sp].op)						      \
+      {									      \
+      case TRUTH_ANDIF_EXPR:						      \
+	c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value	      \
+					  == truthvalue_false_node);	      \
+	break;								      \
+      case TRUTH_ORIF_EXPR:						      \
+	c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value	      \
+					  == truthvalue_true_node);	      \
+	break;								      \
+      default:								      \
+	break;								      \
+      }									      \
+    stack[sp - 1].expr							      \
+      = convert_lvalue_to_rvalue (stack[sp - 1].loc,			      \
+				  stack[sp - 1].expr, true, true);	      \
+    stack[sp].expr							      \
+      = convert_lvalue_to_rvalue (stack[sp].loc,			      \
+				  stack[sp].expr, true, true);		      \
+    if (sp == 1								      \
+	&& c_parser_peek_token (parser)->type == CPP_SEMICOLON		      \
+	&& (((1 << PREC_BITOR) | (1 << PREC_BITXOR) | (1 << PREC_BITAND)      \
+	       | (1 << PREC_SHIFT) | (1 << PREC_ADD) | (1 << PREC_MULT)))     \
+	&& stack[sp].op != TRUNC_MOD_EXPR				      \
+	&& stack[0].expr.value != error_mark_node			      \
+	&& stack[1].expr.value != error_mark_node)			      \
+      stack[0].expr.value						      \
+	= build2 (stack[1].op, TREE_TYPE (stack[0].expr.value),		      \
+		  stack[0].expr.value, stack[1].expr.value);		      \
+    else								      \
+      stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,	      \
+						   stack[sp].op,	      \
+						   stack[sp - 1].expr,	      \
+						   stack[sp].expr);	      \
+    sp--;								      \
+  } while (0)
+  stack[0].loc = c_parser_peek_token (parser)->location;
+  stack[0].expr = c_parser_gimple_unary_expression (parser);
+  sp = 0;
+  source_range src_range;
+  if (parser->error)
+    goto out;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_MULT:
+      *subcode = MULT_EXPR;
+      break;
+    case CPP_DIV:
+      *subcode = TRUNC_DIV_EXPR;
+      break;
+    case CPP_MOD:
+      *subcode = TRUNC_MOD_EXPR;
+      break;
+    case CPP_PLUS:
+      *subcode = PLUS_EXPR;
+      break;
+    case CPP_MINUS:
+      *subcode = MINUS_EXPR;
+      break;
+    case CPP_LSHIFT:
+      *subcode = LSHIFT_EXPR;
+      break;
+    case CPP_RSHIFT:
+      *subcode = RSHIFT_EXPR;
+      break;
+    case CPP_LESS:
+      *subcode = LT_EXPR;
+      break;
+    case CPP_GREATER:
+      *subcode = GT_EXPR;
+      break;
+    case CPP_LESS_EQ:
+      *subcode = LE_EXPR;
+      break;
+    case CPP_GREATER_EQ:
+      *subcode = GE_EXPR;
+      break;
+    case CPP_EQ_EQ:
+      *subcode = EQ_EXPR;
+      break;
+    case CPP_NOT_EQ:
+      *subcode = NE_EXPR;
+      break;
+    case CPP_AND:
+      *subcode = BIT_AND_EXPR;
+      break;
+    case CPP_XOR:
+      *subcode = BIT_XOR_EXPR;
+      break;
+    case CPP_OR:
+      *subcode = BIT_IOR_EXPR;
+      break;
+    case CPP_AND_AND:
+      *subcode = TRUTH_ANDIF_EXPR;
+      break;
+    case CPP_OR_OR:
+      *subcode = TRUTH_ORIF_EXPR;
+      break;
+    default:
+      /* Not a binary operator, so end of the binary
+	 expression.  */
+      *subcode = NOP_EXPR;
+      goto out;
+    }
+  binary_loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_token (parser);
+  switch (*subcode)
+    {
+    case TRUTH_ANDIF_EXPR:
+      src_range = stack[sp].expr.src_range;
+      stack[sp].expr
+	= convert_lvalue_to_rvalue (stack[sp].loc,
+				    stack[sp].expr, true, true);
+      stack[sp].expr.value = c_objc_common_truthvalue_conversion
+	(stack[sp].loc, default_conversion (stack[sp].expr.value));
+      c_inhibit_evaluation_warnings += (stack[sp].expr.value
+					== truthvalue_false_node);
+      set_c_expr_source_range (&stack[sp].expr, src_range);
+      break;
+    case TRUTH_ORIF_EXPR:
+      src_range = stack[sp].expr.src_range;
+      stack[sp].expr
+	= convert_lvalue_to_rvalue (stack[sp].loc,
+				    stack[sp].expr, true, true);
+      stack[sp].expr.value = c_objc_common_truthvalue_conversion
+	(stack[sp].loc, default_conversion (stack[sp].expr.value));
+      c_inhibit_evaluation_warnings += (stack[sp].expr.value
+					== truthvalue_true_node);
+      set_c_expr_source_range (&stack[sp].expr, src_range);
+      break;
+    default:
+      break;
+    }
+  sp++;
+  stack[sp].loc = binary_loc;
+  stack[sp].expr = c_parser_gimple_unary_expression (parser);
+  stack[sp].op = *subcode;
+out:
+  while (sp > 0)
+    POP;
+  return stack[0].expr;
+#undef POP
+
+}
+
+/* Parse gimple unary expression.
+
+   gimple-unary-expression:
+     gimple-postfix-expression
+     unary-operator cast-expression
+
+   unary-operator: one of
+     & * + - ~ !
+*/
+
+static c_expr
+c_parser_gimple_unary_expression (c_parser *parser)
+{
+  struct c_expr ret, op;
+  if (c_parser_peek_token (parser)->value
+      && TREE_CODE (c_parser_peek_token (parser)->value) == IDENTIFIER_NODE
+      && !lookup_name (c_parser_peek_token (parser)->value))
+    return c_parser_parse_ssa_names (parser);
+
+  location_t op_loc = c_parser_peek_token (parser)->location;
+  location_t exp_loc;
+  location_t finish;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_AND:
+      c_parser_consume_token (parser);
+      op = c_parser_cast_expression (parser, NULL);
+      mark_exp_read (op.value);
+      return parser_build_unary_op (op_loc, ADDR_EXPR, op);
+    case CPP_MULT:
+      {
+	c_parser_consume_token (parser);
+	exp_loc = c_parser_peek_token (parser)->location;
+	op = c_parser_cast_expression (parser, NULL);
+	finish = op.get_finish ();
+	op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
+	location_t combined_loc = make_location (op_loc, op_loc, finish);
+	ret.value = build_indirect_ref (combined_loc, op.value,
+					RO_UNARY_STAR);
+	ret.src_range.m_start = op_loc;
+	ret.src_range.m_finish = finish;
+	return ret;
+      }
+    case CPP_PLUS:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
+      return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
+    case CPP_MINUS:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
+      return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
+    case CPP_COMPL:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
+      return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
+    case CPP_NOT:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
+      return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
+    default:
+      return c_parser_gimple_postfix_expression (parser);
+    }
+}
+
+/* Parse gimple ssa names.  */
+
+static c_expr
+c_parser_parse_ssa_names (c_parser *parser)
+{
+  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;
+
+  /* ssa token string.  */
+  const char *ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+  token = new char [strlen (ssa_token)];
+  strcpy (token, ssa_token);
+
+  /* seperate 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);
+
+      /* lookup for parent decl.  */
+      if (lookup_name (id))
+	{
+	  var_version++;
+	  unsigned int version;
+	  version = atoi (var_version);
+	  if (var_version && version)
+	    {
+	      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);
+	    }
+	}
+    }
+
+  /* for default defination ssa names.  */
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      c_parser_consume_token (parser);
+      ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (!strcmp ("D", ssa_token))
+	{
+	  set_ssa_default_def (cfun, lookup_name (id), ret.value);
+	  c_parser_consume_token (parser);
+	}
+      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+	goto out;
+    }
+
+  out:
+  free (var_name);
+  free (token);
+  return ret;
+}
+
+/* Parse gimple postfix expression.
+
+   gimple-postfix-expression:
+     gimple-primary-expression
+     gimple-primary-xpression [ gimple-primary-expression ]
+     gimple-primary-expression ( gimple-argument-expression-list[opt] )
+
+   gimple-argument-expression-list:
+     gimple-unary-expression
+     gimple-argument-expression-list , gimple-unary-expression
+
+   gimple-primary-expression:
+     identifier
+     constant
+     string-literal
+
+*/
+
+static struct c_expr
+c_parser_gimple_postfix_expression (c_parser *parser)
+{
+  struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
+  source_range tok_range = c_parser_peek_token (parser)->get_range ();
+  expr.original_code = ERROR_MARK;
+  expr.original_type = NULL;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_NUMBER:
+      expr.value = c_parser_peek_token (parser)->value;
+      set_c_expr_source_range (&expr, tok_range);
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      if (TREE_CODE (expr.value) == FIXED_CST
+	  && !targetm.fixed_point_supported_p ())
+	{
+	  error_at (loc, "fixed-point types not supported for this target");
+	  expr.value = error_mark_node;
+	}
+      break;
+    case CPP_CHAR:
+    case CPP_CHAR16:
+    case CPP_CHAR32:
+    case CPP_WCHAR:
+      expr.value = c_parser_peek_token (parser)->value;
+      set_c_expr_source_range (&expr, tok_range);
+      c_parser_consume_token (parser);
+      break;
+    case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
+    case CPP_WSTRING:
+    case CPP_UTF8STRING:
+      expr.value = c_parser_peek_token (parser)->value;
+      set_c_expr_source_range (&expr, tok_range);
+      expr.original_code = STRING_CST;
+      c_parser_consume_token (parser);
+      break;
+    case CPP_NAME:
+      if (c_parser_peek_token (parser)->id_kind == C_ID_ID)
+	{
+	  tree id = c_parser_peek_token (parser)->value;
+	  c_parser_consume_token (parser);
+	  expr.value = build_external_ref (loc, id,
+					   (c_parser_peek_token (parser)->type
+					    == CPP_OPEN_PAREN),
+					   &expr.original_type);
+	  set_c_expr_source_range (&expr, tok_range);
+	  break;
+	}
+      else
+	{
+	  c_parser_error (parser, "expected expression");
+	  expr.set_error ();
+	  break;
+	}
+      break;
+    default:
+      c_parser_error (parser, "expected expression");
+      expr.set_error ();
+      break;
+    }
+  return c_parser_gimple_postfix_expression_after_primary
+    (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
+}
+
+/* Parse a gimple postfix expression after the initial primary or compound
+   literal.  */
+
+static struct c_expr
+c_parser_gimple_postfix_expression_after_primary (c_parser *parser,
+						  location_t expr_loc,
+						  struct c_expr expr)
+{
+  struct c_expr orig_expr;
+  location_t sizeof_arg_loc[3];
+  tree sizeof_arg[3];
+  unsigned int literal_zero_mask;
+  unsigned int i;
+  vec<tree, va_gc> *exprlist;
+  vec<tree, va_gc> *origtypes = NULL;
+  vec<location_t> arg_loc = vNULL;
+  location_t start;
+  location_t finish;
+
+  location_t op_loc = c_parser_peek_token (parser)->location;
+
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_OPEN_SQUARE:
+	{
+	  c_parser_consume_token (parser);
+	  tree idx = c_parser_gimple_unary_expression (parser).value;
+
+	  if (!c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>"))
+	    break;
+
+	  start = expr.get_start ();
+	  finish = parser->tokens_buf[0].location;
+	  expr.value = build_array_ref (op_loc, expr.value, idx);
+	  set_c_expr_source_range (&expr, start, finish);
+
+	  expr.original_code = ERROR_MARK;
+	  expr.original_type = NULL;
+	  break;
+	}
+    case CPP_OPEN_PAREN:
+	{
+	  /* Function call */
+	  c_parser_consume_token (parser);
+	  for (i = 0; i < 3; i++)
+	    {
+	      sizeof_arg[i] = NULL_TREE;
+	      sizeof_arg_loc[i] = UNKNOWN_LOCATION;
+	    }
+	  literal_zero_mask = 0;
+	  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+	    exprlist = NULL;
+	  else
+	    exprlist = c_parser_gimple_expr_list (parser, true, &origtypes,
+					   sizeof_arg_loc, sizeof_arg,
+					   &arg_loc, &literal_zero_mask);
+	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+				     "expected %<)%>");
+	  orig_expr = expr;
+	  mark_exp_read (expr.value);
+	  if (warn_sizeof_pointer_memaccess)
+	    sizeof_pointer_memaccess_warning (sizeof_arg_loc,
+					      expr.value, exprlist,
+					      sizeof_arg,
+					      sizeof_ptr_memacc_comptypes);
+	  if (TREE_CODE (expr.value) == FUNCTION_DECL
+	      && DECL_BUILT_IN_CLASS (expr.value) == BUILT_IN_NORMAL
+	      && DECL_FUNCTION_CODE (expr.value) == BUILT_IN_MEMSET
+	      && vec_safe_length (exprlist) == 3)
+	    {
+	      tree arg0 = (*exprlist)[0];
+	      tree arg2 = (*exprlist)[2];
+	      warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
+	    }
+
+	  start = expr.get_start ();
+	  finish = parser->tokens_buf[0].get_finish ();
+	  expr.value
+	    = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
+					 exprlist, origtypes);
+	  set_c_expr_source_range (&expr, start, finish);
+
+	  expr.original_code = ERROR_MARK;
+	  if (TREE_CODE (expr.value) == INTEGER_CST
+	      && TREE_CODE (orig_expr.value) == FUNCTION_DECL
+	      && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
+	      && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
+	    expr.original_code = C_MAYBE_CONST_EXPR;
+	  expr.original_type = NULL;
+	  if (exprlist)
+	    {
+	      release_tree_vector (exprlist);
+	      release_tree_vector (origtypes);
+	    }
+	  arg_loc.release ();
+	  break;
+	default:
+	  return expr;
+
+	}
+    }
+  return expr;
+}
+
+/* Parse expression list.
+
+   gimple-expr-list:
+     gimple-unary-expression
+     gimple-expr-list , gimple-unary-expression
+
+ */
+
+static vec<tree, va_gc> *
+c_parser_gimple_expr_list (c_parser *parser, bool convert_p,
+		    vec<tree, va_gc> **p_orig_types,
+		    location_t *sizeof_arg_loc, tree *sizeof_arg,
+		    vec<location_t> *locations,
+		    unsigned int *literal_zero_mask)
+{
+  vec<tree, va_gc> *ret;
+  vec<tree, va_gc> *orig_types;
+  struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
+  location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION;
+  unsigned int idx = 0;
+
+  ret = make_tree_vector ();
+  if (p_orig_types == NULL)
+    orig_types = NULL;
+  else
+    orig_types = make_tree_vector ();
+
+  if (sizeof_arg != NULL
+      && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
+    cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
+  if (literal_zero_mask)
+    c_parser_check_literal_zero (parser, literal_zero_mask, 0);
+  expr = c_parser_gimple_unary_expression (parser);
+  if (convert_p)
+    expr = convert_lvalue_to_rvalue (loc, expr, true, true);
+  vec_safe_push (ret, expr.value);
+  if (orig_types)
+    vec_safe_push (orig_types, expr.original_type);
+  if (locations)
+    locations->safe_push (loc);
+  if (sizeof_arg != NULL
+      && cur_sizeof_arg_loc != UNKNOWN_LOCATION
+      && expr.original_code == SIZEOF_EXPR)
+    {
+      sizeof_arg[0] = c_last_sizeof_arg;
+      sizeof_arg_loc[0] = cur_sizeof_arg_loc;
+    }
+  while (c_parser_next_token_is (parser, CPP_COMMA))
+    {
+      c_parser_consume_token (parser);
+      loc = c_parser_peek_token (parser)->location;
+      if (sizeof_arg != NULL
+	  && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
+	cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
+      else
+	cur_sizeof_arg_loc = UNKNOWN_LOCATION;
+      if (literal_zero_mask)
+	c_parser_check_literal_zero (parser, literal_zero_mask, idx + 1);
+      expr = c_parser_gimple_unary_expression (parser);
+      if (convert_p)
+	expr = convert_lvalue_to_rvalue (loc, expr, true, true);
+      vec_safe_push (ret, expr.value);
+      if (orig_types)
+	vec_safe_push (orig_types, expr.original_type);
+      if (locations)
+	locations->safe_push (loc);
+      if (++idx < 3
+	  && sizeof_arg != NULL
+	  && cur_sizeof_arg_loc != UNKNOWN_LOCATION
+	  && expr.original_code == SIZEOF_EXPR)
+	{
+	  sizeof_arg[idx] = c_last_sizeof_arg;
+	  sizeof_arg_loc[idx] = cur_sizeof_arg_loc;
+	}
+    }
+  if (orig_types)
+    *p_orig_types = orig_types;
+  return ret;
+}
+
+/* Parse gimple label.
+
+   gimple-label:
+     identifier :
+     case constant-expression :
+     default :
+
+*/
+
+static void
+c_parser_gimple_label (c_parser *parser, gimple_seq *seq)
+{
+  tree name = c_parser_peek_token (parser)->value;
+  location_t loc1 = c_parser_peek_token (parser)->location;
+  gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
+  c_parser_consume_token (parser);
+  gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
+  c_parser_consume_token (parser);
+  tree label = define_label (loc1, name);
+  gimple_seq_add_stmt (seq, gimple_build_label (label));
+  return;
+}
+
+/* Parse gimple pass list.
+
+   gimple-pass-list:
+     startwith("pass-name")
+ */
+
+static void
+c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass,
+			   bool *startwith_p)
+{
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      return;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      return;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      c_parser_consume_token (parser);
+      if (!strcmp (op, "startwith"))
+	{
+	  *pass = c_parser_gimple_pass_list_params (parser, pass);
+	  if (!(*pass))
+	    return;
+
+	  *startwith_p = true;
+	  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+	    return;
+	}
+      else
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "invalid operation");
+	  return;
+	}
+    }
+  else if (c_parser_next_token_is (parser, CPP_EOF))
+    {
+      c_parser_error (parser, "expected parameters");
+      return;
+    }
+
+  return;
+}
+
+/* Support function for c_parser_gimple_pass_list.  */
+
+static opt_pass *
+c_parser_gimple_pass_list_params (c_parser *parser, opt_pass **pass)
+{
+  opt_pass *pass_start = NULL, *new_pass;
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      return NULL;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      return NULL;
+    }
+
+  while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+    {
+      if (c_parser_next_token_is (parser, CPP_EOF))
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "expected pass names");
+	  return NULL;
+	}
+
+      if (c_parser_next_token_is (parser, CPP_STRING))
+	{
+	  const char *name = NULL;
+	  name = TREE_STRING_POINTER (c_parser_peek_token (parser)->value);
+	  c_parser_consume_token (parser);
+	  new_pass = g->get_passes ()->get_pass_by_name (name);
+
+	  if (!new_pass)
+	    {
+	      error_at (c_parser_peek_token (parser)->location,
+			"invalid pass name");
+	      parser->error = true;
+	      c_parser_consume_token (parser);
+	      return NULL;
+	    }
+	  if (*pass)
+	    {
+	      (*pass)->next = new_pass;
+	      (*pass) = (*pass)->next;
+	    }
+	  else
+	    {
+	      *pass = new_pass;
+	      pass_start = *pass;
+	    }
+	}
+      else if (c_parser_next_token_is (parser, CPP_COMMA))
+	c_parser_consume_token (parser);
+      else
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "invalid pass name");
+	  c_parser_consume_token (parser);
+	  return NULL;
+	}
+    }
+  return pass_start;
+}
+
+/* Parse gimple local declaration.
+
+   declaration-specifiers:
+     storage-class-specifier declaration-specifiers[opt]
+     type-specifier declaration-specifiers[opt]
+     type-qualifier declaration-specifiers[opt]
+     function-specifier declaration-specifiers[opt]
+     alignment-specifier declaration-specifiers[opt]
+
+   storage-class-specifier:
+     typedef
+     extern
+     static
+     auto
+     register
+
+   type-specifier:
+     void
+     char
+     short
+     int
+     long
+     float
+     double
+     signed
+     unsigned
+     _Bool
+     _Complex
+
+   type-qualifier:
+     const
+     restrict
+     volatile
+     address-space-qualifier
+     _Atomic
+
+ */
+
+static void
+c_parser_gimple_declaration (c_parser *parser)
+{
+  struct c_declarator *declarator;
+  struct c_declspecs *specs = build_null_declspecs ();
+  c_parser_declspecs (parser, specs, true, true, true,
+		      true, true, cla_nonabstract_decl);
+  finish_declspecs (specs);
+  bool auto_type_p = specs->typespec_word == cts_auto_type;
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      if (auto_type_p)
+	error_at (c_parser_peek_token (parser)->location,
+		  "%<__auto_type%> in empty declaration");
+      c_parser_consume_token (parser);
+      return;
+    }
+
+  /* Provide better error recovery.  Note that a type name here is usually
+     better diagnosed as a redeclaration.  */
+  if (specs->typespec_kind == ctsk_tagdef
+      && c_parser_next_token_starts_declspecs (parser)
+      && !c_parser_next_token_is (parser, CPP_NAME))
+    {
+      c_parser_error (parser, "expected %<;%>");
+      parser->error = false;
+      shadow_tag_warned (specs, 1);
+      return;
+    }
+
+  bool dummy = false;
+  declarator = c_parser_declarator (parser,
+				    specs->typespec_kind != ctsk_none,
+				    C_DTR_NORMAL, &dummy);
+
+  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);
+	}
+    }
+  else
+    {
+      c_parser_error (parser, "expected %<;%>");
+      return;
+    }
+}
+
+/* Parse gimple goto statement.  */
+
+static void
+c_parser_gimple_goto_stmt (location_t loc, tree label, gimple_seq *seq)
+{
+  tree decl = lookup_label_for_goto (loc, label);
+  gimple_seq_add_stmt (seq, gimple_build_goto (decl));
+  return;
+}
+
+/* Parse a parenthesized condition.
+   gimple-condition:
+     ( gimple-binary-expression )    */
+
+static tree
+c_parser_gimple_paren_condition (c_parser *parser)
+{
+  enum tree_code subcode = NOP_EXPR;
+  location_t loc = c_parser_peek_token (parser)->location;
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return error_mark_node;
+  tree cond = c_parser_gimple_binary_expression (parser, &subcode).value;
+  cond = c_objc_common_truthvalue_conversion (loc, cond);
+  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+    return error_mark_node;
+  return cond;
+}
+
+/* Parse gimple if-else statement.
+
+   if-statement:
+     if ( gimple-binary-expression ) gimple-goto-statement
+     if ( gimple-binary-expression ) gimple-goto-statement \
+					else gimple-goto-statement
+ */
+
+static void
+c_parser_gimple_if_stmt (c_parser *parser, gimple_seq *seq)
+{
+  tree t_label, f_label, label;
+  location_t loc;
+  c_parser_consume_token (parser);
+  tree cond = c_parser_gimple_paren_condition (parser);
+
+  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+    {
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      label = c_parser_peek_token (parser)->value;
+      t_label = lookup_label_for_goto (loc, label);
+      c_parser_consume_token (parser);
+      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+	return;
+    }
+  else
+    {
+      c_parser_error (parser, "expected goto expression");
+      return;
+    }
+
+  if (c_parser_next_token_is_keyword (parser, RID_ELSE))
+    c_parser_consume_token (parser);
+  else
+    {
+      c_parser_error (parser, "expected else statement");
+      return;
+    }
+
+  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+    {
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      label = c_parser_peek_token (parser)->value;
+      f_label = lookup_label_for_goto (loc, label);
+      c_parser_consume_token (parser);
+      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+	return;
+    }
+  else
+    {
+      c_parser_error (parser, "expected goto expression");
+      return;
+    }
+
+  gimple_seq_add_stmt (seq, gimple_build_cond_from_tree (cond, t_label,
+							 f_label));
+}
+
+/* Parse gimple switch-statement.
+
+   gimple-switch-statement:
+     switch (gimple-unary-expression) gimple-case-statement
+
+   gimple-case-statement:
+     gimple-case-statement
+     gimple-label-statement : gimple-goto-statment
+*/
+
+static void
+c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
+{
+  c_expr cond_expr;
+  tree case_label, label;
+  auto_vec<tree> labels;
+  tree default_label = NULL_TREE;
+  gimple_seq switch_body = NULL;
+  location_t loc;
+  c_parser_consume_token (parser);
+
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      cond_expr = c_parser_gimple_unary_expression (parser);
+      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+	return;
+    }
+
+  if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+    {
+      while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+	{
+	  if (c_parser_next_token_is (parser, CPP_EOF))
+	    {
+	      c_parser_error (parser, "expected statement");
+	      return;
+	    }
+
+	  switch (c_parser_peek_token (parser)->keyword)
+	    {
+	    case RID_CASE:
+		{
+		  c_expr exp1;
+		  loc = c_parser_peek_token (parser)->location;
+		  c_parser_consume_token (parser);
+
+		  if (c_parser_next_token_is (parser, CPP_NAME) ||
+		      c_parser_peek_token (parser)->type == CPP_NUMBER)
+		    exp1 = c_parser_gimple_unary_expression (parser);
+		  else
+		    c_parser_error (parser, "expected expression");
+
+		  if (c_parser_next_token_is (parser, CPP_COLON))
+		    {
+		      c_parser_consume_token (parser);
+		      label = create_artificial_label (loc);
+		      case_label = build_case_label (exp1.value, NULL_TREE,
+						     label);
+		      labels.safe_push (case_label);
+		      gimple_seq_add_stmt (&switch_body,
+					   gimple_build_label
+					   (CASE_LABEL (case_label)));
+		    }
+		  else
+		    {
+		      if (!c_parser_require (parser, CPP_SEMICOLON,
+					     "expected %<:%>"))
+			return;
+		    }
+		}
+	      break;
+	    case RID_DEFAULT:
+		{
+		  c_parser_consume_token (parser);
+		  if (c_parser_next_token_is (parser, CPP_COLON))
+		    {
+		      c_parser_consume_token (parser);
+		      default_label = build_case_label (NULL_TREE, NULL_TREE,
+							create_artificial_label
+							(UNKNOWN_LOCATION));
+		      gimple_seq_add_stmt (&switch_body,
+					   gimple_build_label
+					   (CASE_LABEL (default_label)));
+		    }
+		  else
+		    {
+		      if (!c_parser_require (parser, CPP_SEMICOLON,
+					     "expected %<:%>"))
+			return;
+		    }
+		}
+	      break;
+	    case RID_GOTO:
+		{
+		  loc = c_parser_peek_token (parser)->location;
+		  c_parser_consume_token (parser);
+		  if (c_parser_next_token_is (parser, CPP_NAME))
+		    {
+		      c_parser_gimple_goto_stmt (loc,
+						 c_parser_peek_token (parser)->value,
+						 &switch_body);
+		      c_parser_consume_token (parser);
+		      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+			c_parser_consume_token (parser);
+		      else
+			{
+			  c_parser_error (parser, "expected semicolon");
+			  return;
+			}
+		    }
+		  else
+		    {
+		      if (!c_parser_require (parser, CPP_NAME,
+					     "expected label"))
+			return;
+		    }
+		}
+	      break;
+	    default:
+	      c_parser_error (parser, "expected case label or goto statement");
+	      return;
+	    }
+
+	}
+    }
+  if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
+    return;
+  gimple_seq_add_stmt (seq, gimple_build_switch (cond_expr.value,
+						 default_label, labels));
+  gimple_seq_add_seq (seq, switch_body);
+  labels.release();
+}
+
+/* Parse gimple return statement.  */
+
+static void
+c_parser_gimple_return_stmt (c_parser *parser, gimple_seq *seq)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  gimple *ret = NULL;
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      c_finish_gimple_return (loc, NULL_TREE);
+      ret = gimple_build_return (NULL);
+      gimple_seq_add_stmt (seq, ret);
+    }
+  else
+    {
+      location_t xloc = c_parser_peek_token (parser)->location;
+      c_expr expr = c_parser_gimple_unary_expression (parser);
+      c_finish_gimple_return (xloc, expr.value);
+      ret = gimple_build_return (expr.value);
+      gimple_seq_add_stmt (seq, ret);
+    }
+}
+
+/* Support function for c_parser_gimple_return_stmt.  */
+
+static void
+c_finish_gimple_return (location_t loc, tree retval)
+{
+  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
+
+  /* Use the expansion point to handle cases such as returning NULL
+     in a function returning void.  */
+  source_location xloc = expansion_point_location_if_in_system_header (loc);
+
+  if (TREE_THIS_VOLATILE (current_function_decl))
+    warning_at (xloc, 0,
+		"function declared %<noreturn%> has a %<return%> statement");
+
+  if (!retval)
+    {
+      current_function_returns_null = 1;
+    }  
+  else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
+    {
+      current_function_returns_null = 1;
+      if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
+	{
+	  error_at
+	    (xloc, "%<return%> with a value, in function returning void");
+	  inform (DECL_SOURCE_LOCATION (current_function_decl),
+		  "declared here");
+	}
+    }
+  else if (TREE_CODE (valtype) != TREE_CODE (TREE_TYPE (retval)))
+    {
+      error_at
+	(xloc, "invalid conversion in return statement");
+      inform (DECL_SOURCE_LOCATION (current_function_decl),
+	      "declared here");
+    }
+  return;
+}
+
 #include "gt-c-c-parser.h"
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 6a1d126..cf6728f 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1944,6 +1944,7 @@ cgraph_node::assemble_thunks_and_aliases (void)
 void
 cgraph_node::expand (void)
 {
+  bool startwith_p = true;
   location_t saved_loc;
 
   /* We ought to not compile any inline clones.  */
@@ -1982,7 +1983,7 @@ cgraph_node::expand (void)
   /* Signal the start of passes.  */
   invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
 
-  execute_pass_list (cfun, g->get_passes ()->all_passes);
+  execute_pass_list (cfun, g->get_passes ()->all_passes, &startwith_p);
 
   /* Signal the end of passes.  */
   invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
@@ -2035,7 +2036,9 @@ cgraph_node::expand (void)
   timevar_pop (TV_REST_OF_COMPILATION);
 
   /* Make sure that BE didn't give up on compiling.  */
-  gcc_assert (TREE_ASM_WRITTEN (decl));
+  if (!(flag_gimple && cfun->pass_startwith))  /* FIXME : for gimplefe custom_pass_list */
+    gcc_assert (TREE_ASM_WRITTEN (decl));
+
   if (cfun)
     pop_cfun ();
 
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index fe1e984..ad6e5ac 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -85,6 +85,7 @@ typedef const union tree_node *const_tree;
 struct gimple;
 typedef gimple *gimple_seq;
 struct gimple_stmt_iterator;
+class opt_pass;
 
 /* Forward decls for leaf gimple subclasses (for individual gimple codes).
    Keep this in the same order as the corresponding codes in gimple.def.  */
@@ -405,6 +406,8 @@ typedef unsigned char uchar;
 #include "input.h"
 #include "is-a.h"
 #include "memory-block.h"
+#include "pass_manager.h"
+#include "tree-pass.h"
 #endif /* GENERATOR_FILE && !USED_FOR_TARGET */
 
 #endif /* coretypes.h */
diff --git a/gcc/function.h b/gcc/function.h
index 501ef68..0adbd68 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -228,6 +228,12 @@ struct GTY(()) function {
   /* GIMPLE body for this function.  */
   gimple_seq gimple_body;
 
+  /* GIMPLEFE pass to start with */
+  opt_pass *pass_startwith = NULL;
+
+  /* Startwith flag */
+  bool startwith;
+
   /* SSA and dataflow information.  */
   struct gimple_df *gimple_df;
 
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 12d9a9c..e4416a5 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -838,7 +838,7 @@ dump_gimple_switch (pretty_printer *buffer, gswitch *gs, int spc,
     {
       pp_string (buffer, "switch (");
       dump_generic_node (buffer, gimple_switch_index (gs), spc, flags, true);
-      pp_string (buffer, ") <");
+      pp_string (buffer, ") {");
     }
 
   for (i = 0; i < gimple_switch_num_labels (gs); i++)
@@ -849,9 +849,9 @@ dump_gimple_switch (pretty_printer *buffer, gswitch *gs, int spc,
       pp_space (buffer);
       dump_generic_node (buffer, CASE_LABEL (case_label), spc, flags, false);
       if (i < gimple_switch_num_labels (gs) - 1)
-        pp_string (buffer, ", ");
+        pp_string (buffer, "; ");
     }
-  pp_greater (buffer);
+  pp_string (buffer, "}");
 }
 
 
@@ -907,16 +907,11 @@ dump_gimple_label (pretty_printer *buffer, glabel *gs, int spc, int flags)
 {
   tree label = gimple_label_label (gs);
   if (flags & TDF_RAW)
-      dump_gimple_fmt (buffer, spc, flags, "%G <%T>", gs, label);
+    dump_gimple_fmt (buffer, spc, flags, "%T", label);
   else
-    {
-      dump_generic_node (buffer, label, spc, flags, false);
-      pp_colon (buffer);
-    }
-  if (DECL_NONLOCAL (label))
-    pp_string (buffer, " [non-local]");
-  if ((flags & TDF_EH) && EH_LANDING_PAD_NR (label))
-    pp_printf (buffer, " [LP %d]", EH_LANDING_PAD_NR (label));
+    dump_generic_node (buffer, label, spc, flags, false);
+
+  pp_colon (buffer);
 }
 
 /* Dump a GIMPLE_GOTO tuple on the pretty_printer BUFFER, SPC
@@ -1966,8 +1961,7 @@ dump_ssaname_info_to_file (FILE *file, tree node, int spc)
    pretty printer.  If COMMENT is true, print this after #.  */
 
 static void
-dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, bool comment,
-		 int flags)
+dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, int flags)
 {
   size_t i;
   tree lhs = gimple_phi_result (phi);
@@ -1975,30 +1969,27 @@ dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, bool comment,
   if (flags & TDF_ALIAS)
     dump_ssaname_info (buffer, lhs, spc);
 
-  if (comment)
-    pp_string (buffer, "# ");
-
   if (flags & TDF_RAW)
     dump_gimple_fmt (buffer, spc, flags, "%G <%T, ", phi,
 		     gimple_phi_result (phi));
   else
     {
       dump_generic_node (buffer, lhs, spc, flags, false);
-      pp_string (buffer, " = PHI <");
+      pp_string (buffer, " = __PHI (");
     }
   for (i = 0; i < gimple_phi_num_args (phi); i++)
     {
       if ((flags & TDF_LINENO) && gimple_phi_arg_has_location (phi, i))
 	dump_location (buffer, gimple_phi_arg_location (phi, i));
+      pp_string (buffer, "bb_");
+      pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index);
+      pp_string (buffer, ": ");
       dump_generic_node (buffer, gimple_phi_arg_def (phi, i), spc, flags,
 			 false);
-      pp_left_paren (buffer);
-      pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index);
-      pp_right_paren (buffer);
       if (i < gimple_phi_num_args (phi) - 1)
 	pp_string (buffer, ", ");
     }
-  pp_greater (buffer);
+  pp_right_paren (buffer);
 }
 
 
@@ -2286,7 +2277,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple *gs, int spc, int flags)
       break;
 
     case GIMPLE_PHI:
-      dump_gimple_phi (buffer, as_a <gphi *> (gs), spc, false, flags);
+      dump_gimple_phi (buffer, as_a <gphi *> (gs), spc, flags);
       break;
 
     case GIMPLE_OMP_PARALLEL:
@@ -2447,7 +2438,7 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, int indent, int flags)
     {
       gimple *stmt = first_stmt (bb);
       if (!stmt || gimple_code (stmt) != GIMPLE_LABEL)
-	fprintf (outf, "%*s<bb %d>:\n", indent, "", bb->index);
+	fprintf (outf, "%*sbb_%d:\n", indent, "", bb->index);
     }
 }
 
@@ -2480,7 +2471,7 @@ dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags)
       if (!virtual_operand_p (gimple_phi_result (phi)) || (flags & TDF_VOPS))
         {
           INDENT (indent);
-	  dump_gimple_phi (buffer, phi, indent, true, flags);
+	  dump_gimple_phi (buffer, phi, indent, flags);
           pp_newline (buffer);
         }
     }
@@ -2493,24 +2484,9 @@ dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags)
 static void
 pp_cfg_jump (pretty_printer *buffer, basic_block bb)
 {
-  gimple *stmt;
-
-  stmt = first_stmt (bb);
-
-  pp_string (buffer, "goto <bb ");
+  pp_string (buffer, "goto bb_");
   pp_decimal_int (buffer, bb->index);
-  pp_greater (buffer);
-  if (stmt && gimple_code (stmt) == GIMPLE_LABEL)
-    {
-      pp_string (buffer, " (");
-      dump_generic_node (buffer,
-			 gimple_label_label (as_a <glabel *> (stmt)),
-			 0, 0, false);
-      pp_right_paren (buffer);
-      pp_semicolon (buffer);
-    }
-  else
-    pp_semicolon (buffer);
+  pp_semicolon (buffer);
 }
 
 
@@ -2627,7 +2603,7 @@ gimple_dump_bb (FILE *file, basic_block bb, int indent, int flags)
 void
 gimple_dump_bb_for_graph (pretty_printer *pp, basic_block bb)
 {
-  pp_printf (pp, "<bb %d>:\n", bb->index);
+  pp_printf (pp, "bb_%d:\n", bb->index);
   pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
 
   for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 4715332..12b9ec9 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -11848,7 +11848,22 @@ gimplify_function_tree (tree fndecl)
       && !needs_to_live_in_memory (ret))
     DECL_GIMPLE_REG_P (ret) = 1;
 
-  bind = gimplify_body (fndecl, true);
+  if (!cfun->gimple_body)
+    bind = gimplify_body (fndecl, true);
+  else
+    {
+      gimple_seq seq;
+      gimple *outer_stmt;
+      seq = cfun->gimple_body;
+      outer_stmt = gimple_seq_first_stmt (seq);
+      if (gimple_code (outer_stmt) == GIMPLE_BIND
+	  && gimple_seq_first (seq) == gimple_seq_last (seq))
+	bind = as_a <gbind *> (outer_stmt);
+      else
+	bind = gimple_build_bind (NULL_TREE, seq, NULL);
+
+      DECL_SAVED_TREE (fndecl) = NULL_TREE;
+    }
 
   /* The tree body of the function is no longer needed, replace it
      with the new GIMPLE body.  */
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index cd4b625..3824fb7 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2412,3 +2412,9 @@ expand_internal_call (gcall *stmt)
 {
   expand_internal_call (gimple_call_internal_fn (stmt), stmt);
 }
+
+void
+expand_PHI (internal_fn, gcall *)
+{
+    gcc_unreachable ();
+}
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 6701cd9..a5dd23e 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -169,6 +169,7 @@ DEF_INTERNAL_FN (VA_ARG, ECF_NOTHROW | ECF_LEAF, NULL)
    other such optimizations.  The first argument distinguishes
    between uses.  See internal-fn.h for usage.  */
 DEF_INTERNAL_FN (UNIQUE, ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (PHI, 0, NULL)
 
 /* DIM_SIZE and DIM_POS return the size of a particular compute
    dimension and the executing thread's position within that
diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
index bb31465..9c39dd67 100644
--- a/gcc/internal-fn.h
+++ b/gcc/internal-fn.h
@@ -174,5 +174,6 @@ extern bool set_edom_supported_p (void);
 
 extern void expand_internal_call (gcall *);
 extern void expand_internal_call (internal_fn, gcall *);
+extern void expand_PHI (internal_fn, gcall *);
 
 #endif
diff --git a/gcc/passes.c b/gcc/passes.c
index c7d7dbe..04caf39 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -1685,12 +1685,13 @@ remove_cgraph_node_from_order (cgraph_node *node, void *data)
    call CALLBACK on the current function.
    This function is global so that plugins can use it.  */
 void
-do_per_function_toporder (void (*callback) (function *, void *data), void *data)
+do_per_function_toporder (void (*callback) (function *, void *data, void *flag),
+			  void *data, void *flag)
 {
   int i;
 
   if (current_function_decl)
-    callback (cfun, data);
+    callback (cfun, data, flag);
   else
     {
       cgraph_node_hook_list *hook;
@@ -1725,7 +1726,7 @@ do_per_function_toporder (void (*callback) (function *, void *data), void *data)
 	    {
 	      struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
 	      push_cfun (fn);
-	      callback (fn, data);
+	      callback (fn, data, flag);
 	      pop_cfun ();
 	    }
 	}
@@ -2276,8 +2277,18 @@ override_gate_status (opt_pass *pass, tree func, bool gate_status)
 /* Execute PASS. */
 
 bool
-execute_one_pass (opt_pass *pass)
+execute_one_pass (opt_pass *pass, bool startwith_p)
 {
+  /* For skipping passes until startwith pass */
+  if (cfun && startwith_p && cfun->startwith)
+    {
+      if (!strcmp (pass->name, cfun->pass_startwith->name)
+	  || !strcmp (pass->name, "*clean_state"))
+	cfun->startwith = false;
+      else
+	return true;
+    }
+
   unsigned int todo_after = 0;
 
   bool gate_status;
@@ -2417,7 +2428,7 @@ execute_one_pass (opt_pass *pass)
 }
 
 static void
-execute_pass_list_1 (opt_pass *pass)
+execute_pass_list_1 (opt_pass *pass, bool startwith_p)
 {
   do
     {
@@ -2426,18 +2437,23 @@ execute_pass_list_1 (opt_pass *pass)
 
       if (cfun == NULL)
 	return;
-      if (execute_one_pass (pass) && pass->sub)
-        execute_pass_list_1 (pass->sub);
+      if (execute_one_pass (pass, startwith_p) && pass->sub)
+	execute_pass_list_1 (pass->sub, startwith_p);
       pass = pass->next;
     }
   while (pass);
 }
 
 void
-execute_pass_list (function *fn, opt_pass *pass)
+execute_pass_list (function *fn, opt_pass *pass, bool *startwith_p)
 {
   gcc_assert (fn == cfun);
-  execute_pass_list_1 (pass);
+
+  if (startwith_p)
+    execute_pass_list_1 (pass, *startwith_p);
+  else
+    execute_pass_list_1 (pass, false);
+
   if (cfun && fn->cfg)
     {
       free_dominance_info (CDI_DOMINATORS);
@@ -2767,19 +2783,22 @@ ipa_read_optimization_summaries (void)
 void
 execute_ipa_pass_list (opt_pass *pass)
 {
+  bool startwith_p = false;
   do
     {
       gcc_assert (!current_function_decl);
       gcc_assert (!cfun);
       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
-      if (execute_one_pass (pass) && pass->sub)
+      if (!strcmp (pass->name, "opt_local_passes"))
+	startwith_p = true;
+      if (execute_one_pass (pass, startwith_p) && pass->sub)
 	{
 	  if (pass->sub->type == GIMPLE_PASS)
 	    {
 	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL);
-	      do_per_function_toporder ((void (*)(function *, void *))
+	      do_per_function_toporder ((void (*)(function *, void *, void *))
 					  execute_pass_list,
-					pass->sub);
+					pass->sub, &startwith_p);
 	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL);
 	    }
 	  else if (pass->sub->type == SIMPLE_IPA_PASS
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 57c8410..7fe994e 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -170,6 +170,7 @@ static edge find_taken_edge_computed_goto (basic_block, tree);
 static edge find_taken_edge_cond_expr (basic_block, tree);
 static edge find_taken_edge_switch_expr (gswitch *, basic_block, tree);
 static tree find_case_label_for_value (gswitch *, tree);
+static void lower_phi_internal_fn ();
 
 void
 init_empty_tree_cfg_for_function (struct function *fn)
@@ -244,6 +245,7 @@ build_gimple_cfg (gimple_seq seq)
   discriminator_per_locus = new hash_table<locus_discrim_hasher> (13);
   make_edges ();
   assign_discriminators ();
+  lower_phi_internal_fn ();
   cleanup_dead_labels ();
   delete discriminator_per_locus;
   discriminator_per_locus = NULL;
@@ -345,6 +347,50 @@ replace_loop_annotate (void)
     }
 }
 
+/* Lower internal PHI function from GIMPLE FE.  */
+
+static void
+lower_phi_internal_fn ()
+{
+  basic_block bb, pred = NULL;
+  gimple_stmt_iterator gsi;
+  tree lhs;
+  gphi *phi_node;
+  gimple *stmt;
+
+  /* After edge creation, handle __PHI function from GIMPLE FE.  */
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	{
+	  stmt = gsi_stmt (gsi);
+	  if (gimple_code (stmt) != GIMPLE_CALL)
+	    continue;
+
+	  if (gimple_call_internal_p (stmt) &&
+	      gimple_call_internal_fn (stmt) == IFN_PHI)
+	    {
+	      gsi_remove (&gsi, true);
+	      unsigned int i;
+	      lhs = gimple_call_lhs (stmt);
+	      phi_node = create_phi_node (lhs, bb);
+
+	      /* Add arguments to the PHI node.  */
+	      for (i = 0; i < gimple_call_num_args (stmt); ++i)
+		{
+		  tree arg = gimple_call_arg (stmt, i);
+		  if (TREE_CODE (arg) == LABEL_DECL)
+		    pred = label_to_block (arg);
+		  else
+		    {
+		      edge e = find_edge (pred, bb);
+		      add_phi_arg (phi_node, arg, e, UNKNOWN_LOCATION);
+		    }
+		}
+	    }
+	}
+    }
+}
 
 static unsigned int
 execute_build_cfg (void)
@@ -3340,6 +3386,11 @@ verify_gimple_call (gcall *stmt)
 	  debug_generic_stmt (fn);
 	  return true;
 	}
+      /* FIXME : for passing label as arg in internal fn PHI from GIMPLE FE*/
+      else if (gimple_call_internal_fn (stmt) == IFN_PHI)
+	{
+	  return false;
+	}
     }
   else
     {
@@ -7504,7 +7555,8 @@ dump_function_to_file (tree fndecl, FILE *file, int flags)
     }
 
   current_function_decl = fndecl;
-  fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
+  print_generic_expr (file, TREE_TYPE (TREE_TYPE (fndecl)), dump_flags);
+  fprintf (file, "\n%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
 
   arg = DECL_ARGUMENTS (fndecl);
   while (arg)
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index ceafa68..ba3dc05 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -1379,12 +1379,19 @@ rewrite_add_phi_arguments (basic_block bb)
       for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi);
 	   gsi_next (&gsi))
 	{
-	  tree currdef, res;
+	  tree currdef, res, argvar;
 	  location_t loc;
 
 	  phi = gsi.phi ();
 	  res = gimple_phi_result (phi);
-	  currdef = get_reaching_def (SSA_NAME_VAR (res));
+	  /* If we have pre-existing PHI its args may be different
+	     vars than existing vars */
+	  argvar = gimple_phi_arg_def (phi, e->dest_idx);
+	  if (argvar && TREE_CODE (argvar) == SSA_NAME)
+	    continue;
+	  if (!argvar)
+	    argvar = SSA_NAME_VAR (res);
+	  currdef = get_reaching_def (argvar);
 	  /* Virtual operand PHI args do not need a location.  */
 	  if (virtual_operand_p (res))
 	    loc = UNKNOWN_LOCATION;
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index c0059de..213070b 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -617,8 +617,9 @@ extern gimple_opt_pass *make_pass_lower_vaarg (gcc::context *ctxt);
 /* Current optimization pass.  */
 extern opt_pass *current_pass;
 
-extern bool execute_one_pass (opt_pass *);
-extern void execute_pass_list (function *, opt_pass *);
+extern bool execute_one_pass (opt_pass *, bool startwith_p = false);
+extern void execute_pass_list (function *, opt_pass *,
+			       bool *startwith_p = NULL);
 extern void execute_ipa_pass_list (opt_pass *);
 extern void execute_ipa_summary_passes (ipa_opt_pass_d *);
 extern void execute_all_ipa_transforms (void);
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 734ecda..aa53bd2 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -260,7 +260,7 @@ dump_decl_name (pretty_printer *pp, tree node, int flags)
   if ((flags & TDF_UID) || DECL_NAME (node) == NULL_TREE)
     {
       if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1)
-	pp_printf (pp, "L.%d", (int) LABEL_DECL_UID (node));
+	pp_printf (pp, "L_%d", (int) LABEL_DECL_UID (node));
       else if (TREE_CODE (node) == DEBUG_EXPR_DECL)
 	{
 	  if (flags & TDF_NOUID)
@@ -274,7 +274,7 @@ dump_decl_name (pretty_printer *pp, tree node, int flags)
 	  if (flags & TDF_NOUID)
 	    pp_printf (pp, "%c.xxxx", c);
 	  else
-	    pp_printf (pp, "%c.%u", c, DECL_UID (node));
+	    pp_printf (pp, "%c_%u", c, DECL_UID (node));
 	}
     }
   if ((flags & TDF_ALIAS) && DECL_PT_UID (node) != DECL_UID (node))
@@ -3965,14 +3965,14 @@ dump_function_header (FILE *dump_file, tree fdecl, int flags)
   else
     aname = "<unset-asm-name>";
 
-  fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d",
+  fprintf (dump_file, "\n/* Function %s (%s, funcdef_no=%d",
 	   dname, aname, fun->funcdef_no);
   if (!(flags & TDF_NOUID))
     fprintf (dump_file, ", decl_uid=%d", DECL_UID (fdecl));
   if (node)
     {
       fprintf (dump_file, ", cgraph_uid=%d", node->uid);
-      fprintf (dump_file, ", symbol_order=%d)%s\n\n", node->order,
+      fprintf (dump_file, ", symbol_order=%d)%s", node->order,
                node->frequency == NODE_FREQUENCY_HOT
                ? " (hot)"
                : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
@@ -3982,7 +3982,8 @@ dump_function_header (FILE *dump_file, tree fdecl, int flags)
                : "");
     }
   else
-    fprintf (dump_file, ")\n\n");
+    fprintf (dump_file, ")");
+  fprintf (dump_file, "*/\n\n");
 }
 
 /* Dump double_int D to pretty_printer PP.  UNS is true
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 91a8f97..8b8863b 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -255,7 +255,8 @@ flush_ssaname_freelist (void)
    used without a preceding definition).  */
 
 tree
-make_ssa_name_fn (struct function *fn, tree var, gimple *stmt)
+make_ssa_name_fn (struct function *fn, tree var, gimple *stmt,
+		  unsigned int version)
 {
   tree t;
   use_operand_p imm;
@@ -265,8 +266,19 @@ make_ssa_name_fn (struct function *fn, tree var, gimple *stmt)
 	      || TREE_CODE (var) == RESULT_DECL
 	      || (TYPE_P (var) && is_gimple_reg_type (var)));
 
+  /* parsing ssa names with versions.	*/
+  if (version != 0)
+    {
+      t = make_node (SSA_NAME);
+      SSA_NAME_VERSION (t) = version;
+      if (version >= SSANAMES (fn)->length ())
+	vec_safe_grow_cleared (SSANAMES (fn), version + 1);
+      gcc_assert ((*SSANAMES (fn))[version] == NULL);
+      (*SSANAMES (fn))[version] = t;
+      ssa_name_nodes_created++;
+    }
   /* If our free list has an element, then use it.  */
-  if (!vec_safe_is_empty (FREE_SSANAMES (fn)))
+  else if (!vec_safe_is_empty (FREE_SSANAMES (fn)))
     {
       t = FREE_SSANAMES (fn)->pop ();
       ssa_name_nodes_reused++;
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index 8e66ce6..3ce9327 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -74,7 +74,8 @@ extern bool ssa_name_has_boolean_range (tree);
 extern void init_ssanames (struct function *, int);
 extern void fini_ssanames (struct function *);
 extern void ssanames_print_statistics (void);
-extern tree make_ssa_name_fn (struct function *, tree, gimple *);
+extern tree make_ssa_name_fn (struct function *, tree, gimple *,
+			      unsigned int version = 0);
 extern void release_ssa_name_fn (struct function *, tree);
 extern bool get_ptr_info_alignment (struct ptr_info_def *, unsigned int *,
 				    unsigned int *);

[-- Attachment #4: testcases.patch --]
[-- Type: text/x-diff, Size: 5193 bytes --]

diff --git a/gcc/testsuite/gcc.dg/gimplefe-1.c b/gcc/testsuite/gcc.dg/gimplefe-1.c
new file mode 100644
index 0000000..0786d47
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int i;
+void __GIMPLE () foo()
+{
+  i = 1;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-10.c b/gcc/testsuite/gcc.dg/gimplefe-10.c
new file mode 100644
index 0000000..7f63c58
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-10.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE() bar(int a, int b, int c)
+{
+  a = 1;
+  b = a + 1;
+  c = b * 4;
+  return b;
+}
+
+void __GIMPLE() foo()
+{
+  int a;
+  int b;
+  int c;
+  b = bar(a, b, c);
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-11.c b/gcc/testsuite/gcc.dg/gimplefe-11.c
new file mode 100644
index 0000000..e1483f4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-11.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE() bar(int a, int b, int c)
+{
+  a = 1;
+  b = a + 1;
+  c = b * 4;
+  return;
+}
+
+void __GIMPLE() foo()
+{
+  int a;
+  int b;
+  int c;
+  bar(a, b, c);
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-12.c b/gcc/testsuite/gcc.dg/gimplefe-12.c
new file mode 100644
index 0000000..cbaf8a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-12.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE (startwith ("tree-ccp1")) foo ()
+{
+  int a;
+  int b;
+  a = b + 2;
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-13.c b/gcc/testsuite/gcc.dg/gimplefe-13.c
new file mode 100644
index 0000000..c0da9fa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-13.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE (startwith ("tree-dse1")) foo ()
+{
+  int a;
+
+bb_2:
+  if (a > 4)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_3:
+  a_2 = 10;
+  goto bb_5;
+
+bb_4:
+  a_3 = 20;
+
+bb_5:
+  a_1 = __PHI (bb_3: a_2, bb_4: a_3);
+  a_4 = a_1 + 4;
+
+return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-2.c b/gcc/testsuite/gcc.dg/gimplefe-2.c
new file mode 100644
index 0000000..e3a23cf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile }*/
+/* { dg-options "-fgimple" } */
+
+int a;
+void __GIMPLE () foo ()
+{
+  int b;
+  b = a;
+  b = b + 1;
+  a = b;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-3.c b/gcc/testsuite/gcc.dg/gimplefe-3.c
new file mode 100644
index 0000000..595365e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-3.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int *b;
+  *b = 1;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-4.c b/gcc/testsuite/gcc.dg/gimplefe-4.c
new file mode 100644
index 0000000..3600c7c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-4.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int a;
+  char b;
+  a = (int) b;
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-5.c b/gcc/testsuite/gcc.dg/gimplefe-5.c
new file mode 100644
index 0000000..1dab4af
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-5.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int a;
+void __GIMPLE () foo ()
+{
+  int b;
+  int c;
+
+bb_2:
+  b = a;
+  if (b > 3)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_3:
+  b = c + 4;
+  goto bb_5;
+
+bb_4:
+  b = b + 1;
+  goto bb_5;
+
+bb_5:
+  a = b;
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-6.c b/gcc/testsuite/gcc.dg/gimplefe-6.c
new file mode 100644
index 0000000..242e08f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-6.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int a;
+  int b;
+  int c;
+  int d;
+
+bb_2:
+  a = ~b;
+  b = a << c;
+  c = a & b;
+  d = b | c;
+
+bb_3:
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-7.c b/gcc/testsuite/gcc.dg/gimplefe-7.c
new file mode 100644
index 0000000..6125541
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-7.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int a;
+
+bb_2:
+  if (a > 4)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_3:
+  a_2 = 10;
+  goto bb_5;
+
+bb_4:
+  a_3 = 20;
+
+bb_5:
+  a_1 = __PHI (bb_3: a_2, bb_4: a_3);
+  a_4 = a_1 + 4;
+
+return;
+}
+
diff --git a/gcc/testsuite/gcc.dg/gimplefe-8.c b/gcc/testsuite/gcc.dg/gimplefe-8.c
new file mode 100644
index 0000000..4936bec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-8.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE () foo ()
+{
+  int a;
+  int b;
+
+bb_2:
+  b = a_1(D) + 1;
+bb_3:
+  return b;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-9.c b/gcc/testsuite/gcc.dg/gimplefe-9.c
new file mode 100644
index 0000000..a24be273
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-9.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE() bar()
+{
+  int a;
+  a = a + 1;
+  return a;
+}
+
+void __GIMPLE() foo()
+{
+  int b;
+  b = bar();
+}


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-22 18:40   ` Prasad Ghangal
@ 2016-08-22 21:20     ` Trevor Saunders
  2016-08-22 21:27     ` David Malcolm
  2016-08-24 10:02     ` Richard Biener
  2 siblings, 0 replies; 24+ messages in thread
From: Trevor Saunders @ 2016-08-22 21:20 UTC (permalink / raw)
  To: Prasad Ghangal; +Cc: gcc-patches, Richard Biener

On Tue, Aug 23, 2016 at 12:10:29AM +0530, Prasad Ghangal wrote:
> On 22 August 2016 at 16:55, Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
> > On Sun, Aug 21, 2016 at 10:35:17PM +0530, Prasad Ghangal wrote:
> >> Hi all,
> >>
> >> As a part of my gsoc project. I have completed the following tasks:
> >>
> >> * Parsed gimple-expression
> >> * Parsed gimple-labels
> >> * Parsed local declaration
> >> * Parsed gimple-goto statement
> >> * Parsed gimple-if-else statement
> >> * Parsed gimple-switch statement
> >> * Parsed gimple-return statement
> >> * Parsed gimple-PHI function
> >> * Parsed gimple ssa-names along with default def
> >> * Parsed gimple-call
> >>
> >> * Hacked pass manager to add support for startwith (pass-name) to skip
> >> early opt passes
> >> * Modified gimple dump for making it parsable
> >>
> >> I am willing to continue work on the project, some TODOs for the projects are:
> >>
> >> * Error handling
> >> * Parse more gimple syntax
> >> * Add startwith support for IPA passes
> >>
> >> The complete code of gimple fe project can be found at
> >> https://github.com/PrasadG193/gcc_gimple_fe
> >>
> >>
> >> PFA patch for complete project (rebased for latest trunk revision).
> >> I have successfully bootstrapped and tested on x86_64-pc-linux-gnu.
> >> Some testcases failed due to modified gimple dump as expected.
> >>
> >>
> >> Thanks,
> >> Prasad
> >
> > only some rather minor comments
> >
> >
> > +++ b/gcc/c/c-parser.c
> > @@ -59,6 +59,18 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "gimple-expr.h"
> >  #include "context.h"
> >  #include "gcc-rich-location.h"
> > +#include "tree-vrp.h"
> >
> > given that you need these headers it might be better to put most of the
> > gimple parsing in its own file so only what actually needs to know about
> > this part of the compiler does now about it.
> >
> > +void
> > +c_parser_parse_gimple_body (c_parser *parser)
> > +{
> > +  bool return_p = false;
> > +  gimple_seq seq;
> > +  gimple_seq body;
> > +  tree stmt = push_stmt_list ();
> >
> > it would be nice to move the declarations down to their first use.
> >
> > +      gimple *ret;
> > +      ret = gimple_build_return (NULL);
> >
> > there's no reason for a separate declaration and assignment ;)
> >
> > +  tree block = NULL;
> > +  block = pop_scope ();
> >
> > same here, and a number of other places.
> >
> > +c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
> > +{
> > +  bool return_p = false;
> > +
> > +  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
> > +      return return_p;
> >
> > return false would work fine.
> >
> > +
> > +  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
> > +    {
> > +      c_parser_consume_token (parser);
> > +      goto out;
> >
> > I don't see the need for the gotos, there's no cleanup in this function.
> >
> > +  /* gimple PHI expression.  */
> > +  if (c_parser_next_token_is_keyword (parser, RID_PHI))
> > +    {
> > +      c_parser_consume_token (parser);
> > +
> > +      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
> > +       {
> > +         return;
> > +       }
> > +
> > +      gcall *call_stmt;
> > +      tree arg = NULL_TREE;
> > +      vec<tree> vargs = vNULL;
> >
> > I think you can use auto_vec here, as is I think this leaks the vectors
> > storage.
> >
> > +c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)
> >
> > you can skip the explicit 'enum' keyword.
> >
> > +  struct {
> > +    /* The expression at this stack level.  */
> > +    struct c_expr expr;
> >
> > similar with struct here.
> >
> > +    /* The precedence of the operator on its left, PREC_NONE at the
> > +       bottom of the stack.  */
> > +    enum c_parser_prec prec;
> > +    /* The operation on its left.  */
> > +    enum tree_code op;
> > +    /* The source location of this operation.  */
> > +    location_t loc;
> > +  } stack[2];
> > +  int sp;
> > +  /* Location of the binary operator.  */
> > +  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
> > +#define POP                                                                  \
> >
> > it seems like it would be nicer to name the type, and then make this a
> > function.
> >
> > +                                       RO_UNARY_STAR);
> > +       ret.src_range.m_start = op_loc;
> > +       ret.src_range.m_finish = finish;
> > +       return ret;
> > +      }
> > +    case CPP_PLUS:
> > +      if (!c_dialect_objc () && !in_system_header_at (input_location))
> > +       warning_at (op_loc,
> > +                   OPT_Wtraditional,
> > +                   "traditional C rejects the unary plus operator");
> >
> > does it really make sense to warn about C issues when compiling gimple?
> >
> > +c_parser_parse_ssa_names (c_parser *parser)
> > +{
> > +  tree id = NULL_TREE;
> > +  c_expr ret;
> > +  char *var_name, *var_version, *token;
> > +  ret.original_code = ERROR_MARK;
> > +  ret.original_type = NULL;
> > +
> > +  /* ssa token string.  */
> > +  const char *ssa_token = NULL;
> > +  ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
> > +  token = new char [strlen (ssa_token)];
> >
> > I'm not sure I see why you need this copy, and getting rid of it would
> > mean you don't need to free it.
> >
> > +  strcpy (token, ssa_token);
> > +
> > +  /* seperate var name and version.  */
> > +  var_version = strrchr (token, '_');
> > +  if (var_version)
> > +    {
> > +      var_name = new char[var_version - token + 1];
> >
> > you should free this when done with it.
> >
> > +c_parser_gimple_postfix_expression (c_parser *parser)
> > +{
> > +  struct c_expr expr;
> > +  location_t loc = c_parser_peek_token (parser)->location;;
> >
> > extra ;
> >
> > +    case CPP_OBJC_STRING:
> > +      gcc_assert (c_dialect_objc ());
> > +      expr.value
> > +       = objc_build_string_object (c_parser_peek_token (parser)->value);
> > +      set_c_expr_source_range (&expr, tok_range);
> > +      c_parser_consume_token (parser);
> > +      break;
> >
> > is there a reason to support objc stuff in gimple?
> >
> > +c_parser_gimple_expr_list (c_parser *parser, bool convert_p,
> > +                   vec<tree, va_gc> **p_orig_types,
> > +                   location_t *sizeof_arg_loc, tree *sizeof_arg,
> > +                   vec<location_t> *locations,
> > +                   unsigned int *literal_zero_mask)
> > +{
> > +  vec<tree, va_gc> *ret;
> > +  vec<tree, va_gc> *orig_types;
> > +  struct c_expr expr;
> > +  location_t loc = c_parser_peek_token (parser)->location;
> > +  location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION;
> > +  unsigned int idx = 0;
> > +
> > +  ret = make_tree_vector ();
> > +  if (p_orig_types == NULL)
> > +    orig_types = NULL;
> > +  else
> > +    orig_types = make_tree_vector ();
> > +
> > +  if (sizeof_arg != NULL
> > +      && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
> > +    cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
> > +  if (literal_zero_mask)
> > +    c_parser_check_literal_zero (parser, literal_zero_mask, 0);
> > +  expr = c_parser_gimple_unary_expression (parser);
> > +  if (convert_p)
> > +    expr = convert_lvalue_to_rvalue (loc, expr, true, true);
> > +  ret->quick_push (expr.value);
> >
> >  That kind of relies on the details of make_tree_vector (), so it seems
> >  somewhat safer to use vec_safe_push.
> >
> > +  if (orig_types)
> > +    orig_types->quick_push (expr.original_type);
> >
> > same
> >
> > +c_parser_gimple_declaration (c_parser *parser)
> > +{
> > +  struct c_declspecs *specs;
> > +  struct c_declarator *declarator;
> > +  specs = build_null_declspecs ();
> > +  c_parser_declspecs (parser, specs, true, true, true,
> > +                     true, true, cla_nonabstract_decl);
> > +  finish_declspecs (specs);
> > +  bool auto_type_p = specs->typespec_word == cts_auto_type;
> >
> > is it useful to support auto here in gimple?
> >
> > +c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
> > +{
> > +  c_expr cond_expr;
> > +  tree case_label, label;
> > +  vec<tree> labels = vNULL;
> >
> > auto_vec?
> >
> > +static void
> > +c_finish_gimple_return (location_t loc, tree retval)
> > +{
> > +  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
> > +
> > +  /* Use the expansion point to handle cases such as returning NULL
> > +     in a function returning void.  */
> > +  source_location xloc = expansion_point_location_if_in_system_header (loc);
> > +
> > +  if (TREE_THIS_VOLATILE (current_function_decl))
> > +    warning_at (xloc, 0,
> > +               "function declared %<noreturn%> has a %<return%> statement");
> > +
> > +  if (!retval)
> > +    {
> > +      current_function_returns_null = 1;
> > +      if ((warn_return_type || flag_isoc99)
> >
> > I'm not sure what to do about warnings, but checking the language we are
> > compiling as seems kind of wrong when we're compiling gimple?
> >
> > @@ -228,6 +228,12 @@ struct GTY(()) function {
> >    /* GIMPLE body for this function.  */
> >    gimple_seq gimple_body;
> >
> > +  /* GIMPLEFE pass to start with */
> > +  opt_pass *pass_startwith = NULL;
> >
> > I'm guessing you've only compiled in C++11 mode? because I'm pretty sure
> > you are using a C++11 feature here (the default member value you
> > assign).
> >
> > Thanks!
> >
> > Trev
> >
> 
> Hi Trevor,
> 
> Thanks for your feedback. I had missed removing some unwanted code
> while code cleanup. I have updated the patch.
> I am not sure if we should move all gimple parsing related functions
> to the new file (?)

I would think it makes sense to keep it all togehter, but probably not
terribly important where it goes.

> I am not getting what did you mean by C++11 mode (I am not explicitly
> giving any option while configure or make). I also have successfully
> bootstrapped and tested the project on another system. Is there any
> way to check that ?

consider this simplified example

struct foo
{
	int *x = 0;
};

g++ -std=gnu++98 test.cc produces

/tmp/test.cc:3:11: warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11
  int *x = 0;
           ^

gcc needs to compile as C++98 with compilers that don't understand this
construct, so you need to make sure the member is null when the struct
is created instead of putting = NULL next to the members declaration.

Thanks!

Trev

> 
> 
> Thanks,
> Prasad

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-22 18:40   ` Prasad Ghangal
  2016-08-22 21:20     ` Trevor Saunders
@ 2016-08-22 21:27     ` David Malcolm
  2016-08-22 21:54       ` Pedro Alves
  2016-08-23 15:45       ` Prasad Ghangal
  2016-08-24 10:02     ` Richard Biener
  2 siblings, 2 replies; 24+ messages in thread
From: David Malcolm @ 2016-08-22 21:27 UTC (permalink / raw)
  To: Prasad Ghangal, Trevor Saunders; +Cc: gcc-patches, Richard Biener

On Tue, 2016-08-23 at 00:10 +0530, Prasad Ghangal wrote:
> On 22 August 2016 at 16:55, Trevor Saunders <tbsaunde@tbsaunde.org>
> wrote:
> > On Sun, Aug 21, 2016 at 10:35:17PM +0530, Prasad Ghangal wrote:

[...]

> > @@ -228,6 +228,12 @@ struct GTY(()) function {
> >    /* GIMPLE body for this function.  */
> >    gimple_seq gimple_body;
> > 
> > +  /* GIMPLEFE pass to start with */
> > +  opt_pass *pass_startwith = NULL;
I'm guessing you've only compiled in C++11 mode? because I'm pretty
> > sure
> > you are using a C++11 feature here (the default member value you
> > assign).
> 

[...]

> I am not getting what did you mean by C++11 mode (I am not explicitly

Prasad: what compiler version are you using to build your patched gcc? 
 My guess is that you're using gcc 6 to build.

In gcc 6 we changed the default C++ mode from -std=gnu++98
to -std=gnu++14. See: 
  https://gcc.gnu.org/gcc-6/porting_to.html#gxx14

I believe the syntax that Trevor spotted is only available in C++11
onwards:

  $ cat test.cc
  struct foo
  {
    int field = 42;
  };

With the default for gcc 6:

  $ gcc -c test.cc -std=c++14

it has no problems, whereas with the default for gcc 5 and earlier:

  $ gcc -c test.cc -std=gnu++98
  test.cc:3:15: warning: non-static data member initializers only  
available with -std=c++11 or -std=gnu++11
   int field = 42;
               ^~

So it's probably worth attempting to bootstrap with an older gcc as the
starting compiler.

Hope this is helpful
Dave

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-22 21:27     ` David Malcolm
@ 2016-08-22 21:54       ` Pedro Alves
  2016-08-23  7:47         ` Richard Biener
  2016-08-23 15:45       ` Prasad Ghangal
  1 sibling, 1 reply; 24+ messages in thread
From: Pedro Alves @ 2016-08-22 21:54 UTC (permalink / raw)
  To: David Malcolm, Prasad Ghangal, Trevor Saunders
  Cc: gcc-patches, Richard Biener

On 08/22/2016 10:26 PM, David Malcolm wrote:

> it has no problems, whereas with the default for gcc 5 and earlier:
> 
>   $ gcc -c test.cc -std=gnu++98
>   test.cc:3:15: warning: non-static data member initializers only  
> available with -std=c++11 or -std=gnu++11
>    int field = 42;
>                ^~
> 
> So it's probably worth attempting to bootstrap with an older gcc as the
> starting compiler.

I believe that only stage 1 is built with -std=gnu++98 forced, and also
stage 1 is built without -Werror, so I think you'd need to start with a
compiler that predates support for that construct, not just one
that predates the flip of the default.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-22 21:54       ` Pedro Alves
@ 2016-08-23  7:47         ` Richard Biener
  2016-08-23 10:32           ` Pedro Alves
  2016-08-23 15:17           ` Trevor Saunders
  0 siblings, 2 replies; 24+ messages in thread
From: Richard Biener @ 2016-08-23  7:47 UTC (permalink / raw)
  To: Pedro Alves; +Cc: David Malcolm, Prasad Ghangal, Trevor Saunders, GCC Patches

On Mon, Aug 22, 2016 at 11:54 PM, Pedro Alves <palves@redhat.com> wrote:
> On 08/22/2016 10:26 PM, David Malcolm wrote:
>
>> it has no problems, whereas with the default for gcc 5 and earlier:
>>
>>   $ gcc -c test.cc -std=gnu++98
>>   test.cc:3:15: warning: non-static data member initializers only
>> available with -std=c++11 or -std=gnu++11
>>    int field = 42;
>>                ^~
>>
>> So it's probably worth attempting to bootstrap with an older gcc as the
>> starting compiler.
>
> I believe that only stage 1 is built with -std=gnu++98 forced, and also
> stage 1 is built without -Werror, so I think you'd need to start with a
> compiler that predates support for that construct, not just one
> that predates the flip of the default.

Uh, so we don't actually catch these errors during bootstrap with a too
recent host compiler?  That's pretty bad.  Ah, we add -pedantic if supported
but with now using C++ that only warns and does not error (the C FE errors)
so we actually need -pedantic-errors here.

So should we change config/warnings.m4:ACX_PROG_CXX_WARNING_ALMOST_PEDANTIC
to use -pedantic-errors?

In the end conditionally allowing C++11 code in stage2+ was a mistake
if we can't catch
this kind of issues reliably.

Richard.

> Thanks,
> Pedro Alves
>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-23  7:47         ` Richard Biener
@ 2016-08-23 10:32           ` Pedro Alves
  2016-08-23 15:17           ` Trevor Saunders
  1 sibling, 0 replies; 24+ messages in thread
From: Pedro Alves @ 2016-08-23 10:32 UTC (permalink / raw)
  To: Richard Biener
  Cc: David Malcolm, Prasad Ghangal, Trevor Saunders, GCC Patches

On 08/23/2016 08:46 AM, Richard Biener wrote:
> On Mon, Aug 22, 2016 at 11:54 PM, Pedro Alves <palves@redhat.com> wrote:

>> I believe that only stage 1 is built with -std=gnu++98 forced, and also
>> stage 1 is built without -Werror, so I think you'd need to start with a
>> compiler that predates support for that construct, not just one
>> that predates the flip of the default.
> 
> Uh, so we don't actually catch these errors during bootstrap with a too
> recent host compiler?  That's pretty bad.  

...

> In the end conditionally allowing C++11 code in stage2+ was a mistake
> if we can't catch
> this kind of issues reliably.

Generally speaking, let me state my current view on the theme:

The oldest compiler that people are using in practice to
bootstrap gcc with is what matters in the end.  Forcing -std=foo and
-pedantic is useful as a proxy but it can only go so far.  Routinely
testing bootstrap with the oldest compiler version people are
willing to support, is the only reliable check, and better
yet if that is left for auto testers / buildbot.

Because, even if a feature is in the standard, if compilers
that people want to bootstrap gcc with don't implement it,
or don't implement it correctly, then we'll find ways to
work around it.  That happens once in a while.

On the same vein, if some code using some newer language feature
that is supported as a GNU extension manages to land in the tree, and
nobody trips on it for a long while, then that indicates that no one
is actually building with ancient compilers anymore.  That indicates
that we should be able to start using the feature and bump the
minimum bootstrapping compiler in the documentation.

From that angle, forcing pedantic errors is a little counter
productive, as it may be imposing an artificial barrier, leading
to a glacier pace of newer language feature adoption in the
compiler itself.  E.g., what if all of gcc/clang/foo/bar
have been supporting some language/library feature for a decade,
as an extension?  Why restrict usage of the feature?

That said, I don't know when was support for the construct
first added, and this patch hasn't landed yet.  Support
for it probably postdates gcc 4.3 and your autotesters would
likely catch it (and you'd probably be annoyed).

> So should we change config/warnings.m4:ACX_PROG_CXX_WARNING_ALMOST_PEDANTIC
> to use -pedantic-errors?

That might well be the best proxy available, but others will
know better whether that is likely to cause fallout.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-23  7:47         ` Richard Biener
  2016-08-23 10:32           ` Pedro Alves
@ 2016-08-23 15:17           ` Trevor Saunders
  1 sibling, 0 replies; 24+ messages in thread
From: Trevor Saunders @ 2016-08-23 15:17 UTC (permalink / raw)
  To: Richard Biener; +Cc: Pedro Alves, David Malcolm, Prasad Ghangal, GCC Patches

On Tue, Aug 23, 2016 at 09:46:50AM +0200, Richard Biener wrote:
> On Mon, Aug 22, 2016 at 11:54 PM, Pedro Alves <palves@redhat.com> wrote:
> > On 08/22/2016 10:26 PM, David Malcolm wrote:
> >
> >> it has no problems, whereas with the default for gcc 5 and earlier:
> >>
> >>   $ gcc -c test.cc -std=gnu++98
> >>   test.cc:3:15: warning: non-static data member initializers only
> >> available with -std=c++11 or -std=gnu++11
> >>    int field = 42;
> >>                ^~
> >>
> >> So it's probably worth attempting to bootstrap with an older gcc as the
> >> starting compiler.
> >
> > I believe that only stage 1 is built with -std=gnu++98 forced, and also
> > stage 1 is built without -Werror, so I think you'd need to start with a
> > compiler that predates support for that construct, not just one
> > that predates the flip of the default.
> 
> Uh, so we don't actually catch these errors during bootstrap with a too
> recent host compiler?  That's pretty bad.  Ah, we add -pedantic if supported
> but with now using C++ that only warns and does not error (the C FE errors)
> so we actually need -pedantic-errors here.

ultimately there will always be some C++ things that newer compilers
accept, but old ones don't.  For example see PR 61679, where as far as
I'm aware its just a bug in old versions and unrelated to C++ version.

One thing I think we could do is add a -WC++98-compat warning, and pass
-Werror=c++98-compat when supported if we run into these problems often
enough.

> So should we change config/warnings.m4:ACX_PROG_CXX_WARNING_ALMOST_PEDANTIC
> to use -pedantic-errors?
> 
> In the end conditionally allowing C++11 code in stage2+ was a mistake
> if we can't catch
> this kind of issues reliably.

Well, I don't think we can ever catch all problems that may crop up on
old toolchains reliably, though we should try and minimize it where
possible.

I'm not sure using C++11 for the final compiler is a mistake though, it
allows safer, and perhaps more importantly faster code in some cases.
We don't have too much use of it for performance yet, but I have some
ideas I want to work on.

Trev

> 
> Richard.
> 
> > Thanks,
> > Pedro Alves
> >

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-22 21:27     ` David Malcolm
  2016-08-22 21:54       ` Pedro Alves
@ 2016-08-23 15:45       ` Prasad Ghangal
  2016-08-24  7:03         ` Prasad Ghangal
  1 sibling, 1 reply; 24+ messages in thread
From: Prasad Ghangal @ 2016-08-23 15:45 UTC (permalink / raw)
  To: David Malcolm; +Cc: Trevor Saunders, gcc-patches, Richard Biener

[-- Attachment #1: Type: text/plain, Size: 1834 bytes --]

On 23 August 2016 at 02:56, David Malcolm <dmalcolm@redhat.com> wrote:
> On Tue, 2016-08-23 at 00:10 +0530, Prasad Ghangal wrote:
>> On 22 August 2016 at 16:55, Trevor Saunders <tbsaunde@tbsaunde.org>
>> wrote:
>> > On Sun, Aug 21, 2016 at 10:35:17PM +0530, Prasad Ghangal wrote:
>
> [...]
>
>> > @@ -228,6 +228,12 @@ struct GTY(()) function {
>> >    /* GIMPLE body for this function.  */
>> >    gimple_seq gimple_body;
>> >
>> > +  /* GIMPLEFE pass to start with */
>> > +  opt_pass *pass_startwith = NULL;
> I'm guessing you've only compiled in C++11 mode? because I'm pretty
>> > sure
>> > you are using a C++11 feature here (the default member value you
>> > assign).
>>
>
> [...]
>
>> I am not getting what did you mean by C++11 mode (I am not explicitly
>
> Prasad: what compiler version are you using to build your patched gcc?
>  My guess is that you're using gcc 6 to build.
>
I am using gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.1)

> In gcc 6 we changed the default C++ mode from -std=gnu++98
> to -std=gnu++14. See:
>   https://gcc.gnu.org/gcc-6/porting_to.html#gxx14
>
> I believe the syntax that Trevor spotted is only available in C++11
> onwards:
>
>   $ cat test.cc
>   struct foo
>   {
>     int field = 42;
>   };
>
> With the default for gcc 6:
>
>   $ gcc -c test.cc -std=c++14
>
> it has no problems, whereas with the default for gcc 5 and earlier:
>
>   $ gcc -c test.cc -std=gnu++98
>   test.cc:3:15: warning: non-static data member initializers only
> available with -std=c++11 or -std=gnu++11
>    int field = 42;
>                ^~
>
and it does give me the warning. I will try compiling on < 5 version.

> So it's probably worth attempting to bootstrap with an older gcc as the
> starting compiler.
>
> Hope this is helpful
> Dave

Re-attaching the patch as it has a typo


Thanks,
Prasad

[-- Attachment #2: ChangeLog.patch --]
[-- Type: text/x-diff, Size: 5458 bytes --]

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1929ba8..cded23f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,55 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+	
+	* cgraphunit.c (cgraph_node::assemble_thunks_and_aliases): New variable.
+	(cgraph_node::expand): Add new argument to function.
+	execute_pass_list, guard gcc_assert (TREE_ASM_WRITTEN (decl)) with 
+	condition.
+	* coretypes.h (tree_node *const_tree): New decl, add headers, new
+	variables.
+	* function.h (struct GTY()) function): Add new member to store
+	startwith pass also add new member as a flag.
+	* gimple-pretty-print.c (dump_gimple_switch): Change dumping formats.
+	(dump_gimple_label): Remove condition for DECL_NONLOCAL, flags & 
+	TDF_EH, EH_LANDING_PAD_NR. Change dumping format.
+	(dump_ssaname_info_to_file): Change passing arguments of dump_gimple_phi
+	(dump_gimple_phi): Remove condition for comment, change format of
+	dumping PHI and PHI arguments.
+	(pp_gimple_stmt_1): Remove argument of dump_gimple_phi function.
+	(dump_gimple_bb_header): Change format of dumping gimple basic block
+	header.
+	(dump_phi_nodes): Remove argument of dump_gimple_phi function.
+	(pp_cfg_jump): Remove stmt, remove condition for GIMPLE_LABEL, change 
+	dumping format of gimple basic block header.
+	(gimple_dump_bb_for_graph): Change format of dumping gimple basic block
+	* gimplify.c (gimplify_function_tree): Add condition for presence of
+	gimple body in the cfun.
+	* internal-fn.c (expand_PHI): New function.
+	* internal-fn.h (expand_PHI): Declared here.
+	* internal-fn.def: New defination for PHI.
+	* passes.c (do_per_function_toporder): Add new argument flag, add new
+	argument in callback function call.
+	(execute_one_pass): Add new function argument, add condition for 
+	skipping passes until startwith pass.
+	(execute_pass_list_1): Add new function argument, add condition to 
+	check starwith flag.
+	(execute_ipa_pass_list): New variable, add condition to check and skip
+	passes for startwith pass, pass new argument to function 
+	do_per_function_toporder.
+	* tree-pass.h (execute_one_pass): Add new argument to the function.
+	(execute_pass_list): Likewise.
+	* tree-cfg.c (lower_phi_internal_fn): New function.
+	(verify_gimple_call): Condition for passing label as arg in internal
+	function PHI.
+	(dump_function_to_file): Change format of gimple dump.
+	* tree-into-ssa.c (rewrite_add_phi_arguments): New variable, add 
+	condition for avoiding ssa name versions.
+	* tree-pretty-print.c (dump_decl_name): Change format of dumping gimple
+	labels.
+	(dump_function_header): Change format of gimple dump header
+	* tree-ssanames.c (make_ssa_name_fn): New argument, check for version
+	and assign proper version for parsed ssa names.
+	* tree-ssanames.h (make_ssa_name_fn): Add new argument to the function.
+
 2016-08-20  Kugan Vivekanandarajah  <kuganv@linaro.org>
 
 	* Makefile.in: Add tree-vrp.h to GTFILES.
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index bec37cf..a8c0ab1 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+	
+	* c-common.h (c_common_resword): Add RID_GIMPLE, RID_PHI types.
+	* c-common.h (enum rid): Add RID_GIMPLE, RID_PHI.
+	* c.opt (fgimple): New option.
+
 2016-08-19  Joseph Myers  <joseph@codesourcery.com>
 
 	PR c/32187
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 8d9d4aa..71e78f3 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,29 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+	
+	* c_parser.c: Add headers.
+	(c_parser_parse_gimple_body): New function.
+	(c_parser_gimple_compound_statement): Likewise.
+	(c_parser_gimple_label): Likewise.
+	(c_parser_gimple_expression): Likewise
+	(c_parser_gimple_binary_expression): Likewise.
+	(c_parser_gimple_unary_expression): Likewise.
+	(c_parser_gimple_postfix_expression): Likewise.
+	(c_parser_gimple_postfix_expression_after_primary): Likewise.
+	(c_parser_gimple_pass_list): Likewise.
+	(c_parser_gimple_pass_list_params): Likewise.
+	(c_parser_gimple_declaration): Likewise.
+	(c_parser_gimple_goto_stmt): Likewise.
+	(c_parser_gimple_if_stmt): Likewise.
+	(c_parser_gimple_switch_stmt): Likewise.
+	(c_parser_gimple_return_stmt): Likewise.
+	(c_finish_gimple_return): Likewise.
+	(c_parser_parse_ssa_names): Likewise.
+	(c_parser_gimple_paren_condition): Likewise.
+	(c_parser_gimple_expr_list): Likewise.
+	(c_parser_declaration_or_fndef): New decls. Call function.
+	c_parser_gimple_pass_list, set startwith passes, call
+	c_parser_parse_gimple_body.
+
 2016-08-19  Joseph Myers  <joseph@codesourcery.com>
 
 	PR c/32187
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6201e0c..3da6354 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,19 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+
+	* gcc.dg/gimplefe-1.c: New testcase.
+	* gcc.dg/gimplefe-2.c: Likewise.
+	* gcc.dg/gimplefe-3.c: Likewise.
+	* gcc.dg/gimplefe-4.c: Likewise.
+	* gcc.dg/gimplefe-5.c: Likewise.
+	* gcc.dg/gimplefe-6.c: Likewise.
+	* gcc.dg/gimplefe-7.c: Likewise.
+	* gcc.dg/gimplefe-8.c: Likewise.
+	* gcc.dg/gimplefe-9.c: Likewise.
+	* gcc.dg/gimplefe-10.c: Likewise.
+	* gcc.dg/gimplefe-11.c: Likewise.
+	* gcc.dg/gimplefe-12.c: Likewise.
+	* gcc.dg/gimplefe-13.c: Likewise.
+
 2016-08-20  Kugan Vivekanandarajah  <kuganv@linaro.org>
 
 	PR tree-optimization/61839


[-- Attachment #3: gimplefe.patch --]
[-- Type: text/x-diff, Size: 69973 bytes --]

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 32468ca..5b43016 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -522,6 +522,8 @@ const struct c_common_resword c_common_reswords[] =
   { "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY },
   { "__volatile",	RID_VOLATILE,	0 },
   { "__volatile__",	RID_VOLATILE,	0 },
+  { "__GIMPLE",		RID_GIMPLE,	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-family/c-common.h b/gcc/c-family/c-common.h
index bc22baa..17dc91e 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -118,6 +118,12 @@ enum rid
 
   RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN,
 
+  /* "__GIMPLE", for the GIMPLE-parsing extension to the C frontend. */
+  RID_GIMPLE,
+
+  /* "__PHI", for parsing PHI function in GIMPLE FE.  */
+  RID_PHI,
+
   /* C11 */
   RID_ALIGNAS, RID_GENERIC,
 
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index a5358ed..3c4d2cc 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -200,6 +200,10 @@ F
 Driver C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -F <dir>	Add <dir> to the end of the main framework include path.
 
+fgimple
+C Var(flag_gimple) Init(0)
+Enable parsing GIMPLE
+
 H
 C ObjC C++ ObjC++
 Print the name of header files as they are used.
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index fe0c95f..31b4616 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -59,6 +59,18 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-expr.h"
 #include "context.h"
 #include "gcc-rich-location.h"
+#include "tree-vrp.h"
+#include "tree-pass.h"
+#include "tree-pretty-print.h"
+#include "tree.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-pretty-print.h"
+#include "tree-ssa.h"
+#include "pass_manager.h"
+#include "tree-ssanames.h"
+#include "gimple-ssa.h"
+#include "tree-dfa.h"
 
 /* We need to walk over decls with incomplete struct/union/enum types
    after parsing the whole translation unit.
@@ -1416,6 +1428,29 @@ static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context);
 static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
 static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool);
 static void c_parser_cilk_grainsize (c_parser *, bool *);
+static void c_parser_parse_gimple_body (c_parser *);
+static bool c_parser_gimple_compound_statement (c_parser *, gimple_seq *);
+static void c_parser_gimple_label (c_parser *, gimple_seq *);
+static void c_parser_gimple_expression (c_parser *, gimple_seq *);
+static struct c_expr c_parser_gimple_binary_expression (c_parser *, enum tree_code *);
+static struct c_expr c_parser_gimple_unary_expression (c_parser *);
+static struct c_expr c_parser_gimple_postfix_expression (c_parser *);
+static struct c_expr c_parser_gimple_postfix_expression_after_primary (c_parser *,
+								       location_t,
+								       struct c_expr);
+static void c_parser_gimple_pass_list (c_parser *, opt_pass **, bool *);
+static opt_pass *c_parser_gimple_pass_list_params (c_parser *, opt_pass **);
+static void c_parser_gimple_declaration (c_parser *);
+static void c_parser_gimple_goto_stmt (location_t, tree, gimple_seq *);
+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 *, bool,
+		    vec<tree, va_gc> **, location_t *, tree *,
+		    vec<location_t> *, unsigned int *);
 
 /* Parse a translation unit (C90 6.7, C99 6.9).
 
@@ -1659,6 +1694,9 @@ 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;
+  opt_pass *pass = NULL;
+  bool startwith_p = false;
 
   if (static_assert_ok
       && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
@@ -1743,6 +1781,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       c_parser_skip_to_end_of_block_or_statement (parser);
       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, &startwith_p);
+	  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))
@@ -2144,6 +2196,13 @@ 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 (pass)
+	{
+	  cfun->pass_startwith = pass;
+	  cfun->startwith = startwith_p;
+	}
+
       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,
@@ -2152,6 +2211,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
 	= c_parser_peek_token (parser)->location;
+
+      if (gimple_body_p && flag_gimple)
+	{
+	  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);
@@ -18194,4 +18267,1460 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
   return value_tree;
 }
 
+/* Parse the body of a function declaration marked with "__GIMPLE".  */
+
+void
+c_parser_parse_gimple_body (c_parser *parser)
+{
+  gimple_seq seq = NULL;
+  gimple_seq body = NULL;
+  tree stmt = push_stmt_list ();
+  push_scope ();
+  location_t loc1 = c_parser_peek_token (parser)->location;
+
+  init_tree_ssa (cfun);
+
+  if (!c_parser_gimple_compound_statement (parser, &seq))
+    {
+      gimple *ret = gimple_build_return (NULL);
+      gimple_seq_add_stmt (&seq, ret);
+    }
+
+  tree block = pop_scope ();
+  stmt = pop_stmt_list (stmt);
+  stmt = c_build_bind_expr (loc1, block, stmt);
+
+  block = DECL_INITIAL (current_function_decl);
+  BLOCK_SUBBLOCKS (block) = NULL_TREE;
+  BLOCK_CHAIN (block) = NULL_TREE;
+  TREE_ASM_WRITTEN (block) = 1;
+
+  gbind *bind_stmt = gimple_build_bind (BIND_EXPR_VARS (stmt), NULL,
+					BIND_EXPR_BLOCK (stmt));
+  gimple_bind_set_body (bind_stmt, seq);
+  gimple_seq_add_stmt (&body, bind_stmt);
+  gimple_set_body (current_function_decl, body);
+  cfun->curr_properties = PROP_gimple_any;
+
+  return;
+}
+
+/* Parse a compound statement in gimple function body.
+
+   gimple-statement:
+     gimple-statement
+     gimple-declaration-statement
+     gimple-if-statement
+     gimple-switch-statement
+     gimple-labeled-statement
+     gimple-expression-statement
+     gimple-goto-statement
+     gimple-phi-statement
+     gimple-return-statement
+*/
+
+static bool
+c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
+{
+  bool return_p = false;
+
+  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+    return false;
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      c_parser_consume_token (parser);
+      return false;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      c_parser_error (parser, "expected declaration or statement");
+      c_parser_consume_token (parser);
+      return false;
+    }
+
+  while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+    {
+
+      if (parser->error)
+	{
+	  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
+	  return return_p;
+	}
+
+      if (c_parser_next_token_is (parser, CPP_NAME)
+	  && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+	c_parser_gimple_label (parser, seq);
+
+      else if (c_parser_next_tokens_start_declaration (parser))
+	c_parser_gimple_declaration (parser);
+
+      else if (c_parser_next_token_is (parser, CPP_EOF))
+	{
+	  c_parser_error (parser, "expected declaration or statement");
+	  return return_p;
+	}
+
+      else
+	{
+	  switch (c_parser_peek_token (parser)->type)
+	    {
+	    case CPP_KEYWORD:
+	      switch (c_parser_peek_token (parser)->keyword)
+		{
+		case RID_IF:
+		  c_parser_gimple_if_stmt (parser, seq);
+		  break;
+		case RID_SWITCH:
+		  c_parser_gimple_switch_stmt (parser, seq);
+		  break;
+		case RID_GOTO:
+		    {
+		      location_t loc = c_parser_peek_token (parser)->location;
+		      c_parser_consume_token (parser);
+		      if (c_parser_next_token_is (parser, CPP_NAME))
+			{
+			  c_parser_gimple_goto_stmt (loc,
+						     c_parser_peek_token (parser)->value,
+						     seq);
+			  c_parser_consume_token (parser);
+			  if (!c_parser_require (parser, CPP_SEMICOLON,
+						 "expected %<;%>"))
+			    return return_p;
+			}
+		    }
+		  break;
+		case RID_RETURN:
+		  return_p = true;
+		  c_parser_gimple_return_stmt (parser, seq);
+		  if (!c_parser_require (parser, CPP_SEMICOLON,
+					 "expected %<;%>"))
+		    return return_p;
+		  break;
+		default:
+		  goto expr_stmt;
+		}
+	      break;
+	    case CPP_SEMICOLON:
+	      c_parser_consume_token (parser);
+	      break;
+	    default:
+	    expr_stmt:
+	      c_parser_gimple_expression (parser, seq);
+	      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+		return return_p;
+	    }
+	}
+    }
+  c_parser_consume_token (parser);
+  return return_p; 
+}
+
+/* Parse a gimple expression.
+
+   gimple-expression:
+     gimple-unary-expression
+     gimple-call-statement
+     gimple-binary-expression
+     gimple-assign-expression
+     gimple-cast-expression
+
+*/
+
+static void
+c_parser_gimple_expression (c_parser *parser, gimple_seq *seq)
+{
+  c_expr lhs, rhs;
+  gimple *assign = NULL;
+  enum tree_code subcode = NOP_EXPR;
+  location_t loc;
+  tree arg = NULL_TREE;
+  auto_vec<tree> vargs;
+
+
+  lhs = c_parser_gimple_unary_expression (parser);
+
+  if (c_parser_next_token_is (parser, CPP_EQ))
+    {
+      c_parser_consume_token (parser);
+    }
+
+  loc = EXPR_LOCATION (lhs.value);
+
+  /* gimple call expression. */
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON) &&
+      TREE_CODE (lhs.value) == CALL_EXPR)
+    {
+      gimple *call;
+      call = gimple_build_call_from_tree (lhs.value);
+      gimple_seq_add_stmt (seq, call);
+      gimple_set_location (call, loc);
+      return;
+    }
+
+  /* cast expression.  */
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+    {
+      rhs = c_parser_cast_expression (parser, NULL);	  //TODO: have a gimple_cast_expr function
+      if (lhs.value != error_mark_node &&
+	  rhs.value != error_mark_node)
+	{
+	  assign = gimple_build_assign (lhs.value, rhs.value);
+	  gimple_seq_add_stmt (seq, assign);
+	  gimple_set_location (assign, loc);
+	  return;
+	}
+    }
+
+  if (POINTER_TYPE_P (TREE_TYPE (lhs.value)))
+    {
+      STRIP_USELESS_TYPE_CONVERSION (rhs.value);
+      if (!useless_type_conversion_p (TREE_TYPE (lhs.value),
+				      TREE_TYPE (rhs.value)))
+	rhs.value = fold_convert_loc (loc, TREE_TYPE (lhs.value), rhs.value);
+    }
+
+  /* pointer expression.  */
+  if (TREE_CODE (lhs.value) == INDIRECT_REF)
+    {
+      tree save_expr = lhs.value;
+      bool volatilep = TREE_THIS_VOLATILE (lhs.value);
+      bool notrap = TREE_THIS_NOTRAP (lhs.value);
+      tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (lhs.value, 0));
+
+      lhs.value = fold_indirect_ref_loc (loc, lhs.value);
+      if (lhs.value == save_expr)
+	{
+	  lhs.value = fold_build2_loc (input_location, MEM_REF,
+				       TREE_TYPE (lhs.value),
+				       TREE_OPERAND (lhs.value, 0),
+				       build_int_cst (saved_ptr_type, 0));
+	  TREE_THIS_VOLATILE (lhs.value) = volatilep;
+	  TREE_THIS_NOTRAP (lhs.value) = notrap;
+	}
+    }
+
+  if (c_parser_next_token_is (parser, CPP_AND) ||
+      c_parser_next_token_is (parser, CPP_MULT) ||
+      c_parser_next_token_is (parser, CPP_PLUS) ||
+      c_parser_next_token_is (parser, CPP_MINUS) ||
+      c_parser_next_token_is (parser, CPP_COMPL) ||
+      c_parser_next_token_is (parser, CPP_NOT))
+    {
+      rhs = c_parser_gimple_unary_expression (parser);
+      assign = gimple_build_assign (lhs.value, rhs.value);
+      gimple_set_location (assign, loc);
+      gimple_seq_add_stmt (seq, assign);
+      return;
+    }
+
+  /* gimple PHI expression.  */
+  if (c_parser_next_token_is_keyword (parser, RID_PHI))
+    {
+      c_parser_consume_token (parser);
+
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+	{
+	  return;
+	}
+
+      if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+	c_parser_consume_token (parser);
+
+      while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+	{
+	  if (c_parser_next_token_is (parser, CPP_NAME) &&
+	      c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+	    {
+	      arg = lookup_label_for_goto (loc,
+					   c_parser_peek_token (parser)->value);
+	      c_parser_consume_token (parser);
+
+	      if (c_parser_next_token_is (parser, CPP_COLON))
+		c_parser_consume_token (parser);
+	      vargs.safe_push (arg);
+	    }
+	  else if (c_parser_next_token_is (parser, CPP_COMMA))
+	    {
+	      c_parser_consume_token (parser);
+	    }
+	  else
+	    {
+	      arg = c_parser_parse_ssa_names (parser).value;
+	      vargs.safe_push (arg);
+	    }
+	}
+
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+				 "expected %<)%>");
+
+      /* build internal function for PHI. */
+      gcall *call_stmt = gimple_build_call_internal_vec (IFN_PHI, vargs);
+      gimple_call_set_lhs (call_stmt, lhs.value);
+      gimple_set_location (call_stmt, UNKNOWN_LOCATION);
+      gimple_seq_add_stmt (seq, call_stmt);
+      return;
+    }
+
+  /* gimple call with lhs. */
+  if (c_parser_next_token_is (parser, CPP_NAME) &&
+      c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN &&
+      lookup_name (c_parser_peek_token (parser)->value))
+    {
+      rhs = c_parser_gimple_unary_expression (parser);
+      gimple *call = gimple_build_call_from_tree (rhs.value);
+      gimple_call_set_lhs (call, lhs.value);
+      gimple_seq_add_stmt (seq, call);
+      gimple_set_location (call, loc);
+      return;
+    }
+
+  location_t exp_location = c_parser_peek_token (parser)->location;
+  rhs = c_parser_gimple_binary_expression (parser, &subcode);
+  rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true);
+
+  if (lhs.value != error_mark_node &&
+      rhs.value != error_mark_node)
+    {
+      if (subcode == NOP_EXPR)
+	assign = gimple_build_assign (lhs.value, rhs.value);
+      else
+	assign = gimple_build_assign (lhs.value, subcode,
+				      TREE_OPERAND (rhs.value, 0),
+				      TREE_OPERAND (rhs.value, 1));
+      gimple_seq_add_stmt (seq, assign);
+      gimple_set_location (assign, loc);
+    }
+  return;
+}
+
+/* Parse gimple binary expr.
+
+   gimple-multiplicative-expression:
+     gimple-unary-expression * gimple-unary-expression
+     gimple-unary-expression / gimple-unary-expression
+     gimple-unary-expression % gimple-unary-expression
+
+   gimple-additive-expression:
+     gimple-unary-expression + gimple-unary-expression
+     gimple-unary-expression - gimple-unary-expression
+
+   gimple-shift-expression:
+     gimple-unary-expression << gimple-unary-expression
+     gimple-unary-expression >> gimple-unary-expression
+
+   gimple-relational-expression:
+     gimple-unary-expression < gimple-unary-expression
+     gimple-unary-expression > gimple-unary-expression
+     gimple-unary-expression <= gimple-unary-expression
+     gimple-unary-expression >= gimple-unary-expression
+
+   gimple-equality-expression:
+     gimple-unary-expression == gimple-unary-expression
+     gimple-unary-expression != gimple-unary-expression
+
+   gimple-AND-expression:
+     gimple-unary-expression & gimple-unary-expression
+
+   gimple-exclusive-OR-expression:
+     gimple-unary-expression ^ gimple-unary-expression
+
+   gimple-inclusive-OR-expression:
+     gimple-unary-expression | gimple-unary-expression
+
+   gimple-logical-AND-expression:
+     gimple-unary-expression && gimple-unary-expression
+
+   gimple-logical-OR-expression:
+     gimple-unary-expression || gimple-unary-expression
+
+*/
+
+static c_expr
+c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)
+{
+  struct {
+    /* The expression at this stack level.  */
+    struct c_expr expr;
+    /* The operation on its left.  */
+    enum tree_code op;
+    /* The source location of this operation.  */
+    location_t loc;
+  } stack[2];
+  int sp;
+  /* Location of the binary operator.  */
+  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
+#define POP								      \
+  do {									      \
+    switch (stack[sp].op)						      \
+      {									      \
+      case TRUTH_ANDIF_EXPR:						      \
+	c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value	      \
+					  == truthvalue_false_node);	      \
+	break;								      \
+      case TRUTH_ORIF_EXPR:						      \
+	c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value	      \
+					  == truthvalue_true_node);	      \
+	break;								      \
+      default:								      \
+	break;								      \
+      }									      \
+    stack[sp - 1].expr							      \
+      = convert_lvalue_to_rvalue (stack[sp - 1].loc,			      \
+				  stack[sp - 1].expr, true, true);	      \
+    stack[sp].expr							      \
+      = convert_lvalue_to_rvalue (stack[sp].loc,			      \
+				  stack[sp].expr, true, true);		      \
+    if (sp == 1								      \
+	&& c_parser_peek_token (parser)->type == CPP_SEMICOLON		      \
+	&& (((1 << PREC_BITOR) | (1 << PREC_BITXOR) | (1 << PREC_BITAND)      \
+	       | (1 << PREC_SHIFT) | (1 << PREC_ADD) | (1 << PREC_MULT)))     \
+	&& stack[sp].op != TRUNC_MOD_EXPR				      \
+	&& stack[0].expr.value != error_mark_node			      \
+	&& stack[1].expr.value != error_mark_node)			      \
+      stack[0].expr.value						      \
+	= build2 (stack[1].op, TREE_TYPE (stack[0].expr.value),		      \
+		  stack[0].expr.value, stack[1].expr.value);		      \
+    else								      \
+      stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,	      \
+						   stack[sp].op,	      \
+						   stack[sp - 1].expr,	      \
+						   stack[sp].expr);	      \
+    sp--;								      \
+  } while (0)
+  stack[0].loc = c_parser_peek_token (parser)->location;
+  stack[0].expr = c_parser_gimple_unary_expression (parser);
+  sp = 0;
+  source_range src_range;
+  if (parser->error)
+    goto out;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_MULT:
+      *subcode = MULT_EXPR;
+      break;
+    case CPP_DIV:
+      *subcode = TRUNC_DIV_EXPR;
+      break;
+    case CPP_MOD:
+      *subcode = TRUNC_MOD_EXPR;
+      break;
+    case CPP_PLUS:
+      *subcode = PLUS_EXPR;
+      break;
+    case CPP_MINUS:
+      *subcode = MINUS_EXPR;
+      break;
+    case CPP_LSHIFT:
+      *subcode = LSHIFT_EXPR;
+      break;
+    case CPP_RSHIFT:
+      *subcode = RSHIFT_EXPR;
+      break;
+    case CPP_LESS:
+      *subcode = LT_EXPR;
+      break;
+    case CPP_GREATER:
+      *subcode = GT_EXPR;
+      break;
+    case CPP_LESS_EQ:
+      *subcode = LE_EXPR;
+      break;
+    case CPP_GREATER_EQ:
+      *subcode = GE_EXPR;
+      break;
+    case CPP_EQ_EQ:
+      *subcode = EQ_EXPR;
+      break;
+    case CPP_NOT_EQ:
+      *subcode = NE_EXPR;
+      break;
+    case CPP_AND:
+      *subcode = BIT_AND_EXPR;
+      break;
+    case CPP_XOR:
+      *subcode = BIT_XOR_EXPR;
+      break;
+    case CPP_OR:
+      *subcode = BIT_IOR_EXPR;
+      break;
+    case CPP_AND_AND:
+      *subcode = TRUTH_ANDIF_EXPR;
+      break;
+    case CPP_OR_OR:
+      *subcode = TRUTH_ORIF_EXPR;
+      break;
+    default:
+      /* Not a binary operator, so end of the binary
+	 expression.  */
+      *subcode = NOP_EXPR;
+      goto out;
+    }
+  binary_loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_token (parser);
+  switch (*subcode)
+    {
+    case TRUTH_ANDIF_EXPR:
+      src_range = stack[sp].expr.src_range;
+      stack[sp].expr
+	= convert_lvalue_to_rvalue (stack[sp].loc,
+				    stack[sp].expr, true, true);
+      stack[sp].expr.value = c_objc_common_truthvalue_conversion
+	(stack[sp].loc, default_conversion (stack[sp].expr.value));
+      c_inhibit_evaluation_warnings += (stack[sp].expr.value
+					== truthvalue_false_node);
+      set_c_expr_source_range (&stack[sp].expr, src_range);
+      break;
+    case TRUTH_ORIF_EXPR:
+      src_range = stack[sp].expr.src_range;
+      stack[sp].expr
+	= convert_lvalue_to_rvalue (stack[sp].loc,
+				    stack[sp].expr, true, true);
+      stack[sp].expr.value = c_objc_common_truthvalue_conversion
+	(stack[sp].loc, default_conversion (stack[sp].expr.value));
+      c_inhibit_evaluation_warnings += (stack[sp].expr.value
+					== truthvalue_true_node);
+      set_c_expr_source_range (&stack[sp].expr, src_range);
+      break;
+    default:
+      break;
+    }
+  sp++;
+  stack[sp].loc = binary_loc;
+  stack[sp].expr = c_parser_gimple_unary_expression (parser);
+  stack[sp].op = *subcode;
+out:
+  while (sp > 0)
+    POP;
+  return stack[0].expr;
+#undef POP
+
+}
+
+/* Parse gimple unary expression.
+
+   gimple-unary-expression:
+     gimple-postfix-expression
+     unary-operator cast-expression
+
+   unary-operator: one of
+     & * + - ~ !
+*/
+
+static c_expr
+c_parser_gimple_unary_expression (c_parser *parser)
+{
+  struct c_expr ret, op;
+  if (c_parser_peek_token (parser)->value
+      && TREE_CODE (c_parser_peek_token (parser)->value) == IDENTIFIER_NODE
+      && !lookup_name (c_parser_peek_token (parser)->value))
+    return c_parser_parse_ssa_names (parser);
+
+  location_t op_loc = c_parser_peek_token (parser)->location;
+  location_t exp_loc;
+  location_t finish;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_AND:
+      c_parser_consume_token (parser);
+      op = c_parser_cast_expression (parser, NULL);
+      mark_exp_read (op.value);
+      return parser_build_unary_op (op_loc, ADDR_EXPR, op);
+    case CPP_MULT:
+      {
+	c_parser_consume_token (parser);
+	exp_loc = c_parser_peek_token (parser)->location;
+	op = c_parser_cast_expression (parser, NULL);
+	finish = op.get_finish ();
+	op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
+	location_t combined_loc = make_location (op_loc, op_loc, finish);
+	ret.value = build_indirect_ref (combined_loc, op.value,
+					RO_UNARY_STAR);
+	ret.src_range.m_start = op_loc;
+	ret.src_range.m_finish = finish;
+	return ret;
+      }
+    case CPP_PLUS:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
+      return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
+    case CPP_MINUS:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
+      return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
+    case CPP_COMPL:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
+      return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
+    case CPP_NOT:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
+      return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
+    default:
+      return c_parser_gimple_postfix_expression (parser);
+    }
+}
+
+/* Parse gimple ssa names.  */
+
+static c_expr
+c_parser_parse_ssa_names (c_parser *parser)
+{
+  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;
+
+  /* ssa token string.  */
+  const char *ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+  token = new char [strlen (ssa_token)];
+  strcpy (token, ssa_token);
+
+  /* seperate 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);
+
+      /* lookup for parent decl.  */
+      if (lookup_name (id))
+	{
+	  var_version++;
+	  unsigned int version;
+	  version = atoi (var_version);
+	  if (var_version && version)
+	    {
+	      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);
+	    }
+	}
+    }
+
+  /* for default defination ssa names.  */
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      c_parser_consume_token (parser);
+      ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (!strcmp ("D", ssa_token))
+	{
+	  set_ssa_default_def (cfun, lookup_name (id), ret.value);
+	  c_parser_consume_token (parser);
+	}
+      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+	goto out;
+    }
+
+  out:
+  free (var_name);
+  free (token);
+  return ret;
+}
+
+/* Parse gimple postfix expression.
+
+   gimple-postfix-expression:
+     gimple-primary-expression
+     gimple-primary-xpression [ gimple-primary-expression ]
+     gimple-primary-expression ( gimple-argument-expression-list[opt] )
+
+   gimple-argument-expression-list:
+     gimple-unary-expression
+     gimple-argument-expression-list , gimple-unary-expression
+
+   gimple-primary-expression:
+     identifier
+     constant
+     string-literal
+
+*/
+
+static struct c_expr
+c_parser_gimple_postfix_expression (c_parser *parser)
+{
+  struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
+  source_range tok_range = c_parser_peek_token (parser)->get_range ();
+  expr.original_code = ERROR_MARK;
+  expr.original_type = NULL;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_NUMBER:
+      expr.value = c_parser_peek_token (parser)->value;
+      set_c_expr_source_range (&expr, tok_range);
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      if (TREE_CODE (expr.value) == FIXED_CST
+	  && !targetm.fixed_point_supported_p ())
+	{
+	  error_at (loc, "fixed-point types not supported for this target");
+	  expr.value = error_mark_node;
+	}
+      break;
+    case CPP_CHAR:
+    case CPP_CHAR16:
+    case CPP_CHAR32:
+    case CPP_WCHAR:
+      expr.value = c_parser_peek_token (parser)->value;
+      set_c_expr_source_range (&expr, tok_range);
+      c_parser_consume_token (parser);
+      break;
+    case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
+    case CPP_WSTRING:
+    case CPP_UTF8STRING:
+      expr.value = c_parser_peek_token (parser)->value;
+      set_c_expr_source_range (&expr, tok_range);
+      expr.original_code = STRING_CST;
+      c_parser_consume_token (parser);
+      break;
+    case CPP_NAME:
+      if (c_parser_peek_token (parser)->id_kind == C_ID_ID)
+	{
+	  tree id = c_parser_peek_token (parser)->value;
+	  c_parser_consume_token (parser);
+	  expr.value = build_external_ref (loc, id,
+					   (c_parser_peek_token (parser)->type
+					    == CPP_OPEN_PAREN),
+					   &expr.original_type);
+	  set_c_expr_source_range (&expr, tok_range);
+	  break;
+	}
+      else
+	{
+	  c_parser_error (parser, "expected expression");
+	  expr.set_error ();
+	  break;
+	}
+      break;
+    default:
+      c_parser_error (parser, "expected expression");
+      expr.set_error ();
+      break;
+    }
+  return c_parser_gimple_postfix_expression_after_primary
+    (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
+}
+
+/* Parse a gimple postfix expression after the initial primary or compound
+   literal.  */
+
+static struct c_expr
+c_parser_gimple_postfix_expression_after_primary (c_parser *parser,
+						  location_t expr_loc,
+						  struct c_expr expr)
+{
+  struct c_expr orig_expr;
+  location_t sizeof_arg_loc[3];
+  tree sizeof_arg[3];
+  unsigned int literal_zero_mask;
+  unsigned int i;
+  vec<tree, va_gc> *exprlist;
+  vec<tree, va_gc> *origtypes = NULL;
+  vec<location_t> arg_loc = vNULL;
+  location_t start;
+  location_t finish;
+
+  location_t op_loc = c_parser_peek_token (parser)->location;
+
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_OPEN_SQUARE:
+	{
+	  c_parser_consume_token (parser);
+	  tree idx = c_parser_gimple_unary_expression (parser).value;
+
+	  if (!c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>"))
+	    break;
+
+	  start = expr.get_start ();
+	  finish = parser->tokens_buf[0].location;
+	  expr.value = build_array_ref (op_loc, expr.value, idx);
+	  set_c_expr_source_range (&expr, start, finish);
+
+	  expr.original_code = ERROR_MARK;
+	  expr.original_type = NULL;
+	  break;
+	}
+    case CPP_OPEN_PAREN:
+	{
+	  /* Function call */
+	  c_parser_consume_token (parser);
+	  for (i = 0; i < 3; i++)
+	    {
+	      sizeof_arg[i] = NULL_TREE;
+	      sizeof_arg_loc[i] = UNKNOWN_LOCATION;
+	    }
+	  literal_zero_mask = 0;
+	  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+	    exprlist = NULL;
+	  else
+	    exprlist = c_parser_gimple_expr_list (parser, true, &origtypes,
+					   sizeof_arg_loc, sizeof_arg,
+					   &arg_loc, &literal_zero_mask);
+	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+				     "expected %<)%>");
+	  orig_expr = expr;
+	  mark_exp_read (expr.value);
+	  if (warn_sizeof_pointer_memaccess)
+	    sizeof_pointer_memaccess_warning (sizeof_arg_loc,
+					      expr.value, exprlist,
+					      sizeof_arg,
+					      sizeof_ptr_memacc_comptypes);
+	  if (TREE_CODE (expr.value) == FUNCTION_DECL
+	      && DECL_BUILT_IN_CLASS (expr.value) == BUILT_IN_NORMAL
+	      && DECL_FUNCTION_CODE (expr.value) == BUILT_IN_MEMSET
+	      && vec_safe_length (exprlist) == 3)
+	    {
+	      tree arg0 = (*exprlist)[0];
+	      tree arg2 = (*exprlist)[2];
+	      warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
+	    }
+
+	  start = expr.get_start ();
+	  finish = parser->tokens_buf[0].get_finish ();
+	  expr.value
+	    = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
+					 exprlist, origtypes);
+	  set_c_expr_source_range (&expr, start, finish);
+
+	  expr.original_code = ERROR_MARK;
+	  if (TREE_CODE (expr.value) == INTEGER_CST
+	      && TREE_CODE (orig_expr.value) == FUNCTION_DECL
+	      && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
+	      && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
+	    expr.original_code = C_MAYBE_CONST_EXPR;
+	  expr.original_type = NULL;
+	  if (exprlist)
+	    {
+	      release_tree_vector (exprlist);
+	      release_tree_vector (origtypes);
+	    }
+	  arg_loc.release ();
+	  break;
+	default:
+	  return expr;
+
+	}
+    }
+  return expr;
+}
+
+/* Parse expression list.
+
+   gimple-expr-list:
+     gimple-unary-expression
+     gimple-expr-list , gimple-unary-expression
+
+ */
+
+static vec<tree, va_gc> *
+c_parser_gimple_expr_list (c_parser *parser, bool convert_p,
+		    vec<tree, va_gc> **p_orig_types,
+		    location_t *sizeof_arg_loc, tree *sizeof_arg,
+		    vec<location_t> *locations,
+		    unsigned int *literal_zero_mask)
+{
+  vec<tree, va_gc> *ret;
+  vec<tree, va_gc> *orig_types;
+  struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
+  location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION;
+  unsigned int idx = 0;
+
+  ret = make_tree_vector ();
+  if (p_orig_types == NULL)
+    orig_types = NULL;
+  else
+    orig_types = make_tree_vector ();
+
+  if (sizeof_arg != NULL
+      && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
+    cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
+  if (literal_zero_mask)
+    c_parser_check_literal_zero (parser, literal_zero_mask, 0);
+  expr = c_parser_gimple_unary_expression (parser);
+  if (convert_p)
+    expr = convert_lvalue_to_rvalue (loc, expr, true, true);
+  vec_safe_push (ret, expr.value);
+  if (orig_types)
+    vec_safe_push (orig_types, expr.original_type);
+  if (locations)
+    locations->safe_push (loc);
+  if (sizeof_arg != NULL
+      && cur_sizeof_arg_loc != UNKNOWN_LOCATION
+      && expr.original_code == SIZEOF_EXPR)
+    {
+      sizeof_arg[0] = c_last_sizeof_arg;
+      sizeof_arg_loc[0] = cur_sizeof_arg_loc;
+    }
+  while (c_parser_next_token_is (parser, CPP_COMMA))
+    {
+      c_parser_consume_token (parser);
+      loc = c_parser_peek_token (parser)->location;
+      if (sizeof_arg != NULL
+	  && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
+	cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
+      else
+	cur_sizeof_arg_loc = UNKNOWN_LOCATION;
+      if (literal_zero_mask)
+	c_parser_check_literal_zero (parser, literal_zero_mask, idx + 1);
+      expr = c_parser_gimple_unary_expression (parser);
+      if (convert_p)
+	expr = convert_lvalue_to_rvalue (loc, expr, true, true);
+      vec_safe_push (ret, expr.value);
+      if (orig_types)
+	vec_safe_push (orig_types, expr.original_type);
+      if (locations)
+	locations->safe_push (loc);
+      if (++idx < 3
+	  && sizeof_arg != NULL
+	  && cur_sizeof_arg_loc != UNKNOWN_LOCATION
+	  && expr.original_code == SIZEOF_EXPR)
+	{
+	  sizeof_arg[idx] = c_last_sizeof_arg;
+	  sizeof_arg_loc[idx] = cur_sizeof_arg_loc;
+	}
+    }
+  if (orig_types)
+    *p_orig_types = orig_types;
+  return ret;
+}
+
+/* Parse gimple label.
+
+   gimple-label:
+     identifier :
+     case constant-expression :
+     default :
+
+*/
+
+static void
+c_parser_gimple_label (c_parser *parser, gimple_seq *seq)
+{
+  tree name = c_parser_peek_token (parser)->value;
+  location_t loc1 = c_parser_peek_token (parser)->location;
+  gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
+  c_parser_consume_token (parser);
+  gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
+  c_parser_consume_token (parser);
+  tree label = define_label (loc1, name);
+  gimple_seq_add_stmt (seq, gimple_build_label (label));
+  return;
+}
+
+/* Parse gimple pass list.
+
+   gimple-pass-list:
+     startwith("pass-name")
+ */
+
+static void
+c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass,
+			   bool *startwith_p)
+{
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      return;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      return;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      c_parser_consume_token (parser);
+      if (!strcmp (op, "startwith"))
+	{
+	  *pass = c_parser_gimple_pass_list_params (parser, pass);
+	  if (!(*pass))
+	    return;
+
+	  *startwith_p = true;
+	  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+	    return;
+	}
+      else
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "invalid operation");
+	  return;
+	}
+    }
+  else if (c_parser_next_token_is (parser, CPP_EOF))
+    {
+      c_parser_error (parser, "expected parameters");
+      return;
+    }
+
+  return;
+}
+
+/* Support function for c_parser_gimple_pass_list.  */
+
+static opt_pass *
+c_parser_gimple_pass_list_params (c_parser *parser, opt_pass **pass)
+{
+  opt_pass *pass_start = NULL, *new_pass;
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      return NULL;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      return NULL;
+    }
+
+  while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+    {
+      if (c_parser_next_token_is (parser, CPP_EOF))
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "expected pass names");
+	  return NULL;
+	}
+
+      if (c_parser_next_token_is (parser, CPP_STRING))
+	{
+	  const char *name = NULL;
+	  name = TREE_STRING_POINTER (c_parser_peek_token (parser)->value);
+	  c_parser_consume_token (parser);
+	  new_pass = g->get_passes ()->get_pass_by_name (name);
+
+	  if (!new_pass)
+	    {
+	      error_at (c_parser_peek_token (parser)->location,
+			"invalid pass name");
+	      parser->error = true;
+	      c_parser_consume_token (parser);
+	      return NULL;
+	    }
+	  if (*pass)
+	    {
+	      (*pass)->next = new_pass;
+	      (*pass) = (*pass)->next;
+	    }
+	  else
+	    {
+	      *pass = new_pass;
+	      pass_start = *pass;
+	    }
+	}
+      else if (c_parser_next_token_is (parser, CPP_COMMA))
+	c_parser_consume_token (parser);
+      else
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "invalid pass name");
+	  c_parser_consume_token (parser);
+	  return NULL;
+	}
+    }
+  return pass_start;
+}
+
+/* Parse gimple local declaration.
+
+   declaration-specifiers:
+     storage-class-specifier declaration-specifiers[opt]
+     type-specifier declaration-specifiers[opt]
+     type-qualifier declaration-specifiers[opt]
+     function-specifier declaration-specifiers[opt]
+     alignment-specifier declaration-specifiers[opt]
+
+   storage-class-specifier:
+     typedef
+     extern
+     static
+     auto
+     register
+
+   type-specifier:
+     void
+     char
+     short
+     int
+     long
+     float
+     double
+     signed
+     unsigned
+     _Bool
+     _Complex
+
+   type-qualifier:
+     const
+     restrict
+     volatile
+     address-space-qualifier
+     _Atomic
+
+ */
+
+static void
+c_parser_gimple_declaration (c_parser *parser)
+{
+  struct c_declarator *declarator;
+  struct c_declspecs *specs = build_null_declspecs ();
+  c_parser_declspecs (parser, specs, true, true, true,
+		      true, true, cla_nonabstract_decl);
+  finish_declspecs (specs);
+  bool auto_type_p = specs->typespec_word == cts_auto_type;
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      if (auto_type_p)
+	error_at (c_parser_peek_token (parser)->location,
+		  "%<__auto_type%> in empty declaration");
+      c_parser_consume_token (parser);
+      return;
+    }
+
+  /* Provide better error recovery.  Note that a type name here is usually
+     better diagnosed as a redeclaration.  */
+  if (specs->typespec_kind == ctsk_tagdef
+      && c_parser_next_token_starts_declspecs (parser)
+      && !c_parser_next_token_is (parser, CPP_NAME))
+    {
+      c_parser_error (parser, "expected %<;%>");
+      parser->error = false;
+      shadow_tag_warned (specs, 1);
+      return;
+    }
+
+  bool dummy = false;
+  declarator = c_parser_declarator (parser,
+				    specs->typespec_kind != ctsk_none,
+				    C_DTR_NORMAL, &dummy);
+
+  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);
+	}
+    }
+  else
+    {
+      c_parser_error (parser, "expected %<;%>");
+      return;
+    }
+}
+
+/* Parse gimple goto statement.  */
+
+static void
+c_parser_gimple_goto_stmt (location_t loc, tree label, gimple_seq *seq)
+{
+  tree decl = lookup_label_for_goto (loc, label);
+  gimple_seq_add_stmt (seq, gimple_build_goto (decl));
+  return;
+}
+
+/* Parse a parenthesized condition.
+   gimple-condition:
+     ( gimple-binary-expression )    */
+
+static tree
+c_parser_gimple_paren_condition (c_parser *parser)
+{
+  enum tree_code subcode = NOP_EXPR;
+  location_t loc = c_parser_peek_token (parser)->location;
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return error_mark_node;
+  tree cond = c_parser_gimple_binary_expression (parser, &subcode).value;
+  cond = c_objc_common_truthvalue_conversion (loc, cond);
+  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+    return error_mark_node;
+  return cond;
+}
+
+/* Parse gimple if-else statement.
+
+   if-statement:
+     if ( gimple-binary-expression ) gimple-goto-statement
+     if ( gimple-binary-expression ) gimple-goto-statement \
+					else gimple-goto-statement
+ */
+
+static void
+c_parser_gimple_if_stmt (c_parser *parser, gimple_seq *seq)
+{
+  tree t_label, f_label, label;
+  location_t loc;
+  c_parser_consume_token (parser);
+  tree cond = c_parser_gimple_paren_condition (parser);
+
+  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+    {
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      label = c_parser_peek_token (parser)->value;
+      t_label = lookup_label_for_goto (loc, label);
+      c_parser_consume_token (parser);
+      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+	return;
+    }
+  else
+    {
+      c_parser_error (parser, "expected goto expression");
+      return;
+    }
+
+  if (c_parser_next_token_is_keyword (parser, RID_ELSE))
+    c_parser_consume_token (parser);
+  else
+    {
+      c_parser_error (parser, "expected else statement");
+      return;
+    }
+
+  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+    {
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      label = c_parser_peek_token (parser)->value;
+      f_label = lookup_label_for_goto (loc, label);
+      c_parser_consume_token (parser);
+      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+	return;
+    }
+  else
+    {
+      c_parser_error (parser, "expected goto expression");
+      return;
+    }
+
+  gimple_seq_add_stmt (seq, gimple_build_cond_from_tree (cond, t_label,
+							 f_label));
+}
+
+/* Parse gimple switch-statement.
+
+   gimple-switch-statement:
+     switch (gimple-unary-expression) gimple-case-statement
+
+   gimple-case-statement:
+     gimple-case-statement
+     gimple-label-statement : gimple-goto-statment
+*/
+
+static void
+c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
+{
+  c_expr cond_expr;
+  tree case_label, label;
+  auto_vec<tree> labels;
+  tree default_label = NULL_TREE;
+  gimple_seq switch_body = NULL;
+  location_t loc;
+  c_parser_consume_token (parser);
+
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      cond_expr = c_parser_gimple_unary_expression (parser);
+      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+	return;
+    }
+
+  if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+    {
+      while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+	{
+	  if (c_parser_next_token_is (parser, CPP_EOF))
+	    {
+	      c_parser_error (parser, "expected statement");
+	      return;
+	    }
+
+	  switch (c_parser_peek_token (parser)->keyword)
+	    {
+	    case RID_CASE:
+		{
+		  c_expr exp1;
+		  loc = c_parser_peek_token (parser)->location;
+		  c_parser_consume_token (parser);
+
+		  if (c_parser_next_token_is (parser, CPP_NAME) ||
+		      c_parser_peek_token (parser)->type == CPP_NUMBER)
+		    exp1 = c_parser_gimple_unary_expression (parser);
+		  else
+		    c_parser_error (parser, "expected expression");
+
+		  if (c_parser_next_token_is (parser, CPP_COLON))
+		    {
+		      c_parser_consume_token (parser);
+		      label = create_artificial_label (loc);
+		      case_label = build_case_label (exp1.value, NULL_TREE,
+						     label);
+		      labels.safe_push (case_label);
+		      gimple_seq_add_stmt (&switch_body,
+					   gimple_build_label
+					   (CASE_LABEL (case_label)));
+		    }
+		  else
+		    {
+		      if (!c_parser_require (parser, CPP_SEMICOLON,
+					     "expected %<:%>"))
+			return;
+		    }
+		}
+	      break;
+	    case RID_DEFAULT:
+		{
+		  c_parser_consume_token (parser);
+		  if (c_parser_next_token_is (parser, CPP_COLON))
+		    {
+		      c_parser_consume_token (parser);
+		      default_label = build_case_label (NULL_TREE, NULL_TREE,
+							create_artificial_label
+							(UNKNOWN_LOCATION));
+		      gimple_seq_add_stmt (&switch_body,
+					   gimple_build_label
+					   (CASE_LABEL (default_label)));
+		    }
+		  else
+		    {
+		      if (!c_parser_require (parser, CPP_SEMICOLON,
+					     "expected %<:%>"))
+			return;
+		    }
+		}
+	      break;
+	    case RID_GOTO:
+		{
+		  loc = c_parser_peek_token (parser)->location;
+		  c_parser_consume_token (parser);
+		  if (c_parser_next_token_is (parser, CPP_NAME))
+		    {
+		      c_parser_gimple_goto_stmt (loc,
+						 c_parser_peek_token (parser)->value,
+						 &switch_body);
+		      c_parser_consume_token (parser);
+		      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+			c_parser_consume_token (parser);
+		      else
+			{
+			  c_parser_error (parser, "expected semicolon");
+			  return;
+			}
+		    }
+		  else
+		    {
+		      if (!c_parser_require (parser, CPP_NAME,
+					     "expected label"))
+			return;
+		    }
+		}
+	      break;
+	    default:
+	      c_parser_error (parser, "expected case label or goto statement");
+	      return;
+	    }
+
+	}
+    }
+  if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
+    return;
+  gimple_seq_add_stmt (seq, gimple_build_switch (cond_expr.value,
+						 default_label, labels));
+  gimple_seq_add_seq (seq, switch_body);
+  labels.release();
+}
+
+/* Parse gimple return statement.  */
+
+static void
+c_parser_gimple_return_stmt (c_parser *parser, gimple_seq *seq)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  gimple *ret = NULL;
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      c_finish_gimple_return (loc, NULL_TREE);
+      ret = gimple_build_return (NULL);
+      gimple_seq_add_stmt (seq, ret);
+    }
+  else
+    {
+      location_t xloc = c_parser_peek_token (parser)->location;
+      c_expr expr = c_parser_gimple_unary_expression (parser);
+      c_finish_gimple_return (xloc, expr.value);
+      ret = gimple_build_return (expr.value);
+      gimple_seq_add_stmt (seq, ret);
+    }
+}
+
+/* Support function for c_parser_gimple_return_stmt.  */
+
+static void
+c_finish_gimple_return (location_t loc, tree retval)
+{
+  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
+
+  /* Use the expansion point to handle cases such as returning NULL
+     in a function returning void.  */
+  source_location xloc = expansion_point_location_if_in_system_header (loc);
+
+  if (TREE_THIS_VOLATILE (current_function_decl))
+    warning_at (xloc, 0,
+		"function declared %<noreturn%> has a %<return%> statement");
+
+  if (!retval)
+    {
+      current_function_returns_null = 1;
+    }  
+  else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
+    {
+      current_function_returns_null = 1;
+      if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
+	{
+	  error_at
+	    (xloc, "%<return%> with a value, in function returning void");
+	  inform (DECL_SOURCE_LOCATION (current_function_decl),
+		  "declared here");
+	}
+    }
+  else if (TREE_CODE (valtype) != TREE_CODE (TREE_TYPE (retval)))
+    {
+      error_at
+	(xloc, "invalid conversion in return statement");
+      inform (DECL_SOURCE_LOCATION (current_function_decl),
+	      "declared here");
+    }
+  return;
+}
+
 #include "gt-c-c-parser.h"
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 6a1d126..cf6728f 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1944,6 +1944,7 @@ cgraph_node::assemble_thunks_and_aliases (void)
 void
 cgraph_node::expand (void)
 {
+  bool startwith_p = true;
   location_t saved_loc;
 
   /* We ought to not compile any inline clones.  */
@@ -1982,7 +1983,7 @@ cgraph_node::expand (void)
   /* Signal the start of passes.  */
   invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
 
-  execute_pass_list (cfun, g->get_passes ()->all_passes);
+  execute_pass_list (cfun, g->get_passes ()->all_passes, &startwith_p);
 
   /* Signal the end of passes.  */
   invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
@@ -2035,7 +2036,9 @@ cgraph_node::expand (void)
   timevar_pop (TV_REST_OF_COMPILATION);
 
   /* Make sure that BE didn't give up on compiling.  */
-  gcc_assert (TREE_ASM_WRITTEN (decl));
+  if (!(flag_gimple && cfun->pass_startwith))  /* FIXME : for gimplefe custom_pass_list */
+    gcc_assert (TREE_ASM_WRITTEN (decl));
+
   if (cfun)
     pop_cfun ();
 
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index fe1e984..ad6e5ac 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -85,6 +85,7 @@ typedef const union tree_node *const_tree;
 struct gimple;
 typedef gimple *gimple_seq;
 struct gimple_stmt_iterator;
+class opt_pass;
 
 /* Forward decls for leaf gimple subclasses (for individual gimple codes).
    Keep this in the same order as the corresponding codes in gimple.def.  */
@@ -405,6 +406,8 @@ typedef unsigned char uchar;
 #include "input.h"
 #include "is-a.h"
 #include "memory-block.h"
+#include "pass_manager.h"
+#include "tree-pass.h"
 #endif /* GENERATOR_FILE && !USED_FOR_TARGET */
 
 #endif /* coretypes.h */
diff --git a/gcc/function.h b/gcc/function.h
index 501ef68..0adbd68 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -228,6 +228,12 @@ struct GTY(()) function {
   /* GIMPLE body for this function.  */
   gimple_seq gimple_body;
 
+  /* GIMPLEFE pass to start with */
+  opt_pass *pass_startwith = NULL;
+
+  /* Startwith flag */
+  bool startwith;
+
   /* SSA and dataflow information.  */
   struct gimple_df *gimple_df;
 
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 12d9a9c..e4416a5 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -838,7 +838,7 @@ dump_gimple_switch (pretty_printer *buffer, gswitch *gs, int spc,
     {
       pp_string (buffer, "switch (");
       dump_generic_node (buffer, gimple_switch_index (gs), spc, flags, true);
-      pp_string (buffer, ") <");
+      pp_string (buffer, ") {");
     }
 
   for (i = 0; i < gimple_switch_num_labels (gs); i++)
@@ -849,9 +849,9 @@ dump_gimple_switch (pretty_printer *buffer, gswitch *gs, int spc,
       pp_space (buffer);
       dump_generic_node (buffer, CASE_LABEL (case_label), spc, flags, false);
       if (i < gimple_switch_num_labels (gs) - 1)
-        pp_string (buffer, ", ");
+        pp_string (buffer, "; ");
     }
-  pp_greater (buffer);
+  pp_string (buffer, "}");
 }
 
 
@@ -907,16 +907,11 @@ dump_gimple_label (pretty_printer *buffer, glabel *gs, int spc, int flags)
 {
   tree label = gimple_label_label (gs);
   if (flags & TDF_RAW)
-      dump_gimple_fmt (buffer, spc, flags, "%G <%T>", gs, label);
+    dump_gimple_fmt (buffer, spc, flags, "%T", label);
   else
-    {
-      dump_generic_node (buffer, label, spc, flags, false);
-      pp_colon (buffer);
-    }
-  if (DECL_NONLOCAL (label))
-    pp_string (buffer, " [non-local]");
-  if ((flags & TDF_EH) && EH_LANDING_PAD_NR (label))
-    pp_printf (buffer, " [LP %d]", EH_LANDING_PAD_NR (label));
+    dump_generic_node (buffer, label, spc, flags, false);
+
+  pp_colon (buffer);
 }
 
 /* Dump a GIMPLE_GOTO tuple on the pretty_printer BUFFER, SPC
@@ -1966,8 +1961,7 @@ dump_ssaname_info_to_file (FILE *file, tree node, int spc)
    pretty printer.  If COMMENT is true, print this after #.  */
 
 static void
-dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, bool comment,
-		 int flags)
+dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, int flags)
 {
   size_t i;
   tree lhs = gimple_phi_result (phi);
@@ -1975,30 +1969,27 @@ dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, bool comment,
   if (flags & TDF_ALIAS)
     dump_ssaname_info (buffer, lhs, spc);
 
-  if (comment)
-    pp_string (buffer, "# ");
-
   if (flags & TDF_RAW)
     dump_gimple_fmt (buffer, spc, flags, "%G <%T, ", phi,
 		     gimple_phi_result (phi));
   else
     {
       dump_generic_node (buffer, lhs, spc, flags, false);
-      pp_string (buffer, " = PHI <");
+      pp_string (buffer, " = __PHI (");
     }
   for (i = 0; i < gimple_phi_num_args (phi); i++)
     {
       if ((flags & TDF_LINENO) && gimple_phi_arg_has_location (phi, i))
 	dump_location (buffer, gimple_phi_arg_location (phi, i));
+      pp_string (buffer, "bb_");
+      pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index);
+      pp_string (buffer, ": ");
       dump_generic_node (buffer, gimple_phi_arg_def (phi, i), spc, flags,
 			 false);
-      pp_left_paren (buffer);
-      pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index);
-      pp_right_paren (buffer);
       if (i < gimple_phi_num_args (phi) - 1)
 	pp_string (buffer, ", ");
     }
-  pp_greater (buffer);
+  pp_right_paren (buffer);
 }
 
 
@@ -2286,7 +2277,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple *gs, int spc, int flags)
       break;
 
     case GIMPLE_PHI:
-      dump_gimple_phi (buffer, as_a <gphi *> (gs), spc, false, flags);
+      dump_gimple_phi (buffer, as_a <gphi *> (gs), spc, flags);
       break;
 
     case GIMPLE_OMP_PARALLEL:
@@ -2447,7 +2438,7 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, int indent, int flags)
     {
       gimple *stmt = first_stmt (bb);
       if (!stmt || gimple_code (stmt) != GIMPLE_LABEL)
-	fprintf (outf, "%*s<bb %d>:\n", indent, "", bb->index);
+	fprintf (outf, "%*sbb_%d:\n", indent, "", bb->index);
     }
 }
 
@@ -2480,7 +2471,7 @@ dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags)
       if (!virtual_operand_p (gimple_phi_result (phi)) || (flags & TDF_VOPS))
         {
           INDENT (indent);
-	  dump_gimple_phi (buffer, phi, indent, true, flags);
+	  dump_gimple_phi (buffer, phi, indent, flags);
           pp_newline (buffer);
         }
     }
@@ -2493,24 +2484,9 @@ dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags)
 static void
 pp_cfg_jump (pretty_printer *buffer, basic_block bb)
 {
-  gimple *stmt;
-
-  stmt = first_stmt (bb);
-
-  pp_string (buffer, "goto <bb ");
+  pp_string (buffer, "goto bb_");
   pp_decimal_int (buffer, bb->index);
-  pp_greater (buffer);
-  if (stmt && gimple_code (stmt) == GIMPLE_LABEL)
-    {
-      pp_string (buffer, " (");
-      dump_generic_node (buffer,
-			 gimple_label_label (as_a <glabel *> (stmt)),
-			 0, 0, false);
-      pp_right_paren (buffer);
-      pp_semicolon (buffer);
-    }
-  else
-    pp_semicolon (buffer);
+  pp_semicolon (buffer);
 }
 
 
@@ -2627,7 +2603,7 @@ gimple_dump_bb (FILE *file, basic_block bb, int indent, int flags)
 void
 gimple_dump_bb_for_graph (pretty_printer *pp, basic_block bb)
 {
-  pp_printf (pp, "<bb %d>:\n", bb->index);
+  pp_printf (pp, "bb_%d:\n", bb->index);
   pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
 
   for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 4715332..12b9ec9 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -11848,7 +11848,22 @@ gimplify_function_tree (tree fndecl)
       && !needs_to_live_in_memory (ret))
     DECL_GIMPLE_REG_P (ret) = 1;
 
-  bind = gimplify_body (fndecl, true);
+  if (!cfun->gimple_body)
+    bind = gimplify_body (fndecl, true);
+  else
+    {
+      gimple_seq seq;
+      gimple *outer_stmt;
+      seq = cfun->gimple_body;
+      outer_stmt = gimple_seq_first_stmt (seq);
+      if (gimple_code (outer_stmt) == GIMPLE_BIND
+	  && gimple_seq_first (seq) == gimple_seq_last (seq))
+	bind = as_a <gbind *> (outer_stmt);
+      else
+	bind = gimple_build_bind (NULL_TREE, seq, NULL);
+
+      DECL_SAVED_TREE (fndecl) = NULL_TREE;
+    }
 
   /* The tree body of the function is no longer needed, replace it
      with the new GIMPLE body.  */
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index cd4b625..3824fb7 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2412,3 +2412,9 @@ expand_internal_call (gcall *stmt)
 {
   expand_internal_call (gimple_call_internal_fn (stmt), stmt);
 }
+
+void
+expand_PHI (internal_fn, gcall *)
+{
+    gcc_unreachable ();
+}
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 6701cd9..a5dd23e 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -169,6 +169,7 @@ DEF_INTERNAL_FN (VA_ARG, ECF_NOTHROW | ECF_LEAF, NULL)
    other such optimizations.  The first argument distinguishes
    between uses.  See internal-fn.h for usage.  */
 DEF_INTERNAL_FN (UNIQUE, ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (PHI, 0, NULL)
 
 /* DIM_SIZE and DIM_POS return the size of a particular compute
    dimension and the executing thread's position within that
diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
index bb31465..9c39dd67 100644
--- a/gcc/internal-fn.h
+++ b/gcc/internal-fn.h
@@ -174,5 +174,6 @@ extern bool set_edom_supported_p (void);
 
 extern void expand_internal_call (gcall *);
 extern void expand_internal_call (internal_fn, gcall *);
+extern void expand_PHI (internal_fn, gcall *);
 
 #endif
diff --git a/gcc/passes.c b/gcc/passes.c
index c7d7dbe..04caf39 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -1685,12 +1685,13 @@ remove_cgraph_node_from_order (cgraph_node *node, void *data)
    call CALLBACK on the current function.
    This function is global so that plugins can use it.  */
 void
-do_per_function_toporder (void (*callback) (function *, void *data), void *data)
+do_per_function_toporder (void (*callback) (function *, void *data, void *flag),
+			  void *data, void *flag)
 {
   int i;
 
   if (current_function_decl)
-    callback (cfun, data);
+    callback (cfun, data, flag);
   else
     {
       cgraph_node_hook_list *hook;
@@ -1725,7 +1726,7 @@ do_per_function_toporder (void (*callback) (function *, void *data), void *data)
 	    {
 	      struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
 	      push_cfun (fn);
-	      callback (fn, data);
+	      callback (fn, data, flag);
 	      pop_cfun ();
 	    }
 	}
@@ -2276,8 +2277,18 @@ override_gate_status (opt_pass *pass, tree func, bool gate_status)
 /* Execute PASS. */
 
 bool
-execute_one_pass (opt_pass *pass)
+execute_one_pass (opt_pass *pass, bool startwith_p)
 {
+  /* For skipping passes until startwith pass */
+  if (cfun && startwith_p && cfun->startwith)
+    {
+      if (!strcmp (pass->name, cfun->pass_startwith->name)
+	  || !strcmp (pass->name, "*clean_state"))
+	cfun->startwith = false;
+      else
+	return true;
+    }
+
   unsigned int todo_after = 0;
 
   bool gate_status;
@@ -2417,7 +2428,7 @@ execute_one_pass (opt_pass *pass)
 }
 
 static void
-execute_pass_list_1 (opt_pass *pass)
+execute_pass_list_1 (opt_pass *pass, bool startwith_p)
 {
   do
     {
@@ -2426,18 +2437,23 @@ execute_pass_list_1 (opt_pass *pass)
 
       if (cfun == NULL)
 	return;
-      if (execute_one_pass (pass) && pass->sub)
-        execute_pass_list_1 (pass->sub);
+      if (execute_one_pass (pass, startwith_p) && pass->sub)
+	execute_pass_list_1 (pass->sub, startwith_p);
       pass = pass->next;
     }
   while (pass);
 }
 
 void
-execute_pass_list (function *fn, opt_pass *pass)
+execute_pass_list (function *fn, opt_pass *pass, bool *startwith_p)
 {
   gcc_assert (fn == cfun);
-  execute_pass_list_1 (pass);
+
+  if (startwith_p)
+    execute_pass_list_1 (pass, *startwith_p);
+  else
+    execute_pass_list_1 (pass, false);
+
   if (cfun && fn->cfg)
     {
       free_dominance_info (CDI_DOMINATORS);
@@ -2767,19 +2783,22 @@ ipa_read_optimization_summaries (void)
 void
 execute_ipa_pass_list (opt_pass *pass)
 {
+  bool startwith_p = false;
   do
     {
       gcc_assert (!current_function_decl);
       gcc_assert (!cfun);
       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
-      if (execute_one_pass (pass) && pass->sub)
+      if (!strcmp (pass->name, "opt_local_passes"))
+	startwith_p = true;
+      if (execute_one_pass (pass, startwith_p) && pass->sub)
 	{
 	  if (pass->sub->type == GIMPLE_PASS)
 	    {
 	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL);
-	      do_per_function_toporder ((void (*)(function *, void *))
+	      do_per_function_toporder ((void (*)(function *, void *, void *))
 					  execute_pass_list,
-					pass->sub);
+					pass->sub, &startwith_p);
 	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL);
 	    }
 	  else if (pass->sub->type == SIMPLE_IPA_PASS
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 57c8410..7fe994e 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -170,6 +170,7 @@ static edge find_taken_edge_computed_goto (basic_block, tree);
 static edge find_taken_edge_cond_expr (basic_block, tree);
 static edge find_taken_edge_switch_expr (gswitch *, basic_block, tree);
 static tree find_case_label_for_value (gswitch *, tree);
+static void lower_phi_internal_fn ();
 
 void
 init_empty_tree_cfg_for_function (struct function *fn)
@@ -244,6 +245,7 @@ build_gimple_cfg (gimple_seq seq)
   discriminator_per_locus = new hash_table<locus_discrim_hasher> (13);
   make_edges ();
   assign_discriminators ();
+  lower_phi_internal_fn ();
   cleanup_dead_labels ();
   delete discriminator_per_locus;
   discriminator_per_locus = NULL;
@@ -345,6 +347,50 @@ replace_loop_annotate (void)
     }
 }
 
+/* Lower internal PHI function from GIMPLE FE.  */
+
+static void
+lower_phi_internal_fn ()
+{
+  basic_block bb, pred = NULL;
+  gimple_stmt_iterator gsi;
+  tree lhs;
+  gphi *phi_node;
+  gimple *stmt;
+
+  /* After edge creation, handle __PHI function from GIMPLE FE.  */
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	{
+	  stmt = gsi_stmt (gsi);
+	  if (gimple_code (stmt) != GIMPLE_CALL)
+	    continue;
+
+	  if (gimple_call_internal_p (stmt) &&
+	      gimple_call_internal_fn (stmt) == IFN_PHI)
+	    {
+	      gsi_remove (&gsi, true);
+	      unsigned int i;
+	      lhs = gimple_call_lhs (stmt);
+	      phi_node = create_phi_node (lhs, bb);
+
+	      /* Add arguments to the PHI node.  */
+	      for (i = 0; i < gimple_call_num_args (stmt); ++i)
+		{
+		  tree arg = gimple_call_arg (stmt, i);
+		  if (TREE_CODE (arg) == LABEL_DECL)
+		    pred = label_to_block (arg);
+		  else
+		    {
+		      edge e = find_edge (pred, bb);
+		      add_phi_arg (phi_node, arg, e, UNKNOWN_LOCATION);
+		    }
+		}
+	    }
+	}
+    }
+}
 
 static unsigned int
 execute_build_cfg (void)
@@ -3340,6 +3386,11 @@ verify_gimple_call (gcall *stmt)
 	  debug_generic_stmt (fn);
 	  return true;
 	}
+      /* FIXME : for passing label as arg in internal fn PHI from GIMPLE FE*/
+      else if (gimple_call_internal_fn (stmt) == IFN_PHI)
+	{
+	  return false;
+	}
     }
   else
     {
@@ -7504,7 +7555,8 @@ dump_function_to_file (tree fndecl, FILE *file, int flags)
     }
 
   current_function_decl = fndecl;
-  fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
+  print_generic_expr (file, TREE_TYPE (TREE_TYPE (fndecl)), dump_flags);
+  fprintf (file, "\n%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
 
   arg = DECL_ARGUMENTS (fndecl);
   while (arg)
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index ceafa68..ba3dc05 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -1379,12 +1379,19 @@ rewrite_add_phi_arguments (basic_block bb)
       for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi);
 	   gsi_next (&gsi))
 	{
-	  tree currdef, res;
+	  tree currdef, res, argvar;
 	  location_t loc;
 
 	  phi = gsi.phi ();
 	  res = gimple_phi_result (phi);
-	  currdef = get_reaching_def (SSA_NAME_VAR (res));
+	  /* If we have pre-existing PHI its args may be different
+	     vars than existing vars */
+	  argvar = gimple_phi_arg_def (phi, e->dest_idx);
+	  if (argvar && TREE_CODE (argvar) == SSA_NAME)
+	    continue;
+	  if (!argvar)
+	    argvar = SSA_NAME_VAR (res);
+	  currdef = get_reaching_def (argvar);
 	  /* Virtual operand PHI args do not need a location.  */
 	  if (virtual_operand_p (res))
 	    loc = UNKNOWN_LOCATION;
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index c0059de..213070b 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -617,8 +617,9 @@ extern gimple_opt_pass *make_pass_lower_vaarg (gcc::context *ctxt);
 /* Current optimization pass.  */
 extern opt_pass *current_pass;
 
-extern bool execute_one_pass (opt_pass *);
-extern void execute_pass_list (function *, opt_pass *);
+extern bool execute_one_pass (opt_pass *, bool startwith_p = false);
+extern void execute_pass_list (function *, opt_pass *,
+			       bool *startwith_p = NULL);
 extern void execute_ipa_pass_list (opt_pass *);
 extern void execute_ipa_summary_passes (ipa_opt_pass_d *);
 extern void execute_all_ipa_transforms (void);
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 734ecda..aa53bd2 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -260,7 +260,7 @@ dump_decl_name (pretty_printer *pp, tree node, int flags)
   if ((flags & TDF_UID) || DECL_NAME (node) == NULL_TREE)
     {
       if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1)
-	pp_printf (pp, "L.%d", (int) LABEL_DECL_UID (node));
+	pp_printf (pp, "L_%d", (int) LABEL_DECL_UID (node));
       else if (TREE_CODE (node) == DEBUG_EXPR_DECL)
 	{
 	  if (flags & TDF_NOUID)
@@ -274,7 +274,7 @@ dump_decl_name (pretty_printer *pp, tree node, int flags)
 	  if (flags & TDF_NOUID)
 	    pp_printf (pp, "%c.xxxx", c);
 	  else
-	    pp_printf (pp, "%c.%u", c, DECL_UID (node));
+	    pp_printf (pp, "%c_%u", c, DECL_UID (node));
 	}
     }
   if ((flags & TDF_ALIAS) && DECL_PT_UID (node) != DECL_UID (node))
@@ -3965,14 +3965,14 @@ dump_function_header (FILE *dump_file, tree fdecl, int flags)
   else
     aname = "<unset-asm-name>";
 
-  fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d",
+  fprintf (dump_file, "\n/* Function %s (%s, funcdef_no=%d",
 	   dname, aname, fun->funcdef_no);
   if (!(flags & TDF_NOUID))
     fprintf (dump_file, ", decl_uid=%d", DECL_UID (fdecl));
   if (node)
     {
       fprintf (dump_file, ", cgraph_uid=%d", node->uid);
-      fprintf (dump_file, ", symbol_order=%d)%s\n\n", node->order,
+      fprintf (dump_file, ", symbol_order=%d)%s", node->order,
                node->frequency == NODE_FREQUENCY_HOT
                ? " (hot)"
                : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
@@ -3982,7 +3982,8 @@ dump_function_header (FILE *dump_file, tree fdecl, int flags)
                : "");
     }
   else
-    fprintf (dump_file, ")\n\n");
+    fprintf (dump_file, ")");
+  fprintf (dump_file, "*/\n\n");
 }
 
 /* Dump double_int D to pretty_printer PP.  UNS is true
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 91a8f97..8b8863b 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -255,7 +255,8 @@ flush_ssaname_freelist (void)
    used without a preceding definition).  */
 
 tree
-make_ssa_name_fn (struct function *fn, tree var, gimple *stmt)
+make_ssa_name_fn (struct function *fn, tree var, gimple *stmt,
+		  unsigned int version)
 {
   tree t;
   use_operand_p imm;
@@ -265,8 +266,19 @@ make_ssa_name_fn (struct function *fn, tree var, gimple *stmt)
 	      || TREE_CODE (var) == RESULT_DECL
 	      || (TYPE_P (var) && is_gimple_reg_type (var)));
 
+  /* parsing ssa names with versions.	*/
+  if (version != 0)
+    {
+      t = make_node (SSA_NAME);
+      SSA_NAME_VERSION (t) = version;
+      if (version >= SSANAMES (fn)->length ())
+	vec_safe_grow_cleared (SSANAMES (fn), version + 1);
+      gcc_assert ((*SSANAMES (fn))[version] == NULL);
+      (*SSANAMES (fn))[version] = t;
+      ssa_name_nodes_created++;
+    }
   /* If our free list has an element, then use it.  */
-  if (!vec_safe_is_empty (FREE_SSANAMES (fn)))
+  else if (!vec_safe_is_empty (FREE_SSANAMES (fn)))
     {
       t = FREE_SSANAMES (fn)->pop ();
       ssa_name_nodes_reused++;
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index 8e66ce6..3ce9327 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -74,7 +74,8 @@ extern bool ssa_name_has_boolean_range (tree);
 extern void init_ssanames (struct function *, int);
 extern void fini_ssanames (struct function *);
 extern void ssanames_print_statistics (void);
-extern tree make_ssa_name_fn (struct function *, tree, gimple *);
+extern tree make_ssa_name_fn (struct function *, tree, gimple *,
+			      unsigned int version = 0);
 extern void release_ssa_name_fn (struct function *, tree);
 extern bool get_ptr_info_alignment (struct ptr_info_def *, unsigned int *,
 				    unsigned int *);

[-- Attachment #4: testcases.patch --]
[-- Type: text/x-diff, Size: 5193 bytes --]

diff --git a/gcc/testsuite/gcc.dg/gimplefe-1.c b/gcc/testsuite/gcc.dg/gimplefe-1.c
new file mode 100644
index 0000000..0786d47
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int i;
+void __GIMPLE () foo()
+{
+  i = 1;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-10.c b/gcc/testsuite/gcc.dg/gimplefe-10.c
new file mode 100644
index 0000000..7f63c58
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-10.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE() bar(int a, int b, int c)
+{
+  a = 1;
+  b = a + 1;
+  c = b * 4;
+  return b;
+}
+
+void __GIMPLE() foo()
+{
+  int a;
+  int b;
+  int c;
+  b = bar(a, b, c);
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-11.c b/gcc/testsuite/gcc.dg/gimplefe-11.c
new file mode 100644
index 0000000..e1483f4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-11.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE() bar(int a, int b, int c)
+{
+  a = 1;
+  b = a + 1;
+  c = b * 4;
+  return;
+}
+
+void __GIMPLE() foo()
+{
+  int a;
+  int b;
+  int c;
+  bar(a, b, c);
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-12.c b/gcc/testsuite/gcc.dg/gimplefe-12.c
new file mode 100644
index 0000000..cbaf8a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-12.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE (startwith ("tree-ccp1")) foo ()
+{
+  int a;
+  int b;
+  a = b + 2;
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-13.c b/gcc/testsuite/gcc.dg/gimplefe-13.c
new file mode 100644
index 0000000..c0da9fa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-13.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE (startwith ("tree-dse1")) foo ()
+{
+  int a;
+
+bb_2:
+  if (a > 4)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_3:
+  a_2 = 10;
+  goto bb_5;
+
+bb_4:
+  a_3 = 20;
+
+bb_5:
+  a_1 = __PHI (bb_3: a_2, bb_4: a_3);
+  a_4 = a_1 + 4;
+
+return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-2.c b/gcc/testsuite/gcc.dg/gimplefe-2.c
new file mode 100644
index 0000000..e3a23cf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile }*/
+/* { dg-options "-fgimple" } */
+
+int a;
+void __GIMPLE () foo ()
+{
+  int b;
+  b = a;
+  b = b + 1;
+  a = b;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-3.c b/gcc/testsuite/gcc.dg/gimplefe-3.c
new file mode 100644
index 0000000..595365e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-3.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int *b;
+  *b = 1;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-4.c b/gcc/testsuite/gcc.dg/gimplefe-4.c
new file mode 100644
index 0000000..3600c7c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-4.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int a;
+  char b;
+  a = (int) b;
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-5.c b/gcc/testsuite/gcc.dg/gimplefe-5.c
new file mode 100644
index 0000000..1dab4af
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-5.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int a;
+void __GIMPLE () foo ()
+{
+  int b;
+  int c;
+
+bb_2:
+  b = a;
+  if (b > 3)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_3:
+  b = c + 4;
+  goto bb_5;
+
+bb_4:
+  b = b + 1;
+  goto bb_5;
+
+bb_5:
+  a = b;
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-6.c b/gcc/testsuite/gcc.dg/gimplefe-6.c
new file mode 100644
index 0000000..242e08f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-6.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int a;
+  int b;
+  int c;
+  int d;
+
+bb_2:
+  a = ~b;
+  b = a << c;
+  c = a & b;
+  d = b | c;
+
+bb_3:
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-7.c b/gcc/testsuite/gcc.dg/gimplefe-7.c
new file mode 100644
index 0000000..6125541
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-7.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int a;
+
+bb_2:
+  if (a > 4)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_3:
+  a_2 = 10;
+  goto bb_5;
+
+bb_4:
+  a_3 = 20;
+
+bb_5:
+  a_1 = __PHI (bb_3: a_2, bb_4: a_3);
+  a_4 = a_1 + 4;
+
+return;
+}
+
diff --git a/gcc/testsuite/gcc.dg/gimplefe-8.c b/gcc/testsuite/gcc.dg/gimplefe-8.c
new file mode 100644
index 0000000..4936bec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-8.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE () foo ()
+{
+  int a;
+  int b;
+
+bb_2:
+  b = a_1(D) + 1;
+bb_3:
+  return b;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-9.c b/gcc/testsuite/gcc.dg/gimplefe-9.c
new file mode 100644
index 0000000..a24be273
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-9.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE() bar()
+{
+  int a;
+  a = a + 1;
+  return a;
+}
+
+void __GIMPLE() foo()
+{
+  int b;
+  b = bar();
+}


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-23 15:45       ` Prasad Ghangal
@ 2016-08-24  7:03         ` Prasad Ghangal
  2016-08-24  8:45           ` Richard Biener
  0 siblings, 1 reply; 24+ messages in thread
From: Prasad Ghangal @ 2016-08-24  7:03 UTC (permalink / raw)
  To: David Malcolm; +Cc: Trevor Saunders, gcc-patches, Richard Biener

On 23 August 2016 at 21:15, Prasad Ghangal <prasad.ghangal@gmail.com> wrote:
> On 23 August 2016 at 02:56, David Malcolm <dmalcolm@redhat.com> wrote:
>> On Tue, 2016-08-23 at 00:10 +0530, Prasad Ghangal wrote:
>>> On 22 August 2016 at 16:55, Trevor Saunders <tbsaunde@tbsaunde.org>
>>> wrote:
>>> > On Sun, Aug 21, 2016 at 10:35:17PM +0530, Prasad Ghangal wrote:
>>
>> [...]
>>
>>> > @@ -228,6 +228,12 @@ struct GTY(()) function {
>>> >    /* GIMPLE body for this function.  */
>>> >    gimple_seq gimple_body;
>>> >
>>> > +  /* GIMPLEFE pass to start with */
>>> > +  opt_pass *pass_startwith = NULL;
>> I'm guessing you've only compiled in C++11 mode? because I'm pretty
>>> > sure
>>> > you are using a C++11 feature here (the default member value you
>>> > assign).
>>>
>>
>> [...]
>>
>>> I am not getting what did you mean by C++11 mode (I am not explicitly
>>
>> Prasad: what compiler version are you using to build your patched gcc?
>>  My guess is that you're using gcc 6 to build.
>>
> I am using gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.1)
>
>> In gcc 6 we changed the default C++ mode from -std=gnu++98
>> to -std=gnu++14. See:
>>   https://gcc.gnu.org/gcc-6/porting_to.html#gxx14
>>
>> I believe the syntax that Trevor spotted is only available in C++11
>> onwards:
>>
>>   $ cat test.cc
>>   struct foo
>>   {
>>     int field = 42;
>>   };
>>
>> With the default for gcc 6:
>>
>>   $ gcc -c test.cc -std=c++14
>>
>> it has no problems, whereas with the default for gcc 5 and earlier:
>>
>>   $ gcc -c test.cc -std=gnu++98
>>   test.cc:3:15: warning: non-static data member initializers only
>> available with -std=c++11 or -std=gnu++11
>>    int field = 42;
>>                ^~
>>
> and it does give me the warning. I will try compiling on < 5 version.
>
I have successfully bootstrapped using gcc 4.8 version. I think while
stage2+ builds it is putting -std=gnu++11 flag. Should I remove C++11
syntax ?


Thanks,
Prasad

>> So it's probably worth attempting to bootstrap with an older gcc as the
>> starting compiler.
>>
>> Hope this is helpful
>> Dave
>
> Re-attaching the patch as it has a typo
>
>
> Thanks,
> Prasad

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-24  7:03         ` Prasad Ghangal
@ 2016-08-24  8:45           ` Richard Biener
  0 siblings, 0 replies; 24+ messages in thread
From: Richard Biener @ 2016-08-24  8:45 UTC (permalink / raw)
  To: Prasad Ghangal; +Cc: David Malcolm, Trevor Saunders, GCC Patches

On Wed, Aug 24, 2016 at 9:02 AM, Prasad Ghangal
<prasad.ghangal@gmail.com> wrote:
> On 23 August 2016 at 21:15, Prasad Ghangal <prasad.ghangal@gmail.com> wrote:
>> On 23 August 2016 at 02:56, David Malcolm <dmalcolm@redhat.com> wrote:
>>> On Tue, 2016-08-23 at 00:10 +0530, Prasad Ghangal wrote:
>>>> On 22 August 2016 at 16:55, Trevor Saunders <tbsaunde@tbsaunde.org>
>>>> wrote:
>>>> > On Sun, Aug 21, 2016 at 10:35:17PM +0530, Prasad Ghangal wrote:
>>>
>>> [...]
>>>
>>>> > @@ -228,6 +228,12 @@ struct GTY(()) function {
>>>> >    /* GIMPLE body for this function.  */
>>>> >    gimple_seq gimple_body;
>>>> >
>>>> > +  /* GIMPLEFE pass to start with */
>>>> > +  opt_pass *pass_startwith = NULL;
>>> I'm guessing you've only compiled in C++11 mode? because I'm pretty
>>>> > sure
>>>> > you are using a C++11 feature here (the default member value you
>>>> > assign).
>>>>
>>>
>>> [...]
>>>
>>>> I am not getting what did you mean by C++11 mode (I am not explicitly
>>>
>>> Prasad: what compiler version are you using to build your patched gcc?
>>>  My guess is that you're using gcc 6 to build.
>>>
>> I am using gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.1)
>>
>>> In gcc 6 we changed the default C++ mode from -std=gnu++98
>>> to -std=gnu++14. See:
>>>   https://gcc.gnu.org/gcc-6/porting_to.html#gxx14
>>>
>>> I believe the syntax that Trevor spotted is only available in C++11
>>> onwards:
>>>
>>>   $ cat test.cc
>>>   struct foo
>>>   {
>>>     int field = 42;
>>>   };
>>>
>>> With the default for gcc 6:
>>>
>>>   $ gcc -c test.cc -std=c++14
>>>
>>> it has no problems, whereas with the default for gcc 5 and earlier:
>>>
>>>   $ gcc -c test.cc -std=gnu++98
>>>   test.cc:3:15: warning: non-static data member initializers only
>>> available with -std=c++11 or -std=gnu++11
>>>    int field = 42;
>>>                ^~
>>>
>> and it does give me the warning. I will try compiling on < 5 version.
>>
> I have successfully bootstrapped using gcc 4.8 version. I think while
> stage2+ builds it is putting -std=gnu++11 flag. Should I remove C++11
> syntax ?

Yes, we can't use C++ syntax generally.

Thanks,
Richard.

>
> Thanks,
> Prasad
>
>>> So it's probably worth attempting to bootstrap with an older gcc as the
>>> starting compiler.
>>>
>>> Hope this is helpful
>>> Dave
>>
>> Re-attaching the patch as it has a typo
>>
>>
>> Thanks,
>> Prasad

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-22 18:40   ` Prasad Ghangal
  2016-08-22 21:20     ` Trevor Saunders
  2016-08-22 21:27     ` David Malcolm
@ 2016-08-24 10:02     ` Richard Biener
  2016-08-26  3:10       ` Prasad Ghangal
  2 siblings, 1 reply; 24+ messages in thread
From: Richard Biener @ 2016-08-24 10:02 UTC (permalink / raw)
  To: Prasad Ghangal; +Cc: Trevor Saunders, GCC Patches

On Mon, Aug 22, 2016 at 8:40 PM, Prasad Ghangal
<prasad.ghangal@gmail.com> wrote:
> On 22 August 2016 at 16:55, Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
>> On Sun, Aug 21, 2016 at 10:35:17PM +0530, Prasad Ghangal wrote:
>>> Hi all,
>>>
>>> As a part of my gsoc project. I have completed the following tasks:
>>>
>>> * Parsed gimple-expression
>>> * Parsed gimple-labels
>>> * Parsed local declaration
>>> * Parsed gimple-goto statement
>>> * Parsed gimple-if-else statement
>>> * Parsed gimple-switch statement
>>> * Parsed gimple-return statement
>>> * Parsed gimple-PHI function
>>> * Parsed gimple ssa-names along with default def
>>> * Parsed gimple-call
>>>
>>> * Hacked pass manager to add support for startwith (pass-name) to skip
>>> early opt passes
>>> * Modified gimple dump for making it parsable
>>>
>>> I am willing to continue work on the project, some TODOs for the projects are:
>>>
>>> * Error handling
>>> * Parse more gimple syntax
>>> * Add startwith support for IPA passes
>>>
>>> The complete code of gimple fe project can be found at
>>> https://github.com/PrasadG193/gcc_gimple_fe
>>>
>>>
>>> PFA patch for complete project (rebased for latest trunk revision).
>>> I have successfully bootstrapped and tested on x86_64-pc-linux-gnu.
>>> Some testcases failed due to modified gimple dump as expected.
>>>
>>>
>>> Thanks,
>>> Prasad
>>
>> only some rather minor comments
>>
>>
>> +++ b/gcc/c/c-parser.c
>> @@ -59,6 +59,18 @@ along with GCC; see the file COPYING3.  If not see
>>  #include "gimple-expr.h"
>>  #include "context.h"
>>  #include "gcc-rich-location.h"
>> +#include "tree-vrp.h"
>>
>> given that you need these headers it might be better to put most of the
>> gimple parsing in its own file so only what actually needs to know about
>> this part of the compiler does now about it.
>>
>> +void
>> +c_parser_parse_gimple_body (c_parser *parser)
>> +{
>> +  bool return_p = false;
>> +  gimple_seq seq;
>> +  gimple_seq body;
>> +  tree stmt = push_stmt_list ();
>>
>> it would be nice to move the declarations down to their first use.
>>
>> +      gimple *ret;
>> +      ret = gimple_build_return (NULL);
>>
>> there's no reason for a separate declaration and assignment ;)
>>
>> +  tree block = NULL;
>> +  block = pop_scope ();
>>
>> same here, and a number of other places.
>>
>> +c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
>> +{
>> +  bool return_p = false;
>> +
>> +  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
>> +      return return_p;
>>
>> return false would work fine.
>>
>> +
>> +  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
>> +    {
>> +      c_parser_consume_token (parser);
>> +      goto out;
>>
>> I don't see the need for the gotos, there's no cleanup in this function.
>>
>> +  /* gimple PHI expression.  */
>> +  if (c_parser_next_token_is_keyword (parser, RID_PHI))
>> +    {
>> +      c_parser_consume_token (parser);
>> +
>> +      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
>> +       {
>> +         return;
>> +       }
>> +
>> +      gcall *call_stmt;
>> +      tree arg = NULL_TREE;
>> +      vec<tree> vargs = vNULL;
>>
>> I think you can use auto_vec here, as is I think this leaks the vectors
>> storage.
>>
>> +c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)
>>
>> you can skip the explicit 'enum' keyword.
>>
>> +  struct {
>> +    /* The expression at this stack level.  */
>> +    struct c_expr expr;
>>
>> similar with struct here.
>>
>> +    /* The precedence of the operator on its left, PREC_NONE at the
>> +       bottom of the stack.  */
>> +    enum c_parser_prec prec;
>> +    /* The operation on its left.  */
>> +    enum tree_code op;
>> +    /* The source location of this operation.  */
>> +    location_t loc;
>> +  } stack[2];
>> +  int sp;
>> +  /* Location of the binary operator.  */
>> +  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
>> +#define POP                                                                  \
>>
>> it seems like it would be nicer to name the type, and then make this a
>> function.
>>
>> +                                       RO_UNARY_STAR);
>> +       ret.src_range.m_start = op_loc;
>> +       ret.src_range.m_finish = finish;
>> +       return ret;
>> +      }
>> +    case CPP_PLUS:
>> +      if (!c_dialect_objc () && !in_system_header_at (input_location))
>> +       warning_at (op_loc,
>> +                   OPT_Wtraditional,
>> +                   "traditional C rejects the unary plus operator");
>>
>> does it really make sense to warn about C issues when compiling gimple?
>>
>> +c_parser_parse_ssa_names (c_parser *parser)
>> +{
>> +  tree id = NULL_TREE;
>> +  c_expr ret;
>> +  char *var_name, *var_version, *token;
>> +  ret.original_code = ERROR_MARK;
>> +  ret.original_type = NULL;
>> +
>> +  /* ssa token string.  */
>> +  const char *ssa_token = NULL;
>> +  ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
>> +  token = new char [strlen (ssa_token)];
>>
>> I'm not sure I see why you need this copy, and getting rid of it would
>> mean you don't need to free it.
>>
>> +  strcpy (token, ssa_token);
>> +
>> +  /* seperate var name and version.  */
>> +  var_version = strrchr (token, '_');
>> +  if (var_version)
>> +    {
>> +      var_name = new char[var_version - token + 1];
>>
>> you should free this when done with it.
>>
>> +c_parser_gimple_postfix_expression (c_parser *parser)
>> +{
>> +  struct c_expr expr;
>> +  location_t loc = c_parser_peek_token (parser)->location;;
>>
>> extra ;
>>
>> +    case CPP_OBJC_STRING:
>> +      gcc_assert (c_dialect_objc ());
>> +      expr.value
>> +       = objc_build_string_object (c_parser_peek_token (parser)->value);
>> +      set_c_expr_source_range (&expr, tok_range);
>> +      c_parser_consume_token (parser);
>> +      break;
>>
>> is there a reason to support objc stuff in gimple?
>>
>> +c_parser_gimple_expr_list (c_parser *parser, bool convert_p,
>> +                   vec<tree, va_gc> **p_orig_types,
>> +                   location_t *sizeof_arg_loc, tree *sizeof_arg,
>> +                   vec<location_t> *locations,
>> +                   unsigned int *literal_zero_mask)
>> +{
>> +  vec<tree, va_gc> *ret;
>> +  vec<tree, va_gc> *orig_types;
>> +  struct c_expr expr;
>> +  location_t loc = c_parser_peek_token (parser)->location;
>> +  location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION;
>> +  unsigned int idx = 0;
>> +
>> +  ret = make_tree_vector ();
>> +  if (p_orig_types == NULL)
>> +    orig_types = NULL;
>> +  else
>> +    orig_types = make_tree_vector ();
>> +
>> +  if (sizeof_arg != NULL
>> +      && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
>> +    cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
>> +  if (literal_zero_mask)
>> +    c_parser_check_literal_zero (parser, literal_zero_mask, 0);
>> +  expr = c_parser_gimple_unary_expression (parser);
>> +  if (convert_p)
>> +    expr = convert_lvalue_to_rvalue (loc, expr, true, true);
>> +  ret->quick_push (expr.value);
>>
>>  That kind of relies on the details of make_tree_vector (), so it seems
>>  somewhat safer to use vec_safe_push.
>>
>> +  if (orig_types)
>> +    orig_types->quick_push (expr.original_type);
>>
>> same
>>
>> +c_parser_gimple_declaration (c_parser *parser)
>> +{
>> +  struct c_declspecs *specs;
>> +  struct c_declarator *declarator;
>> +  specs = build_null_declspecs ();
>> +  c_parser_declspecs (parser, specs, true, true, true,
>> +                     true, true, cla_nonabstract_decl);
>> +  finish_declspecs (specs);
>> +  bool auto_type_p = specs->typespec_word == cts_auto_type;
>>
>> is it useful to support auto here in gimple?
>>
>> +c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
>> +{
>> +  c_expr cond_expr;
>> +  tree case_label, label;
>> +  vec<tree> labels = vNULL;
>>
>> auto_vec?
>>
>> +static void
>> +c_finish_gimple_return (location_t loc, tree retval)
>> +{
>> +  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
>> +
>> +  /* Use the expansion point to handle cases such as returning NULL
>> +     in a function returning void.  */
>> +  source_location xloc = expansion_point_location_if_in_system_header (loc);
>> +
>> +  if (TREE_THIS_VOLATILE (current_function_decl))
>> +    warning_at (xloc, 0,
>> +               "function declared %<noreturn%> has a %<return%> statement");
>> +
>> +  if (!retval)
>> +    {
>> +      current_function_returns_null = 1;
>> +      if ((warn_return_type || flag_isoc99)
>>
>> I'm not sure what to do about warnings, but checking the language we are
>> compiling as seems kind of wrong when we're compiling gimple?
>>
>> @@ -228,6 +228,12 @@ struct GTY(()) function {
>>    /* GIMPLE body for this function.  */
>>    gimple_seq gimple_body;
>>
>> +  /* GIMPLEFE pass to start with */
>> +  opt_pass *pass_startwith = NULL;
>>
>> I'm guessing you've only compiled in C++11 mode? because I'm pretty sure
>> you are using a C++11 feature here (the default member value you
>> assign).
>>
>> Thanks!
>>
>> Trev
>>
>
> Hi Trevor,
>
> Thanks for your feedback. I had missed removing some unwanted code
> while code cleanup. I have updated the patch.
> I am not sure if we should move all gimple parsing related functions
> to the new file (?)

I think it might be good to make the parts of the C parser you use more
obvious (you'd need to export functions like c_parser_next_token_is).

The easiest way to "force" that is to put all of the gimple parsing into
a separate file.

Note I am not so much concerned about this at the moment, the parts to
improve would be avoiding more of the C-isms like convert_lvalue_to_rvalue,
handling of SIZEOF_EXPR and other stuff that looks redundant (you've
probably copied this from the C parsing routines and refactored it).
Also the GIMPLE parser shouldn't do any warnings (just spotted
a call to warn_for_memset).

Thanks,
Richard.

> I am not getting what did you mean by C++11 mode (I am not explicitly
> giving any option while configure or make). I also have successfully
> bootstrapped and tested the project on another system. Is there any
> way to check that ?
>
>
> Thanks,
> Prasad

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-24 10:02     ` Richard Biener
@ 2016-08-26  3:10       ` Prasad Ghangal
  2016-08-26  8:58         ` Richard Biener
  2016-10-05 23:28         ` Joseph Myers
  0 siblings, 2 replies; 24+ messages in thread
From: Prasad Ghangal @ 2016-08-26  3:10 UTC (permalink / raw)
  To: Richard Biener; +Cc: Trevor Saunders, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 10935 bytes --]

On 24 August 2016 at 15:32, Richard Biener <richard.guenther@gmail.com> wrote:
> On Mon, Aug 22, 2016 at 8:40 PM, Prasad Ghangal
> <prasad.ghangal@gmail.com> wrote:
>> On 22 August 2016 at 16:55, Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
>>> On Sun, Aug 21, 2016 at 10:35:17PM +0530, Prasad Ghangal wrote:
>>>> Hi all,
>>>>
>>>> As a part of my gsoc project. I have completed the following tasks:
>>>>
>>>> * Parsed gimple-expression
>>>> * Parsed gimple-labels
>>>> * Parsed local declaration
>>>> * Parsed gimple-goto statement
>>>> * Parsed gimple-if-else statement
>>>> * Parsed gimple-switch statement
>>>> * Parsed gimple-return statement
>>>> * Parsed gimple-PHI function
>>>> * Parsed gimple ssa-names along with default def
>>>> * Parsed gimple-call
>>>>
>>>> * Hacked pass manager to add support for startwith (pass-name) to skip
>>>> early opt passes
>>>> * Modified gimple dump for making it parsable
>>>>
>>>> I am willing to continue work on the project, some TODOs for the projects are:
>>>>
>>>> * Error handling
>>>> * Parse more gimple syntax
>>>> * Add startwith support for IPA passes
>>>>
>>>> The complete code of gimple fe project can be found at
>>>> https://github.com/PrasadG193/gcc_gimple_fe
>>>>
>>>>
>>>> PFA patch for complete project (rebased for latest trunk revision).
>>>> I have successfully bootstrapped and tested on x86_64-pc-linux-gnu.
>>>> Some testcases failed due to modified gimple dump as expected.
>>>>
>>>>
>>>> Thanks,
>>>> Prasad
>>>
>>> only some rather minor comments
>>>
>>>
>>> +++ b/gcc/c/c-parser.c
>>> @@ -59,6 +59,18 @@ along with GCC; see the file COPYING3.  If not see
>>>  #include "gimple-expr.h"
>>>  #include "context.h"
>>>  #include "gcc-rich-location.h"
>>> +#include "tree-vrp.h"
>>>
>>> given that you need these headers it might be better to put most of the
>>> gimple parsing in its own file so only what actually needs to know about
>>> this part of the compiler does now about it.
>>>
>>> +void
>>> +c_parser_parse_gimple_body (c_parser *parser)
>>> +{
>>> +  bool return_p = false;
>>> +  gimple_seq seq;
>>> +  gimple_seq body;
>>> +  tree stmt = push_stmt_list ();
>>>
>>> it would be nice to move the declarations down to their first use.
>>>
>>> +      gimple *ret;
>>> +      ret = gimple_build_return (NULL);
>>>
>>> there's no reason for a separate declaration and assignment ;)
>>>
>>> +  tree block = NULL;
>>> +  block = pop_scope ();
>>>
>>> same here, and a number of other places.
>>>
>>> +c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
>>> +{
>>> +  bool return_p = false;
>>> +
>>> +  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
>>> +      return return_p;
>>>
>>> return false would work fine.
>>>
>>> +
>>> +  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
>>> +    {
>>> +      c_parser_consume_token (parser);
>>> +      goto out;
>>>
>>> I don't see the need for the gotos, there's no cleanup in this function.
>>>
>>> +  /* gimple PHI expression.  */
>>> +  if (c_parser_next_token_is_keyword (parser, RID_PHI))
>>> +    {
>>> +      c_parser_consume_token (parser);
>>> +
>>> +      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
>>> +       {
>>> +         return;
>>> +       }
>>> +
>>> +      gcall *call_stmt;
>>> +      tree arg = NULL_TREE;
>>> +      vec<tree> vargs = vNULL;
>>>
>>> I think you can use auto_vec here, as is I think this leaks the vectors
>>> storage.
>>>
>>> +c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)
>>>
>>> you can skip the explicit 'enum' keyword.
>>>
>>> +  struct {
>>> +    /* The expression at this stack level.  */
>>> +    struct c_expr expr;
>>>
>>> similar with struct here.
>>>
>>> +    /* The precedence of the operator on its left, PREC_NONE at the
>>> +       bottom of the stack.  */
>>> +    enum c_parser_prec prec;
>>> +    /* The operation on its left.  */
>>> +    enum tree_code op;
>>> +    /* The source location of this operation.  */
>>> +    location_t loc;
>>> +  } stack[2];
>>> +  int sp;
>>> +  /* Location of the binary operator.  */
>>> +  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
>>> +#define POP                                                                  \
>>>
>>> it seems like it would be nicer to name the type, and then make this a
>>> function.
>>>
>>> +                                       RO_UNARY_STAR);
>>> +       ret.src_range.m_start = op_loc;
>>> +       ret.src_range.m_finish = finish;
>>> +       return ret;
>>> +      }
>>> +    case CPP_PLUS:
>>> +      if (!c_dialect_objc () && !in_system_header_at (input_location))
>>> +       warning_at (op_loc,
>>> +                   OPT_Wtraditional,
>>> +                   "traditional C rejects the unary plus operator");
>>>
>>> does it really make sense to warn about C issues when compiling gimple?
>>>
>>> +c_parser_parse_ssa_names (c_parser *parser)
>>> +{
>>> +  tree id = NULL_TREE;
>>> +  c_expr ret;
>>> +  char *var_name, *var_version, *token;
>>> +  ret.original_code = ERROR_MARK;
>>> +  ret.original_type = NULL;
>>> +
>>> +  /* ssa token string.  */
>>> +  const char *ssa_token = NULL;
>>> +  ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
>>> +  token = new char [strlen (ssa_token)];
>>>
>>> I'm not sure I see why you need this copy, and getting rid of it would
>>> mean you don't need to free it.
>>>
>>> +  strcpy (token, ssa_token);
>>> +
>>> +  /* seperate var name and version.  */
>>> +  var_version = strrchr (token, '_');
>>> +  if (var_version)
>>> +    {
>>> +      var_name = new char[var_version - token + 1];
>>>
>>> you should free this when done with it.
>>>
>>> +c_parser_gimple_postfix_expression (c_parser *parser)
>>> +{
>>> +  struct c_expr expr;
>>> +  location_t loc = c_parser_peek_token (parser)->location;;
>>>
>>> extra ;
>>>
>>> +    case CPP_OBJC_STRING:
>>> +      gcc_assert (c_dialect_objc ());
>>> +      expr.value
>>> +       = objc_build_string_object (c_parser_peek_token (parser)->value);
>>> +      set_c_expr_source_range (&expr, tok_range);
>>> +      c_parser_consume_token (parser);
>>> +      break;
>>>
>>> is there a reason to support objc stuff in gimple?
>>>
>>> +c_parser_gimple_expr_list (c_parser *parser, bool convert_p,
>>> +                   vec<tree, va_gc> **p_orig_types,
>>> +                   location_t *sizeof_arg_loc, tree *sizeof_arg,
>>> +                   vec<location_t> *locations,
>>> +                   unsigned int *literal_zero_mask)
>>> +{
>>> +  vec<tree, va_gc> *ret;
>>> +  vec<tree, va_gc> *orig_types;
>>> +  struct c_expr expr;
>>> +  location_t loc = c_parser_peek_token (parser)->location;
>>> +  location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION;
>>> +  unsigned int idx = 0;
>>> +
>>> +  ret = make_tree_vector ();
>>> +  if (p_orig_types == NULL)
>>> +    orig_types = NULL;
>>> +  else
>>> +    orig_types = make_tree_vector ();
>>> +
>>> +  if (sizeof_arg != NULL
>>> +      && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
>>> +    cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
>>> +  if (literal_zero_mask)
>>> +    c_parser_check_literal_zero (parser, literal_zero_mask, 0);
>>> +  expr = c_parser_gimple_unary_expression (parser);
>>> +  if (convert_p)
>>> +    expr = convert_lvalue_to_rvalue (loc, expr, true, true);
>>> +  ret->quick_push (expr.value);
>>>
>>>  That kind of relies on the details of make_tree_vector (), so it seems
>>>  somewhat safer to use vec_safe_push.
>>>
>>> +  if (orig_types)
>>> +    orig_types->quick_push (expr.original_type);
>>>
>>> same
>>>
>>> +c_parser_gimple_declaration (c_parser *parser)
>>> +{
>>> +  struct c_declspecs *specs;
>>> +  struct c_declarator *declarator;
>>> +  specs = build_null_declspecs ();
>>> +  c_parser_declspecs (parser, specs, true, true, true,
>>> +                     true, true, cla_nonabstract_decl);
>>> +  finish_declspecs (specs);
>>> +  bool auto_type_p = specs->typespec_word == cts_auto_type;
>>>
>>> is it useful to support auto here in gimple?
>>>
>>> +c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
>>> +{
>>> +  c_expr cond_expr;
>>> +  tree case_label, label;
>>> +  vec<tree> labels = vNULL;
>>>
>>> auto_vec?
>>>
>>> +static void
>>> +c_finish_gimple_return (location_t loc, tree retval)
>>> +{
>>> +  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
>>> +
>>> +  /* Use the expansion point to handle cases such as returning NULL
>>> +     in a function returning void.  */
>>> +  source_location xloc = expansion_point_location_if_in_system_header (loc);
>>> +
>>> +  if (TREE_THIS_VOLATILE (current_function_decl))
>>> +    warning_at (xloc, 0,
>>> +               "function declared %<noreturn%> has a %<return%> statement");
>>> +
>>> +  if (!retval)
>>> +    {
>>> +      current_function_returns_null = 1;
>>> +      if ((warn_return_type || flag_isoc99)
>>>
>>> I'm not sure what to do about warnings, but checking the language we are
>>> compiling as seems kind of wrong when we're compiling gimple?
>>>
>>> @@ -228,6 +228,12 @@ struct GTY(()) function {
>>>    /* GIMPLE body for this function.  */
>>>    gimple_seq gimple_body;
>>>
>>> +  /* GIMPLEFE pass to start with */
>>> +  opt_pass *pass_startwith = NULL;
>>>
>>> I'm guessing you've only compiled in C++11 mode? because I'm pretty sure
>>> you are using a C++11 feature here (the default member value you
>>> assign).
>>>
>>> Thanks!
>>>
>>> Trev
>>>
>>
>> Hi Trevor,
>>
>> Thanks for your feedback. I had missed removing some unwanted code
>> while code cleanup. I have updated the patch.
>> I am not sure if we should move all gimple parsing related functions
>> to the new file (?)
>
> I think it might be good to make the parts of the C parser you use more
> obvious (you'd need to export functions like c_parser_next_token_is).
>
> The easiest way to "force" that is to put all of the gimple parsing into
> a separate file.
>
> Note I am not so much concerned about this at the moment, the parts to
> improve would be avoiding more of the C-isms like convert_lvalue_to_rvalue,
> handling of SIZEOF_EXPR and other stuff that looks redundant (you've
> probably copied this from the C parsing routines and refactored it).
> Also the GIMPLE parser shouldn't do any warnings (just spotted
> a call to warn_for_memset).
>
PFA updated patch (successfully bootstrapped and tested on
x86_64-pc-linux-gnu). I have removed unnecessary code. On side I am
also trying to move gimple parser related functions to new file. But
for it we also have to move structs like c_token, c_parser. Won't it
disturb the c-parser code structure ?


Thanks,
Prasad

> Thanks,
> Richard.
>
>> I am not getting what did you mean by C++11 mode (I am not explicitly
>> giving any option while configure or make). I also have successfully
>> bootstrapped and tested the project on another system. Is there any
>> way to check that ?
>>
>>
>> Thanks,
>> Prasad

[-- Attachment #2: ChangeLog.patch --]
[-- Type: text/x-diff, Size: 5458 bytes --]

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1929ba8..cded23f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,55 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+	
+	* cgraphunit.c (cgraph_node::assemble_thunks_and_aliases): New variable.
+	(cgraph_node::expand): Add new argument to function.
+	execute_pass_list, guard gcc_assert (TREE_ASM_WRITTEN (decl)) with 
+	condition.
+	* coretypes.h (tree_node *const_tree): New decl, add headers, new
+	variables.
+	* function.h (struct GTY()) function): Add new member to store
+	startwith pass also add new member as a flag.
+	* gimple-pretty-print.c (dump_gimple_switch): Change dumping formats.
+	(dump_gimple_label): Remove condition for DECL_NONLOCAL, flags & 
+	TDF_EH, EH_LANDING_PAD_NR. Change dumping format.
+	(dump_ssaname_info_to_file): Change passing arguments of dump_gimple_phi
+	(dump_gimple_phi): Remove condition for comment, change format of
+	dumping PHI and PHI arguments.
+	(pp_gimple_stmt_1): Remove argument of dump_gimple_phi function.
+	(dump_gimple_bb_header): Change format of dumping gimple basic block
+	header.
+	(dump_phi_nodes): Remove argument of dump_gimple_phi function.
+	(pp_cfg_jump): Remove stmt, remove condition for GIMPLE_LABEL, change 
+	dumping format of gimple basic block header.
+	(gimple_dump_bb_for_graph): Change format of dumping gimple basic block
+	* gimplify.c (gimplify_function_tree): Add condition for presence of
+	gimple body in the cfun.
+	* internal-fn.c (expand_PHI): New function.
+	* internal-fn.h (expand_PHI): Declared here.
+	* internal-fn.def: New defination for PHI.
+	* passes.c (do_per_function_toporder): Add new argument flag, add new
+	argument in callback function call.
+	(execute_one_pass): Add new function argument, add condition for 
+	skipping passes until startwith pass.
+	(execute_pass_list_1): Add new function argument, add condition to 
+	check starwith flag.
+	(execute_ipa_pass_list): New variable, add condition to check and skip
+	passes for startwith pass, pass new argument to function 
+	do_per_function_toporder.
+	* tree-pass.h (execute_one_pass): Add new argument to the function.
+	(execute_pass_list): Likewise.
+	* tree-cfg.c (lower_phi_internal_fn): New function.
+	(verify_gimple_call): Condition for passing label as arg in internal
+	function PHI.
+	(dump_function_to_file): Change format of gimple dump.
+	* tree-into-ssa.c (rewrite_add_phi_arguments): New variable, add 
+	condition for avoiding ssa name versions.
+	* tree-pretty-print.c (dump_decl_name): Change format of dumping gimple
+	labels.
+	(dump_function_header): Change format of gimple dump header
+	* tree-ssanames.c (make_ssa_name_fn): New argument, check for version
+	and assign proper version for parsed ssa names.
+	* tree-ssanames.h (make_ssa_name_fn): Add new argument to the function.
+
 2016-08-20  Kugan Vivekanandarajah  <kuganv@linaro.org>
 
 	* Makefile.in: Add tree-vrp.h to GTFILES.
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index bec37cf..a8c0ab1 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+	
+	* c-common.h (c_common_resword): Add RID_GIMPLE, RID_PHI types.
+	* c-common.h (enum rid): Add RID_GIMPLE, RID_PHI.
+	* c.opt (fgimple): New option.
+
 2016-08-19  Joseph Myers  <joseph@codesourcery.com>
 
 	PR c/32187
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 8d9d4aa..71e78f3 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,29 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+	
+	* c_parser.c: Add headers.
+	(c_parser_parse_gimple_body): New function.
+	(c_parser_gimple_compound_statement): Likewise.
+	(c_parser_gimple_label): Likewise.
+	(c_parser_gimple_expression): Likewise
+	(c_parser_gimple_binary_expression): Likewise.
+	(c_parser_gimple_unary_expression): Likewise.
+	(c_parser_gimple_postfix_expression): Likewise.
+	(c_parser_gimple_postfix_expression_after_primary): Likewise.
+	(c_parser_gimple_pass_list): Likewise.
+	(c_parser_gimple_pass_list_params): Likewise.
+	(c_parser_gimple_declaration): Likewise.
+	(c_parser_gimple_goto_stmt): Likewise.
+	(c_parser_gimple_if_stmt): Likewise.
+	(c_parser_gimple_switch_stmt): Likewise.
+	(c_parser_gimple_return_stmt): Likewise.
+	(c_finish_gimple_return): Likewise.
+	(c_parser_parse_ssa_names): Likewise.
+	(c_parser_gimple_paren_condition): Likewise.
+	(c_parser_gimple_expr_list): Likewise.
+	(c_parser_declaration_or_fndef): New decls. Call function.
+	c_parser_gimple_pass_list, set startwith passes, call
+	c_parser_parse_gimple_body.
+
 2016-08-19  Joseph Myers  <joseph@codesourcery.com>
 
 	PR c/32187
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6201e0c..3da6354 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,19 @@
+2016-08-21  Prasad Ghangal  <prasad.ghangal@gmail.com>
+
+	* gcc.dg/gimplefe-1.c: New testcase.
+	* gcc.dg/gimplefe-2.c: Likewise.
+	* gcc.dg/gimplefe-3.c: Likewise.
+	* gcc.dg/gimplefe-4.c: Likewise.
+	* gcc.dg/gimplefe-5.c: Likewise.
+	* gcc.dg/gimplefe-6.c: Likewise.
+	* gcc.dg/gimplefe-7.c: Likewise.
+	* gcc.dg/gimplefe-8.c: Likewise.
+	* gcc.dg/gimplefe-9.c: Likewise.
+	* gcc.dg/gimplefe-10.c: Likewise.
+	* gcc.dg/gimplefe-11.c: Likewise.
+	* gcc.dg/gimplefe-12.c: Likewise.
+	* gcc.dg/gimplefe-13.c: Likewise.
+
 2016-08-20  Kugan Vivekanandarajah  <kuganv@linaro.org>
 
 	PR tree-optimization/61839


[-- Attachment #3: gimplefe.patch --]
[-- Type: text/x-diff, Size: 65108 bytes --]

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 32468ca..5b43016 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -522,6 +522,8 @@ const struct c_common_resword c_common_reswords[] =
   { "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY },
   { "__volatile",	RID_VOLATILE,	0 },
   { "__volatile__",	RID_VOLATILE,	0 },
+  { "__GIMPLE",		RID_GIMPLE,	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-family/c-common.h b/gcc/c-family/c-common.h
index bc22baa..17dc91e 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -118,6 +118,12 @@ enum rid
 
   RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN,
 
+  /* "__GIMPLE", for the GIMPLE-parsing extension to the C frontend. */
+  RID_GIMPLE,
+
+  /* "__PHI", for parsing PHI function in GIMPLE FE.  */
+  RID_PHI,
+
   /* C11 */
   RID_ALIGNAS, RID_GENERIC,
 
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index a5358ed..3c4d2cc 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -200,6 +200,10 @@ F
 Driver C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -F <dir>	Add <dir> to the end of the main framework include path.
 
+fgimple
+C Var(flag_gimple) Init(0)
+Enable parsing GIMPLE
+
 H
 C ObjC C++ ObjC++
 Print the name of header files as they are used.
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index fe0c95f..fab8694 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -59,6 +59,18 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-expr.h"
 #include "context.h"
 #include "gcc-rich-location.h"
+#include "tree-vrp.h"
+#include "tree-pass.h"
+#include "tree-pretty-print.h"
+#include "tree.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-pretty-print.h"
+#include "tree-ssa.h"
+#include "pass_manager.h"
+#include "tree-ssanames.h"
+#include "gimple-ssa.h"
+#include "tree-dfa.h"
 
 /* We need to walk over decls with incomplete struct/union/enum types
    after parsing the whole translation unit.
@@ -1417,6 +1429,30 @@ static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
 static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool);
 static void c_parser_cilk_grainsize (c_parser *, bool *);
 
+/* Gimple parsing functions.  */
+static void c_parser_parse_gimple_body (c_parser *);
+static bool c_parser_gimple_compound_statement (c_parser *, gimple_seq *);
+static void c_parser_gimple_label (c_parser *, gimple_seq *);
+static void c_parser_gimple_expression (c_parser *, gimple_seq *);
+static struct c_expr c_parser_gimple_binary_expression (c_parser *, enum tree_code *);
+static struct c_expr c_parser_gimple_unary_expression (c_parser *);
+static struct c_expr c_parser_gimple_postfix_expression (c_parser *);
+static struct c_expr c_parser_gimple_postfix_expression_after_primary (c_parser *,
+								       location_t,
+								       struct c_expr);
+static void c_parser_gimple_pass_list (c_parser *, opt_pass **, bool *);
+static opt_pass *c_parser_gimple_pass_list_params (c_parser *, opt_pass **);
+static void c_parser_gimple_declaration (c_parser *);
+static void c_parser_gimple_goto_stmt (location_t, tree, gimple_seq *);
+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> *);
+
 /* Parse a translation unit (C90 6.7, C99 6.9).
 
    translation-unit:
@@ -1659,6 +1695,9 @@ 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;
+  opt_pass *pass = NULL;
+  bool startwith_p = false;
 
   if (static_assert_ok
       && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
@@ -1743,6 +1782,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       c_parser_skip_to_end_of_block_or_statement (parser);
       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, &startwith_p);
+	  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))
@@ -2144,6 +2197,13 @@ 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 (pass)
+	{
+	  cfun->pass_startwith = pass;
+	  cfun->startwith = startwith_p;
+	}
+
       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,
@@ -2152,6 +2212,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
 	= c_parser_peek_token (parser)->location;
+
+      if (gimple_body_p && flag_gimple)
+	{
+	  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);
@@ -18194,4 +18268,1338 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
   return value_tree;
 }
 
+/* Parse the body of a function declaration marked with "__GIMPLE".  */
+
+void
+c_parser_parse_gimple_body (c_parser *parser)
+{
+  gimple_seq seq = NULL;
+  gimple_seq body = NULL;
+  tree stmt = push_stmt_list ();
+  push_scope ();
+  location_t loc1 = c_parser_peek_token (parser)->location;
+
+  init_tree_ssa (cfun);
+
+  if (!c_parser_gimple_compound_statement (parser, &seq))
+    {
+      gimple *ret = gimple_build_return (NULL);
+      gimple_seq_add_stmt (&seq, ret);
+    }
+
+  tree block = pop_scope ();
+  stmt = pop_stmt_list (stmt);
+  stmt = c_build_bind_expr (loc1, block, stmt);
+
+  block = DECL_INITIAL (current_function_decl);
+  BLOCK_SUBBLOCKS (block) = NULL_TREE;
+  BLOCK_CHAIN (block) = NULL_TREE;
+  TREE_ASM_WRITTEN (block) = 1;
+
+  gbind *bind_stmt = gimple_build_bind (BIND_EXPR_VARS (stmt), NULL,
+					BIND_EXPR_BLOCK (stmt));
+  gimple_bind_set_body (bind_stmt, seq);
+  gimple_seq_add_stmt (&body, bind_stmt);
+  gimple_set_body (current_function_decl, body);
+  cfun->curr_properties = PROP_gimple_any;
+
+  return;
+}
+
+/* Parse a compound statement in gimple function body.
+
+   gimple-statement:
+     gimple-statement
+     gimple-declaration-statement
+     gimple-if-statement
+     gimple-switch-statement
+     gimple-labeled-statement
+     gimple-expression-statement
+     gimple-goto-statement
+     gimple-phi-statement
+     gimple-return-statement
+*/
+
+static bool
+c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
+{
+  bool return_p = false;
+
+  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+    return false;
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      c_parser_consume_token (parser);
+      return false;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      c_parser_error (parser, "expected declaration or statement");
+      c_parser_consume_token (parser);
+      return false;
+    }
+
+  while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+    {
+
+      if (parser->error)
+	{
+	  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
+	  return return_p;
+	}
+
+      if (c_parser_next_token_is (parser, CPP_NAME)
+	  && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+	c_parser_gimple_label (parser, seq);
+
+      else if (c_parser_next_tokens_start_declaration (parser))
+	c_parser_gimple_declaration (parser);
+
+      else if (c_parser_next_token_is (parser, CPP_EOF))
+	{
+	  c_parser_error (parser, "expected declaration or statement");
+	  return return_p;
+	}
+
+      else
+	{
+	  switch (c_parser_peek_token (parser)->type)
+	    {
+	    case CPP_KEYWORD:
+	      switch (c_parser_peek_token (parser)->keyword)
+		{
+		case RID_IF:
+		  c_parser_gimple_if_stmt (parser, seq);
+		  break;
+		case RID_SWITCH:
+		  c_parser_gimple_switch_stmt (parser, seq);
+		  break;
+		case RID_GOTO:
+		    {
+		      location_t loc = c_parser_peek_token (parser)->location;
+		      c_parser_consume_token (parser);
+		      if (c_parser_next_token_is (parser, CPP_NAME))
+			{
+			  c_parser_gimple_goto_stmt (loc,
+						     c_parser_peek_token (parser)->value,
+						     seq);
+			  c_parser_consume_token (parser);
+			  if (!c_parser_require (parser, CPP_SEMICOLON,
+						 "expected %<;%>"))
+			    return return_p;
+			}
+		    }
+		  break;
+		case RID_RETURN:
+		  return_p = true;
+		  c_parser_gimple_return_stmt (parser, seq);
+		  if (!c_parser_require (parser, CPP_SEMICOLON,
+					 "expected %<;%>"))
+		    return return_p;
+		  break;
+		default:
+		  goto expr_stmt;
+		}
+	      break;
+	    case CPP_SEMICOLON:
+	      c_parser_consume_token (parser);
+	      break;
+	    default:
+	    expr_stmt:
+	      c_parser_gimple_expression (parser, seq);
+	      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+		return return_p;
+	    }
+	}
+    }
+  c_parser_consume_token (parser);
+  return return_p; 
+}
+
+/* Parse a gimple expression.
+
+   gimple-expression:
+     gimple-unary-expression
+     gimple-call-statement
+     gimple-binary-expression
+     gimple-assign-expression
+     gimple-cast-expression
+
+*/
+
+static void
+c_parser_gimple_expression (c_parser *parser, gimple_seq *seq)
+{
+  struct c_expr lhs, rhs;
+  gimple *assign = NULL;
+  enum tree_code subcode = NOP_EXPR;
+  location_t loc;
+  tree arg = NULL_TREE;
+  auto_vec<tree> vargs;
+
+  lhs = c_parser_gimple_unary_expression (parser);
+  rhs.value = error_mark_node;
+
+  if (c_parser_next_token_is (parser, CPP_EQ))
+    {
+      c_parser_consume_token (parser);
+    }
+
+  loc = EXPR_LOCATION (lhs.value);
+
+  /* gimple call expression. */
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON) &&
+      TREE_CODE (lhs.value) == CALL_EXPR)
+    {
+      gimple *call;
+      call = gimple_build_call_from_tree (lhs.value);
+      gimple_seq_add_stmt (seq, call);
+      gimple_set_location (call, loc);
+      return;
+    }
+
+  /* cast expression.  */
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+    {
+      rhs = c_parser_cast_expression (parser, NULL);	  //TODO: have a gimple_cast_expr function
+      if (lhs.value != error_mark_node &&
+	  rhs.value != error_mark_node)
+	{
+	  assign = gimple_build_assign (lhs.value, rhs.value);
+	  gimple_seq_add_stmt (seq, assign);
+	  gimple_set_location (assign, loc);
+	  return;
+	}
+    }
+
+  if (POINTER_TYPE_P (TREE_TYPE (lhs.value)))
+    {
+      STRIP_USELESS_TYPE_CONVERSION (rhs.value);
+      if (!useless_type_conversion_p (TREE_TYPE (lhs.value),
+				      TREE_TYPE (rhs.value)))
+	rhs.value = fold_convert_loc (loc, TREE_TYPE (lhs.value), rhs.value);
+    }
+
+  /* pointer expression.  */
+  if (TREE_CODE (lhs.value) == INDIRECT_REF)
+    {
+      tree save_expr = lhs.value;
+      bool volatilep = TREE_THIS_VOLATILE (lhs.value);
+      bool notrap = TREE_THIS_NOTRAP (lhs.value);
+      tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (lhs.value, 0));
+
+      lhs.value = fold_indirect_ref_loc (loc, lhs.value);
+      if (lhs.value == save_expr)
+	{
+	  lhs.value = fold_build2_loc (input_location, MEM_REF,
+				       TREE_TYPE (lhs.value),
+				       TREE_OPERAND (lhs.value, 0),
+				       build_int_cst (saved_ptr_type, 0));
+	  TREE_THIS_VOLATILE (lhs.value) = volatilep;
+	  TREE_THIS_NOTRAP (lhs.value) = notrap;
+	}
+    }
+
+  if (c_parser_next_token_is (parser, CPP_AND) ||
+      c_parser_next_token_is (parser, CPP_MULT) ||
+      c_parser_next_token_is (parser, CPP_PLUS) ||
+      c_parser_next_token_is (parser, CPP_MINUS) ||
+      c_parser_next_token_is (parser, CPP_COMPL) ||
+      c_parser_next_token_is (parser, CPP_NOT))
+    {
+      rhs = c_parser_gimple_unary_expression (parser);
+      assign = gimple_build_assign (lhs.value, rhs.value);
+      gimple_set_location (assign, loc);
+      gimple_seq_add_stmt (seq, assign);
+      return;
+    }
+
+  /* gimple PHI expression.  */
+  if (c_parser_next_token_is_keyword (parser, RID_PHI))
+    {
+      c_parser_consume_token (parser);
+
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+	{
+	  return;
+	}
+
+      if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+	c_parser_consume_token (parser);
+
+      while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+	{
+	  if (c_parser_next_token_is (parser, CPP_NAME) &&
+	      c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+	    {
+	      arg = lookup_label_for_goto (loc,
+					   c_parser_peek_token (parser)->value);
+	      c_parser_consume_token (parser);
+
+	      if (c_parser_next_token_is (parser, CPP_COLON))
+		c_parser_consume_token (parser);
+	      vargs.safe_push (arg);
+	    }
+	  else if (c_parser_next_token_is (parser, CPP_COMMA))
+	    {
+	      c_parser_consume_token (parser);
+	    }
+	  else
+	    {
+	      arg = c_parser_parse_ssa_names (parser).value;
+	      vargs.safe_push (arg);
+	    }
+	}
+
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+				 "expected %<)%>");
+
+      /* build internal function for PHI. */
+      gcall *call_stmt = gimple_build_call_internal_vec (IFN_PHI, vargs);
+      gimple_call_set_lhs (call_stmt, lhs.value);
+      gimple_set_location (call_stmt, UNKNOWN_LOCATION);
+      gimple_seq_add_stmt (seq, call_stmt);
+      return;
+    }
+
+  /* gimple call with lhs. */
+  if (c_parser_next_token_is (parser, CPP_NAME) &&
+      c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN &&
+      lookup_name (c_parser_peek_token (parser)->value))
+    {
+      rhs = c_parser_gimple_unary_expression (parser);
+      gimple *call = gimple_build_call_from_tree (rhs.value);
+      gimple_call_set_lhs (call, lhs.value);
+      gimple_seq_add_stmt (seq, call);
+      gimple_set_location (call, loc);
+      return;
+    }
+
+  rhs = c_parser_gimple_binary_expression (parser, &subcode);
+
+  if (lhs.value != error_mark_node &&
+      rhs.value != error_mark_node)
+    {
+      if (subcode == NOP_EXPR)
+	assign = gimple_build_assign (lhs.value, rhs.value);
+      else
+	assign = gimple_build_assign (lhs.value, subcode,
+				      TREE_OPERAND (rhs.value, 0),
+				      TREE_OPERAND (rhs.value, 1));
+      gimple_seq_add_stmt (seq, assign);
+      gimple_set_location (assign, loc);
+    }
+  return;
+}
+
+/* Parse gimple binary expr.
+
+   gimple-multiplicative-expression:
+     gimple-unary-expression * gimple-unary-expression
+     gimple-unary-expression / gimple-unary-expression
+     gimple-unary-expression % gimple-unary-expression
+
+   gimple-additive-expression:
+     gimple-unary-expression + gimple-unary-expression
+     gimple-unary-expression - gimple-unary-expression
+
+   gimple-shift-expression:
+     gimple-unary-expression << gimple-unary-expression
+     gimple-unary-expression >> gimple-unary-expression
+
+   gimple-relational-expression:
+     gimple-unary-expression < gimple-unary-expression
+     gimple-unary-expression > gimple-unary-expression
+     gimple-unary-expression <= gimple-unary-expression
+     gimple-unary-expression >= gimple-unary-expression
+
+   gimple-equality-expression:
+     gimple-unary-expression == gimple-unary-expression
+     gimple-unary-expression != gimple-unary-expression
+
+   gimple-AND-expression:
+     gimple-unary-expression & gimple-unary-expression
+
+   gimple-exclusive-OR-expression:
+     gimple-unary-expression ^ gimple-unary-expression
+
+   gimple-inclusive-OR-expression:
+     gimple-unary-expression | gimple-unary-expression
+
+   gimple-logical-AND-expression:
+     gimple-unary-expression && gimple-unary-expression
+
+   gimple-logical-OR-expression:
+     gimple-unary-expression || gimple-unary-expression
+
+*/
+
+static c_expr
+c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)
+{
+  struct {
+    /* The expression at this stack level.  */
+    struct c_expr expr;
+    /* The operation on its left.  */
+    enum tree_code op;
+    /* The source location of this operation.  */
+    location_t loc;
+  } stack[2];
+  int sp;
+  /* Location of the binary operator.  */
+  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
+#define POP								      \
+  do {									      \
+    if (sp == 1								      \
+	&& c_parser_peek_token (parser)->type == CPP_SEMICOLON		      \
+	&& (((1 << PREC_BITOR) | (1 << PREC_BITXOR) | (1 << PREC_BITAND)      \
+	       | (1 << PREC_SHIFT) | (1 << PREC_ADD) | (1 << PREC_MULT)))     \
+	&& stack[sp].op != TRUNC_MOD_EXPR				      \
+	&& stack[0].expr.value != error_mark_node			      \
+	&& stack[1].expr.value != error_mark_node)			      \
+      stack[0].expr.value						      \
+	= build2 (stack[1].op, TREE_TYPE (stack[0].expr.value),		      \
+		  stack[0].expr.value, stack[1].expr.value);		      \
+    else								      \
+      stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,	      \
+						   stack[sp].op,	      \
+						   stack[sp - 1].expr,	      \
+						   stack[sp].expr);	      \
+    sp--;								      \
+  } while (0)
+  stack[0].loc = c_parser_peek_token (parser)->location;
+  stack[0].expr = c_parser_gimple_unary_expression (parser);
+  sp = 0;
+  source_range src_range;
+  if (parser->error)
+    goto out;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_MULT:
+      *subcode = MULT_EXPR;
+      break;
+    case CPP_DIV:
+      *subcode = TRUNC_DIV_EXPR;
+      break;
+    case CPP_MOD:
+      *subcode = TRUNC_MOD_EXPR;
+      break;
+    case CPP_PLUS:
+      *subcode = PLUS_EXPR;
+      break;
+    case CPP_MINUS:
+      *subcode = MINUS_EXPR;
+      break;
+    case CPP_LSHIFT:
+      *subcode = LSHIFT_EXPR;
+      break;
+    case CPP_RSHIFT:
+      *subcode = RSHIFT_EXPR;
+      break;
+    case CPP_LESS:
+      *subcode = LT_EXPR;
+      break;
+    case CPP_GREATER:
+      *subcode = GT_EXPR;
+      break;
+    case CPP_LESS_EQ:
+      *subcode = LE_EXPR;
+      break;
+    case CPP_GREATER_EQ:
+      *subcode = GE_EXPR;
+      break;
+    case CPP_EQ_EQ:
+      *subcode = EQ_EXPR;
+      break;
+    case CPP_NOT_EQ:
+      *subcode = NE_EXPR;
+      break;
+    case CPP_AND:
+      *subcode = BIT_AND_EXPR;
+      break;
+    case CPP_XOR:
+      *subcode = BIT_XOR_EXPR;
+      break;
+    case CPP_OR:
+      *subcode = BIT_IOR_EXPR;
+      break;
+    case CPP_AND_AND:
+      *subcode = TRUTH_ANDIF_EXPR;
+      break;
+    case CPP_OR_OR:
+      *subcode = TRUTH_ORIF_EXPR;
+      break;
+    default:
+      /* Not a binary operator, so end of the binary
+	 expression.  */
+      *subcode = NOP_EXPR;
+      goto out;
+    }
+  binary_loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_token (parser);
+  switch (*subcode)
+    {
+    case TRUTH_ANDIF_EXPR:
+      src_range = stack[sp].expr.src_range;
+      stack[sp].expr.value = c_objc_common_truthvalue_conversion
+	(stack[sp].loc, default_conversion (stack[sp].expr.value));
+      set_c_expr_source_range (&stack[sp].expr, src_range);
+      break;
+    case TRUTH_ORIF_EXPR:
+      src_range = stack[sp].expr.src_range;
+      stack[sp].expr.value = c_objc_common_truthvalue_conversion
+	(stack[sp].loc, default_conversion (stack[sp].expr.value));
+      set_c_expr_source_range (&stack[sp].expr, src_range);
+      break;
+    default:
+      break;
+    }
+  sp++;
+  stack[sp].loc = binary_loc;
+  stack[sp].expr = c_parser_gimple_unary_expression (parser);
+  stack[sp].op = *subcode;
+out:
+  while (sp > 0)
+    POP;
+  return stack[0].expr;
+#undef POP
+
+}
+
+/* Parse gimple unary expression.
+
+   gimple-unary-expression:
+     gimple-postfix-expression
+     unary-operator cast-expression
+
+   unary-operator: one of
+     & * + - ~ !
+*/
+
+static c_expr
+c_parser_gimple_unary_expression (c_parser *parser)
+{
+  struct c_expr ret, op;
+  if (c_parser_peek_token (parser)->value
+      && TREE_CODE (c_parser_peek_token (parser)->value) == IDENTIFIER_NODE
+      && !lookup_name (c_parser_peek_token (parser)->value))
+    return c_parser_parse_ssa_names (parser);
+
+  location_t op_loc = c_parser_peek_token (parser)->location;
+  location_t finish;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_AND:
+      c_parser_consume_token (parser);
+      op = c_parser_cast_expression (parser, NULL);
+      mark_exp_read (op.value);
+      return parser_build_unary_op (op_loc, ADDR_EXPR, op);
+    case CPP_MULT:
+      {
+	c_parser_consume_token (parser);
+	op = c_parser_cast_expression (parser, NULL);
+	finish = op.get_finish ();
+	location_t combined_loc = make_location (op_loc, op_loc, finish);
+	ret.value = build_indirect_ref (combined_loc, op.value,
+					RO_UNARY_STAR);
+	ret.src_range.m_start = op_loc;
+	ret.src_range.m_finish = finish;
+	return ret;
+      }
+    case CPP_PLUS:
+      c_parser_consume_token (parser);
+      op = c_parser_cast_expression (parser, NULL);
+      return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
+    case CPP_MINUS:
+      c_parser_consume_token (parser);
+      op = c_parser_cast_expression (parser, NULL);
+      return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
+    case CPP_COMPL:
+      c_parser_consume_token (parser);
+      op = c_parser_cast_expression (parser, NULL);
+      return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
+    case CPP_NOT:
+      c_parser_consume_token (parser);
+      op = c_parser_cast_expression (parser, NULL);
+      return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
+    default:
+      return c_parser_gimple_postfix_expression (parser);
+    }
+}
+
+/* Parse gimple ssa names.  */
+
+static c_expr
+c_parser_parse_ssa_names (c_parser *parser)
+{
+  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;
+
+  /* ssa token string.  */
+  const char *ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+  token = new char [strlen (ssa_token)];
+  strcpy (token, ssa_token);
+
+  /* seperate 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);
+
+      /* lookup for parent decl.  */
+      if (lookup_name (id))
+	{
+	  var_version++;
+	  unsigned int version;
+	  version = atoi (var_version);
+	  if (var_version && version)
+	    {
+	      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);
+	    }
+	}
+    }
+
+  /* for default defination ssa names.  */
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      c_parser_consume_token (parser);
+      ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (!strcmp ("D", ssa_token))
+	{
+	  set_ssa_default_def (cfun, lookup_name (id), ret.value);
+	  c_parser_consume_token (parser);
+	}
+      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+	goto out;
+    }
+
+  out:
+  free (var_name);
+  free (token);
+  return ret;
+}
+
+/* Parse gimple postfix expression.
+
+   gimple-postfix-expression:
+     gimple-primary-expression
+     gimple-primary-xpression [ gimple-primary-expression ]
+     gimple-primary-expression ( gimple-argument-expression-list[opt] )
+
+   gimple-argument-expression-list:
+     gimple-unary-expression
+     gimple-argument-expression-list , gimple-unary-expression
+
+   gimple-primary-expression:
+     identifier
+     constant
+     string-literal
+
+*/
+
+static struct c_expr
+c_parser_gimple_postfix_expression (c_parser *parser)
+{
+  struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
+  source_range tok_range = c_parser_peek_token (parser)->get_range ();
+  expr.original_code = ERROR_MARK;
+  expr.original_type = NULL;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_NUMBER:
+      expr.value = c_parser_peek_token (parser)->value;
+      set_c_expr_source_range (&expr, tok_range);
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      break;
+    case CPP_CHAR:
+    case CPP_CHAR16:
+    case CPP_CHAR32:
+    case CPP_WCHAR:
+      expr.value = c_parser_peek_token (parser)->value;
+      set_c_expr_source_range (&expr, tok_range);
+      c_parser_consume_token (parser);
+      break;
+    case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
+    case CPP_WSTRING:
+    case CPP_UTF8STRING:
+      expr.value = c_parser_peek_token (parser)->value;
+      set_c_expr_source_range (&expr, tok_range);
+      expr.original_code = STRING_CST;
+      c_parser_consume_token (parser);
+      break;
+    case CPP_NAME:
+      if (c_parser_peek_token (parser)->id_kind == C_ID_ID)
+	{
+	  tree id = c_parser_peek_token (parser)->value;
+	  c_parser_consume_token (parser);
+	  expr.value = build_external_ref (loc, id,
+					   (c_parser_peek_token (parser)->type
+					    == CPP_OPEN_PAREN),
+					   &expr.original_type);
+	  set_c_expr_source_range (&expr, tok_range);
+	  break;
+	}
+      else
+	{
+	  c_parser_error (parser, "expected expression");
+	  expr.set_error ();
+	  break;
+	}
+      break;
+    default:
+      c_parser_error (parser, "expected expression");
+      expr.set_error ();
+      break;
+    }
+  return c_parser_gimple_postfix_expression_after_primary
+    (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
+}
+
+/* Parse a gimple postfix expression after the initial primary or compound
+   literal.  */
+
+static struct c_expr
+c_parser_gimple_postfix_expression_after_primary (c_parser *parser,
+						  location_t expr_loc,
+						  struct c_expr expr)
+{
+  struct c_expr orig_expr;
+  vec<tree, va_gc> *exprlist;
+  vec<tree, va_gc> *origtypes = NULL;
+  vec<location_t> arg_loc = vNULL;
+  location_t start;
+  location_t finish;
+
+  location_t op_loc = c_parser_peek_token (parser)->location;
+
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_OPEN_SQUARE:
+	{
+	  c_parser_consume_token (parser);
+	  tree idx = c_parser_gimple_unary_expression (parser).value;
+
+	  if (!c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>"))
+	    break;
+
+	  start = expr.get_start ();
+	  finish = parser->tokens_buf[0].location;
+	  expr.value = build_array_ref (op_loc, expr.value, idx);
+	  set_c_expr_source_range (&expr, start, finish);
+
+	  expr.original_code = ERROR_MARK;
+	  expr.original_type = NULL;
+	  break;
+	}
+    case CPP_OPEN_PAREN:
+	{
+	  /* Function call */
+	  c_parser_consume_token (parser);
+	  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+	    exprlist = NULL;
+	  else
+	    exprlist = c_parser_gimple_expr_list (parser, &origtypes, 
+						  &arg_loc);
+	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+				     "expected %<)%>");
+	  orig_expr = expr;
+	  start = expr.get_start ();
+	  finish = parser->tokens_buf[0].get_finish ();
+	  expr.value
+	    = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
+					 exprlist, origtypes);
+	  set_c_expr_source_range (&expr, start, finish);
+
+	  expr.original_code = ERROR_MARK;
+	  if (TREE_CODE (expr.value) == INTEGER_CST
+	      && TREE_CODE (orig_expr.value) == FUNCTION_DECL
+	      && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
+	      && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
+	    expr.original_code = C_MAYBE_CONST_EXPR;
+	  expr.original_type = NULL;
+	  if (exprlist)
+	    {
+	      release_tree_vector (exprlist);
+	      release_tree_vector (origtypes);
+	    }
+	  arg_loc.release ();
+	  break;
+	default:
+	  return expr;
+
+	}
+    }
+  return expr;
+}
+
+/* Parse expression list.
+
+   gimple-expr-list:
+     gimple-unary-expression
+     gimple-expr-list , gimple-unary-expression
+
+ */
+
+static vec<tree, va_gc> *
+c_parser_gimple_expr_list (c_parser *parser, vec<tree, va_gc> **p_orig_types,
+			   vec<location_t> *locations)
+{
+  vec<tree, va_gc> *ret;
+  vec<tree, va_gc> *orig_types;
+  struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
+
+  ret = make_tree_vector ();
+  if (p_orig_types == NULL)
+    orig_types = NULL;
+  else
+    orig_types = make_tree_vector ();
+
+  expr = c_parser_gimple_unary_expression (parser);
+  vec_safe_push (ret, expr.value);
+  if (orig_types)
+    vec_safe_push (orig_types, expr.original_type);
+  if (locations)
+    locations->safe_push (loc);
+  while (c_parser_next_token_is (parser, CPP_COMMA))
+    {
+      c_parser_consume_token (parser);
+      loc = c_parser_peek_token (parser)->location;
+      expr = c_parser_gimple_unary_expression (parser);
+      vec_safe_push (ret, expr.value);
+      if (orig_types)
+	vec_safe_push (orig_types, expr.original_type);
+      if (locations)
+	locations->safe_push (loc);
+    }
+  if (orig_types)
+    *p_orig_types = orig_types;
+  return ret;
+}
+
+/* Parse gimple label.
+
+   gimple-label:
+     identifier :
+     case constant-expression :
+     default :
+
+*/
+
+static void
+c_parser_gimple_label (c_parser *parser, gimple_seq *seq)
+{
+  tree name = c_parser_peek_token (parser)->value;
+  location_t loc1 = c_parser_peek_token (parser)->location;
+  gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
+  c_parser_consume_token (parser);
+  gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
+  c_parser_consume_token (parser);
+  tree label = define_label (loc1, name);
+  gimple_seq_add_stmt (seq, gimple_build_label (label));
+  return;
+}
+
+/* Parse gimple pass list.
+
+   gimple-pass-list:
+     startwith("pass-name")
+ */
+
+static void
+c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass,
+			   bool *startwith_p)
+{
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      return;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      return;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      c_parser_consume_token (parser);
+      if (!strcmp (op, "startwith"))
+	{
+	  *pass = c_parser_gimple_pass_list_params (parser, pass);
+	  if (!(*pass))
+	    return;
+
+	  *startwith_p = true;
+	  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+	    return;
+	}
+      else
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "invalid operation");
+	  return;
+	}
+    }
+  else if (c_parser_next_token_is (parser, CPP_EOF))
+    {
+      c_parser_error (parser, "expected parameters");
+      return;
+    }
+
+  return;
+}
+
+/* Support function for c_parser_gimple_pass_list.  */
+
+static opt_pass *
+c_parser_gimple_pass_list_params (c_parser *parser, opt_pass **pass)
+{
+  opt_pass *pass_start = NULL, *new_pass;
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      return NULL;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      return NULL;
+    }
+
+  while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+    {
+      if (c_parser_next_token_is (parser, CPP_EOF))
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "expected pass names");
+	  return NULL;
+	}
+
+      if (c_parser_next_token_is (parser, CPP_STRING))
+	{
+	  const char *name = NULL;
+	  name = TREE_STRING_POINTER (c_parser_peek_token (parser)->value);
+	  c_parser_consume_token (parser);
+	  new_pass = g->get_passes ()->get_pass_by_name (name);
+
+	  if (!new_pass)
+	    {
+	      error_at (c_parser_peek_token (parser)->location,
+			"invalid pass name");
+	      parser->error = true;
+	      c_parser_consume_token (parser);
+	      return NULL;
+	    }
+	  if (*pass)
+	    {
+	      (*pass)->next = new_pass;
+	      (*pass) = (*pass)->next;
+	    }
+	  else
+	    {
+	      *pass = new_pass;
+	      pass_start = *pass;
+	    }
+	}
+      else if (c_parser_next_token_is (parser, CPP_COMMA))
+	c_parser_consume_token (parser);
+      else
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "invalid pass name");
+	  c_parser_consume_token (parser);
+	  return NULL;
+	}
+    }
+  return pass_start;
+}
+
+/* Parse gimple local declaration.
+
+   declaration-specifiers:
+     storage-class-specifier declaration-specifiers[opt]
+     type-specifier declaration-specifiers[opt]
+     type-qualifier declaration-specifiers[opt]
+     function-specifier declaration-specifiers[opt]
+     alignment-specifier declaration-specifiers[opt]
+
+   storage-class-specifier:
+     typedef
+     extern
+     static
+     auto
+     register
+
+   type-specifier:
+     void
+     char
+     short
+     int
+     long
+     float
+     double
+     signed
+     unsigned
+     _Bool
+     _Complex
+
+   type-qualifier:
+     const
+     restrict
+     volatile
+     address-space-qualifier
+     _Atomic
+
+ */
+
+static void
+c_parser_gimple_declaration (c_parser *parser)
+{
+  struct c_declarator *declarator;
+  struct c_declspecs *specs = build_null_declspecs ();
+  c_parser_declspecs (parser, specs, true, true, true,
+		      true, true, cla_nonabstract_decl);
+  finish_declspecs (specs);
+
+  /* Provide better error recovery.  Note that a type name here is usually
+     better diagnosed as a redeclaration.  */
+  if (c_parser_next_token_starts_declspecs (parser)
+      && !c_parser_next_token_is (parser, CPP_NAME))
+    {
+      c_parser_error (parser, "expected %<;%>");
+      parser->error = false;
+      return;
+    }
+
+  bool dummy = false;
+  declarator = c_parser_declarator (parser,
+				    specs->typespec_kind != ctsk_none,
+				    C_DTR_NORMAL, &dummy);
+
+  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);
+	}
+    }
+  else
+    {
+      c_parser_error (parser, "expected %<;%>");
+      return;
+    }
+}
+
+/* Parse gimple goto statement.  */
+
+static void
+c_parser_gimple_goto_stmt (location_t loc, tree label, gimple_seq *seq)
+{
+  tree decl = lookup_label_for_goto (loc, label);
+  gimple_seq_add_stmt (seq, gimple_build_goto (decl));
+  return;
+}
+
+/* Parse a parenthesized condition.
+   gimple-condition:
+     ( gimple-binary-expression )    */
+
+static tree
+c_parser_gimple_paren_condition (c_parser *parser)
+{
+  enum tree_code subcode = NOP_EXPR;
+  location_t loc = c_parser_peek_token (parser)->location;
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return error_mark_node;
+  tree cond = c_parser_gimple_binary_expression (parser, &subcode).value;
+  cond = c_objc_common_truthvalue_conversion (loc, cond);
+  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+    return error_mark_node;
+  return cond;
+}
+
+/* Parse gimple if-else statement.
+
+   if-statement:
+     if ( gimple-binary-expression ) gimple-goto-statement
+     if ( gimple-binary-expression ) gimple-goto-statement \
+					else gimple-goto-statement
+ */
+
+static void
+c_parser_gimple_if_stmt (c_parser *parser, gimple_seq *seq)
+{
+  tree t_label, f_label, label;
+  location_t loc;
+  c_parser_consume_token (parser);
+  tree cond = c_parser_gimple_paren_condition (parser);
+
+  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+    {
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      label = c_parser_peek_token (parser)->value;
+      t_label = lookup_label_for_goto (loc, label);
+      c_parser_consume_token (parser);
+      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+	return;
+    }
+  else
+    {
+      c_parser_error (parser, "expected goto expression");
+      return;
+    }
+
+  if (c_parser_next_token_is_keyword (parser, RID_ELSE))
+    c_parser_consume_token (parser);
+  else
+    {
+      c_parser_error (parser, "expected else statement");
+      return;
+    }
+
+  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+    {
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      label = c_parser_peek_token (parser)->value;
+      f_label = lookup_label_for_goto (loc, label);
+      c_parser_consume_token (parser);
+      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+	return;
+    }
+  else
+    {
+      c_parser_error (parser, "expected goto expression");
+      return;
+    }
+
+  gimple_seq_add_stmt (seq, gimple_build_cond_from_tree (cond, t_label,
+							 f_label));
+}
+
+/* Parse gimple switch-statement.
+
+   gimple-switch-statement:
+     switch (gimple-unary-expression) gimple-case-statement
+
+   gimple-case-statement:
+     gimple-case-statement
+     gimple-label-statement : gimple-goto-statment
+*/
+
+static void
+c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
+{
+  c_expr cond_expr;
+  tree case_label, label;
+  auto_vec<tree> labels;
+  tree default_label = NULL_TREE;
+  gimple_seq switch_body = NULL;
+  location_t loc;
+  c_parser_consume_token (parser);
+
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      cond_expr = c_parser_gimple_unary_expression (parser);
+      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+	return;
+    }
+
+  if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+    {
+      while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+	{
+	  if (c_parser_next_token_is (parser, CPP_EOF))
+	    {
+	      c_parser_error (parser, "expected statement");
+	      return;
+	    }
+
+	  switch (c_parser_peek_token (parser)->keyword)
+	    {
+	    case RID_CASE:
+		{
+		  c_expr exp1;
+		  loc = c_parser_peek_token (parser)->location;
+		  c_parser_consume_token (parser);
+
+		  if (c_parser_next_token_is (parser, CPP_NAME) ||
+		      c_parser_peek_token (parser)->type == CPP_NUMBER)
+		    exp1 = c_parser_gimple_unary_expression (parser);
+		  else
+		    c_parser_error (parser, "expected expression");
+
+		  if (c_parser_next_token_is (parser, CPP_COLON))
+		    {
+		      c_parser_consume_token (parser);
+		      label = create_artificial_label (loc);
+		      case_label = build_case_label (exp1.value, NULL_TREE,
+						     label);
+		      labels.safe_push (case_label);
+		      gimple_seq_add_stmt (&switch_body,
+					   gimple_build_label
+					   (CASE_LABEL (case_label)));
+		    }
+		  else
+		    {
+		      if (!c_parser_require (parser, CPP_SEMICOLON,
+					     "expected %<:%>"))
+			return;
+		    }
+		}
+	      break;
+	    case RID_DEFAULT:
+		{
+		  c_parser_consume_token (parser);
+		  if (c_parser_next_token_is (parser, CPP_COLON))
+		    {
+		      c_parser_consume_token (parser);
+		      default_label = build_case_label (NULL_TREE, NULL_TREE,
+							create_artificial_label
+							(UNKNOWN_LOCATION));
+		      gimple_seq_add_stmt (&switch_body,
+					   gimple_build_label
+					   (CASE_LABEL (default_label)));
+		    }
+		  else
+		    {
+		      if (!c_parser_require (parser, CPP_SEMICOLON,
+					     "expected %<:%>"))
+			return;
+		    }
+		}
+	      break;
+	    case RID_GOTO:
+		{
+		  loc = c_parser_peek_token (parser)->location;
+		  c_parser_consume_token (parser);
+		  if (c_parser_next_token_is (parser, CPP_NAME))
+		    {
+		      c_parser_gimple_goto_stmt (loc,
+						 c_parser_peek_token (parser)->value,
+						 &switch_body);
+		      c_parser_consume_token (parser);
+		      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+			c_parser_consume_token (parser);
+		      else
+			{
+			  c_parser_error (parser, "expected semicolon");
+			  return;
+			}
+		    }
+		  else
+		    {
+		      if (!c_parser_require (parser, CPP_NAME,
+					     "expected label"))
+			return;
+		    }
+		}
+	      break;
+	    default:
+	      c_parser_error (parser, "expected case label or goto statement");
+	      return;
+	    }
+
+	}
+    }
+  if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
+    return;
+  gimple_seq_add_stmt (seq, gimple_build_switch (cond_expr.value,
+						 default_label, labels));
+  gimple_seq_add_seq (seq, switch_body);
+  labels.release();
+}
+
+/* Parse gimple return statement.  */
+
+static void
+c_parser_gimple_return_stmt (c_parser *parser, gimple_seq *seq)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  gimple *ret = NULL;
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      c_finish_gimple_return (loc, NULL_TREE);
+      ret = gimple_build_return (NULL);
+      gimple_seq_add_stmt (seq, ret);
+    }
+  else
+    {
+      location_t xloc = c_parser_peek_token (parser)->location;
+      c_expr expr = c_parser_gimple_unary_expression (parser);
+      c_finish_gimple_return (xloc, expr.value);
+      ret = gimple_build_return (expr.value);
+      gimple_seq_add_stmt (seq, ret);
+    }
+}
+
+/* Support function for c_parser_gimple_return_stmt.  */
+
+static void
+c_finish_gimple_return (location_t loc, tree retval)
+{
+  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
+
+  /* Use the expansion point to handle cases such as returning NULL
+     in a function returning void.  */
+  source_location xloc = expansion_point_location_if_in_system_header (loc);
+
+  if (TREE_THIS_VOLATILE (current_function_decl))
+    warning_at (xloc, 0,
+		"function declared %<noreturn%> has a %<return%> statement");
+
+  if (!retval)
+    {
+      current_function_returns_null = 1;
+    }  
+  else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
+    {
+      current_function_returns_null = 1;
+      if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
+	{
+	  error_at
+	    (xloc, "%<return%> with a value, in function returning void");
+	  inform (DECL_SOURCE_LOCATION (current_function_decl),
+		  "declared here");
+	}
+    }
+  else if (TREE_CODE (valtype) != TREE_CODE (TREE_TYPE (retval)))
+    {
+      error_at
+	(xloc, "invalid conversion in return statement");
+      inform (DECL_SOURCE_LOCATION (current_function_decl),
+	      "declared here");
+    }
+  return;
+}
+
 #include "gt-c-c-parser.h"
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 6a1d126..cf6728f 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1944,6 +1944,7 @@ cgraph_node::assemble_thunks_and_aliases (void)
 void
 cgraph_node::expand (void)
 {
+  bool startwith_p = true;
   location_t saved_loc;
 
   /* We ought to not compile any inline clones.  */
@@ -1982,7 +1983,7 @@ cgraph_node::expand (void)
   /* Signal the start of passes.  */
   invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
 
-  execute_pass_list (cfun, g->get_passes ()->all_passes);
+  execute_pass_list (cfun, g->get_passes ()->all_passes, &startwith_p);
 
   /* Signal the end of passes.  */
   invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
@@ -2035,7 +2036,9 @@ cgraph_node::expand (void)
   timevar_pop (TV_REST_OF_COMPILATION);
 
   /* Make sure that BE didn't give up on compiling.  */
-  gcc_assert (TREE_ASM_WRITTEN (decl));
+  if (!(flag_gimple && cfun->pass_startwith))  /* FIXME : for gimplefe custom_pass_list */
+    gcc_assert (TREE_ASM_WRITTEN (decl));
+
   if (cfun)
     pop_cfun ();
 
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index fe1e984..ad6e5ac 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -85,6 +85,7 @@ typedef const union tree_node *const_tree;
 struct gimple;
 typedef gimple *gimple_seq;
 struct gimple_stmt_iterator;
+class opt_pass;
 
 /* Forward decls for leaf gimple subclasses (for individual gimple codes).
    Keep this in the same order as the corresponding codes in gimple.def.  */
@@ -405,6 +406,8 @@ typedef unsigned char uchar;
 #include "input.h"
 #include "is-a.h"
 #include "memory-block.h"
+#include "pass_manager.h"
+#include "tree-pass.h"
 #endif /* GENERATOR_FILE && !USED_FOR_TARGET */
 
 #endif /* coretypes.h */
diff --git a/gcc/function.h b/gcc/function.h
index 501ef68..38c00fd 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -228,6 +228,12 @@ struct GTY(()) function {
   /* GIMPLE body for this function.  */
   gimple_seq gimple_body;
 
+  /* GIMPLEFE pass to start with */
+  opt_pass *pass_startwith;
+
+  /* Startwith flag */
+  bool startwith;
+
   /* SSA and dataflow information.  */
   struct gimple_df *gimple_df;
 
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 12d9a9c..e4416a5 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -838,7 +838,7 @@ dump_gimple_switch (pretty_printer *buffer, gswitch *gs, int spc,
     {
       pp_string (buffer, "switch (");
       dump_generic_node (buffer, gimple_switch_index (gs), spc, flags, true);
-      pp_string (buffer, ") <");
+      pp_string (buffer, ") {");
     }
 
   for (i = 0; i < gimple_switch_num_labels (gs); i++)
@@ -849,9 +849,9 @@ dump_gimple_switch (pretty_printer *buffer, gswitch *gs, int spc,
       pp_space (buffer);
       dump_generic_node (buffer, CASE_LABEL (case_label), spc, flags, false);
       if (i < gimple_switch_num_labels (gs) - 1)
-        pp_string (buffer, ", ");
+        pp_string (buffer, "; ");
     }
-  pp_greater (buffer);
+  pp_string (buffer, "}");
 }
 
 
@@ -907,16 +907,11 @@ dump_gimple_label (pretty_printer *buffer, glabel *gs, int spc, int flags)
 {
   tree label = gimple_label_label (gs);
   if (flags & TDF_RAW)
-      dump_gimple_fmt (buffer, spc, flags, "%G <%T>", gs, label);
+    dump_gimple_fmt (buffer, spc, flags, "%T", label);
   else
-    {
-      dump_generic_node (buffer, label, spc, flags, false);
-      pp_colon (buffer);
-    }
-  if (DECL_NONLOCAL (label))
-    pp_string (buffer, " [non-local]");
-  if ((flags & TDF_EH) && EH_LANDING_PAD_NR (label))
-    pp_printf (buffer, " [LP %d]", EH_LANDING_PAD_NR (label));
+    dump_generic_node (buffer, label, spc, flags, false);
+
+  pp_colon (buffer);
 }
 
 /* Dump a GIMPLE_GOTO tuple on the pretty_printer BUFFER, SPC
@@ -1966,8 +1961,7 @@ dump_ssaname_info_to_file (FILE *file, tree node, int spc)
    pretty printer.  If COMMENT is true, print this after #.  */
 
 static void
-dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, bool comment,
-		 int flags)
+dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, int flags)
 {
   size_t i;
   tree lhs = gimple_phi_result (phi);
@@ -1975,30 +1969,27 @@ dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, bool comment,
   if (flags & TDF_ALIAS)
     dump_ssaname_info (buffer, lhs, spc);
 
-  if (comment)
-    pp_string (buffer, "# ");
-
   if (flags & TDF_RAW)
     dump_gimple_fmt (buffer, spc, flags, "%G <%T, ", phi,
 		     gimple_phi_result (phi));
   else
     {
       dump_generic_node (buffer, lhs, spc, flags, false);
-      pp_string (buffer, " = PHI <");
+      pp_string (buffer, " = __PHI (");
     }
   for (i = 0; i < gimple_phi_num_args (phi); i++)
     {
       if ((flags & TDF_LINENO) && gimple_phi_arg_has_location (phi, i))
 	dump_location (buffer, gimple_phi_arg_location (phi, i));
+      pp_string (buffer, "bb_");
+      pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index);
+      pp_string (buffer, ": ");
       dump_generic_node (buffer, gimple_phi_arg_def (phi, i), spc, flags,
 			 false);
-      pp_left_paren (buffer);
-      pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index);
-      pp_right_paren (buffer);
       if (i < gimple_phi_num_args (phi) - 1)
 	pp_string (buffer, ", ");
     }
-  pp_greater (buffer);
+  pp_right_paren (buffer);
 }
 
 
@@ -2286,7 +2277,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple *gs, int spc, int flags)
       break;
 
     case GIMPLE_PHI:
-      dump_gimple_phi (buffer, as_a <gphi *> (gs), spc, false, flags);
+      dump_gimple_phi (buffer, as_a <gphi *> (gs), spc, flags);
       break;
 
     case GIMPLE_OMP_PARALLEL:
@@ -2447,7 +2438,7 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, int indent, int flags)
     {
       gimple *stmt = first_stmt (bb);
       if (!stmt || gimple_code (stmt) != GIMPLE_LABEL)
-	fprintf (outf, "%*s<bb %d>:\n", indent, "", bb->index);
+	fprintf (outf, "%*sbb_%d:\n", indent, "", bb->index);
     }
 }
 
@@ -2480,7 +2471,7 @@ dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags)
       if (!virtual_operand_p (gimple_phi_result (phi)) || (flags & TDF_VOPS))
         {
           INDENT (indent);
-	  dump_gimple_phi (buffer, phi, indent, true, flags);
+	  dump_gimple_phi (buffer, phi, indent, flags);
           pp_newline (buffer);
         }
     }
@@ -2493,24 +2484,9 @@ dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags)
 static void
 pp_cfg_jump (pretty_printer *buffer, basic_block bb)
 {
-  gimple *stmt;
-
-  stmt = first_stmt (bb);
-
-  pp_string (buffer, "goto <bb ");
+  pp_string (buffer, "goto bb_");
   pp_decimal_int (buffer, bb->index);
-  pp_greater (buffer);
-  if (stmt && gimple_code (stmt) == GIMPLE_LABEL)
-    {
-      pp_string (buffer, " (");
-      dump_generic_node (buffer,
-			 gimple_label_label (as_a <glabel *> (stmt)),
-			 0, 0, false);
-      pp_right_paren (buffer);
-      pp_semicolon (buffer);
-    }
-  else
-    pp_semicolon (buffer);
+  pp_semicolon (buffer);
 }
 
 
@@ -2627,7 +2603,7 @@ gimple_dump_bb (FILE *file, basic_block bb, int indent, int flags)
 void
 gimple_dump_bb_for_graph (pretty_printer *pp, basic_block bb)
 {
-  pp_printf (pp, "<bb %d>:\n", bb->index);
+  pp_printf (pp, "bb_%d:\n", bb->index);
   pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
 
   for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 4715332..12b9ec9 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -11848,7 +11848,22 @@ gimplify_function_tree (tree fndecl)
       && !needs_to_live_in_memory (ret))
     DECL_GIMPLE_REG_P (ret) = 1;
 
-  bind = gimplify_body (fndecl, true);
+  if (!cfun->gimple_body)
+    bind = gimplify_body (fndecl, true);
+  else
+    {
+      gimple_seq seq;
+      gimple *outer_stmt;
+      seq = cfun->gimple_body;
+      outer_stmt = gimple_seq_first_stmt (seq);
+      if (gimple_code (outer_stmt) == GIMPLE_BIND
+	  && gimple_seq_first (seq) == gimple_seq_last (seq))
+	bind = as_a <gbind *> (outer_stmt);
+      else
+	bind = gimple_build_bind (NULL_TREE, seq, NULL);
+
+      DECL_SAVED_TREE (fndecl) = NULL_TREE;
+    }
 
   /* The tree body of the function is no longer needed, replace it
      with the new GIMPLE body.  */
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index cd4b625..3824fb7 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2412,3 +2412,9 @@ expand_internal_call (gcall *stmt)
 {
   expand_internal_call (gimple_call_internal_fn (stmt), stmt);
 }
+
+void
+expand_PHI (internal_fn, gcall *)
+{
+    gcc_unreachable ();
+}
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 6701cd9..a5dd23e 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -169,6 +169,7 @@ DEF_INTERNAL_FN (VA_ARG, ECF_NOTHROW | ECF_LEAF, NULL)
    other such optimizations.  The first argument distinguishes
    between uses.  See internal-fn.h for usage.  */
 DEF_INTERNAL_FN (UNIQUE, ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (PHI, 0, NULL)
 
 /* DIM_SIZE and DIM_POS return the size of a particular compute
    dimension and the executing thread's position within that
diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
index bb31465..9c39dd67 100644
--- a/gcc/internal-fn.h
+++ b/gcc/internal-fn.h
@@ -174,5 +174,6 @@ extern bool set_edom_supported_p (void);
 
 extern void expand_internal_call (gcall *);
 extern void expand_internal_call (internal_fn, gcall *);
+extern void expand_PHI (internal_fn, gcall *);
 
 #endif
diff --git a/gcc/passes.c b/gcc/passes.c
index c7d7dbe..04caf39 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -1685,12 +1685,13 @@ remove_cgraph_node_from_order (cgraph_node *node, void *data)
    call CALLBACK on the current function.
    This function is global so that plugins can use it.  */
 void
-do_per_function_toporder (void (*callback) (function *, void *data), void *data)
+do_per_function_toporder (void (*callback) (function *, void *data, void *flag),
+			  void *data, void *flag)
 {
   int i;
 
   if (current_function_decl)
-    callback (cfun, data);
+    callback (cfun, data, flag);
   else
     {
       cgraph_node_hook_list *hook;
@@ -1725,7 +1726,7 @@ do_per_function_toporder (void (*callback) (function *, void *data), void *data)
 	    {
 	      struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
 	      push_cfun (fn);
-	      callback (fn, data);
+	      callback (fn, data, flag);
 	      pop_cfun ();
 	    }
 	}
@@ -2276,8 +2277,18 @@ override_gate_status (opt_pass *pass, tree func, bool gate_status)
 /* Execute PASS. */
 
 bool
-execute_one_pass (opt_pass *pass)
+execute_one_pass (opt_pass *pass, bool startwith_p)
 {
+  /* For skipping passes until startwith pass */
+  if (cfun && startwith_p && cfun->startwith)
+    {
+      if (!strcmp (pass->name, cfun->pass_startwith->name)
+	  || !strcmp (pass->name, "*clean_state"))
+	cfun->startwith = false;
+      else
+	return true;
+    }
+
   unsigned int todo_after = 0;
 
   bool gate_status;
@@ -2417,7 +2428,7 @@ execute_one_pass (opt_pass *pass)
 }
 
 static void
-execute_pass_list_1 (opt_pass *pass)
+execute_pass_list_1 (opt_pass *pass, bool startwith_p)
 {
   do
     {
@@ -2426,18 +2437,23 @@ execute_pass_list_1 (opt_pass *pass)
 
       if (cfun == NULL)
 	return;
-      if (execute_one_pass (pass) && pass->sub)
-        execute_pass_list_1 (pass->sub);
+      if (execute_one_pass (pass, startwith_p) && pass->sub)
+	execute_pass_list_1 (pass->sub, startwith_p);
       pass = pass->next;
     }
   while (pass);
 }
 
 void
-execute_pass_list (function *fn, opt_pass *pass)
+execute_pass_list (function *fn, opt_pass *pass, bool *startwith_p)
 {
   gcc_assert (fn == cfun);
-  execute_pass_list_1 (pass);
+
+  if (startwith_p)
+    execute_pass_list_1 (pass, *startwith_p);
+  else
+    execute_pass_list_1 (pass, false);
+
   if (cfun && fn->cfg)
     {
       free_dominance_info (CDI_DOMINATORS);
@@ -2767,19 +2783,22 @@ ipa_read_optimization_summaries (void)
 void
 execute_ipa_pass_list (opt_pass *pass)
 {
+  bool startwith_p = false;
   do
     {
       gcc_assert (!current_function_decl);
       gcc_assert (!cfun);
       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
-      if (execute_one_pass (pass) && pass->sub)
+      if (!strcmp (pass->name, "opt_local_passes"))
+	startwith_p = true;
+      if (execute_one_pass (pass, startwith_p) && pass->sub)
 	{
 	  if (pass->sub->type == GIMPLE_PASS)
 	    {
 	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL);
-	      do_per_function_toporder ((void (*)(function *, void *))
+	      do_per_function_toporder ((void (*)(function *, void *, void *))
 					  execute_pass_list,
-					pass->sub);
+					pass->sub, &startwith_p);
 	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL);
 	    }
 	  else if (pass->sub->type == SIMPLE_IPA_PASS
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 57c8410..7fe994e 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -170,6 +170,7 @@ static edge find_taken_edge_computed_goto (basic_block, tree);
 static edge find_taken_edge_cond_expr (basic_block, tree);
 static edge find_taken_edge_switch_expr (gswitch *, basic_block, tree);
 static tree find_case_label_for_value (gswitch *, tree);
+static void lower_phi_internal_fn ();
 
 void
 init_empty_tree_cfg_for_function (struct function *fn)
@@ -244,6 +245,7 @@ build_gimple_cfg (gimple_seq seq)
   discriminator_per_locus = new hash_table<locus_discrim_hasher> (13);
   make_edges ();
   assign_discriminators ();
+  lower_phi_internal_fn ();
   cleanup_dead_labels ();
   delete discriminator_per_locus;
   discriminator_per_locus = NULL;
@@ -345,6 +347,50 @@ replace_loop_annotate (void)
     }
 }
 
+/* Lower internal PHI function from GIMPLE FE.  */
+
+static void
+lower_phi_internal_fn ()
+{
+  basic_block bb, pred = NULL;
+  gimple_stmt_iterator gsi;
+  tree lhs;
+  gphi *phi_node;
+  gimple *stmt;
+
+  /* After edge creation, handle __PHI function from GIMPLE FE.  */
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	{
+	  stmt = gsi_stmt (gsi);
+	  if (gimple_code (stmt) != GIMPLE_CALL)
+	    continue;
+
+	  if (gimple_call_internal_p (stmt) &&
+	      gimple_call_internal_fn (stmt) == IFN_PHI)
+	    {
+	      gsi_remove (&gsi, true);
+	      unsigned int i;
+	      lhs = gimple_call_lhs (stmt);
+	      phi_node = create_phi_node (lhs, bb);
+
+	      /* Add arguments to the PHI node.  */
+	      for (i = 0; i < gimple_call_num_args (stmt); ++i)
+		{
+		  tree arg = gimple_call_arg (stmt, i);
+		  if (TREE_CODE (arg) == LABEL_DECL)
+		    pred = label_to_block (arg);
+		  else
+		    {
+		      edge e = find_edge (pred, bb);
+		      add_phi_arg (phi_node, arg, e, UNKNOWN_LOCATION);
+		    }
+		}
+	    }
+	}
+    }
+}
 
 static unsigned int
 execute_build_cfg (void)
@@ -3340,6 +3386,11 @@ verify_gimple_call (gcall *stmt)
 	  debug_generic_stmt (fn);
 	  return true;
 	}
+      /* FIXME : for passing label as arg in internal fn PHI from GIMPLE FE*/
+      else if (gimple_call_internal_fn (stmt) == IFN_PHI)
+	{
+	  return false;
+	}
     }
   else
     {
@@ -7504,7 +7555,8 @@ dump_function_to_file (tree fndecl, FILE *file, int flags)
     }
 
   current_function_decl = fndecl;
-  fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
+  print_generic_expr (file, TREE_TYPE (TREE_TYPE (fndecl)), dump_flags);
+  fprintf (file, "\n%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
 
   arg = DECL_ARGUMENTS (fndecl);
   while (arg)
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index ceafa68..ba3dc05 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -1379,12 +1379,19 @@ rewrite_add_phi_arguments (basic_block bb)
       for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi);
 	   gsi_next (&gsi))
 	{
-	  tree currdef, res;
+	  tree currdef, res, argvar;
 	  location_t loc;
 
 	  phi = gsi.phi ();
 	  res = gimple_phi_result (phi);
-	  currdef = get_reaching_def (SSA_NAME_VAR (res));
+	  /* If we have pre-existing PHI its args may be different
+	     vars than existing vars */
+	  argvar = gimple_phi_arg_def (phi, e->dest_idx);
+	  if (argvar && TREE_CODE (argvar) == SSA_NAME)
+	    continue;
+	  if (!argvar)
+	    argvar = SSA_NAME_VAR (res);
+	  currdef = get_reaching_def (argvar);
 	  /* Virtual operand PHI args do not need a location.  */
 	  if (virtual_operand_p (res))
 	    loc = UNKNOWN_LOCATION;
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index c0059de..213070b 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -617,8 +617,9 @@ extern gimple_opt_pass *make_pass_lower_vaarg (gcc::context *ctxt);
 /* Current optimization pass.  */
 extern opt_pass *current_pass;
 
-extern bool execute_one_pass (opt_pass *);
-extern void execute_pass_list (function *, opt_pass *);
+extern bool execute_one_pass (opt_pass *, bool startwith_p = false);
+extern void execute_pass_list (function *, opt_pass *,
+			       bool *startwith_p = NULL);
 extern void execute_ipa_pass_list (opt_pass *);
 extern void execute_ipa_summary_passes (ipa_opt_pass_d *);
 extern void execute_all_ipa_transforms (void);
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 734ecda..aa53bd2 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -260,7 +260,7 @@ dump_decl_name (pretty_printer *pp, tree node, int flags)
   if ((flags & TDF_UID) || DECL_NAME (node) == NULL_TREE)
     {
       if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1)
-	pp_printf (pp, "L.%d", (int) LABEL_DECL_UID (node));
+	pp_printf (pp, "L_%d", (int) LABEL_DECL_UID (node));
       else if (TREE_CODE (node) == DEBUG_EXPR_DECL)
 	{
 	  if (flags & TDF_NOUID)
@@ -274,7 +274,7 @@ dump_decl_name (pretty_printer *pp, tree node, int flags)
 	  if (flags & TDF_NOUID)
 	    pp_printf (pp, "%c.xxxx", c);
 	  else
-	    pp_printf (pp, "%c.%u", c, DECL_UID (node));
+	    pp_printf (pp, "%c_%u", c, DECL_UID (node));
 	}
     }
   if ((flags & TDF_ALIAS) && DECL_PT_UID (node) != DECL_UID (node))
@@ -3965,14 +3965,14 @@ dump_function_header (FILE *dump_file, tree fdecl, int flags)
   else
     aname = "<unset-asm-name>";
 
-  fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d",
+  fprintf (dump_file, "\n/* Function %s (%s, funcdef_no=%d",
 	   dname, aname, fun->funcdef_no);
   if (!(flags & TDF_NOUID))
     fprintf (dump_file, ", decl_uid=%d", DECL_UID (fdecl));
   if (node)
     {
       fprintf (dump_file, ", cgraph_uid=%d", node->uid);
-      fprintf (dump_file, ", symbol_order=%d)%s\n\n", node->order,
+      fprintf (dump_file, ", symbol_order=%d)%s", node->order,
                node->frequency == NODE_FREQUENCY_HOT
                ? " (hot)"
                : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
@@ -3982,7 +3982,8 @@ dump_function_header (FILE *dump_file, tree fdecl, int flags)
                : "");
     }
   else
-    fprintf (dump_file, ")\n\n");
+    fprintf (dump_file, ")");
+  fprintf (dump_file, "*/\n\n");
 }
 
 /* Dump double_int D to pretty_printer PP.  UNS is true
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 91a8f97..8b8863b 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -255,7 +255,8 @@ flush_ssaname_freelist (void)
    used without a preceding definition).  */
 
 tree
-make_ssa_name_fn (struct function *fn, tree var, gimple *stmt)
+make_ssa_name_fn (struct function *fn, tree var, gimple *stmt,
+		  unsigned int version)
 {
   tree t;
   use_operand_p imm;
@@ -265,8 +266,19 @@ make_ssa_name_fn (struct function *fn, tree var, gimple *stmt)
 	      || TREE_CODE (var) == RESULT_DECL
 	      || (TYPE_P (var) && is_gimple_reg_type (var)));
 
+  /* parsing ssa names with versions.	*/
+  if (version != 0)
+    {
+      t = make_node (SSA_NAME);
+      SSA_NAME_VERSION (t) = version;
+      if (version >= SSANAMES (fn)->length ())
+	vec_safe_grow_cleared (SSANAMES (fn), version + 1);
+      gcc_assert ((*SSANAMES (fn))[version] == NULL);
+      (*SSANAMES (fn))[version] = t;
+      ssa_name_nodes_created++;
+    }
   /* If our free list has an element, then use it.  */
-  if (!vec_safe_is_empty (FREE_SSANAMES (fn)))
+  else if (!vec_safe_is_empty (FREE_SSANAMES (fn)))
     {
       t = FREE_SSANAMES (fn)->pop ();
       ssa_name_nodes_reused++;
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index 8e66ce6..3ce9327 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -74,7 +74,8 @@ extern bool ssa_name_has_boolean_range (tree);
 extern void init_ssanames (struct function *, int);
 extern void fini_ssanames (struct function *);
 extern void ssanames_print_statistics (void);
-extern tree make_ssa_name_fn (struct function *, tree, gimple *);
+extern tree make_ssa_name_fn (struct function *, tree, gimple *,
+			      unsigned int version = 0);
 extern void release_ssa_name_fn (struct function *, tree);
 extern bool get_ptr_info_alignment (struct ptr_info_def *, unsigned int *,
 				    unsigned int *);

[-- Attachment #4: testcases.patch --]
[-- Type: text/x-diff, Size: 5193 bytes --]

diff --git a/gcc/testsuite/gcc.dg/gimplefe-1.c b/gcc/testsuite/gcc.dg/gimplefe-1.c
new file mode 100644
index 0000000..0786d47
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int i;
+void __GIMPLE () foo()
+{
+  i = 1;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-10.c b/gcc/testsuite/gcc.dg/gimplefe-10.c
new file mode 100644
index 0000000..7f63c58
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-10.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE() bar(int a, int b, int c)
+{
+  a = 1;
+  b = a + 1;
+  c = b * 4;
+  return b;
+}
+
+void __GIMPLE() foo()
+{
+  int a;
+  int b;
+  int c;
+  b = bar(a, b, c);
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-11.c b/gcc/testsuite/gcc.dg/gimplefe-11.c
new file mode 100644
index 0000000..e1483f4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-11.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE() bar(int a, int b, int c)
+{
+  a = 1;
+  b = a + 1;
+  c = b * 4;
+  return;
+}
+
+void __GIMPLE() foo()
+{
+  int a;
+  int b;
+  int c;
+  bar(a, b, c);
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-12.c b/gcc/testsuite/gcc.dg/gimplefe-12.c
new file mode 100644
index 0000000..cbaf8a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-12.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE (startwith ("tree-ccp1")) foo ()
+{
+  int a;
+  int b;
+  a = b + 2;
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-13.c b/gcc/testsuite/gcc.dg/gimplefe-13.c
new file mode 100644
index 0000000..c0da9fa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-13.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE (startwith ("tree-dse1")) foo ()
+{
+  int a;
+
+bb_2:
+  if (a > 4)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_3:
+  a_2 = 10;
+  goto bb_5;
+
+bb_4:
+  a_3 = 20;
+
+bb_5:
+  a_1 = __PHI (bb_3: a_2, bb_4: a_3);
+  a_4 = a_1 + 4;
+
+return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-2.c b/gcc/testsuite/gcc.dg/gimplefe-2.c
new file mode 100644
index 0000000..e3a23cf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile }*/
+/* { dg-options "-fgimple" } */
+
+int a;
+void __GIMPLE () foo ()
+{
+  int b;
+  b = a;
+  b = b + 1;
+  a = b;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-3.c b/gcc/testsuite/gcc.dg/gimplefe-3.c
new file mode 100644
index 0000000..595365e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-3.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int *b;
+  *b = 1;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-4.c b/gcc/testsuite/gcc.dg/gimplefe-4.c
new file mode 100644
index 0000000..3600c7c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-4.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int a;
+  char b;
+  a = (int) b;
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-5.c b/gcc/testsuite/gcc.dg/gimplefe-5.c
new file mode 100644
index 0000000..1dab4af
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-5.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int a;
+void __GIMPLE () foo ()
+{
+  int b;
+  int c;
+
+bb_2:
+  b = a;
+  if (b > 3)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_3:
+  b = c + 4;
+  goto bb_5;
+
+bb_4:
+  b = b + 1;
+  goto bb_5;
+
+bb_5:
+  a = b;
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-6.c b/gcc/testsuite/gcc.dg/gimplefe-6.c
new file mode 100644
index 0000000..242e08f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-6.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int a;
+  int b;
+  int c;
+  int d;
+
+bb_2:
+  a = ~b;
+  b = a << c;
+  c = a & b;
+  d = b | c;
+
+bb_3:
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-7.c b/gcc/testsuite/gcc.dg/gimplefe-7.c
new file mode 100644
index 0000000..6125541
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-7.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int a;
+
+bb_2:
+  if (a > 4)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_3:
+  a_2 = 10;
+  goto bb_5;
+
+bb_4:
+  a_3 = 20;
+
+bb_5:
+  a_1 = __PHI (bb_3: a_2, bb_4: a_3);
+  a_4 = a_1 + 4;
+
+return;
+}
+
diff --git a/gcc/testsuite/gcc.dg/gimplefe-8.c b/gcc/testsuite/gcc.dg/gimplefe-8.c
new file mode 100644
index 0000000..4936bec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-8.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE () foo ()
+{
+  int a;
+  int b;
+
+bb_2:
+  b = a_1(D) + 1;
+bb_3:
+  return b;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-9.c b/gcc/testsuite/gcc.dg/gimplefe-9.c
new file mode 100644
index 0000000..a24be273
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-9.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE() bar()
+{
+  int a;
+  a = a + 1;
+  return a;
+}
+
+void __GIMPLE() foo()
+{
+  int b;
+  b = bar();
+}


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-26  3:10       ` Prasad Ghangal
@ 2016-08-26  8:58         ` Richard Biener
  2016-09-09 10:58           ` Prasad Ghangal
  2016-10-05 23:28         ` Joseph Myers
  1 sibling, 1 reply; 24+ messages in thread
From: Richard Biener @ 2016-08-26  8:58 UTC (permalink / raw)
  To: Prasad Ghangal; +Cc: Trevor Saunders, GCC Patches, Joseph S. Myers, polacek

On Fri, Aug 26, 2016 at 5:08 AM, Prasad Ghangal
<prasad.ghangal@gmail.com> wrote:
> On 24 August 2016 at 15:32, Richard Biener <richard.guenther@gmail.com> wrote:
>> On Mon, Aug 22, 2016 at 8:40 PM, Prasad Ghangal
>> <prasad.ghangal@gmail.com> wrote:
>>> On 22 August 2016 at 16:55, Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
>>>> On Sun, Aug 21, 2016 at 10:35:17PM +0530, Prasad Ghangal wrote:
>>>>> Hi all,
>>>>>
>>>>> As a part of my gsoc project. I have completed the following tasks:
>>>>>
>>>>> * Parsed gimple-expression
>>>>> * Parsed gimple-labels
>>>>> * Parsed local declaration
>>>>> * Parsed gimple-goto statement
>>>>> * Parsed gimple-if-else statement
>>>>> * Parsed gimple-switch statement
>>>>> * Parsed gimple-return statement
>>>>> * Parsed gimple-PHI function
>>>>> * Parsed gimple ssa-names along with default def
>>>>> * Parsed gimple-call
>>>>>
>>>>> * Hacked pass manager to add support for startwith (pass-name) to skip
>>>>> early opt passes
>>>>> * Modified gimple dump for making it parsable
>>>>>
>>>>> I am willing to continue work on the project, some TODOs for the projects are:
>>>>>
>>>>> * Error handling
>>>>> * Parse more gimple syntax
>>>>> * Add startwith support for IPA passes
>>>>>
>>>>> The complete code of gimple fe project can be found at
>>>>> https://github.com/PrasadG193/gcc_gimple_fe
>>>>>
>>>>>
>>>>> PFA patch for complete project (rebased for latest trunk revision).
>>>>> I have successfully bootstrapped and tested on x86_64-pc-linux-gnu.
>>>>> Some testcases failed due to modified gimple dump as expected.
>>>>>
>>>>>
>>>>> Thanks,
>>>>> Prasad
>>>>
>>>> only some rather minor comments
>>>>
>>>>
>>>> +++ b/gcc/c/c-parser.c
>>>> @@ -59,6 +59,18 @@ along with GCC; see the file COPYING3.  If not see
>>>>  #include "gimple-expr.h"
>>>>  #include "context.h"
>>>>  #include "gcc-rich-location.h"
>>>> +#include "tree-vrp.h"
>>>>
>>>> given that you need these headers it might be better to put most of the
>>>> gimple parsing in its own file so only what actually needs to know about
>>>> this part of the compiler does now about it.
>>>>
>>>> +void
>>>> +c_parser_parse_gimple_body (c_parser *parser)
>>>> +{
>>>> +  bool return_p = false;
>>>> +  gimple_seq seq;
>>>> +  gimple_seq body;
>>>> +  tree stmt = push_stmt_list ();
>>>>
>>>> it would be nice to move the declarations down to their first use.
>>>>
>>>> +      gimple *ret;
>>>> +      ret = gimple_build_return (NULL);
>>>>
>>>> there's no reason for a separate declaration and assignment ;)
>>>>
>>>> +  tree block = NULL;
>>>> +  block = pop_scope ();
>>>>
>>>> same here, and a number of other places.
>>>>
>>>> +c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
>>>> +{
>>>> +  bool return_p = false;
>>>> +
>>>> +  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
>>>> +      return return_p;
>>>>
>>>> return false would work fine.
>>>>
>>>> +
>>>> +  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
>>>> +    {
>>>> +      c_parser_consume_token (parser);
>>>> +      goto out;
>>>>
>>>> I don't see the need for the gotos, there's no cleanup in this function.
>>>>
>>>> +  /* gimple PHI expression.  */
>>>> +  if (c_parser_next_token_is_keyword (parser, RID_PHI))
>>>> +    {
>>>> +      c_parser_consume_token (parser);
>>>> +
>>>> +      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
>>>> +       {
>>>> +         return;
>>>> +       }
>>>> +
>>>> +      gcall *call_stmt;
>>>> +      tree arg = NULL_TREE;
>>>> +      vec<tree> vargs = vNULL;
>>>>
>>>> I think you can use auto_vec here, as is I think this leaks the vectors
>>>> storage.
>>>>
>>>> +c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)
>>>>
>>>> you can skip the explicit 'enum' keyword.
>>>>
>>>> +  struct {
>>>> +    /* The expression at this stack level.  */
>>>> +    struct c_expr expr;
>>>>
>>>> similar with struct here.
>>>>
>>>> +    /* The precedence of the operator on its left, PREC_NONE at the
>>>> +       bottom of the stack.  */
>>>> +    enum c_parser_prec prec;
>>>> +    /* The operation on its left.  */
>>>> +    enum tree_code op;
>>>> +    /* The source location of this operation.  */
>>>> +    location_t loc;
>>>> +  } stack[2];
>>>> +  int sp;
>>>> +  /* Location of the binary operator.  */
>>>> +  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
>>>> +#define POP                                                                  \
>>>>
>>>> it seems like it would be nicer to name the type, and then make this a
>>>> function.
>>>>
>>>> +                                       RO_UNARY_STAR);
>>>> +       ret.src_range.m_start = op_loc;
>>>> +       ret.src_range.m_finish = finish;
>>>> +       return ret;
>>>> +      }
>>>> +    case CPP_PLUS:
>>>> +      if (!c_dialect_objc () && !in_system_header_at (input_location))
>>>> +       warning_at (op_loc,
>>>> +                   OPT_Wtraditional,
>>>> +                   "traditional C rejects the unary plus operator");
>>>>
>>>> does it really make sense to warn about C issues when compiling gimple?
>>>>
>>>> +c_parser_parse_ssa_names (c_parser *parser)
>>>> +{
>>>> +  tree id = NULL_TREE;
>>>> +  c_expr ret;
>>>> +  char *var_name, *var_version, *token;
>>>> +  ret.original_code = ERROR_MARK;
>>>> +  ret.original_type = NULL;
>>>> +
>>>> +  /* ssa token string.  */
>>>> +  const char *ssa_token = NULL;
>>>> +  ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
>>>> +  token = new char [strlen (ssa_token)];
>>>>
>>>> I'm not sure I see why you need this copy, and getting rid of it would
>>>> mean you don't need to free it.
>>>>
>>>> +  strcpy (token, ssa_token);
>>>> +
>>>> +  /* seperate var name and version.  */
>>>> +  var_version = strrchr (token, '_');
>>>> +  if (var_version)
>>>> +    {
>>>> +      var_name = new char[var_version - token + 1];
>>>>
>>>> you should free this when done with it.
>>>>
>>>> +c_parser_gimple_postfix_expression (c_parser *parser)
>>>> +{
>>>> +  struct c_expr expr;
>>>> +  location_t loc = c_parser_peek_token (parser)->location;;
>>>>
>>>> extra ;
>>>>
>>>> +    case CPP_OBJC_STRING:
>>>> +      gcc_assert (c_dialect_objc ());
>>>> +      expr.value
>>>> +       = objc_build_string_object (c_parser_peek_token (parser)->value);
>>>> +      set_c_expr_source_range (&expr, tok_range);
>>>> +      c_parser_consume_token (parser);
>>>> +      break;
>>>>
>>>> is there a reason to support objc stuff in gimple?
>>>>
>>>> +c_parser_gimple_expr_list (c_parser *parser, bool convert_p,
>>>> +                   vec<tree, va_gc> **p_orig_types,
>>>> +                   location_t *sizeof_arg_loc, tree *sizeof_arg,
>>>> +                   vec<location_t> *locations,
>>>> +                   unsigned int *literal_zero_mask)
>>>> +{
>>>> +  vec<tree, va_gc> *ret;
>>>> +  vec<tree, va_gc> *orig_types;
>>>> +  struct c_expr expr;
>>>> +  location_t loc = c_parser_peek_token (parser)->location;
>>>> +  location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION;
>>>> +  unsigned int idx = 0;
>>>> +
>>>> +  ret = make_tree_vector ();
>>>> +  if (p_orig_types == NULL)
>>>> +    orig_types = NULL;
>>>> +  else
>>>> +    orig_types = make_tree_vector ();
>>>> +
>>>> +  if (sizeof_arg != NULL
>>>> +      && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
>>>> +    cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
>>>> +  if (literal_zero_mask)
>>>> +    c_parser_check_literal_zero (parser, literal_zero_mask, 0);
>>>> +  expr = c_parser_gimple_unary_expression (parser);
>>>> +  if (convert_p)
>>>> +    expr = convert_lvalue_to_rvalue (loc, expr, true, true);
>>>> +  ret->quick_push (expr.value);
>>>>
>>>>  That kind of relies on the details of make_tree_vector (), so it seems
>>>>  somewhat safer to use vec_safe_push.
>>>>
>>>> +  if (orig_types)
>>>> +    orig_types->quick_push (expr.original_type);
>>>>
>>>> same
>>>>
>>>> +c_parser_gimple_declaration (c_parser *parser)
>>>> +{
>>>> +  struct c_declspecs *specs;
>>>> +  struct c_declarator *declarator;
>>>> +  specs = build_null_declspecs ();
>>>> +  c_parser_declspecs (parser, specs, true, true, true,
>>>> +                     true, true, cla_nonabstract_decl);
>>>> +  finish_declspecs (specs);
>>>> +  bool auto_type_p = specs->typespec_word == cts_auto_type;
>>>>
>>>> is it useful to support auto here in gimple?
>>>>
>>>> +c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
>>>> +{
>>>> +  c_expr cond_expr;
>>>> +  tree case_label, label;
>>>> +  vec<tree> labels = vNULL;
>>>>
>>>> auto_vec?
>>>>
>>>> +static void
>>>> +c_finish_gimple_return (location_t loc, tree retval)
>>>> +{
>>>> +  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
>>>> +
>>>> +  /* Use the expansion point to handle cases such as returning NULL
>>>> +     in a function returning void.  */
>>>> +  source_location xloc = expansion_point_location_if_in_system_header (loc);
>>>> +
>>>> +  if (TREE_THIS_VOLATILE (current_function_decl))
>>>> +    warning_at (xloc, 0,
>>>> +               "function declared %<noreturn%> has a %<return%> statement");
>>>> +
>>>> +  if (!retval)
>>>> +    {
>>>> +      current_function_returns_null = 1;
>>>> +      if ((warn_return_type || flag_isoc99)
>>>>
>>>> I'm not sure what to do about warnings, but checking the language we are
>>>> compiling as seems kind of wrong when we're compiling gimple?
>>>>
>>>> @@ -228,6 +228,12 @@ struct GTY(()) function {
>>>>    /* GIMPLE body for this function.  */
>>>>    gimple_seq gimple_body;
>>>>
>>>> +  /* GIMPLEFE pass to start with */
>>>> +  opt_pass *pass_startwith = NULL;
>>>>
>>>> I'm guessing you've only compiled in C++11 mode? because I'm pretty sure
>>>> you are using a C++11 feature here (the default member value you
>>>> assign).
>>>>
>>>> Thanks!
>>>>
>>>> Trev
>>>>
>>>
>>> Hi Trevor,
>>>
>>> Thanks for your feedback. I had missed removing some unwanted code
>>> while code cleanup. I have updated the patch.
>>> I am not sure if we should move all gimple parsing related functions
>>> to the new file (?)
>>
>> I think it might be good to make the parts of the C parser you use more
>> obvious (you'd need to export functions like c_parser_next_token_is).
>>
>> The easiest way to "force" that is to put all of the gimple parsing into
>> a separate file.
>>
>> Note I am not so much concerned about this at the moment, the parts to
>> improve would be avoiding more of the C-isms like convert_lvalue_to_rvalue,
>> handling of SIZEOF_EXPR and other stuff that looks redundant (you've
>> probably copied this from the C parsing routines and refactored it).
>> Also the GIMPLE parser shouldn't do any warnings (just spotted
>> a call to warn_for_memset).
>>
> PFA updated patch (successfully bootstrapped and tested on
> x86_64-pc-linux-gnu). I have removed unnecessary code. On side I am
> also trying to move gimple parser related functions to new file. But
> for it we also have to move structs like c_token, c_parser. Won't it
> disturb the c-parser code structure ?

Yeah, as I said it would be nice but it might be quite some work.  I'd move
such stuff into a new c-parser.h header that can be included by the
gimple parser file.  Note existing exports from c-parser are mostly
declared in c-tree.h but I think having a c-parser.h for all the new exported
stuff is cleaner.

I'd wish one of the C frontend maintainers would have a quick look at the
overall structure and guide us here - they are the ones that have to
approve the patch in the end.  (CCed)

Thanks,
Richard.

>
> Thanks,
> Prasad
>
>> Thanks,
>> Richard.
>>
>>> I am not getting what did you mean by C++11 mode (I am not explicitly
>>> giving any option while configure or make). I also have successfully
>>> bootstrapped and tested the project on another system. Is there any
>>> way to check that ?
>>>
>>>
>>> Thanks,
>>> Prasad

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-26  8:58         ` Richard Biener
@ 2016-09-09 10:58           ` Prasad Ghangal
  2016-09-14 13:28             ` Richard Biener
  0 siblings, 1 reply; 24+ messages in thread
From: Prasad Ghangal @ 2016-09-09 10:58 UTC (permalink / raw)
  To: Richard Biener; +Cc: Trevor Saunders, GCC Patches, Joseph S. Myers, polacek

On 26 August 2016 at 14:28, Richard Biener <richard.guenther@gmail.com> wrote:
> On Fri, Aug 26, 2016 at 5:08 AM, Prasad Ghangal
> <prasad.ghangal@gmail.com> wrote:
>> On 24 August 2016 at 15:32, Richard Biener <richard.guenther@gmail.com> wrote:
>>> On Mon, Aug 22, 2016 at 8:40 PM, Prasad Ghangal
>>> <prasad.ghangal@gmail.com> wrote:
>>>> On 22 August 2016 at 16:55, Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
>>>>> On Sun, Aug 21, 2016 at 10:35:17PM +0530, Prasad Ghangal wrote:
>>>>>> Hi all,
>>>>>>
>>>>>> As a part of my gsoc project. I have completed the following tasks:
>>>>>>
>>>>>> * Parsed gimple-expression
>>>>>> * Parsed gimple-labels
>>>>>> * Parsed local declaration
>>>>>> * Parsed gimple-goto statement
>>>>>> * Parsed gimple-if-else statement
>>>>>> * Parsed gimple-switch statement
>>>>>> * Parsed gimple-return statement
>>>>>> * Parsed gimple-PHI function
>>>>>> * Parsed gimple ssa-names along with default def
>>>>>> * Parsed gimple-call
>>>>>>
>>>>>> * Hacked pass manager to add support for startwith (pass-name) to skip
>>>>>> early opt passes
>>>>>> * Modified gimple dump for making it parsable
>>>>>>
>>>>>> I am willing to continue work on the project, some TODOs for the projects are:
>>>>>>
>>>>>> * Error handling
>>>>>> * Parse more gimple syntax
>>>>>> * Add startwith support for IPA passes
>>>>>>
>>>>>> The complete code of gimple fe project can be found at
>>>>>> https://github.com/PrasadG193/gcc_gimple_fe
>>>>>>
>>>>>>
>>>>>> PFA patch for complete project (rebased for latest trunk revision).
>>>>>> I have successfully bootstrapped and tested on x86_64-pc-linux-gnu.
>>>>>> Some testcases failed due to modified gimple dump as expected.
>>>>>>
>>>>>>
>>>>>> Thanks,
>>>>>> Prasad
>>>>>
>>>>> only some rather minor comments
>>>>>
>>>>>
>>>>> +++ b/gcc/c/c-parser.c
>>>>> @@ -59,6 +59,18 @@ along with GCC; see the file COPYING3.  If not see
>>>>>  #include "gimple-expr.h"
>>>>>  #include "context.h"
>>>>>  #include "gcc-rich-location.h"
>>>>> +#include "tree-vrp.h"
>>>>>
>>>>> given that you need these headers it might be better to put most of the
>>>>> gimple parsing in its own file so only what actually needs to know about
>>>>> this part of the compiler does now about it.
>>>>>
>>>>> +void
>>>>> +c_parser_parse_gimple_body (c_parser *parser)
>>>>> +{
>>>>> +  bool return_p = false;
>>>>> +  gimple_seq seq;
>>>>> +  gimple_seq body;
>>>>> +  tree stmt = push_stmt_list ();
>>>>>
>>>>> it would be nice to move the declarations down to their first use.
>>>>>
>>>>> +      gimple *ret;
>>>>> +      ret = gimple_build_return (NULL);
>>>>>
>>>>> there's no reason for a separate declaration and assignment ;)
>>>>>
>>>>> +  tree block = NULL;
>>>>> +  block = pop_scope ();
>>>>>
>>>>> same here, and a number of other places.
>>>>>
>>>>> +c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
>>>>> +{
>>>>> +  bool return_p = false;
>>>>> +
>>>>> +  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
>>>>> +      return return_p;
>>>>>
>>>>> return false would work fine.
>>>>>
>>>>> +
>>>>> +  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
>>>>> +    {
>>>>> +      c_parser_consume_token (parser);
>>>>> +      goto out;
>>>>>
>>>>> I don't see the need for the gotos, there's no cleanup in this function.
>>>>>
>>>>> +  /* gimple PHI expression.  */
>>>>> +  if (c_parser_next_token_is_keyword (parser, RID_PHI))
>>>>> +    {
>>>>> +      c_parser_consume_token (parser);
>>>>> +
>>>>> +      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
>>>>> +       {
>>>>> +         return;
>>>>> +       }
>>>>> +
>>>>> +      gcall *call_stmt;
>>>>> +      tree arg = NULL_TREE;
>>>>> +      vec<tree> vargs = vNULL;
>>>>>
>>>>> I think you can use auto_vec here, as is I think this leaks the vectors
>>>>> storage.
>>>>>
>>>>> +c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)
>>>>>
>>>>> you can skip the explicit 'enum' keyword.
>>>>>
>>>>> +  struct {
>>>>> +    /* The expression at this stack level.  */
>>>>> +    struct c_expr expr;
>>>>>
>>>>> similar with struct here.
>>>>>
>>>>> +    /* The precedence of the operator on its left, PREC_NONE at the
>>>>> +       bottom of the stack.  */
>>>>> +    enum c_parser_prec prec;
>>>>> +    /* The operation on its left.  */
>>>>> +    enum tree_code op;
>>>>> +    /* The source location of this operation.  */
>>>>> +    location_t loc;
>>>>> +  } stack[2];
>>>>> +  int sp;
>>>>> +  /* Location of the binary operator.  */
>>>>> +  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
>>>>> +#define POP                                                                  \
>>>>>
>>>>> it seems like it would be nicer to name the type, and then make this a
>>>>> function.
>>>>>
>>>>> +                                       RO_UNARY_STAR);
>>>>> +       ret.src_range.m_start = op_loc;
>>>>> +       ret.src_range.m_finish = finish;
>>>>> +       return ret;
>>>>> +      }
>>>>> +    case CPP_PLUS:
>>>>> +      if (!c_dialect_objc () && !in_system_header_at (input_location))
>>>>> +       warning_at (op_loc,
>>>>> +                   OPT_Wtraditional,
>>>>> +                   "traditional C rejects the unary plus operator");
>>>>>
>>>>> does it really make sense to warn about C issues when compiling gimple?
>>>>>
>>>>> +c_parser_parse_ssa_names (c_parser *parser)
>>>>> +{
>>>>> +  tree id = NULL_TREE;
>>>>> +  c_expr ret;
>>>>> +  char *var_name, *var_version, *token;
>>>>> +  ret.original_code = ERROR_MARK;
>>>>> +  ret.original_type = NULL;
>>>>> +
>>>>> +  /* ssa token string.  */
>>>>> +  const char *ssa_token = NULL;
>>>>> +  ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
>>>>> +  token = new char [strlen (ssa_token)];
>>>>>
>>>>> I'm not sure I see why you need this copy, and getting rid of it would
>>>>> mean you don't need to free it.
>>>>>
>>>>> +  strcpy (token, ssa_token);
>>>>> +
>>>>> +  /* seperate var name and version.  */
>>>>> +  var_version = strrchr (token, '_');
>>>>> +  if (var_version)
>>>>> +    {
>>>>> +      var_name = new char[var_version - token + 1];
>>>>>
>>>>> you should free this when done with it.
>>>>>
>>>>> +c_parser_gimple_postfix_expression (c_parser *parser)
>>>>> +{
>>>>> +  struct c_expr expr;
>>>>> +  location_t loc = c_parser_peek_token (parser)->location;;
>>>>>
>>>>> extra ;
>>>>>
>>>>> +    case CPP_OBJC_STRING:
>>>>> +      gcc_assert (c_dialect_objc ());
>>>>> +      expr.value
>>>>> +       = objc_build_string_object (c_parser_peek_token (parser)->value);
>>>>> +      set_c_expr_source_range (&expr, tok_range);
>>>>> +      c_parser_consume_token (parser);
>>>>> +      break;
>>>>>
>>>>> is there a reason to support objc stuff in gimple?
>>>>>
>>>>> +c_parser_gimple_expr_list (c_parser *parser, bool convert_p,
>>>>> +                   vec<tree, va_gc> **p_orig_types,
>>>>> +                   location_t *sizeof_arg_loc, tree *sizeof_arg,
>>>>> +                   vec<location_t> *locations,
>>>>> +                   unsigned int *literal_zero_mask)
>>>>> +{
>>>>> +  vec<tree, va_gc> *ret;
>>>>> +  vec<tree, va_gc> *orig_types;
>>>>> +  struct c_expr expr;
>>>>> +  location_t loc = c_parser_peek_token (parser)->location;
>>>>> +  location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION;
>>>>> +  unsigned int idx = 0;
>>>>> +
>>>>> +  ret = make_tree_vector ();
>>>>> +  if (p_orig_types == NULL)
>>>>> +    orig_types = NULL;
>>>>> +  else
>>>>> +    orig_types = make_tree_vector ();
>>>>> +
>>>>> +  if (sizeof_arg != NULL
>>>>> +      && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
>>>>> +    cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
>>>>> +  if (literal_zero_mask)
>>>>> +    c_parser_check_literal_zero (parser, literal_zero_mask, 0);
>>>>> +  expr = c_parser_gimple_unary_expression (parser);
>>>>> +  if (convert_p)
>>>>> +    expr = convert_lvalue_to_rvalue (loc, expr, true, true);
>>>>> +  ret->quick_push (expr.value);
>>>>>
>>>>>  That kind of relies on the details of make_tree_vector (), so it seems
>>>>>  somewhat safer to use vec_safe_push.
>>>>>
>>>>> +  if (orig_types)
>>>>> +    orig_types->quick_push (expr.original_type);
>>>>>
>>>>> same
>>>>>
>>>>> +c_parser_gimple_declaration (c_parser *parser)
>>>>> +{
>>>>> +  struct c_declspecs *specs;
>>>>> +  struct c_declarator *declarator;
>>>>> +  specs = build_null_declspecs ();
>>>>> +  c_parser_declspecs (parser, specs, true, true, true,
>>>>> +                     true, true, cla_nonabstract_decl);
>>>>> +  finish_declspecs (specs);
>>>>> +  bool auto_type_p = specs->typespec_word == cts_auto_type;
>>>>>
>>>>> is it useful to support auto here in gimple?
>>>>>
>>>>> +c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
>>>>> +{
>>>>> +  c_expr cond_expr;
>>>>> +  tree case_label, label;
>>>>> +  vec<tree> labels = vNULL;
>>>>>
>>>>> auto_vec?
>>>>>
>>>>> +static void
>>>>> +c_finish_gimple_return (location_t loc, tree retval)
>>>>> +{
>>>>> +  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
>>>>> +
>>>>> +  /* Use the expansion point to handle cases such as returning NULL
>>>>> +     in a function returning void.  */
>>>>> +  source_location xloc = expansion_point_location_if_in_system_header (loc);
>>>>> +
>>>>> +  if (TREE_THIS_VOLATILE (current_function_decl))
>>>>> +    warning_at (xloc, 0,
>>>>> +               "function declared %<noreturn%> has a %<return%> statement");
>>>>> +
>>>>> +  if (!retval)
>>>>> +    {
>>>>> +      current_function_returns_null = 1;
>>>>> +      if ((warn_return_type || flag_isoc99)
>>>>>
>>>>> I'm not sure what to do about warnings, but checking the language we are
>>>>> compiling as seems kind of wrong when we're compiling gimple?
>>>>>
>>>>> @@ -228,6 +228,12 @@ struct GTY(()) function {
>>>>>    /* GIMPLE body for this function.  */
>>>>>    gimple_seq gimple_body;
>>>>>
>>>>> +  /* GIMPLEFE pass to start with */
>>>>> +  opt_pass *pass_startwith = NULL;
>>>>>
>>>>> I'm guessing you've only compiled in C++11 mode? because I'm pretty sure
>>>>> you are using a C++11 feature here (the default member value you
>>>>> assign).
>>>>>
>>>>> Thanks!
>>>>>
>>>>> Trev
>>>>>
>>>>
>>>> Hi Trevor,
>>>>
>>>> Thanks for your feedback. I had missed removing some unwanted code
>>>> while code cleanup. I have updated the patch.
>>>> I am not sure if we should move all gimple parsing related functions
>>>> to the new file (?)
>>>
>>> I think it might be good to make the parts of the C parser you use more
>>> obvious (you'd need to export functions like c_parser_next_token_is).
>>>
>>> The easiest way to "force" that is to put all of the gimple parsing into
>>> a separate file.
>>>
>>> Note I am not so much concerned about this at the moment, the parts to
>>> improve would be avoiding more of the C-isms like convert_lvalue_to_rvalue,
>>> handling of SIZEOF_EXPR and other stuff that looks redundant (you've
>>> probably copied this from the C parsing routines and refactored it).
>>> Also the GIMPLE parser shouldn't do any warnings (just spotted
>>> a call to warn_for_memset).
>>>
>> PFA updated patch (successfully bootstrapped and tested on
>> x86_64-pc-linux-gnu). I have removed unnecessary code. On side I am
>> also trying to move gimple parser related functions to new file. But
>> for it we also have to move structs like c_token, c_parser. Won't it
>> disturb the c-parser code structure ?
>
> Yeah, as I said it would be nice but it might be quite some work.  I'd move
> such stuff into a new c-parser.h header that can be included by the
> gimple parser file.  Note existing exports from c-parser are mostly
> declared in c-tree.h but I think having a c-parser.h for all the new exported
> stuff is cleaner.
>
> I'd wish one of the C frontend maintainers would have a quick look at the
> overall structure and guide us here - they are the ones that have to
> approve the patch in the end.  (CCed)
>
> Thanks,
> Richard.
>

PING.

https://gcc.gnu.org/ml/gcc-patches/2016-08/msg01837.html


Thanks,
Prasad
>>
>> Thanks,
>> Prasad
>>
>>> Thanks,
>>> Richard.
>>>
>>>> I am not getting what did you mean by C++11 mode (I am not explicitly
>>>> giving any option while configure or make). I also have successfully
>>>> bootstrapped and tested the project on another system. Is there any
>>>> way to check that ?
>>>>
>>>>
>>>> Thanks,
>>>> Prasad

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-09-09 10:58           ` Prasad Ghangal
@ 2016-09-14 13:28             ` Richard Biener
  2016-09-14 13:37               ` Marek Polacek
  2016-09-15  4:23               ` Prasad Ghangal
  0 siblings, 2 replies; 24+ messages in thread
From: Richard Biener @ 2016-09-14 13:28 UTC (permalink / raw)
  To: Prasad Ghangal; +Cc: Trevor Saunders, GCC Patches, Joseph S. Myers, polacek

On Fri, Sep 9, 2016 at 12:38 PM, Prasad Ghangal
<prasad.ghangal@gmail.com> wrote:
> On 26 August 2016 at 14:28, Richard Biener <richard.guenther@gmail.com> wrote:
>> On Fri, Aug 26, 2016 at 5:08 AM, Prasad Ghangal
>> <prasad.ghangal@gmail.com> wrote:
>>> On 24 August 2016 at 15:32, Richard Biener <richard.guenther@gmail.com> wrote:
>>>> On Mon, Aug 22, 2016 at 8:40 PM, Prasad Ghangal
>>>> <prasad.ghangal@gmail.com> wrote:
>>>>> On 22 August 2016 at 16:55, Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
>>>>>> On Sun, Aug 21, 2016 at 10:35:17PM +0530, Prasad Ghangal wrote:
>>>>>>> Hi all,
>>>>>>>
>>>>>>> As a part of my gsoc project. I have completed the following tasks:
>>>>>>>
>>>>>>> * Parsed gimple-expression
>>>>>>> * Parsed gimple-labels
>>>>>>> * Parsed local declaration
>>>>>>> * Parsed gimple-goto statement
>>>>>>> * Parsed gimple-if-else statement
>>>>>>> * Parsed gimple-switch statement
>>>>>>> * Parsed gimple-return statement
>>>>>>> * Parsed gimple-PHI function
>>>>>>> * Parsed gimple ssa-names along with default def
>>>>>>> * Parsed gimple-call
>>>>>>>
>>>>>>> * Hacked pass manager to add support for startwith (pass-name) to skip
>>>>>>> early opt passes
>>>>>>> * Modified gimple dump for making it parsable
>>>>>>>
>>>>>>> I am willing to continue work on the project, some TODOs for the projects are:
>>>>>>>
>>>>>>> * Error handling
>>>>>>> * Parse more gimple syntax
>>>>>>> * Add startwith support for IPA passes
>>>>>>>
>>>>>>> The complete code of gimple fe project can be found at
>>>>>>> https://github.com/PrasadG193/gcc_gimple_fe
>>>>>>>
>>>>>>>
>>>>>>> PFA patch for complete project (rebased for latest trunk revision).
>>>>>>> I have successfully bootstrapped and tested on x86_64-pc-linux-gnu.
>>>>>>> Some testcases failed due to modified gimple dump as expected.
>>>>>>>
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Prasad
>>>>>>
>>>>>> only some rather minor comments
>>>>>>
>>>>>>
>>>>>> +++ b/gcc/c/c-parser.c
>>>>>> @@ -59,6 +59,18 @@ along with GCC; see the file COPYING3.  If not see
>>>>>>  #include "gimple-expr.h"
>>>>>>  #include "context.h"
>>>>>>  #include "gcc-rich-location.h"
>>>>>> +#include "tree-vrp.h"
>>>>>>
>>>>>> given that you need these headers it might be better to put most of the
>>>>>> gimple parsing in its own file so only what actually needs to know about
>>>>>> this part of the compiler does now about it.
>>>>>>
>>>>>> +void
>>>>>> +c_parser_parse_gimple_body (c_parser *parser)
>>>>>> +{
>>>>>> +  bool return_p = false;
>>>>>> +  gimple_seq seq;
>>>>>> +  gimple_seq body;
>>>>>> +  tree stmt = push_stmt_list ();
>>>>>>
>>>>>> it would be nice to move the declarations down to their first use.
>>>>>>
>>>>>> +      gimple *ret;
>>>>>> +      ret = gimple_build_return (NULL);
>>>>>>
>>>>>> there's no reason for a separate declaration and assignment ;)
>>>>>>
>>>>>> +  tree block = NULL;
>>>>>> +  block = pop_scope ();
>>>>>>
>>>>>> same here, and a number of other places.
>>>>>>
>>>>>> +c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
>>>>>> +{
>>>>>> +  bool return_p = false;
>>>>>> +
>>>>>> +  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
>>>>>> +      return return_p;
>>>>>>
>>>>>> return false would work fine.
>>>>>>
>>>>>> +
>>>>>> +  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
>>>>>> +    {
>>>>>> +      c_parser_consume_token (parser);
>>>>>> +      goto out;
>>>>>>
>>>>>> I don't see the need for the gotos, there's no cleanup in this function.
>>>>>>
>>>>>> +  /* gimple PHI expression.  */
>>>>>> +  if (c_parser_next_token_is_keyword (parser, RID_PHI))
>>>>>> +    {
>>>>>> +      c_parser_consume_token (parser);
>>>>>> +
>>>>>> +      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
>>>>>> +       {
>>>>>> +         return;
>>>>>> +       }
>>>>>> +
>>>>>> +      gcall *call_stmt;
>>>>>> +      tree arg = NULL_TREE;
>>>>>> +      vec<tree> vargs = vNULL;
>>>>>>
>>>>>> I think you can use auto_vec here, as is I think this leaks the vectors
>>>>>> storage.
>>>>>>
>>>>>> +c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)
>>>>>>
>>>>>> you can skip the explicit 'enum' keyword.
>>>>>>
>>>>>> +  struct {
>>>>>> +    /* The expression at this stack level.  */
>>>>>> +    struct c_expr expr;
>>>>>>
>>>>>> similar with struct here.
>>>>>>
>>>>>> +    /* The precedence of the operator on its left, PREC_NONE at the
>>>>>> +       bottom of the stack.  */
>>>>>> +    enum c_parser_prec prec;
>>>>>> +    /* The operation on its left.  */
>>>>>> +    enum tree_code op;
>>>>>> +    /* The source location of this operation.  */
>>>>>> +    location_t loc;
>>>>>> +  } stack[2];
>>>>>> +  int sp;
>>>>>> +  /* Location of the binary operator.  */
>>>>>> +  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
>>>>>> +#define POP                                                                  \
>>>>>>
>>>>>> it seems like it would be nicer to name the type, and then make this a
>>>>>> function.
>>>>>>
>>>>>> +                                       RO_UNARY_STAR);
>>>>>> +       ret.src_range.m_start = op_loc;
>>>>>> +       ret.src_range.m_finish = finish;
>>>>>> +       return ret;
>>>>>> +      }
>>>>>> +    case CPP_PLUS:
>>>>>> +      if (!c_dialect_objc () && !in_system_header_at (input_location))
>>>>>> +       warning_at (op_loc,
>>>>>> +                   OPT_Wtraditional,
>>>>>> +                   "traditional C rejects the unary plus operator");
>>>>>>
>>>>>> does it really make sense to warn about C issues when compiling gimple?
>>>>>>
>>>>>> +c_parser_parse_ssa_names (c_parser *parser)
>>>>>> +{
>>>>>> +  tree id = NULL_TREE;
>>>>>> +  c_expr ret;
>>>>>> +  char *var_name, *var_version, *token;
>>>>>> +  ret.original_code = ERROR_MARK;
>>>>>> +  ret.original_type = NULL;
>>>>>> +
>>>>>> +  /* ssa token string.  */
>>>>>> +  const char *ssa_token = NULL;
>>>>>> +  ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
>>>>>> +  token = new char [strlen (ssa_token)];
>>>>>>
>>>>>> I'm not sure I see why you need this copy, and getting rid of it would
>>>>>> mean you don't need to free it.
>>>>>>
>>>>>> +  strcpy (token, ssa_token);
>>>>>> +
>>>>>> +  /* seperate var name and version.  */
>>>>>> +  var_version = strrchr (token, '_');
>>>>>> +  if (var_version)
>>>>>> +    {
>>>>>> +      var_name = new char[var_version - token + 1];
>>>>>>
>>>>>> you should free this when done with it.
>>>>>>
>>>>>> +c_parser_gimple_postfix_expression (c_parser *parser)
>>>>>> +{
>>>>>> +  struct c_expr expr;
>>>>>> +  location_t loc = c_parser_peek_token (parser)->location;;
>>>>>>
>>>>>> extra ;
>>>>>>
>>>>>> +    case CPP_OBJC_STRING:
>>>>>> +      gcc_assert (c_dialect_objc ());
>>>>>> +      expr.value
>>>>>> +       = objc_build_string_object (c_parser_peek_token (parser)->value);
>>>>>> +      set_c_expr_source_range (&expr, tok_range);
>>>>>> +      c_parser_consume_token (parser);
>>>>>> +      break;
>>>>>>
>>>>>> is there a reason to support objc stuff in gimple?
>>>>>>
>>>>>> +c_parser_gimple_expr_list (c_parser *parser, bool convert_p,
>>>>>> +                   vec<tree, va_gc> **p_orig_types,
>>>>>> +                   location_t *sizeof_arg_loc, tree *sizeof_arg,
>>>>>> +                   vec<location_t> *locations,
>>>>>> +                   unsigned int *literal_zero_mask)
>>>>>> +{
>>>>>> +  vec<tree, va_gc> *ret;
>>>>>> +  vec<tree, va_gc> *orig_types;
>>>>>> +  struct c_expr expr;
>>>>>> +  location_t loc = c_parser_peek_token (parser)->location;
>>>>>> +  location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION;
>>>>>> +  unsigned int idx = 0;
>>>>>> +
>>>>>> +  ret = make_tree_vector ();
>>>>>> +  if (p_orig_types == NULL)
>>>>>> +    orig_types = NULL;
>>>>>> +  else
>>>>>> +    orig_types = make_tree_vector ();
>>>>>> +
>>>>>> +  if (sizeof_arg != NULL
>>>>>> +      && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
>>>>>> +    cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
>>>>>> +  if (literal_zero_mask)
>>>>>> +    c_parser_check_literal_zero (parser, literal_zero_mask, 0);
>>>>>> +  expr = c_parser_gimple_unary_expression (parser);
>>>>>> +  if (convert_p)
>>>>>> +    expr = convert_lvalue_to_rvalue (loc, expr, true, true);
>>>>>> +  ret->quick_push (expr.value);
>>>>>>
>>>>>>  That kind of relies on the details of make_tree_vector (), so it seems
>>>>>>  somewhat safer to use vec_safe_push.
>>>>>>
>>>>>> +  if (orig_types)
>>>>>> +    orig_types->quick_push (expr.original_type);
>>>>>>
>>>>>> same
>>>>>>
>>>>>> +c_parser_gimple_declaration (c_parser *parser)
>>>>>> +{
>>>>>> +  struct c_declspecs *specs;
>>>>>> +  struct c_declarator *declarator;
>>>>>> +  specs = build_null_declspecs ();
>>>>>> +  c_parser_declspecs (parser, specs, true, true, true,
>>>>>> +                     true, true, cla_nonabstract_decl);
>>>>>> +  finish_declspecs (specs);
>>>>>> +  bool auto_type_p = specs->typespec_word == cts_auto_type;
>>>>>>
>>>>>> is it useful to support auto here in gimple?
>>>>>>
>>>>>> +c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
>>>>>> +{
>>>>>> +  c_expr cond_expr;
>>>>>> +  tree case_label, label;
>>>>>> +  vec<tree> labels = vNULL;
>>>>>>
>>>>>> auto_vec?
>>>>>>
>>>>>> +static void
>>>>>> +c_finish_gimple_return (location_t loc, tree retval)
>>>>>> +{
>>>>>> +  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
>>>>>> +
>>>>>> +  /* Use the expansion point to handle cases such as returning NULL
>>>>>> +     in a function returning void.  */
>>>>>> +  source_location xloc = expansion_point_location_if_in_system_header (loc);
>>>>>> +
>>>>>> +  if (TREE_THIS_VOLATILE (current_function_decl))
>>>>>> +    warning_at (xloc, 0,
>>>>>> +               "function declared %<noreturn%> has a %<return%> statement");
>>>>>> +
>>>>>> +  if (!retval)
>>>>>> +    {
>>>>>> +      current_function_returns_null = 1;
>>>>>> +      if ((warn_return_type || flag_isoc99)
>>>>>>
>>>>>> I'm not sure what to do about warnings, but checking the language we are
>>>>>> compiling as seems kind of wrong when we're compiling gimple?
>>>>>>
>>>>>> @@ -228,6 +228,12 @@ struct GTY(()) function {
>>>>>>    /* GIMPLE body for this function.  */
>>>>>>    gimple_seq gimple_body;
>>>>>>
>>>>>> +  /* GIMPLEFE pass to start with */
>>>>>> +  opt_pass *pass_startwith = NULL;
>>>>>>
>>>>>> I'm guessing you've only compiled in C++11 mode? because I'm pretty sure
>>>>>> you are using a C++11 feature here (the default member value you
>>>>>> assign).
>>>>>>
>>>>>> Thanks!
>>>>>>
>>>>>> Trev
>>>>>>
>>>>>
>>>>> Hi Trevor,
>>>>>
>>>>> Thanks for your feedback. I had missed removing some unwanted code
>>>>> while code cleanup. I have updated the patch.
>>>>> I am not sure if we should move all gimple parsing related functions
>>>>> to the new file (?)
>>>>
>>>> I think it might be good to make the parts of the C parser you use more
>>>> obvious (you'd need to export functions like c_parser_next_token_is).
>>>>
>>>> The easiest way to "force" that is to put all of the gimple parsing into
>>>> a separate file.
>>>>
>>>> Note I am not so much concerned about this at the moment, the parts to
>>>> improve would be avoiding more of the C-isms like convert_lvalue_to_rvalue,
>>>> handling of SIZEOF_EXPR and other stuff that looks redundant (you've
>>>> probably copied this from the C parsing routines and refactored it).
>>>> Also the GIMPLE parser shouldn't do any warnings (just spotted
>>>> a call to warn_for_memset).
>>>>
>>> PFA updated patch (successfully bootstrapped and tested on
>>> x86_64-pc-linux-gnu). I have removed unnecessary code. On side I am
>>> also trying to move gimple parser related functions to new file. But
>>> for it we also have to move structs like c_token, c_parser. Won't it
>>> disturb the c-parser code structure ?
>>
>> Yeah, as I said it would be nice but it might be quite some work.  I'd move
>> such stuff into a new c-parser.h header that can be included by the
>> gimple parser file.  Note existing exports from c-parser are mostly
>> declared in c-tree.h but I think having a c-parser.h for all the new exported
>> stuff is cleaner.
>>
>> I'd wish one of the C frontend maintainers would have a quick look at the
>> overall structure and guide us here - they are the ones that have to
>> approve the patch in the end.  (CCed)
>>
>> Thanks,
>> Richard.
>>
>
> PING.
>
> https://gcc.gnu.org/ml/gcc-patches/2016-08/msg01837.html

(that was a ping for the C FE maintainers)

Prasad, can you update the git branch with the changes from the last patch you
sent out?  I don't think you need to keep it unchanged from this point on.

Thanks,
Richard.

>
> Thanks,
> Prasad
>>>
>>> Thanks,
>>> Prasad
>>>
>>>> Thanks,
>>>> Richard.
>>>>
>>>>> I am not getting what did you mean by C++11 mode (I am not explicitly
>>>>> giving any option while configure or make). I also have successfully
>>>>> bootstrapped and tested the project on another system. Is there any
>>>>> way to check that ?
>>>>>
>>>>>
>>>>> Thanks,
>>>>> Prasad

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-09-14 13:28             ` Richard Biener
@ 2016-09-14 13:37               ` Marek Polacek
  2016-09-14 13:38                 ` Richard Biener
  2016-09-15  4:23               ` Prasad Ghangal
  1 sibling, 1 reply; 24+ messages in thread
From: Marek Polacek @ 2016-09-14 13:37 UTC (permalink / raw)
  To: Richard Biener
  Cc: Prasad Ghangal, Trevor Saunders, GCC Patches, Joseph S. Myers

On Wed, Sep 14, 2016 at 03:24:18PM +0200, Richard Biener wrote:
> > PING.
> >
> > https://gcc.gnu.org/ml/gcc-patches/2016-08/msg01837.html
> 
> (that was a ping for the C FE maintainers)
> 
> Prasad, can you update the git branch with the changes from the last patch you
> sent out?  I don't think you need to keep it unchanged from this point on.

So where exactly is the latest patch/branch?  I see the gimple-front-end
branch, but that hasn't been updated for 2 years.

	Marek

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-09-14 13:37               ` Marek Polacek
@ 2016-09-14 13:38                 ` Richard Biener
  0 siblings, 0 replies; 24+ messages in thread
From: Richard Biener @ 2016-09-14 13:38 UTC (permalink / raw)
  To: Marek Polacek
  Cc: Prasad Ghangal, Trevor Saunders, GCC Patches, Joseph S. Myers

On Wed, Sep 14, 2016 at 3:28 PM, Marek Polacek <polacek@redhat.com> wrote:
> On Wed, Sep 14, 2016 at 03:24:18PM +0200, Richard Biener wrote:
>> > PING.
>> >
>> > https://gcc.gnu.org/ml/gcc-patches/2016-08/msg01837.html
>>
>> (that was a ping for the C FE maintainers)
>>
>> Prasad, can you update the git branch with the changes from the last patch you
>> sent out?  I don't think you need to keep it unchanged from this point on.
>
> So where exactly is the latest patch/branch?  I see the gimple-front-end
> branch, but that hasn't been updated for 2 years.

Latest patch was posted here:
https://gcc.gnu.org/ml/gcc-patches/2016-08/msg01830.html

and the git (not up to date with that patch) is at
https://github.com/PrasadG193/gcc_gimple_fe.git

Richard.

>         Marek

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-09-14 13:28             ` Richard Biener
  2016-09-14 13:37               ` Marek Polacek
@ 2016-09-15  4:23               ` Prasad Ghangal
  1 sibling, 0 replies; 24+ messages in thread
From: Prasad Ghangal @ 2016-09-15  4:23 UTC (permalink / raw)
  To: Richard Biener; +Cc: Trevor Saunders, GCC Patches, Joseph S. Myers, polacek

On 14 September 2016 at 18:54, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Fri, Sep 9, 2016 at 12:38 PM, Prasad Ghangal
> <prasad.ghangal@gmail.com> wrote:
>> On 26 August 2016 at 14:28, Richard Biener <richard.guenther@gmail.com> wrote:
>>> On Fri, Aug 26, 2016 at 5:08 AM, Prasad Ghangal
>>> <prasad.ghangal@gmail.com> wrote:
>>>> On 24 August 2016 at 15:32, Richard Biener <richard.guenther@gmail.com> wrote:
>>>>> On Mon, Aug 22, 2016 at 8:40 PM, Prasad Ghangal
>>>>> <prasad.ghangal@gmail.com> wrote:
>>>>>> On 22 August 2016 at 16:55, Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
>>>>>>> On Sun, Aug 21, 2016 at 10:35:17PM +0530, Prasad Ghangal wrote:
>>>>>>>> Hi all,
>>>>>>>>
>>>>>>>> As a part of my gsoc project. I have completed the following tasks:
>>>>>>>>
>>>>>>>> * Parsed gimple-expression
>>>>>>>> * Parsed gimple-labels
>>>>>>>> * Parsed local declaration
>>>>>>>> * Parsed gimple-goto statement
>>>>>>>> * Parsed gimple-if-else statement
>>>>>>>> * Parsed gimple-switch statement
>>>>>>>> * Parsed gimple-return statement
>>>>>>>> * Parsed gimple-PHI function
>>>>>>>> * Parsed gimple ssa-names along with default def
>>>>>>>> * Parsed gimple-call
>>>>>>>>
>>>>>>>> * Hacked pass manager to add support for startwith (pass-name) to skip
>>>>>>>> early opt passes
>>>>>>>> * Modified gimple dump for making it parsable
>>>>>>>>
>>>>>>>> I am willing to continue work on the project, some TODOs for the projects are:
>>>>>>>>
>>>>>>>> * Error handling
>>>>>>>> * Parse more gimple syntax
>>>>>>>> * Add startwith support for IPA passes
>>>>>>>>
>>>>>>>> The complete code of gimple fe project can be found at
>>>>>>>> https://github.com/PrasadG193/gcc_gimple_fe
>>>>>>>>
>>>>>>>>
>>>>>>>> PFA patch for complete project (rebased for latest trunk revision).
>>>>>>>> I have successfully bootstrapped and tested on x86_64-pc-linux-gnu.
>>>>>>>> Some testcases failed due to modified gimple dump as expected.
>>>>>>>>
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> Prasad
>>>>>>>
>>>>>>> only some rather minor comments
>>>>>>>
>>>>>>>
>>>>>>> +++ b/gcc/c/c-parser.c
>>>>>>> @@ -59,6 +59,18 @@ along with GCC; see the file COPYING3.  If not see
>>>>>>>  #include "gimple-expr.h"
>>>>>>>  #include "context.h"
>>>>>>>  #include "gcc-rich-location.h"
>>>>>>> +#include "tree-vrp.h"
>>>>>>>
>>>>>>> given that you need these headers it might be better to put most of the
>>>>>>> gimple parsing in its own file so only what actually needs to know about
>>>>>>> this part of the compiler does now about it.
>>>>>>>
>>>>>>> +void
>>>>>>> +c_parser_parse_gimple_body (c_parser *parser)
>>>>>>> +{
>>>>>>> +  bool return_p = false;
>>>>>>> +  gimple_seq seq;
>>>>>>> +  gimple_seq body;
>>>>>>> +  tree stmt = push_stmt_list ();
>>>>>>>
>>>>>>> it would be nice to move the declarations down to their first use.
>>>>>>>
>>>>>>> +      gimple *ret;
>>>>>>> +      ret = gimple_build_return (NULL);
>>>>>>>
>>>>>>> there's no reason for a separate declaration and assignment ;)
>>>>>>>
>>>>>>> +  tree block = NULL;
>>>>>>> +  block = pop_scope ();
>>>>>>>
>>>>>>> same here, and a number of other places.
>>>>>>>
>>>>>>> +c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
>>>>>>> +{
>>>>>>> +  bool return_p = false;
>>>>>>> +
>>>>>>> +  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
>>>>>>> +      return return_p;
>>>>>>>
>>>>>>> return false would work fine.
>>>>>>>
>>>>>>> +
>>>>>>> +  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
>>>>>>> +    {
>>>>>>> +      c_parser_consume_token (parser);
>>>>>>> +      goto out;
>>>>>>>
>>>>>>> I don't see the need for the gotos, there's no cleanup in this function.
>>>>>>>
>>>>>>> +  /* gimple PHI expression.  */
>>>>>>> +  if (c_parser_next_token_is_keyword (parser, RID_PHI))
>>>>>>> +    {
>>>>>>> +      c_parser_consume_token (parser);
>>>>>>> +
>>>>>>> +      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
>>>>>>> +       {
>>>>>>> +         return;
>>>>>>> +       }
>>>>>>> +
>>>>>>> +      gcall *call_stmt;
>>>>>>> +      tree arg = NULL_TREE;
>>>>>>> +      vec<tree> vargs = vNULL;
>>>>>>>
>>>>>>> I think you can use auto_vec here, as is I think this leaks the vectors
>>>>>>> storage.
>>>>>>>
>>>>>>> +c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)
>>>>>>>
>>>>>>> you can skip the explicit 'enum' keyword.
>>>>>>>
>>>>>>> +  struct {
>>>>>>> +    /* The expression at this stack level.  */
>>>>>>> +    struct c_expr expr;
>>>>>>>
>>>>>>> similar with struct here.
>>>>>>>
>>>>>>> +    /* The precedence of the operator on its left, PREC_NONE at the
>>>>>>> +       bottom of the stack.  */
>>>>>>> +    enum c_parser_prec prec;
>>>>>>> +    /* The operation on its left.  */
>>>>>>> +    enum tree_code op;
>>>>>>> +    /* The source location of this operation.  */
>>>>>>> +    location_t loc;
>>>>>>> +  } stack[2];
>>>>>>> +  int sp;
>>>>>>> +  /* Location of the binary operator.  */
>>>>>>> +  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
>>>>>>> +#define POP                                                                  \
>>>>>>>
>>>>>>> it seems like it would be nicer to name the type, and then make this a
>>>>>>> function.
>>>>>>>
>>>>>>> +                                       RO_UNARY_STAR);
>>>>>>> +       ret.src_range.m_start = op_loc;
>>>>>>> +       ret.src_range.m_finish = finish;
>>>>>>> +       return ret;
>>>>>>> +      }
>>>>>>> +    case CPP_PLUS:
>>>>>>> +      if (!c_dialect_objc () && !in_system_header_at (input_location))
>>>>>>> +       warning_at (op_loc,
>>>>>>> +                   OPT_Wtraditional,
>>>>>>> +                   "traditional C rejects the unary plus operator");
>>>>>>>
>>>>>>> does it really make sense to warn about C issues when compiling gimple?
>>>>>>>
>>>>>>> +c_parser_parse_ssa_names (c_parser *parser)
>>>>>>> +{
>>>>>>> +  tree id = NULL_TREE;
>>>>>>> +  c_expr ret;
>>>>>>> +  char *var_name, *var_version, *token;
>>>>>>> +  ret.original_code = ERROR_MARK;
>>>>>>> +  ret.original_type = NULL;
>>>>>>> +
>>>>>>> +  /* ssa token string.  */
>>>>>>> +  const char *ssa_token = NULL;
>>>>>>> +  ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
>>>>>>> +  token = new char [strlen (ssa_token)];
>>>>>>>
>>>>>>> I'm not sure I see why you need this copy, and getting rid of it would
>>>>>>> mean you don't need to free it.
>>>>>>>
>>>>>>> +  strcpy (token, ssa_token);
>>>>>>> +
>>>>>>> +  /* seperate var name and version.  */
>>>>>>> +  var_version = strrchr (token, '_');
>>>>>>> +  if (var_version)
>>>>>>> +    {
>>>>>>> +      var_name = new char[var_version - token + 1];
>>>>>>>
>>>>>>> you should free this when done with it.
>>>>>>>
>>>>>>> +c_parser_gimple_postfix_expression (c_parser *parser)
>>>>>>> +{
>>>>>>> +  struct c_expr expr;
>>>>>>> +  location_t loc = c_parser_peek_token (parser)->location;;
>>>>>>>
>>>>>>> extra ;
>>>>>>>
>>>>>>> +    case CPP_OBJC_STRING:
>>>>>>> +      gcc_assert (c_dialect_objc ());
>>>>>>> +      expr.value
>>>>>>> +       = objc_build_string_object (c_parser_peek_token (parser)->value);
>>>>>>> +      set_c_expr_source_range (&expr, tok_range);
>>>>>>> +      c_parser_consume_token (parser);
>>>>>>> +      break;
>>>>>>>
>>>>>>> is there a reason to support objc stuff in gimple?
>>>>>>>
>>>>>>> +c_parser_gimple_expr_list (c_parser *parser, bool convert_p,
>>>>>>> +                   vec<tree, va_gc> **p_orig_types,
>>>>>>> +                   location_t *sizeof_arg_loc, tree *sizeof_arg,
>>>>>>> +                   vec<location_t> *locations,
>>>>>>> +                   unsigned int *literal_zero_mask)
>>>>>>> +{
>>>>>>> +  vec<tree, va_gc> *ret;
>>>>>>> +  vec<tree, va_gc> *orig_types;
>>>>>>> +  struct c_expr expr;
>>>>>>> +  location_t loc = c_parser_peek_token (parser)->location;
>>>>>>> +  location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION;
>>>>>>> +  unsigned int idx = 0;
>>>>>>> +
>>>>>>> +  ret = make_tree_vector ();
>>>>>>> +  if (p_orig_types == NULL)
>>>>>>> +    orig_types = NULL;
>>>>>>> +  else
>>>>>>> +    orig_types = make_tree_vector ();
>>>>>>> +
>>>>>>> +  if (sizeof_arg != NULL
>>>>>>> +      && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
>>>>>>> +    cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
>>>>>>> +  if (literal_zero_mask)
>>>>>>> +    c_parser_check_literal_zero (parser, literal_zero_mask, 0);
>>>>>>> +  expr = c_parser_gimple_unary_expression (parser);
>>>>>>> +  if (convert_p)
>>>>>>> +    expr = convert_lvalue_to_rvalue (loc, expr, true, true);
>>>>>>> +  ret->quick_push (expr.value);
>>>>>>>
>>>>>>>  That kind of relies on the details of make_tree_vector (), so it seems
>>>>>>>  somewhat safer to use vec_safe_push.
>>>>>>>
>>>>>>> +  if (orig_types)
>>>>>>> +    orig_types->quick_push (expr.original_type);
>>>>>>>
>>>>>>> same
>>>>>>>
>>>>>>> +c_parser_gimple_declaration (c_parser *parser)
>>>>>>> +{
>>>>>>> +  struct c_declspecs *specs;
>>>>>>> +  struct c_declarator *declarator;
>>>>>>> +  specs = build_null_declspecs ();
>>>>>>> +  c_parser_declspecs (parser, specs, true, true, true,
>>>>>>> +                     true, true, cla_nonabstract_decl);
>>>>>>> +  finish_declspecs (specs);
>>>>>>> +  bool auto_type_p = specs->typespec_word == cts_auto_type;
>>>>>>>
>>>>>>> is it useful to support auto here in gimple?
>>>>>>>
>>>>>>> +c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
>>>>>>> +{
>>>>>>> +  c_expr cond_expr;
>>>>>>> +  tree case_label, label;
>>>>>>> +  vec<tree> labels = vNULL;
>>>>>>>
>>>>>>> auto_vec?
>>>>>>>
>>>>>>> +static void
>>>>>>> +c_finish_gimple_return (location_t loc, tree retval)
>>>>>>> +{
>>>>>>> +  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
>>>>>>> +
>>>>>>> +  /* Use the expansion point to handle cases such as returning NULL
>>>>>>> +     in a function returning void.  */
>>>>>>> +  source_location xloc = expansion_point_location_if_in_system_header (loc);
>>>>>>> +
>>>>>>> +  if (TREE_THIS_VOLATILE (current_function_decl))
>>>>>>> +    warning_at (xloc, 0,
>>>>>>> +               "function declared %<noreturn%> has a %<return%> statement");
>>>>>>> +
>>>>>>> +  if (!retval)
>>>>>>> +    {
>>>>>>> +      current_function_returns_null = 1;
>>>>>>> +      if ((warn_return_type || flag_isoc99)
>>>>>>>
>>>>>>> I'm not sure what to do about warnings, but checking the language we are
>>>>>>> compiling as seems kind of wrong when we're compiling gimple?
>>>>>>>
>>>>>>> @@ -228,6 +228,12 @@ struct GTY(()) function {
>>>>>>>    /* GIMPLE body for this function.  */
>>>>>>>    gimple_seq gimple_body;
>>>>>>>
>>>>>>> +  /* GIMPLEFE pass to start with */
>>>>>>> +  opt_pass *pass_startwith = NULL;
>>>>>>>
>>>>>>> I'm guessing you've only compiled in C++11 mode? because I'm pretty sure
>>>>>>> you are using a C++11 feature here (the default member value you
>>>>>>> assign).
>>>>>>>
>>>>>>> Thanks!
>>>>>>>
>>>>>>> Trev
>>>>>>>
>>>>>>
>>>>>> Hi Trevor,
>>>>>>
>>>>>> Thanks for your feedback. I had missed removing some unwanted code
>>>>>> while code cleanup. I have updated the patch.
>>>>>> I am not sure if we should move all gimple parsing related functions
>>>>>> to the new file (?)
>>>>>
>>>>> I think it might be good to make the parts of the C parser you use more
>>>>> obvious (you'd need to export functions like c_parser_next_token_is).
>>>>>
>>>>> The easiest way to "force" that is to put all of the gimple parsing into
>>>>> a separate file.
>>>>>
>>>>> Note I am not so much concerned about this at the moment, the parts to
>>>>> improve would be avoiding more of the C-isms like convert_lvalue_to_rvalue,
>>>>> handling of SIZEOF_EXPR and other stuff that looks redundant (you've
>>>>> probably copied this from the C parsing routines and refactored it).
>>>>> Also the GIMPLE parser shouldn't do any warnings (just spotted
>>>>> a call to warn_for_memset).
>>>>>
>>>> PFA updated patch (successfully bootstrapped and tested on
>>>> x86_64-pc-linux-gnu). I have removed unnecessary code. On side I am
>>>> also trying to move gimple parser related functions to new file. But
>>>> for it we also have to move structs like c_token, c_parser. Won't it
>>>> disturb the c-parser code structure ?
>>>
>>> Yeah, as I said it would be nice but it might be quite some work.  I'd move
>>> such stuff into a new c-parser.h header that can be included by the
>>> gimple parser file.  Note existing exports from c-parser are mostly
>>> declared in c-tree.h but I think having a c-parser.h for all the new exported
>>> stuff is cleaner.
>>>
>>> I'd wish one of the C frontend maintainers would have a quick look at the
>>> overall structure and guide us here - they are the ones that have to
>>> approve the patch in the end.  (CCed)
>>>
>>> Thanks,
>>> Richard.
>>>
>>
>> PING.
>>
>> https://gcc.gnu.org/ml/gcc-patches/2016-08/msg01837.html
>
> (that was a ping for the C FE maintainers)
>
> Prasad, can you update the git branch with the changes from the last patch you
> sent out?  I don't think you need to keep it unchanged from this point on.
>
I have updated the git branch: https://github.com/PrasadG193/gcc_gimple_fe

Thanks,
Prasad

> Thanks,
> Richard.
>
>>
>> Thanks,
>> Prasad
>>>>
>>>> Thanks,
>>>> Prasad
>>>>
>>>>> Thanks,
>>>>> Richard.
>>>>>
>>>>>> I am not getting what did you mean by C++11 mode (I am not explicitly
>>>>>> giving any option while configure or make). I also have successfully
>>>>>> bootstrapped and tested the project on another system. Is there any
>>>>>> way to check that ?
>>>>>>
>>>>>>
>>>>>> Thanks,
>>>>>> Prasad

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-08-26  3:10       ` Prasad Ghangal
  2016-08-26  8:58         ` Richard Biener
@ 2016-10-05 23:28         ` Joseph Myers
  2016-10-25 10:19           ` Richard Biener
  1 sibling, 1 reply; 24+ messages in thread
From: Joseph Myers @ 2016-10-05 23:28 UTC (permalink / raw)
  To: Prasad Ghangal; +Cc: Richard Biener, Trevor Saunders, GCC Patches

On Fri, 26 Aug 2016, Prasad Ghangal wrote:

> >> Thanks for your feedback. I had missed removing some unwanted code
> >> while code cleanup. I have updated the patch.
> >> I am not sure if we should move all gimple parsing related functions
> >> to the new file (?)
> >
> > I think it might be good to make the parts of the C parser you use more
> > obvious (you'd need to export functions like c_parser_next_token_is).
> >
> > The easiest way to "force" that is to put all of the gimple parsing into
> > a separate file.
> >
> > Note I am not so much concerned about this at the moment, the parts to
> > improve would be avoiding more of the C-isms like convert_lvalue_to_rvalue,
> > handling of SIZEOF_EXPR and other stuff that looks redundant (you've
> > probably copied this from the C parsing routines and refactored it).
> > Also the GIMPLE parser shouldn't do any warnings (just spotted
> > a call to warn_for_memset).
> >
> PFA updated patch (successfully bootstrapped and tested on
> x86_64-pc-linux-gnu). I have removed unnecessary code. On side I am
> also trying to move gimple parser related functions to new file. But
> for it we also have to move structs like c_token, c_parser. Won't it
> disturb the c-parser code structure ?

I think the GIMPLE parsing should go in a separate file (meaning exporting 
relevant types and function declarations in a new c-parser.h).

> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> index a5358ed..3c4d2cc 100644
> --- a/gcc/c-family/c.opt
> +++ b/gcc/c-family/c.opt
> @@ -200,6 +200,10 @@ F
>  Driver C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
>  -F <dir>	Add <dir> to the end of the main framework include path.
>  
> +fgimple
> +C Var(flag_gimple) Init(0)
> +Enable parsing GIMPLE

You should get a test failure here from the missing "." at the end of the 
help text.

Of course the option also needs documenting in invoke.texi.

> @@ -1659,6 +1695,9 @@ 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;
> +  opt_pass *pass = NULL;
> +  bool startwith_p = false;

The comment above the function needs updating to document the new syntax.

> +static void
> +c_parser_gimple_expression (c_parser *parser, gimple_seq *seq)
> +{
> +  struct c_expr lhs, rhs;
> +  gimple *assign = NULL;
> +  enum tree_code subcode = NOP_EXPR;
> +  location_t loc;
> +  tree arg = NULL_TREE;
> +  auto_vec<tree> vargs;
> +
> +  lhs = c_parser_gimple_unary_expression (parser);
> +  rhs.value = error_mark_node;
> +
> +  if (c_parser_next_token_is (parser, CPP_EQ))
> +    {
> +      c_parser_consume_token (parser);
> +    }

Redundant braces around a single statement.  Also, this looks wrong, in 
that it seems like you'd accept a random '=' token at this point 
regardless of what follows and whether '=' makes sense in this context.  
You need to have proper cases: if '=' parse what makes sense after '=', 
otherwise parse what makes sense without '=', so that invalid syntax is 
not accepted.

> +  if (c_parser_next_token_is (parser, CPP_AND) ||
> +      c_parser_next_token_is (parser, CPP_MULT) ||
> +      c_parser_next_token_is (parser, CPP_PLUS) ||
> +      c_parser_next_token_is (parser, CPP_MINUS) ||
> +      c_parser_next_token_is (parser, CPP_COMPL) ||
> +      c_parser_next_token_is (parser, CPP_NOT))

Operators go at the start of a continuation line, not at the end of the 
line.

> +      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
> +	{
> +	  return;
> +	}

Please generally review the patch for redundant braces and remove them.

> +  /* ssa token string.  */
> +  const char *ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
> +  token = new char [strlen (ssa_token)];
> +  strcpy (token, ssa_token);

That looks like a buffer overrun.  To copy a string ssa_token, you need 
strlen (ssa_token) + 1 bytes of space.

> +  /* seperate var name and version.  */

Uppercase letters at start of comments, throughout the patch (and it 
should be "Separate", with 'a' not 'e').

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-10-05 23:28         ` Joseph Myers
@ 2016-10-25 10:19           ` Richard Biener
  2016-10-25 11:13             ` Prasad Ghangal
  0 siblings, 1 reply; 24+ messages in thread
From: Richard Biener @ 2016-10-25 10:19 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Prasad Ghangal, Trevor Saunders, GCC Patches

On Thu, Oct 6, 2016 at 1:28 AM, Joseph Myers <joseph@codesourcery.com> wrote:
> On Fri, 26 Aug 2016, Prasad Ghangal wrote:
>
>> >> Thanks for your feedback. I had missed removing some unwanted code
>> >> while code cleanup. I have updated the patch.
>> >> I am not sure if we should move all gimple parsing related functions
>> >> to the new file (?)
>> >
>> > I think it might be good to make the parts of the C parser you use more
>> > obvious (you'd need to export functions like c_parser_next_token_is).
>> >
>> > The easiest way to "force" that is to put all of the gimple parsing into
>> > a separate file.
>> >
>> > Note I am not so much concerned about this at the moment, the parts to
>> > improve would be avoiding more of the C-isms like convert_lvalue_to_rvalue,
>> > handling of SIZEOF_EXPR and other stuff that looks redundant (you've
>> > probably copied this from the C parsing routines and refactored it).
>> > Also the GIMPLE parser shouldn't do any warnings (just spotted
>> > a call to warn_for_memset).
>> >
>> PFA updated patch (successfully bootstrapped and tested on
>> x86_64-pc-linux-gnu). I have removed unnecessary code. On side I am
>> also trying to move gimple parser related functions to new file. But
>> for it we also have to move structs like c_token, c_parser. Won't it
>> disturb the c-parser code structure ?

Thanks Joseph for the review.  Prasad - do you have time in the next few weeks
to continue working on this?  I'm currently trying to move what is on the github
branch to a branch on git://gcc.gnu.org/git/gcc.git to make it mergeable
(looks like the github repo isn't a clone of the gcc git mirror on github?).

Thanks,
Richard.

> I think the GIMPLE parsing should go in a separate file (meaning exporting
> relevant types and function declarations in a new c-parser.h).
>
>> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
>> index a5358ed..3c4d2cc 100644
>> --- a/gcc/c-family/c.opt
>> +++ b/gcc/c-family/c.opt
>> @@ -200,6 +200,10 @@ F
>>  Driver C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
>>  -F <dir>     Add <dir> to the end of the main framework include path.
>>
>> +fgimple
>> +C Var(flag_gimple) Init(0)
>> +Enable parsing GIMPLE
>
> You should get a test failure here from the missing "." at the end of the
> help text.
>
> Of course the option also needs documenting in invoke.texi.
>
>> @@ -1659,6 +1695,9 @@ 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;
>> +  opt_pass *pass = NULL;
>> +  bool startwith_p = false;
>
> The comment above the function needs updating to document the new syntax.
>
>> +static void
>> +c_parser_gimple_expression (c_parser *parser, gimple_seq *seq)
>> +{
>> +  struct c_expr lhs, rhs;
>> +  gimple *assign = NULL;
>> +  enum tree_code subcode = NOP_EXPR;
>> +  location_t loc;
>> +  tree arg = NULL_TREE;
>> +  auto_vec<tree> vargs;
>> +
>> +  lhs = c_parser_gimple_unary_expression (parser);
>> +  rhs.value = error_mark_node;
>> +
>> +  if (c_parser_next_token_is (parser, CPP_EQ))
>> +    {
>> +      c_parser_consume_token (parser);
>> +    }
>
> Redundant braces around a single statement.  Also, this looks wrong, in
> that it seems like you'd accept a random '=' token at this point
> regardless of what follows and whether '=' makes sense in this context.
> You need to have proper cases: if '=' parse what makes sense after '=',
> otherwise parse what makes sense without '=', so that invalid syntax is
> not accepted.
>
>> +  if (c_parser_next_token_is (parser, CPP_AND) ||
>> +      c_parser_next_token_is (parser, CPP_MULT) ||
>> +      c_parser_next_token_is (parser, CPP_PLUS) ||
>> +      c_parser_next_token_is (parser, CPP_MINUS) ||
>> +      c_parser_next_token_is (parser, CPP_COMPL) ||
>> +      c_parser_next_token_is (parser, CPP_NOT))
>
> Operators go at the start of a continuation line, not at the end of the
> line.
>
>> +      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
>> +     {
>> +       return;
>> +     }
>
> Please generally review the patch for redundant braces and remove them.
>
>> +  /* ssa token string.  */
>> +  const char *ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
>> +  token = new char [strlen (ssa_token)];
>> +  strcpy (token, ssa_token);
>
> That looks like a buffer overrun.  To copy a string ssa_token, you need
> strlen (ssa_token) + 1 bytes of space.
>
>> +  /* seperate var name and version.  */
>
> Uppercase letters at start of comments, throughout the patch (and it
> should be "Separate", with 'a' not 'e').
>
> --
> Joseph S. Myers
> joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-10-25 10:19           ` Richard Biener
@ 2016-10-25 11:13             ` Prasad Ghangal
  2016-10-25 11:20               ` Richard Biener
  0 siblings, 1 reply; 24+ messages in thread
From: Prasad Ghangal @ 2016-10-25 11:13 UTC (permalink / raw)
  To: Richard Biener; +Cc: Joseph Myers, Trevor Saunders, GCC Patches

On 25 October 2016 at 15:49, Richard Biener <richard.guenther@gmail.com> wrote:
> On Thu, Oct 6, 2016 at 1:28 AM, Joseph Myers <joseph@codesourcery.com> wrote:
>> On Fri, 26 Aug 2016, Prasad Ghangal wrote:
>>
>>> >> Thanks for your feedback. I had missed removing some unwanted code
>>> >> while code cleanup. I have updated the patch.
>>> >> I am not sure if we should move all gimple parsing related functions
>>> >> to the new file (?)
>>> >
>>> > I think it might be good to make the parts of the C parser you use more
>>> > obvious (you'd need to export functions like c_parser_next_token_is).
>>> >
>>> > The easiest way to "force" that is to put all of the gimple parsing into
>>> > a separate file.
>>> >
>>> > Note I am not so much concerned about this at the moment, the parts to
>>> > improve would be avoiding more of the C-isms like convert_lvalue_to_rvalue,
>>> > handling of SIZEOF_EXPR and other stuff that looks redundant (you've
>>> > probably copied this from the C parsing routines and refactored it).
>>> > Also the GIMPLE parser shouldn't do any warnings (just spotted
>>> > a call to warn_for_memset).
>>> >
>>> PFA updated patch (successfully bootstrapped and tested on
>>> x86_64-pc-linux-gnu). I have removed unnecessary code. On side I am
>>> also trying to move gimple parser related functions to new file. But
>>> for it we also have to move structs like c_token, c_parser. Won't it
>>> disturb the c-parser code structure ?
>
> Thanks Joseph for the review.  Prasad - do you have time in the next few weeks
> to continue working on this?  I'm currently trying to move what is on the github
> branch to a branch on git://gcc.gnu.org/git/gcc.git to make it mergeable
Sorry I couldn't work on the project in last few weeks. Since I will
be on vacation in the next week, I will definitely work on it. If we
can't merge it before closure of stage1, can we merge it in the stage2
or stage3?

> (looks like the github repo isn't a clone of the gcc git mirror on github?).
No. (Unfortunately) I had reinitialised git locally. That's why I am
also struggling while rebasing and syncing to the trunk. Any solution?
Since I am employed now, do I need to update the copyright assignment?


Thanks,
Prasad
>
> Thanks,
> Richard.
>
>> I think the GIMPLE parsing should go in a separate file (meaning exporting
>> relevant types and function declarations in a new c-parser.h).
>>
>>> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
>>> index a5358ed..3c4d2cc 100644
>>> --- a/gcc/c-family/c.opt
>>> +++ b/gcc/c-family/c.opt
>>> @@ -200,6 +200,10 @@ F
>>>  Driver C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
>>>  -F <dir>     Add <dir> to the end of the main framework include path.
>>>
>>> +fgimple
>>> +C Var(flag_gimple) Init(0)
>>> +Enable parsing GIMPLE
>>
>> You should get a test failure here from the missing "." at the end of the
>> help text.
>>
>> Of course the option also needs documenting in invoke.texi.
>>
>>> @@ -1659,6 +1695,9 @@ 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;
>>> +  opt_pass *pass = NULL;
>>> +  bool startwith_p = false;
>>
>> The comment above the function needs updating to document the new syntax.
>>
>>> +static void
>>> +c_parser_gimple_expression (c_parser *parser, gimple_seq *seq)
>>> +{
>>> +  struct c_expr lhs, rhs;
>>> +  gimple *assign = NULL;
>>> +  enum tree_code subcode = NOP_EXPR;
>>> +  location_t loc;
>>> +  tree arg = NULL_TREE;
>>> +  auto_vec<tree> vargs;
>>> +
>>> +  lhs = c_parser_gimple_unary_expression (parser);
>>> +  rhs.value = error_mark_node;
>>> +
>>> +  if (c_parser_next_token_is (parser, CPP_EQ))
>>> +    {
>>> +      c_parser_consume_token (parser);
>>> +    }
>>
>> Redundant braces around a single statement.  Also, this looks wrong, in
>> that it seems like you'd accept a random '=' token at this point
>> regardless of what follows and whether '=' makes sense in this context.
>> You need to have proper cases: if '=' parse what makes sense after '=',
>> otherwise parse what makes sense without '=', so that invalid syntax is
>> not accepted.
>>
>>> +  if (c_parser_next_token_is (parser, CPP_AND) ||
>>> +      c_parser_next_token_is (parser, CPP_MULT) ||
>>> +      c_parser_next_token_is (parser, CPP_PLUS) ||
>>> +      c_parser_next_token_is (parser, CPP_MINUS) ||
>>> +      c_parser_next_token_is (parser, CPP_COMPL) ||
>>> +      c_parser_next_token_is (parser, CPP_NOT))
>>
>> Operators go at the start of a continuation line, not at the end of the
>> line.
>>
>>> +      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
>>> +     {
>>> +       return;
>>> +     }
>>
>> Please generally review the patch for redundant braces and remove them.
>>
>>> +  /* ssa token string.  */
>>> +  const char *ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
>>> +  token = new char [strlen (ssa_token)];
>>> +  strcpy (token, ssa_token);
>>
>> That looks like a buffer overrun.  To copy a string ssa_token, you need
>> strlen (ssa_token) + 1 bytes of space.
>>
>>> +  /* seperate var name and version.  */
>>
>> Uppercase letters at start of comments, throughout the patch (and it
>> should be "Separate", with 'a' not 'e').
>>
>> --
>> Joseph S. Myers
>> joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [patch] [gsoc] [gimplefe] GIMPLE FE Project
  2016-10-25 11:13             ` Prasad Ghangal
@ 2016-10-25 11:20               ` Richard Biener
  0 siblings, 0 replies; 24+ messages in thread
From: Richard Biener @ 2016-10-25 11:20 UTC (permalink / raw)
  To: Prasad Ghangal; +Cc: Joseph Myers, Trevor Saunders, GCC Patches

On Tue, Oct 25, 2016 at 1:13 PM, Prasad Ghangal
<prasad.ghangal@gmail.com> wrote:
> On 25 October 2016 at 15:49, Richard Biener <richard.guenther@gmail.com> wrote:
>> On Thu, Oct 6, 2016 at 1:28 AM, Joseph Myers <joseph@codesourcery.com> wrote:
>>> On Fri, 26 Aug 2016, Prasad Ghangal wrote:
>>>
>>>> >> Thanks for your feedback. I had missed removing some unwanted code
>>>> >> while code cleanup. I have updated the patch.
>>>> >> I am not sure if we should move all gimple parsing related functions
>>>> >> to the new file (?)
>>>> >
>>>> > I think it might be good to make the parts of the C parser you use more
>>>> > obvious (you'd need to export functions like c_parser_next_token_is).
>>>> >
>>>> > The easiest way to "force" that is to put all of the gimple parsing into
>>>> > a separate file.
>>>> >
>>>> > Note I am not so much concerned about this at the moment, the parts to
>>>> > improve would be avoiding more of the C-isms like convert_lvalue_to_rvalue,
>>>> > handling of SIZEOF_EXPR and other stuff that looks redundant (you've
>>>> > probably copied this from the C parsing routines and refactored it).
>>>> > Also the GIMPLE parser shouldn't do any warnings (just spotted
>>>> > a call to warn_for_memset).
>>>> >
>>>> PFA updated patch (successfully bootstrapped and tested on
>>>> x86_64-pc-linux-gnu). I have removed unnecessary code. On side I am
>>>> also trying to move gimple parser related functions to new file. But
>>>> for it we also have to move structs like c_token, c_parser. Won't it
>>>> disturb the c-parser code structure ?
>>
>> Thanks Joseph for the review.  Prasad - do you have time in the next few weeks
>> to continue working on this?  I'm currently trying to move what is on the github
>> branch to a branch on git://gcc.gnu.org/git/gcc.git to make it mergeable
> Sorry I couldn't work on the project in last few weeks. Since I will
> be on vacation in the next week, I will definitely work on it. If we
> can't merge it before closure of stage1, can we merge it in the stage2
> or stage3?

I think we might be able to merge early during stage3 as well.  I'm working my
way through the changes that affect not just the GIMPLE FE itself.

>> (looks like the github repo isn't a clone of the gcc git mirror on github?).
> No. (Unfortunately) I had reinitialised git locally. That's why I am
> also struggling while rebasing and syncing to the trunk. Any solution?

I almost finished pushing the last state plus Josephs review comments
fixed (the style ones) to the official GCC git mirror as a branch off
current trunk.
I'll send a short announcement once I managed to "push" ...

> Since I am employed now, do I need to update the copyright assignment?

If your employer has a copyright assignment then things should be fine.
If you work on this during non-work time then your personal assignment is
also fine.

Thanks,
Richard.

>
> Thanks,
> Prasad
>>
>> Thanks,
>> Richard.
>>
>>> I think the GIMPLE parsing should go in a separate file (meaning exporting
>>> relevant types and function declarations in a new c-parser.h).
>>>
>>>> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
>>>> index a5358ed..3c4d2cc 100644
>>>> --- a/gcc/c-family/c.opt
>>>> +++ b/gcc/c-family/c.opt
>>>> @@ -200,6 +200,10 @@ F
>>>>  Driver C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
>>>>  -F <dir>     Add <dir> to the end of the main framework include path.
>>>>
>>>> +fgimple
>>>> +C Var(flag_gimple) Init(0)
>>>> +Enable parsing GIMPLE
>>>
>>> You should get a test failure here from the missing "." at the end of the
>>> help text.
>>>
>>> Of course the option also needs documenting in invoke.texi.
>>>
>>>> @@ -1659,6 +1695,9 @@ 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;
>>>> +  opt_pass *pass = NULL;
>>>> +  bool startwith_p = false;
>>>
>>> The comment above the function needs updating to document the new syntax.
>>>
>>>> +static void
>>>> +c_parser_gimple_expression (c_parser *parser, gimple_seq *seq)
>>>> +{
>>>> +  struct c_expr lhs, rhs;
>>>> +  gimple *assign = NULL;
>>>> +  enum tree_code subcode = NOP_EXPR;
>>>> +  location_t loc;
>>>> +  tree arg = NULL_TREE;
>>>> +  auto_vec<tree> vargs;
>>>> +
>>>> +  lhs = c_parser_gimple_unary_expression (parser);
>>>> +  rhs.value = error_mark_node;
>>>> +
>>>> +  if (c_parser_next_token_is (parser, CPP_EQ))
>>>> +    {
>>>> +      c_parser_consume_token (parser);
>>>> +    }
>>>
>>> Redundant braces around a single statement.  Also, this looks wrong, in
>>> that it seems like you'd accept a random '=' token at this point
>>> regardless of what follows and whether '=' makes sense in this context.
>>> You need to have proper cases: if '=' parse what makes sense after '=',
>>> otherwise parse what makes sense without '=', so that invalid syntax is
>>> not accepted.
>>>
>>>> +  if (c_parser_next_token_is (parser, CPP_AND) ||
>>>> +      c_parser_next_token_is (parser, CPP_MULT) ||
>>>> +      c_parser_next_token_is (parser, CPP_PLUS) ||
>>>> +      c_parser_next_token_is (parser, CPP_MINUS) ||
>>>> +      c_parser_next_token_is (parser, CPP_COMPL) ||
>>>> +      c_parser_next_token_is (parser, CPP_NOT))
>>>
>>> Operators go at the start of a continuation line, not at the end of the
>>> line.
>>>
>>>> +      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
>>>> +     {
>>>> +       return;
>>>> +     }
>>>
>>> Please generally review the patch for redundant braces and remove them.
>>>
>>>> +  /* ssa token string.  */
>>>> +  const char *ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
>>>> +  token = new char [strlen (ssa_token)];
>>>> +  strcpy (token, ssa_token);
>>>
>>> That looks like a buffer overrun.  To copy a string ssa_token, you need
>>> strlen (ssa_token) + 1 bytes of space.
>>>
>>>> +  /* seperate var name and version.  */
>>>
>>> Uppercase letters at start of comments, throughout the patch (and it
>>> should be "Separate", with 'a' not 'e').
>>>
>>> --
>>> Joseph S. Myers
>>> joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2016-10-25 11:20 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-21 17:05 [patch] [gsoc] [gimplefe] GIMPLE FE Project Prasad Ghangal
2016-08-22 11:17 ` Trevor Saunders
2016-08-22 18:40   ` Prasad Ghangal
2016-08-22 21:20     ` Trevor Saunders
2016-08-22 21:27     ` David Malcolm
2016-08-22 21:54       ` Pedro Alves
2016-08-23  7:47         ` Richard Biener
2016-08-23 10:32           ` Pedro Alves
2016-08-23 15:17           ` Trevor Saunders
2016-08-23 15:45       ` Prasad Ghangal
2016-08-24  7:03         ` Prasad Ghangal
2016-08-24  8:45           ` Richard Biener
2016-08-24 10:02     ` Richard Biener
2016-08-26  3:10       ` Prasad Ghangal
2016-08-26  8:58         ` Richard Biener
2016-09-09 10:58           ` Prasad Ghangal
2016-09-14 13:28             ` Richard Biener
2016-09-14 13:37               ` Marek Polacek
2016-09-14 13:38                 ` Richard Biener
2016-09-15  4:23               ` Prasad Ghangal
2016-10-05 23:28         ` Joseph Myers
2016-10-25 10:19           ` Richard Biener
2016-10-25 11:13             ` Prasad Ghangal
2016-10-25 11:20               ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).