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