On Fri, 28 Oct 2016, Richard Biener wrote:

> 
> These are the C (and ObjC) Frontend changes required by the GIMPLE
> Frontend which is now itself contained in c/gimple-parser.[ch].
> 
> Most changes are due to a new c-parser.h header where we export
> stuff from the C parser that the GIMPLE frontend requires.  Other
> changes include new __GIMPLE and __PHI keywords, handling
> __GIMPLE as new declspec and dispatching to the GIMPLE parser
> for __GIMPLE marked function definitions.
> 
> We'd like to include the GIMPLE parser for GCC 7, as the parser
> is pretty self-contained (and now works to a good extent) it can
> be improved during stage3 or when testcases show that it needs
> improvement.
> 
> Bootstrapped and tested on x86_64-unknown-linux-gnu (together with [2/2])
> for C, ObjC.
> 
> Ok for trunk?

Ping.

Thanks,
Richard.

> Thanks,
> Richard.
> 
> 2016-10-28  Prasad Ghangal  <prasad.ghan...@gmail.com>
>       Richard Biener  <rguent...@suse.de>
>     
>       c/
>       * Make-lang.in (C_AND_OBJC_OBJS): Add gimple-parser.o.
>       * config-lang.in (gtfiles): Add c/c-parser.h.
>       * c-tree.h (enum c_declspec_word): Add cdw_gimple.
>       (struct c_declspecs): Add gimple_pass member and gimple_p flag.
>       * c-parser.c (enum c_id_kind, struct c_token,
>       c_parser_next_token_is, c_parser_next_token_is_not,
>       c_parser_next_token_is_keyword,
>       enum c_lookahead_kind, enum c_dtr_syn, enum c_parser_prec):
>       Split out to ...
>       * c-parser.h: ... new header.
>       * c-parser.c: Include c-parser.h and gimple-parser.h.
>       (c_parser_peek_token, c_parser_peek_2nd_token,
>       c_token_starts_typename, c_parser_next_token_starts_declspecs,
>       c_parser_next_tokens_start_declaration, c_parser_consume_token,
>       c_parser_error, c_parser_require, c_parser_skip_until_found,
>       c_parser_declspecs, c_parser_declarator, c_parser_peek_nth_token,
>       c_parser_cast_expression): Export.
>       (c_parser_tokens_buf): New function.
>       (c_parser_error): Likewise.
>       (c_parser_set_error): Likewise.
>       (c_parser_declspecs): Handle RID_GIMPLE.
>       (c_parser_declaration_or_fndef): Parse __GIMPLE marked body
>       via c_parser_parse_gimple_body.
>       * c-parser.h (c_parser_peek_token, c_parser_peek_2nd_token,
>       c_token_starts_typename, c_parser_next_token_starts_declspecs,
>       c_parser_next_tokens_start_declaration, c_parser_consume_token,
>       c_parser_error, c_parser_require, c_parser_skip_until_found,
>       c_parser_declspecs, c_parser_declarator, c_parser_peek_nth_token,
>       c_parser_cast_expression): Declare.
>       (struct c_parser): Declare forward.
>       (c_parser_tokens_buf): Declare.
>         (c_parser_error): Likewise.
>         (c_parser_set_error): Likewise.
>       * gimple-parser.c: New file.
>       * gimple-parser.h: Likewise.
>     
>       obj-c/
>       * config-lang.in (gtfiles): Add c/c-parser.h.
> 
>       c-family/
>       * 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.
> 
>       * doc/invoke.texi (fgimple): Document.
>  
> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
> index 307862b..2997c83 100644
> --- a/gcc/c-family/c-common.c
> +++ b/gcc/c-family/c-common.c
> @@ -435,6 +435,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 547bab2..1fbe060 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 458d453..24d3b8e 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/Make-lang.in b/gcc/c/Make-lang.in
> index 72c9ae7..cd7108b 100644
> --- a/gcc/c/Make-lang.in
> +++ b/gcc/c/Make-lang.in
> @@ -51,7 +51,8 @@ CFLAGS-c/gccspec.o += $(DRIVER_DEFINES)
>  # Language-specific object files for C and Objective C.
>  C_AND_OBJC_OBJS = attribs.o c/c-errors.o c/c-decl.o c/c-typeck.o \
>    c/c-convert.o c/c-aux-info.o c/c-objc-common.o c/c-parser.o \
> -  c/c-array-notation.o c/c-fold.o $(C_COMMON_OBJS) $(C_TARGET_OBJS)
> +  c/c-array-notation.o c/c-fold.o c/gimple-parser.o \
> +  $(C_COMMON_OBJS) $(C_TARGET_OBJS)
>  
>  # Language-specific object files for C.
>  C_OBJS = c/c-lang.o c-family/stub-objc.o $(C_AND_OBJC_OBJS)
> diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
> index 6bc42da..d21b8e9 100644
> --- a/gcc/c/c-parser.c
> +++ b/gcc/c/c-parser.c
> @@ -59,6 +59,8 @@ along with GCC; see the file COPYING3.  If not see
>  #include "gimple-expr.h"
>  #include "context.h"
>  #include "gcc-rich-location.h"
> +#include "c-parser.h"
> +#include "gimple-parser.h"
>  
>  /* We need to walk over decls with incomplete struct/union/enum types
>     after parsing the whole translation unit.
> @@ -150,63 +152,6 @@ c_parse_init (void)
>      }
>  }
>  
> -/* The C lexer intermediates between the lexer in cpplib and c-lex.c
> -   and the C parser.  Unlike the C++ lexer, the parser structure
> -   stores the lexer information instead of using a separate structure.
> -   Identifiers are separated into ordinary identifiers, type names,
> -   keywords and some other Objective-C types of identifiers, and some
> -   look-ahead is maintained.
> -
> -   ??? It might be a good idea to lex the whole file up front (as for
> -   C++).  It would then be possible to share more of the C and C++
> -   lexer code, if desired.  */
> -
> -/* More information about the type of a CPP_NAME token.  */
> -enum c_id_kind {
> -  /* An ordinary identifier.  */
> -  C_ID_ID,
> -  /* An identifier declared as a typedef name.  */
> -  C_ID_TYPENAME,
> -  /* An identifier declared as an Objective-C class name.  */
> -  C_ID_CLASSNAME,
> -  /* An address space identifier.  */
> -  C_ID_ADDRSPACE,
> -  /* Not an identifier.  */
> -  C_ID_NONE
> -};
> -
> -/* A single C token after string literal concatenation and conversion
> -   of preprocessing tokens to tokens.  */
> -struct GTY (()) c_token {
> -  /* The kind of token.  */
> -  ENUM_BITFIELD (cpp_ttype) type : 8;
> -  /* If this token is a CPP_NAME, this value indicates whether also
> -     declared as some kind of type.  Otherwise, it is C_ID_NONE.  */
> -  ENUM_BITFIELD (c_id_kind) id_kind : 8;
> -  /* If this token is a keyword, this value indicates which keyword.
> -     Otherwise, this value is RID_MAX.  */
> -  ENUM_BITFIELD (rid) keyword : 8;
> -  /* If this token is a CPP_PRAGMA, this indicates the pragma that
> -     was seen.  Otherwise it is PRAGMA_NONE.  */
> -  ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
> -  /* The location at which this token was found.  */
> -  location_t location;
> -  /* The value associated with this token, if any.  */
> -  tree value;
> -  /* Token flags.  */
> -  unsigned char flags;
> -
> -  source_range get_range () const
> -  {
> -    return get_range_from_loc (line_table, location);
> -  }
> -
> -  location_t get_finish () const
> -  {
> -    return get_range ().m_finish;
> -  }
> -};
> -
>  /* A parser structure recording information about the state and
>     context of parsing.  Includes lexer information with up to two
>     tokens of look-ahead; more are not needed for C.  */
> @@ -259,6 +204,30 @@ struct GTY(()) c_parser {
>    vec <c_token, va_gc> *cilk_simd_fn_tokens;
>  };
>  
> +/* Return a pointer to the Nth token in PARERs tokens_buf.  */
> +
> +c_token *
> +c_parser_tokens_buf (c_parser *parser, unsigned n)
> +{
> +  return &parser->tokens_buf[n];
> +}
> +
> +/* Return the error state of PARSER.  */
> +
> +bool
> +c_parser_error (c_parser *parser)
> +{
> +  return parser->error;
> +}
> +
> +/* Set the error state of PARSER to ERR.  */
> +
> +void
> +c_parser_set_error (c_parser *parser, bool err)
> +{
> +  parser->error = err;
> +}
> +
>  
>  /* The actual parser and external interface.  ??? Does this need to be
>     garbage-collected?  */
> @@ -454,7 +423,7 @@ c_lex_one_token (c_parser *parser, c_token *token)
>  /* Return a pointer to the next token from PARSER, reading it in if
>     necessary.  */
>  
> -static inline c_token *
> +c_token *
>  c_parser_peek_token (c_parser *parser)
>  {
>    if (parser->tokens_avail == 0)
> @@ -465,37 +434,10 @@ c_parser_peek_token (c_parser *parser)
>    return &parser->tokens[0];
>  }
>  
> -/* Return true if the next token from PARSER has the indicated
> -   TYPE.  */
> -
> -static inline bool
> -c_parser_next_token_is (c_parser *parser, enum cpp_ttype type)
> -{
> -  return c_parser_peek_token (parser)->type == type;
> -}
> -
> -/* Return true if the next token from PARSER does not have the
> -   indicated TYPE.  */
> -
> -static inline bool
> -c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type)
> -{
> -  return !c_parser_next_token_is (parser, type);
> -}
> -
> -/* Return true if the next token from PARSER is the indicated
> -   KEYWORD.  */
> -
> -static inline bool
> -c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
> -{
> -  return c_parser_peek_token (parser)->keyword == keyword;
> -}
> -
>  /* Return a pointer to the next-but-one token from PARSER, reading it
>     in if necessary.  The next token is already read in.  */
>  
> -static c_token *
> +c_token *
>  c_parser_peek_2nd_token (c_parser *parser)
>  {
>    if (parser->tokens_avail >= 2)
> @@ -511,7 +453,7 @@ c_parser_peek_2nd_token (c_parser *parser)
>  /* Return a pointer to the Nth token from PARSER, reading it
>     in if necessary.  The N-1th token is already read in.  */
>  
> -static c_token *
> +c_token *
>  c_parser_peek_nth_token (c_parser *parser, unsigned int n)
>  {
>    /* N is 1-based, not zero-based.  */
> @@ -570,7 +512,7 @@ c_keyword_starts_typename (enum rid keyword)
>  
>  /* Return true if TOKEN can start a type name,
>     false otherwise.  */
> -static bool
> +bool
>  c_token_starts_typename (c_token *token)
>  {
>    switch (token->type)
> @@ -601,18 +543,6 @@ c_token_starts_typename (c_token *token)
>      }
>  }
>  
> -enum c_lookahead_kind {
> -  /* Always treat unknown identifiers as typenames.  */
> -  cla_prefer_type,
> -
> -  /* Could be parsing a nonabstract declarator.  Only treat an identifier
> -     as a typename if followed by another identifier or a star.  */
> -  cla_nonabstract_decl,
> -
> -  /* Never treat identifiers as typenames.  */
> -  cla_prefer_id
> -};
> -
>  /* Return true if the next token from PARSER can start a type name,
>     false otherwise.  LA specifies how to do lookahead in order to
>     detect unknown type names.  If unsure, pick CLA_PREFER_ID.  */
> @@ -779,7 +709,7 @@ c_token_starts_declaration (c_token *token)
>  
>  /* Return true if the next token from PARSER can start declaration
>     specifiers, false otherwise.  */
> -static inline bool
> +bool
>  c_parser_next_token_starts_declspecs (c_parser *parser)
>  {
>    c_token *token = c_parser_peek_token (parser);
> @@ -801,7 +731,7 @@ c_parser_next_token_starts_declspecs (c_parser *parser)
>  
>  /* Return true if the next tokens from PARSER can start declaration
>     specifiers or a static assertion, false otherwise.  */
> -static inline bool
> +bool
>  c_parser_next_tokens_start_declaration (c_parser *parser)
>  {
>    c_token *token = c_parser_peek_token (parser);
> @@ -829,7 +759,7 @@ c_parser_next_tokens_start_declaration (c_parser *parser)
>  
>  /* Consume the next token from PARSER.  */
>  
> -static void
> +void
>  c_parser_consume_token (c_parser *parser)
>  {
>    gcc_assert (parser->tokens_avail >= 1);
> @@ -922,7 +852,7 @@ c_parser_peek_conflict_marker (c_parser *parser, enum 
> cpp_ttype tok1_kind,
>     this way is not i18n-friendly and some other approach should be
>     used.  */
>  
> -static void
> +void
>  c_parser_error (c_parser *parser, const char *gmsgid)
>  {
>    c_token *token = c_parser_peek_token (parser);
> @@ -965,7 +895,7 @@ c_parser_error (c_parser *parser, const char *gmsgid)
>     been produced and no message will be produced this time.  Returns
>     true if found, false otherwise.  */
>  
> -static bool
> +bool
>  c_parser_require (c_parser *parser,
>                 enum cpp_ttype type,
>                 const char *msgid)
> @@ -1008,7 +938,7 @@ c_parser_require_keyword (c_parser *parser,
>     already been produced and no message will be produced this
>     time.  */
>  
> -static void
> +void
>  c_parser_skip_until_found (c_parser *parser,
>                          enum cpp_ttype type,
>                          const char *msgid)
> @@ -1243,42 +1173,6 @@ restore_extension_diagnostics (int flags)
>    warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0);
>  }
>  
> -/* Possibly kinds of declarator to parse.  */
> -enum c_dtr_syn {
> -  /* A normal declarator with an identifier.  */
> -  C_DTR_NORMAL,
> -  /* An abstract declarator (maybe empty).  */
> -  C_DTR_ABSTRACT,
> -  /* A parameter declarator: may be either, but after a type name does
> -     not redeclare a typedef name as an identifier if it can
> -     alternatively be interpreted as a typedef name; see DR#009,
> -     applied in C90 TC1, omitted from C99 and reapplied in C99 TC2
> -     following DR#249.  For example, given a typedef T, "int T" and
> -     "int *T" are valid parameter declarations redeclaring T, while
> -     "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are
> -     abstract declarators rather than involving redundant parentheses;
> -     the same applies with attributes inside the parentheses before
> -     "T".  */
> -  C_DTR_PARM
> -};
> -
> -/* The binary operation precedence levels, where 0 is a dummy lowest level
> -   used for the bottom of the stack.  */
> -enum c_parser_prec {
> -  PREC_NONE,
> -  PREC_LOGOR,
> -  PREC_LOGAND,
> -  PREC_BITOR,
> -  PREC_BITXOR,
> -  PREC_BITAND,
> -  PREC_EQ,
> -  PREC_REL,
> -  PREC_SHIFT,
> -  PREC_ADD,
> -  PREC_MULT,
> -  NUM_PRECS
> -};
> -
>  /* Helper data structure for parsing #pragma acc routine.  */
>  struct oacc_routine_data {
>    bool error_seen; /* Set if error has been reported.  */
> @@ -1295,15 +1189,11 @@ static void c_parser_declaration_or_fndef (c_parser 
> *, bool, bool, bool,
>                                          bool * = NULL);
>  static void c_parser_static_assert_declaration_no_semi (c_parser *);
>  static void c_parser_static_assert_declaration (c_parser *);
> -static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
> -                             bool, bool, bool, enum c_lookahead_kind);
>  static struct c_typespec c_parser_enum_specifier (c_parser *);
>  static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
>  static tree c_parser_struct_declaration (c_parser *);
>  static struct c_typespec c_parser_typeof_specifier (c_parser *);
>  static tree c_parser_alignas_specifier (c_parser *);
> -static struct c_declarator *c_parser_declarator (c_parser *, bool, c_dtr_syn,
> -                                              bool *);
>  static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
>                                                       c_dtr_syn, bool *);
>  static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
> @@ -1343,7 +1233,6 @@ static struct c_expr c_parser_conditional_expression 
> (c_parser *,
>                                                     struct c_expr *, tree);
>  static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
>                                                tree);
> -static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
>  static struct c_expr c_parser_unary_expression (c_parser *);
>  static struct c_expr c_parser_sizeof_expression (c_parser *);
>  static struct c_expr c_parser_alignof_expression (c_parser *);
> @@ -1652,7 +1541,13 @@ static void c_finish_oacc_routine (struct 
> oacc_routine_data *, tree, bool);
>     OpenMP:
>  
>     declaration:
> -     threadprivate-directive  */
> +     threadprivate-directive
> +
> +   GIMPLE:
> +
> +   gimple-function-definition:
> +     declaration-specifiers[opt] __GIMPLE (gimple-pass-list) declarator
> +       declaration-list[opt] compound-statement  */
>  
>  static void
>  c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
> @@ -1752,6 +1647,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
> fndef_ok,
>        c_parser_skip_to_end_of_block_or_statement (parser);
>        return;
>      }
> +
>    finish_declspecs (specs);
>    bool auto_type_p = specs->typespec_word == cts_auto_type;
>    if (c_parser_next_token_is (parser, CPP_SEMICOLON))
> @@ -1882,7 +1778,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
> fndef_ok,
>        struct c_declarator *declarator;
>        bool dummy = false;
>        timevar_id_t tv;
> -      tree fnbody;
> +      tree fnbody = NULL_TREE;
>        /* Declaring either one or more declarators (in which case we
>        should diagnose if there were no declaration specifiers) or a
>        function definition (in which case the diagnostic for
> @@ -2173,9 +2069,24 @@ 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;
> -      fnbody = c_parser_compound_statement (parser);
> -      if (flag_cilkplus && contains_array_notation_expr (fnbody))
> -     fnbody = expand_array_notation_exprs (fnbody);
> +
> +      /* If the definition was marked with __GIMPLE then parse the
> +         function body as GIMPLE.  */
> +      if (specs->gimple_p)
> +     {
> +       cfun->pass_startwith = specs->gimple_pass;
> +       bool saved = in_late_binary_op;
> +       in_late_binary_op = true;
> +       c_parser_parse_gimple_body (parser);
> +       in_late_binary_op = saved;
> +     }
> +      else
> +     {
> +       fnbody = c_parser_compound_statement (parser);
> +       if (flag_cilkplus && contains_array_notation_expr (fnbody))
> +         fnbody = expand_array_notation_exprs (fnbody);
> +     }
> +      tree fndecl = current_function_decl;
>        if (nested)
>       {
>         tree decl = current_function_decl;
> @@ -2191,9 +2102,13 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
> fndef_ok,
>       }
>        else
>       {
> -       add_stmt (fnbody);
> +       if (fnbody)
> +         add_stmt (fnbody);
>         finish_function ();
>       }
> +      /* Get rid of the empty stmt list for GIMPLE.  */
> +      if (specs->gimple_p)
> +     DECL_SAVED_TREE (fndecl) = NULL_TREE;
>  
>        timevar_pop (tv);
>        break;
> @@ -2416,7 +2331,7 @@ c_parser_static_assert_declaration_no_semi (c_parser 
> *parser)
>       objc-protocol-refs
>  */
>  
> -static void
> +void
>  c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
>                   bool scspec_ok, bool typespec_ok, bool start_attr_ok,
>                   bool alignspec_ok, bool auto_type_ok,
> @@ -2681,6 +2596,14 @@ c_parser_declspecs (c_parser *parser, struct 
> c_declspecs *specs,
>         align = c_parser_alignas_specifier (parser);
>         declspecs_add_alignas (loc, specs, align);
>         break;
> +     case RID_GIMPLE:
> +       if (! flag_gimple)
> +         error_at (loc, "%<__GIMPLE%> only valid with -fgimple");
> +       c_parser_consume_token (parser);
> +       specs->gimple_p = true;
> +       specs->locations[cdw_gimple] = loc;
> +       specs->gimple_pass = c_parser_gimple_pass_list (parser);
> +       break;
>       default:
>         goto out;
>       }
> @@ -3415,7 +3338,7 @@ c_parser_alignas_specifier (c_parser * parser)
>     This function also accepts an omitted abstract declarator as being
>     an abstract declarator, although not part of the formal syntax.  */
>  
> -static struct c_declarator *
> +struct c_declarator *
>  c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
>                    bool *seen_id)
>  {
> @@ -6866,7 +6789,7 @@ c_parser_binary_expression (c_parser *parser, struct 
> c_expr *after,
>       ( type-name ) unary-expression
>  */
>  
> -static struct c_expr
> +struct c_expr
>  c_parser_cast_expression (c_parser *parser, struct c_expr *after)
>  {
>    location_t cast_loc = c_parser_peek_token (parser)->location;
> diff --git a/gcc/c/c-parser.h b/gcc/c/c-parser.h
> new file mode 100644
> index 0000000..04fa681
> --- /dev/null
> +++ b/gcc/c/c-parser.h
> @@ -0,0 +1,189 @@
> +/* Declarations for the parser for C and Objective-C.
> +   Copyright (C) 1987-2016 Free Software Foundation, Inc.
> +
> +   Parser actions based on the old Bison parser; structure somewhat
> +   influenced by and fragments based on the C++ parser.
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify it under
> +the terms of the GNU General Public License as published by the Free
> +Software Foundation; either version 3, or (at your option) any later
> +version.
> +
> +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> +for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with GCC; see the file COPYING3.  If not see
> +<http://www.gnu.org/licenses/>.  */
> +
> +#ifndef GCC_C_PARSER_H
> +#define GCC_C_PARSER_H
> +
> +/* The C lexer intermediates between the lexer in cpplib and c-lex.c
> +   and the C parser.  Unlike the C++ lexer, the parser structure
> +   stores the lexer information instead of using a separate structure.
> +   Identifiers are separated into ordinary identifiers, type names,
> +   keywords and some other Objective-C types of identifiers, and some
> +   look-ahead is maintained.
> +
> +   ??? It might be a good idea to lex the whole file up front (as for
> +   C++).  It would then be possible to share more of the C and C++
> +   lexer code, if desired.  */
> +
> +/* More information about the type of a CPP_NAME token.  */
> +enum c_id_kind {
> +  /* An ordinary identifier.  */
> +  C_ID_ID,
> +  /* An identifier declared as a typedef name.  */
> +  C_ID_TYPENAME,
> +  /* An identifier declared as an Objective-C class name.  */
> +  C_ID_CLASSNAME,
> +  /* An address space identifier.  */
> +  C_ID_ADDRSPACE,
> +  /* Not an identifier.  */
> +  C_ID_NONE
> +};
> +
> +/* A single C token after string literal concatenation and conversion
> +   of preprocessing tokens to tokens.  */
> +struct GTY (()) c_token {
> +  /* The kind of token.  */
> +  ENUM_BITFIELD (cpp_ttype) type : 8;
> +  /* If this token is a CPP_NAME, this value indicates whether also
> +     declared as some kind of type.  Otherwise, it is C_ID_NONE.  */
> +  ENUM_BITFIELD (c_id_kind) id_kind : 8;
> +  /* If this token is a keyword, this value indicates which keyword.
> +     Otherwise, this value is RID_MAX.  */
> +  ENUM_BITFIELD (rid) keyword : 8;
> +  /* If this token is a CPP_PRAGMA, this indicates the pragma that
> +     was seen.  Otherwise it is PRAGMA_NONE.  */
> +  ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
> +  /* The location at which this token was found.  */
> +  location_t location;
> +  /* The value associated with this token, if any.  */
> +  tree value;
> +  /* Token flags.  */
> +  unsigned char flags;
> +
> +  source_range get_range () const
> +  {
> +    return get_range_from_loc (line_table, location);
> +  }
> +
> +  location_t get_finish () const
> +  {
> +    return get_range ().m_finish;
> +  }
> +};
> +
> +/* The parser.  */
> +struct c_parser;
> +
> +/* Possibly kinds of declarator to parse.  */
> +enum c_dtr_syn {
> +  /* A normal declarator with an identifier.  */
> +  C_DTR_NORMAL,
> +  /* An abstract declarator (maybe empty).  */
> +  C_DTR_ABSTRACT,
> +  /* A parameter declarator: may be either, but after a type name does
> +     not redeclare a typedef name as an identifier if it can
> +     alternatively be interpreted as a typedef name; see DR#009,
> +     applied in C90 TC1, omitted from C99 and reapplied in C99 TC2
> +     following DR#249.  For example, given a typedef T, "int T" and
> +     "int *T" are valid parameter declarations redeclaring T, while
> +     "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are
> +     abstract declarators rather than involving redundant parentheses;
> +     the same applies with attributes inside the parentheses before
> +     "T".  */
> +  C_DTR_PARM
> +};
> +
> +/* The binary operation precedence levels, where 0 is a dummy lowest level
> +   used for the bottom of the stack.  */
> +enum c_parser_prec {
> +  PREC_NONE,
> +  PREC_LOGOR,
> +  PREC_LOGAND,
> +  PREC_BITOR,
> +  PREC_BITXOR,
> +  PREC_BITAND,
> +  PREC_EQ,
> +  PREC_REL,
> +  PREC_SHIFT,
> +  PREC_ADD,
> +  PREC_MULT,
> +  NUM_PRECS
> +};
> +
> +enum c_lookahead_kind {
> +  /* Always treat unknown identifiers as typenames.  */
> +  cla_prefer_type,
> +
> +  /* Could be parsing a nonabstract declarator.  Only treat an identifier
> +     as a typename if followed by another identifier or a star.  */
> +  cla_nonabstract_decl,
> +
> +  /* Never treat identifiers as typenames.  */
> +  cla_prefer_id
> +};
> +
> +
> +extern c_token * c_parser_peek_token (c_parser *parser);
> +extern c_token * c_parser_peek_2nd_token (c_parser *parser);
> +extern c_token * c_parser_peek_nth_token (c_parser *parser, unsigned int n);
> +extern bool c_parser_require (c_parser *parser, enum cpp_ttype type,
> +                           const char *msgid);
> +extern void c_parser_error (c_parser *parser, const char *gmsgid);
> +extern void c_parser_consume_token (c_parser *parser);
> +extern void c_parser_skip_until_found (c_parser *parser, enum cpp_ttype type,
> +                                    const char *msgid);
> +extern bool c_parser_next_token_starts_declspecs (c_parser *parser);
> +bool c_parser_next_tokens_start_declaration (c_parser *parser);
> +bool c_token_starts_typename (c_token *token);
> +
> +/* Abstraction to avoid defining c_parser here which messes up gengtype
> +   output wrt ObjC due to vec<c_token> routines being put in gtype-c.h
> +   but not gtype-objc.h.  */
> +extern c_token * c_parser_tokens_buf (c_parser *parser, unsigned n);
> +extern bool c_parser_error (c_parser *parser);
> +extern void c_parser_set_error (c_parser *parser, bool);
> +
> +/* Return true if the next token from PARSER has the indicated
> +   TYPE.  */
> +
> +static inline bool
> +c_parser_next_token_is (c_parser *parser, enum cpp_ttype type)
> +{
> +  return c_parser_peek_token (parser)->type == type;
> +}
> +
> +/* Return true if the next token from PARSER does not have the
> +   indicated TYPE.  */
> +
> +static inline bool
> +c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type)
> +{
> +  return !c_parser_next_token_is (parser, type);
> +}
> +
> +/* Return true if the next token from PARSER is the indicated
> +   KEYWORD.  */
> +
> +static inline bool
> +c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
> +{
> +  return c_parser_peek_token (parser)->keyword == keyword;
> +}
> +
> +extern struct c_declarator *
> +c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
> +                  bool *seen_id);
> +extern void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
> +                             bool, bool, bool, enum c_lookahead_kind);
> +extern struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
> +
> +#endif
> diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
> index e8060f8..a8cf353 100644
> --- a/gcc/c/c-tree.h
> +++ b/gcc/c/c-tree.h
> @@ -267,6 +267,7 @@ enum c_declspec_word {
>    cdw_saturating,
>    cdw_alignas,
>    cdw_address_space,
> +  cdw_gimple,
>    cdw_number_of_elements /* This one must always be the last
>                           enumerator.  */
>  };
> @@ -290,6 +291,8 @@ struct c_declspecs {
>       NULL; attributes (possibly from multiple lists) will be passed
>       separately.  */
>    tree attrs;
> +  /* The pass to start compiling a __GIMPLE function with.  */
> +  char *gimple_pass;
>    /* The base-2 log of the greatest alignment required by an _Alignas
>       specifier, in bytes, or -1 if no such specifiers with nonzero
>       alignment.  */
> @@ -362,6 +365,8 @@ struct c_declspecs {
>    /* Whether any alignment specifier (even with zero alignment) was
>       specified.  */
>    BOOL_BITFIELD alignas_p : 1;
> +  /* Whether any __GIMPLE specifier was specified.  */
> +  BOOL_BITFIELD gimple_p : 1;
>    /* The address space that the declaration belongs to.  */
>    addr_space_t address_space;
>  };
> diff --git a/gcc/c/config-lang.in b/gcc/c/config-lang.in
> index b9cdc8e..51fbb53 100644
> --- a/gcc/c/config-lang.in
> +++ b/gcc/c/config-lang.in
> @@ -29,4 +29,4 @@ compilers="cc1\$(exeext)"
>  
>  target_libs=
>  
> -gtfiles="\$(srcdir)/c/c-lang.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c 
> \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h 
> \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c 
> \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c 
> \$(srcdir)/c/c-objc-common.c \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-lang.h"
> +gtfiles="\$(srcdir)/c/c-lang.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c 
> \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h 
> \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c 
> \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c 
> \$(srcdir)/c/c-objc-common.c \$(srcdir)/c/c-parser.h \$(srcdir)/c/c-parser.c 
> \$(srcdir)/c/c-lang.h"
> diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
> new file mode 100644
> index 0000000..7f8d948
> --- /dev/null
> +++ b/gcc/c/gimple-parser.c
> @@ -0,0 +1,1483 @@
> +/* Parser for GIMPLE.
> +   Copyright (C) 2016 Free Software Foundation, Inc.
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify it under
> +the terms of the GNU General Public License as published by the Free
> +Software Foundation; either version 3, or (at your option) any later
> +version.
> +
> +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> +for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with GCC; see the file COPYING3.  If not see
> +<http://www.gnu.org/licenses/>.  */
> +
> +#include "config.h"
> +#include "system.h"
> +#include "coretypes.h"
> +#include "target.h"
> +#include "function.h"
> +#include "c-tree.h"
> +#include "timevar.h"
> +#include "stringpool.h"
> +#include "cgraph.h"
> +#include "attribs.h"
> +#include "stor-layout.h"
> +#include "varasm.h"
> +#include "trans-mem.h"
> +#include "c-family/c-pragma.h"
> +#include "c-lang.h"
> +#include "c-family/c-objc.h"
> +#include "plugin.h"
> +#include "omp-low.h"
> +#include "builtins.h"
> +#include "gomp-constants.h"
> +#include "c-family/c-indentation.h"
> +#include "gimple-expr.h"
> +#include "context.h"
> +#include "gcc-rich-location.h"
> +#include "c-parser.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"
> +#include "tree-dump.h"
> +
> +
> +/* Gimple parsing functions.  */
> +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_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 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 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);
> +
> +  /* While we have SSA names in the IL we do not have a CFG built yet
> +     and PHIs are represented using a PHI internal function.  We do
> +     have lowered control flow and exception handling (well, we do not
> +     have parser support for EH yet).  But as we still have BINDs
> +     we have to go through lowering again.  */
> +  cfun->curr_properties = PROP_gimple_any;
> +
> +  dump_function (TDI_generic, current_function_decl);
> +}
> +
> +/* 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;
> +
> +  /* A compund statement starts with optional declarations.  */
> +  while (c_parser_next_tokens_start_declaration (parser))
> +    {
> +      c_parser_gimple_declaration (parser);
> +      if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
> +     return false;
> +    }
> +
> +  while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
> +    {
> +      if (c_parser_error (parser))
> +     {
> +       c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
> +       return return_p;
> +     }
> +      else if (c_parser_next_token_is (parser, CPP_EOF))
> +     {
> +       c_parser_error (parser, "expected declaration or statement");
> +       return return_p;
> +     }
> +
> +      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_NAME:
> +       if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
> +         {
> +           c_parser_gimple_label (parser, seq);
> +           break;
> +         }
> +       goto expr_stmt;
> +
> +     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)))
> +    {
> +      /* TODO: have a gimple_cast_expr function.  */
> +      rhs = c_parser_cast_expression (parser, NULL);
> +      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;
> +     }
> +    }
> +
> +  /* 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;
> +     }
> +    }
> +
> +  switch (c_parser_peek_token (parser)->type)
> +    {
> +    case CPP_AND:
> +    case CPP_PLUS:
> +    case CPP_MINUS:
> +    case CPP_COMPL:
> +    case CPP_NOT:
> +    case CPP_MULT: /* pointer deref */
> +      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;
> +
> +    default:;
> +    }
> +
> +  /* 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_gimple_unary_expression (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 (c_parser_error (parser))
> +    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;
> +  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);
> +    case CPP_KEYWORD:
> +      switch (c_parser_peek_token (parser)->keyword)
> +     {
> +     case RID_REALPART:
> +       c_parser_consume_token (parser);
> +       op = c_parser_cast_expression (parser, NULL);
> +       return parser_build_unary_op (op_loc, REALPART_EXPR, op);
> +     case RID_IMAGPART:
> +       c_parser_consume_token (parser);
> +       op = c_parser_cast_expression (parser, NULL);
> +       return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
> +     default:
> +       return c_parser_gimple_postfix_expression (parser);
> +     }
> +    default:
> +      return c_parser_gimple_postfix_expression (parser);
> +    }
> +}
> +
> +/* Decompose ID into base name (ID until ver_offset) and VERSION.  Return
> +   true if ID matches a SSA name.  */
> +
> +static bool
> +c_parser_parse_ssa_name_id (tree id, unsigned *version, unsigned *ver_offset)
> +{
> +  const char *token = IDENTIFIER_POINTER (id);
> +  const char *var_version = strrchr (token, '_');
> +  if (! var_version)
> +    return false;
> +
> +  *ver_offset = var_version - token;
> +  for (const char *p = var_version + 1; *p; ++p)
> +    if (! ISDIGIT (*p))
> +      return false;
> +  *version = atoi (var_version + 1);
> +  return *version > 0;
> +}
> +
> +/* Get at the actual SSA name ID with VERSION starting at VER_OFFSET.
> +   TYPE is the type if the SSA name is being declared.  */
> +
> +static tree 
> +c_parser_parse_ssa_name (c_parser *parser,
> +                      tree id, tree type, unsigned version,
> +                      unsigned ver_offset)
> +{
> +  tree name = NULL_TREE;
> +  const char *token = IDENTIFIER_POINTER (id);
> +
> +  if (ver_offset == 0)
> +    {
> +      /* Anonymous unnamed SSA name.  */
> +      if (version < num_ssa_names)
> +     name = ssa_name (version);
> +      if (! name)
> +     {
> +       if (! type)
> +         {
> +           c_parser_error (parser, "SSA name not declared"); 
> +           return error_mark_node;
> +         }
> +       name = make_ssa_name_fn (cfun, type, NULL, version);
> +     }
> +    }
> +  else
> +    {
> +      if (version < num_ssa_names)
> +     name = ssa_name (version);
> +      if (! name)
> +     {
> +       /* Separate var name from version.  */
> +       char *var_name = XNEWVEC (char, ver_offset + 1);
> +       memcpy (var_name, token, ver_offset);
> +       var_name[ver_offset] = '\0';
> +       /* lookup for parent decl.  */
> +       id = get_identifier (var_name);
> +       tree parent = lookup_name (id);
> +       XDELETEVEC (var_name);
> +       if (! parent)
> +         {
> +           c_parser_error (parser, "base variable or SSA name not 
> declared"); 
> +           return error_mark_node;
> +         }
> +       if (VECTOR_TYPE_P (TREE_TYPE (parent))
> +           || TREE_CODE (TREE_TYPE (parent)) == COMPLEX_TYPE)
> +         DECL_GIMPLE_REG_P (parent) = 1;
> +       name = make_ssa_name_fn (cfun, parent,
> +                                gimple_build_nop (), version);
> +     }
> +    }
> +
> +  return name;
> +}
> +
> +/* Parse gimple postfix expression.
> +
> +   gimple-postfix-expression:
> +     gimple-primary-expression
> +     gimple-primary-xpression [ gimple-primary-expression ]
> +     gimple-primary-expression ( gimple-argument-expression-list[opt] )
> +     postfix-expression . identifier
> +     postfix-expression -> identifier
> +
> +   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;
> +       unsigned version, ver_offset;
> +       if (! lookup_name (id)
> +           && c_parser_parse_ssa_name_id (id, &version, &ver_offset))
> +         {
> +           c_parser_consume_token (parser);
> +           expr.value = c_parser_parse_ssa_name (parser, id, NULL_TREE,
> +                                                 version, ver_offset);
> +           /* For default definition SSA names.  */
> +           if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
> +               && c_parser_peek_2nd_token (parser)->type == CPP_NAME
> +               && strcmp ("D",
> +                          IDENTIFIER_POINTER
> +                            (c_parser_peek_2nd_token (parser)->value)) == 0
> +               && c_parser_peek_nth_token (parser, 3)->type == 
> CPP_CLOSE_PAREN)
> +             {
> +               c_parser_consume_token (parser);
> +               c_parser_consume_token (parser);
> +               c_parser_consume_token (parser);
> +               if (! SSA_NAME_IS_DEFAULT_DEF (expr.value))
> +                 {
> +                   set_ssa_default_def (cfun, SSA_NAME_VAR (expr.value),
> +                                        expr.value);
> +                   SSA_NAME_DEF_STMT (expr.value) = gimple_build_nop ();
> +                 }
> +             }
> +         }
> +       else
> +         {
> +           c_parser_consume_token (parser);
> +           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;
> +  tree ident;
> +  location_t comp_loc;
> +
> +  while (true)
> +    {
> +      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 = c_parser_tokens_buf (parser, 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 = c_parser_tokens_buf (parser, 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;
> +       }
> +     case CPP_DOT:
> +       {
> +         /* Structure element reference.  */
> +         c_parser_consume_token (parser);
> +         if (c_parser_next_token_is (parser, CPP_NAME))
> +           {
> +             c_token *comp_tok = c_parser_peek_token (parser);
> +             ident = comp_tok->value;
> +             comp_loc = comp_tok->location;
> +           }
> +         else
> +           {
> +             c_parser_error (parser, "expected identifier");
> +             expr.set_error ();
> +             expr.original_code = ERROR_MARK;
> +             expr.original_type = NULL;
> +             return expr;
> +           }
> +         start = expr.get_start ();
> +         finish = c_parser_peek_token (parser)->get_finish ();
> +         c_parser_consume_token (parser);
> +         expr.value = build_component_ref (op_loc, expr.value, ident,
> +                                           comp_loc);
> +         set_c_expr_source_range (&expr, start, finish);
> +         expr.original_code = ERROR_MARK;
> +         if (TREE_CODE (expr.value) != COMPONENT_REF)
> +           expr.original_type = NULL;
> +         else
> +           {
> +             /* Remember the original type of a bitfield.  */
> +             tree field = TREE_OPERAND (expr.value, 1);
> +             if (TREE_CODE (field) != FIELD_DECL)
> +               expr.original_type = NULL;
> +             else
> +               expr.original_type = DECL_BIT_FIELD_TYPE (field);
> +           }
> +         break;
> +       }
> +     case CPP_DEREF:
> +       {
> +         /* Structure element reference.  */
> +         c_parser_consume_token (parser);
> +         if (c_parser_next_token_is (parser, CPP_NAME))
> +           {
> +             c_token *comp_tok = c_parser_peek_token (parser);
> +             ident = comp_tok->value;
> +             comp_loc = comp_tok->location;
> +           }
> +         else
> +           {
> +             c_parser_error (parser, "expected identifier");
> +             expr.set_error ();
> +             expr.original_code = ERROR_MARK;
> +             expr.original_type = NULL;
> +             return expr;
> +           }
> +         start = expr.get_start ();
> +         finish = c_parser_peek_token (parser)->get_finish ();
> +         c_parser_consume_token (parser);
> +         expr.value = build_component_ref (op_loc,
> +                                           build_simple_mem_ref_loc
> +                                             (op_loc, expr.value),
> +                                           ident, comp_loc);
> +         set_c_expr_source_range (&expr, start, finish);
> +         expr.original_code = ERROR_MARK;
> +         if (TREE_CODE (expr.value) != COMPONENT_REF)
> +           expr.original_type = NULL;
> +         else
> +           {
> +             /* Remember the original type of a bitfield.  */
> +             tree field = TREE_OPERAND (expr.value, 1);
> +             if (TREE_CODE (field) != FIELD_DECL)
> +               expr.original_type = NULL;
> +             else
> +               expr.original_type = DECL_BIT_FIELD_TYPE (field);
> +           }
> +         break;
> +       }
> +     default:
> +       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")
> + */
> +
> +char *
> +c_parser_gimple_pass_list (c_parser *parser)
> +{
> +  char *pass = NULL;
> +
> +  /* Accept __GIMPLE.  */
> +  if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
> +    return NULL;
> +  c_parser_consume_token (parser);
> +
> +  if (c_parser_next_token_is (parser, CPP_NAME))
> +    {
> +      const char *op = IDENTIFIER_POINTER (c_parser_peek_token 
> (parser)->value);
> +      c_parser_consume_token (parser);
> +      if (! strcmp (op, "startwith"))
> +     {
> +       if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
> +         return NULL;
> +       if (c_parser_next_token_is_not (parser, CPP_STRING))
> +         {
> +           error_at (c_parser_peek_token (parser)->location,
> +                     "expected pass name");
> +           return NULL;
> +         }
> +       pass = xstrdup (TREE_STRING_POINTER
> +                             (c_parser_peek_token (parser)->value));
> +       c_parser_consume_token (parser);
> +       if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
> +         return NULL;
> +     }
> +      else
> +     {
> +       error_at (c_parser_peek_token (parser)->location,
> +                 "invalid operation");
> +       return NULL;
> +     }
> +    }
> +
> +  if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
> +    return NULL;
> +
> +  return pass;
> +}
> +
> +/* 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 %<;%>");
> +      c_parser_set_error (parser, 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))
> +    {
> +      /* Handle SSA name decls specially, they do not go into the identifier
> +         table but we simply build the SSA name for later lookup.  */
> +      unsigned version, ver_offset;
> +      if (declarator->kind == cdk_id
> +       && is_gimple_reg_type (specs->type)
> +       && c_parser_parse_ssa_name_id (declarator->u.id,
> +                                      &version, &ver_offset)
> +       /* The following restricts it to unnamed anonymous SSA names
> +          which fails parsing of named ones in dumps (we could
> +          decide to not dump their name for -gimple).  */
> +       && ver_offset == 0)
> +     c_parser_parse_ssa_name (parser, declarator->u.id, specs->type,
> +                              version, ver_offset);
> +      else
> +     {
> +       tree postfix_attrs = NULL_TREE;
> +       tree all_prefix_attrs = specs->attrs;
> +       specs->attrs = NULL;
> +       tree decl = start_decl (declarator, specs, false,
> +                               chainon (postfix_attrs, all_prefix_attrs));
> +       if (decl)
> +         finish_decl (decl, UNKNOWN_LOCATION, NULL_TREE, NULL_TREE,
> +                      NULL_TREE);
> +     }
> +    }
> +  else
> +    {
> +      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;
> +  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;
> +             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_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);
> +                 if (c_parser_next_token_is (parser, CPP_NAME))
> +                   {
> +                     label = c_parser_peek_token (parser)->value;
> +                     c_parser_consume_token (parser);
> +                     tree decl = lookup_label_for_goto (loc, label);
> +                     case_label = build_case_label (exp1.value, NULL_TREE,
> +                                                    decl);
> +                     labels.safe_push (case_label);
> +                     if (! c_parser_require (parser, CPP_SEMICOLON,
> +                                             "expected %<;%>"))
> +                       return;
> +                   }
> +                 else if (! c_parser_require (parser, CPP_NAME,
> +                                              "expected label"))
> +                   return;
> +               }
> +             else if (! c_parser_require (parser, CPP_SEMICOLON,
> +                                         "expected %<:%>"))
> +               return;
> +             break;
> +           }
> +         case RID_DEFAULT:
> +           {
> +             location_t loc = c_parser_peek_token (parser)->location;
> +             c_parser_consume_token (parser);
> +             if (c_parser_next_token_is (parser, CPP_COLON))
> +               {
> +                 c_parser_consume_token (parser);
> +                 if (c_parser_next_token_is (parser, CPP_NAME))
> +                   {
> +                     label = c_parser_peek_token (parser)->value;
> +                     c_parser_consume_token (parser);
> +                     tree decl = lookup_label_for_goto (loc, label);
> +                     default_label = build_case_label (NULL_TREE, NULL_TREE,
> +                                                       decl);
> +                     if (! c_parser_require (parser, CPP_SEMICOLON,
> +                                             "expected %<;%>"))
> +                       return;
> +                   }
> +                 else if (! c_parser_require (parser, CPP_NAME,
> +                                              "expected label"))
> +                   return;
> +               }
> +             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 = 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;
> +}
> diff --git a/gcc/c/gimple-parser.h b/gcc/c/gimple-parser.h
> new file mode 100644
> index 0000000..f72b626
> --- /dev/null
> +++ b/gcc/c/gimple-parser.h
> @@ -0,0 +1,27 @@
> +/* Declarations for the parser for GIMPLE.
> +   Copyright (C) 2016 Free Software Foundation, Inc.
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify it under
> +the terms of the GNU General Public License as published by the Free
> +Software Foundation; either version 3, or (at your option) any later
> +version.
> +
> +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> +for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with GCC; see the file COPYING3.  If not see
> +<http://www.gnu.org/licenses/>.  */
> +
> +#ifndef GCC_GIMPLE_PARSER_H
> +#define GCC_GIMPLE_PARSER_H
> +
> +/* Gimple parsing functions.  */
> +extern void c_parser_parse_gimple_body (c_parser *);
> +extern char *c_parser_gimple_pass_list (c_parser *);
> +
> +#endif
> diff --git a/gcc/objc/config-lang.in b/gcc/objc/config-lang.in
> index f5a74a7..912af22 100644
> --- a/gcc/objc/config-lang.in
> +++ b/gcc/objc/config-lang.in
> @@ -35,4 +35,4 @@ lang_requires="c"
>  # Order is important.  If you change this list, make sure you test
>  # building without C++ as well; that is, remove the gcc/cp directory,
>  # and build with --enable-languages=c,objc.
> -gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h 
> \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c 
> \$(srcdir)/objc/objc-runtime-shared-support.c 
> \$(srcdir)/objc/objc-gnu-runtime-abi-01.c 
> \$(srcdir)/objc/objc-next-runtime-abi-01.c 
> \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c/c-parser.c 
> \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c/c-lang.h 
> \$(srcdir)/c/c-objc-common.c \$(srcdir)/c-family/c-common.c 
> \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c 
> \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c"
> +gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h 
> \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c 
> \$(srcdir)/objc/objc-runtime-shared-support.c 
> \$(srcdir)/objc/objc-gnu-runtime-abi-01.c 
> \$(srcdir)/objc/objc-next-runtime-abi-01.c 
> \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c/c-parser.h 
> \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c 
> \$(srcdir)/c/c-lang.h \$(srcdir)/c/c-objc-common.c 
> \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h 
> \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h 
> \$(srcdir)/c-family/c-pragma.c"
> 
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 5ccd424..e0517b6 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -179,7 +179,7 @@ in the following sections.
>  @xref{C Dialect Options,,Options Controlling C Dialect}.
>  @gccoptlist{-ansi  -std=@var{standard}  -fgnu89-inline @gol
>  -aux-info @var{filename} -fallow-parameterless-variadic-functions @gol
> --fno-asm  -fno-builtin  -fno-builtin-@var{function} @gol
> +-fno-asm  -fno-builtin  -fno-builtin-@var{function} -fgimple@gol
>  -fhosted  -ffreestanding -fopenacc -fopenmp -fopenmp-simd @gol
>  -fms-extensions -fplan9-extensions -fsso-struct=@var{endianness}
>  -fallow-single-precision  -fcond-mismatch -flax-vector-conversions @gol
> @@ -1948,6 +1948,13 @@ built-in functions selectively when using 
> @option{-fno-builtin} or
>  #define strcpy(d, s)    __builtin_strcpy ((d), (s))
>  @end smallexample
>  
> +@item -fgimple
> +@opindex fgimple
> +
> +Enable parsing of function definitions marked with @code{__GIMPLE}.
> +This is an experimental feature that allows unit testing of GIMPLE
> +passes.
> +
>  @item -fhosted
>  @opindex fhosted
>  @cindex hosted environment
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to