On 24 August 2016 at 15:32, Richard Biener <richard.guent...@gmail.com> wrote: > On Mon, Aug 22, 2016 at 8:40 PM, Prasad Ghangal > <prasad.ghan...@gmail.com> wrote: >> On 22 August 2016 at 16:55, Trevor Saunders <tbsau...@tbsaunde.org> wrote: >>> On Sun, Aug 21, 2016 at 10:35:17PM +0530, Prasad Ghangal wrote: >>>> Hi all, >>>> >>>> As a part of my gsoc project. I have completed the following tasks: >>>> >>>> * Parsed gimple-expression >>>> * Parsed gimple-labels >>>> * Parsed local declaration >>>> * Parsed gimple-goto statement >>>> * Parsed gimple-if-else statement >>>> * Parsed gimple-switch statement >>>> * Parsed gimple-return statement >>>> * Parsed gimple-PHI function >>>> * Parsed gimple ssa-names along with default def >>>> * Parsed gimple-call >>>> >>>> * Hacked pass manager to add support for startwith (pass-name) to skip >>>> early opt passes >>>> * Modified gimple dump for making it parsable >>>> >>>> I am willing to continue work on the project, some TODOs for the projects >>>> are: >>>> >>>> * Error handling >>>> * Parse more gimple syntax >>>> * Add startwith support for IPA passes >>>> >>>> The complete code of gimple fe project can be found at >>>> https://github.com/PrasadG193/gcc_gimple_fe >>>> >>>> >>>> PFA patch for complete project (rebased for latest trunk revision). >>>> I have successfully bootstrapped and tested on x86_64-pc-linux-gnu. >>>> Some testcases failed due to modified gimple dump as expected. >>>> >>>> >>>> Thanks, >>>> Prasad >>> >>> only some rather minor comments >>> >>> >>> +++ b/gcc/c/c-parser.c >>> @@ -59,6 +59,18 @@ along with GCC; see the file COPYING3. If not see >>> #include "gimple-expr.h" >>> #include "context.h" >>> #include "gcc-rich-location.h" >>> +#include "tree-vrp.h" >>> >>> given that you need these headers it might be better to put most of the >>> gimple parsing in its own file so only what actually needs to know about >>> this part of the compiler does now about it. >>> >>> +void >>> +c_parser_parse_gimple_body (c_parser *parser) >>> +{ >>> + bool return_p = false; >>> + gimple_seq seq; >>> + gimple_seq body; >>> + tree stmt = push_stmt_list (); >>> >>> it would be nice to move the declarations down to their first use. >>> >>> + gimple *ret; >>> + ret = gimple_build_return (NULL); >>> >>> there's no reason for a separate declaration and assignment ;) >>> >>> + tree block = NULL; >>> + block = pop_scope (); >>> >>> same here, and a number of other places. >>> >>> +c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq) >>> +{ >>> + bool return_p = false; >>> + >>> + if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) >>> + return return_p; >>> >>> return false would work fine. >>> >>> + >>> + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) >>> + { >>> + c_parser_consume_token (parser); >>> + goto out; >>> >>> I don't see the need for the gotos, there's no cleanup in this function. >>> >>> + /* gimple PHI expression. */ >>> + if (c_parser_next_token_is_keyword (parser, RID_PHI)) >>> + { >>> + c_parser_consume_token (parser); >>> + >>> + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) >>> + { >>> + return; >>> + } >>> + >>> + gcall *call_stmt; >>> + tree arg = NULL_TREE; >>> + vec<tree> vargs = vNULL; >>> >>> I think you can use auto_vec here, as is I think this leaks the vectors >>> storage. >>> >>> +c_parser_gimple_binary_expression (c_parser *parser, enum tree_code >>> *subcode) >>> >>> you can skip the explicit 'enum' keyword. >>> >>> + struct { >>> + /* The expression at this stack level. */ >>> + struct c_expr expr; >>> >>> similar with struct here. >>> >>> + /* The precedence of the operator on its left, PREC_NONE at the >>> + bottom of the stack. */ >>> + enum c_parser_prec prec; >>> + /* The operation on its left. */ >>> + enum tree_code op; >>> + /* The source location of this operation. */ >>> + location_t loc; >>> + } stack[2]; >>> + int sp; >>> + /* Location of the binary operator. */ >>> + location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */ >>> +#define POP >>> \ >>> >>> it seems like it would be nicer to name the type, and then make this a >>> function. >>> >>> + RO_UNARY_STAR); >>> + ret.src_range.m_start = op_loc; >>> + ret.src_range.m_finish = finish; >>> + return ret; >>> + } >>> + case CPP_PLUS: >>> + if (!c_dialect_objc () && !in_system_header_at (input_location)) >>> + warning_at (op_loc, >>> + OPT_Wtraditional, >>> + "traditional C rejects the unary plus operator"); >>> >>> does it really make sense to warn about C issues when compiling gimple? >>> >>> +c_parser_parse_ssa_names (c_parser *parser) >>> +{ >>> + tree id = NULL_TREE; >>> + c_expr ret; >>> + char *var_name, *var_version, *token; >>> + ret.original_code = ERROR_MARK; >>> + ret.original_type = NULL; >>> + >>> + /* ssa token string. */ >>> + const char *ssa_token = NULL; >>> + ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); >>> + token = new char [strlen (ssa_token)]; >>> >>> I'm not sure I see why you need this copy, and getting rid of it would >>> mean you don't need to free it. >>> >>> + strcpy (token, ssa_token); >>> + >>> + /* seperate var name and version. */ >>> + var_version = strrchr (token, '_'); >>> + if (var_version) >>> + { >>> + var_name = new char[var_version - token + 1]; >>> >>> you should free this when done with it. >>> >>> +c_parser_gimple_postfix_expression (c_parser *parser) >>> +{ >>> + struct c_expr expr; >>> + location_t loc = c_parser_peek_token (parser)->location;; >>> >>> extra ; >>> >>> + case CPP_OBJC_STRING: >>> + gcc_assert (c_dialect_objc ()); >>> + expr.value >>> + = objc_build_string_object (c_parser_peek_token (parser)->value); >>> + set_c_expr_source_range (&expr, tok_range); >>> + c_parser_consume_token (parser); >>> + break; >>> >>> is there a reason to support objc stuff in gimple? >>> >>> +c_parser_gimple_expr_list (c_parser *parser, bool convert_p, >>> + vec<tree, va_gc> **p_orig_types, >>> + location_t *sizeof_arg_loc, tree *sizeof_arg, >>> + vec<location_t> *locations, >>> + unsigned int *literal_zero_mask) >>> +{ >>> + vec<tree, va_gc> *ret; >>> + vec<tree, va_gc> *orig_types; >>> + struct c_expr expr; >>> + location_t loc = c_parser_peek_token (parser)->location; >>> + location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION; >>> + unsigned int idx = 0; >>> + >>> + ret = make_tree_vector (); >>> + if (p_orig_types == NULL) >>> + orig_types = NULL; >>> + else >>> + orig_types = make_tree_vector (); >>> + >>> + if (sizeof_arg != NULL >>> + && c_parser_next_token_is_keyword (parser, RID_SIZEOF)) >>> + cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location; >>> + if (literal_zero_mask) >>> + c_parser_check_literal_zero (parser, literal_zero_mask, 0); >>> + expr = c_parser_gimple_unary_expression (parser); >>> + if (convert_p) >>> + expr = convert_lvalue_to_rvalue (loc, expr, true, true); >>> + ret->quick_push (expr.value); >>> >>> That kind of relies on the details of make_tree_vector (), so it seems >>> somewhat safer to use vec_safe_push. >>> >>> + if (orig_types) >>> + orig_types->quick_push (expr.original_type); >>> >>> same >>> >>> +c_parser_gimple_declaration (c_parser *parser) >>> +{ >>> + struct c_declspecs *specs; >>> + struct c_declarator *declarator; >>> + specs = build_null_declspecs (); >>> + c_parser_declspecs (parser, specs, true, true, true, >>> + true, true, cla_nonabstract_decl); >>> + finish_declspecs (specs); >>> + bool auto_type_p = specs->typespec_word == cts_auto_type; >>> >>> is it useful to support auto here in gimple? >>> >>> +c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq) >>> +{ >>> + c_expr cond_expr; >>> + tree case_label, label; >>> + vec<tree> labels = vNULL; >>> >>> auto_vec? >>> >>> +static void >>> +c_finish_gimple_return (location_t loc, tree retval) >>> +{ >>> + tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)); >>> + >>> + /* Use the expansion point to handle cases such as returning NULL >>> + in a function returning void. */ >>> + source_location xloc = expansion_point_location_if_in_system_header >>> (loc); >>> + >>> + if (TREE_THIS_VOLATILE (current_function_decl)) >>> + warning_at (xloc, 0, >>> + "function declared %<noreturn%> has a %<return%> >>> statement"); >>> + >>> + if (!retval) >>> + { >>> + current_function_returns_null = 1; >>> + if ((warn_return_type || flag_isoc99) >>> >>> I'm not sure what to do about warnings, but checking the language we are >>> compiling as seems kind of wrong when we're compiling gimple? >>> >>> @@ -228,6 +228,12 @@ struct GTY(()) function { >>> /* GIMPLE body for this function. */ >>> gimple_seq gimple_body; >>> >>> + /* GIMPLEFE pass to start with */ >>> + opt_pass *pass_startwith = NULL; >>> >>> I'm guessing you've only compiled in C++11 mode? because I'm pretty sure >>> you are using a C++11 feature here (the default member value you >>> assign). >>> >>> Thanks! >>> >>> Trev >>> >> >> Hi Trevor, >> >> Thanks for your feedback. I had missed removing some unwanted code >> while code cleanup. I have updated the patch. >> I am not sure if we should move all gimple parsing related functions >> to the new file (?) > > I think it might be good to make the parts of the C parser you use more > obvious (you'd need to export functions like c_parser_next_token_is). > > The easiest way to "force" that is to put all of the gimple parsing into > a separate file. > > Note I am not so much concerned about this at the moment, the parts to > improve would be avoiding more of the C-isms like convert_lvalue_to_rvalue, > handling of SIZEOF_EXPR and other stuff that looks redundant (you've > probably copied this from the C parsing routines and refactored it). > Also the GIMPLE parser shouldn't do any warnings (just spotted > a call to warn_for_memset). > PFA updated patch (successfully bootstrapped and tested on x86_64-pc-linux-gnu). I have removed unnecessary code. On side I am also trying to move gimple parser related functions to new file. But for it we also have to move structs like c_token, c_parser. Won't it disturb the c-parser code structure ?
Thanks, Prasad > Thanks, > Richard. > >> I am not getting what did you mean by C++11 mode (I am not explicitly >> giving any option while configure or make). I also have successfully >> bootstrapped and tested the project on another system. Is there any >> way to check that ? >> >> >> Thanks, >> Prasad
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1929ba8..cded23f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,55 @@ +2016-08-21 Prasad Ghangal <prasad.ghan...@gmail.com> + + * cgraphunit.c (cgraph_node::assemble_thunks_and_aliases): New variable. + (cgraph_node::expand): Add new argument to function. + execute_pass_list, guard gcc_assert (TREE_ASM_WRITTEN (decl)) with + condition. + * coretypes.h (tree_node *const_tree): New decl, add headers, new + variables. + * function.h (struct GTY()) function): Add new member to store + startwith pass also add new member as a flag. + * gimple-pretty-print.c (dump_gimple_switch): Change dumping formats. + (dump_gimple_label): Remove condition for DECL_NONLOCAL, flags & + TDF_EH, EH_LANDING_PAD_NR. Change dumping format. + (dump_ssaname_info_to_file): Change passing arguments of dump_gimple_phi + (dump_gimple_phi): Remove condition for comment, change format of + dumping PHI and PHI arguments. + (pp_gimple_stmt_1): Remove argument of dump_gimple_phi function. + (dump_gimple_bb_header): Change format of dumping gimple basic block + header. + (dump_phi_nodes): Remove argument of dump_gimple_phi function. + (pp_cfg_jump): Remove stmt, remove condition for GIMPLE_LABEL, change + dumping format of gimple basic block header. + (gimple_dump_bb_for_graph): Change format of dumping gimple basic block + * gimplify.c (gimplify_function_tree): Add condition for presence of + gimple body in the cfun. + * internal-fn.c (expand_PHI): New function. + * internal-fn.h (expand_PHI): Declared here. + * internal-fn.def: New defination for PHI. + * passes.c (do_per_function_toporder): Add new argument flag, add new + argument in callback function call. + (execute_one_pass): Add new function argument, add condition for + skipping passes until startwith pass. + (execute_pass_list_1): Add new function argument, add condition to + check starwith flag. + (execute_ipa_pass_list): New variable, add condition to check and skip + passes for startwith pass, pass new argument to function + do_per_function_toporder. + * tree-pass.h (execute_one_pass): Add new argument to the function. + (execute_pass_list): Likewise. + * tree-cfg.c (lower_phi_internal_fn): New function. + (verify_gimple_call): Condition for passing label as arg in internal + function PHI. + (dump_function_to_file): Change format of gimple dump. + * tree-into-ssa.c (rewrite_add_phi_arguments): New variable, add + condition for avoiding ssa name versions. + * tree-pretty-print.c (dump_decl_name): Change format of dumping gimple + labels. + (dump_function_header): Change format of gimple dump header + * tree-ssanames.c (make_ssa_name_fn): New argument, check for version + and assign proper version for parsed ssa names. + * tree-ssanames.h (make_ssa_name_fn): Add new argument to the function. + 2016-08-20 Kugan Vivekanandarajah <kug...@linaro.org> * Makefile.in: Add tree-vrp.h to GTFILES. diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index bec37cf..a8c0ab1 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2016-08-21 Prasad Ghangal <prasad.ghan...@gmail.com> + + * c-common.h (c_common_resword): Add RID_GIMPLE, RID_PHI types. + * c-common.h (enum rid): Add RID_GIMPLE, RID_PHI. + * c.opt (fgimple): New option. + 2016-08-19 Joseph Myers <jos...@codesourcery.com> PR c/32187 diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 8d9d4aa..71e78f3 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,29 @@ +2016-08-21 Prasad Ghangal <prasad.ghan...@gmail.com> + + * c_parser.c: Add headers. + (c_parser_parse_gimple_body): New function. + (c_parser_gimple_compound_statement): Likewise. + (c_parser_gimple_label): Likewise. + (c_parser_gimple_expression): Likewise + (c_parser_gimple_binary_expression): Likewise. + (c_parser_gimple_unary_expression): Likewise. + (c_parser_gimple_postfix_expression): Likewise. + (c_parser_gimple_postfix_expression_after_primary): Likewise. + (c_parser_gimple_pass_list): Likewise. + (c_parser_gimple_pass_list_params): Likewise. + (c_parser_gimple_declaration): Likewise. + (c_parser_gimple_goto_stmt): Likewise. + (c_parser_gimple_if_stmt): Likewise. + (c_parser_gimple_switch_stmt): Likewise. + (c_parser_gimple_return_stmt): Likewise. + (c_finish_gimple_return): Likewise. + (c_parser_parse_ssa_names): Likewise. + (c_parser_gimple_paren_condition): Likewise. + (c_parser_gimple_expr_list): Likewise. + (c_parser_declaration_or_fndef): New decls. Call function. + c_parser_gimple_pass_list, set startwith passes, call + c_parser_parse_gimple_body. + 2016-08-19 Joseph Myers <jos...@codesourcery.com> PR c/32187 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6201e0c..3da6354 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2016-08-21 Prasad Ghangal <prasad.ghan...@gmail.com> + + * gcc.dg/gimplefe-1.c: New testcase. + * gcc.dg/gimplefe-2.c: Likewise. + * gcc.dg/gimplefe-3.c: Likewise. + * gcc.dg/gimplefe-4.c: Likewise. + * gcc.dg/gimplefe-5.c: Likewise. + * gcc.dg/gimplefe-6.c: Likewise. + * gcc.dg/gimplefe-7.c: Likewise. + * gcc.dg/gimplefe-8.c: Likewise. + * gcc.dg/gimplefe-9.c: Likewise. + * gcc.dg/gimplefe-10.c: Likewise. + * gcc.dg/gimplefe-11.c: Likewise. + * gcc.dg/gimplefe-12.c: Likewise. + * gcc.dg/gimplefe-13.c: Likewise. + 2016-08-20 Kugan Vivekanandarajah <kug...@linaro.org> PR tree-optimization/61839
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 32468ca..5b43016 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -522,6 +522,8 @@ const struct c_common_resword c_common_reswords[] = { "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY }, { "__volatile", RID_VOLATILE, 0 }, { "__volatile__", RID_VOLATILE, 0 }, + { "__GIMPLE", RID_GIMPLE, D_CONLY }, + { "__PHI", RID_PHI, D_CONLY}, { "alignas", RID_ALIGNAS, D_CXXONLY | D_CXX11 | D_CXXWARN }, { "alignof", RID_ALIGNOF, D_CXXONLY | D_CXX11 | D_CXXWARN }, { "asm", RID_ASM, D_ASM }, diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index bc22baa..17dc91e 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -118,6 +118,12 @@ enum rid RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN, + /* "__GIMPLE", for the GIMPLE-parsing extension to the C frontend. */ + RID_GIMPLE, + + /* "__PHI", for parsing PHI function in GIMPLE FE. */ + RID_PHI, + /* C11 */ RID_ALIGNAS, RID_GENERIC, diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index a5358ed..3c4d2cc 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -200,6 +200,10 @@ F Driver C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs) -F <dir> Add <dir> to the end of the main framework include path. +fgimple +C Var(flag_gimple) Init(0) +Enable parsing GIMPLE + H C ObjC C++ ObjC++ Print the name of header files as they are used. diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index fe0c95f..fab8694 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -59,6 +59,18 @@ along with GCC; see the file COPYING3. If not see #include "gimple-expr.h" #include "context.h" #include "gcc-rich-location.h" +#include "tree-vrp.h" +#include "tree-pass.h" +#include "tree-pretty-print.h" +#include "tree.h" +#include "basic-block.h" +#include "gimple.h" +#include "gimple-pretty-print.h" +#include "tree-ssa.h" +#include "pass_manager.h" +#include "tree-ssanames.h" +#include "gimple-ssa.h" +#include "tree-dfa.h" /* We need to walk over decls with incomplete struct/union/enum types after parsing the whole translation unit. @@ -1417,6 +1429,30 @@ static tree c_parser_array_notation (location_t, c_parser *, tree, tree); static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool); static void c_parser_cilk_grainsize (c_parser *, bool *); +/* Gimple parsing functions. */ +static void c_parser_parse_gimple_body (c_parser *); +static bool c_parser_gimple_compound_statement (c_parser *, gimple_seq *); +static void c_parser_gimple_label (c_parser *, gimple_seq *); +static void c_parser_gimple_expression (c_parser *, gimple_seq *); +static struct c_expr c_parser_gimple_binary_expression (c_parser *, enum tree_code *); +static struct c_expr c_parser_gimple_unary_expression (c_parser *); +static struct c_expr c_parser_gimple_postfix_expression (c_parser *); +static struct c_expr c_parser_gimple_postfix_expression_after_primary (c_parser *, + location_t, + struct c_expr); +static void c_parser_gimple_pass_list (c_parser *, opt_pass **, bool *); +static opt_pass *c_parser_gimple_pass_list_params (c_parser *, opt_pass **); +static void c_parser_gimple_declaration (c_parser *); +static void c_parser_gimple_goto_stmt (location_t, tree, gimple_seq *); +static void c_parser_gimple_if_stmt (c_parser *, gimple_seq *); +static void c_parser_gimple_switch_stmt (c_parser *, gimple_seq *); +static void c_parser_gimple_return_stmt (c_parser *, gimple_seq *); +static void c_finish_gimple_return (location_t, tree); +static c_expr c_parser_parse_ssa_names (c_parser *); +static tree c_parser_gimple_paren_condition (c_parser *); +static vec<tree, va_gc> *c_parser_gimple_expr_list (c_parser *, + vec<tree, va_gc> **, vec<location_t> *); + /* Parse a translation unit (C90 6.7, C99 6.9). translation-unit: @@ -1659,6 +1695,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, tree all_prefix_attrs; bool diagnosed_no_specs = false; location_t here = c_parser_peek_token (parser)->location; + bool gimple_body_p = false; + opt_pass *pass = NULL; + bool startwith_p = false; if (static_assert_ok && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT)) @@ -1743,6 +1782,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, c_parser_skip_to_end_of_block_or_statement (parser); return; } + + if (c_parser_next_token_is (parser, CPP_KEYWORD)) + { + c_token *kw_token = c_parser_peek_token (parser); + if (kw_token->keyword == RID_GIMPLE) + { + gimple_body_p = true; + c_parser_consume_token (parser); + c_parser_gimple_pass_list (parser, &pass, &startwith_p); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + } + } + finish_declspecs (specs); bool auto_type_p = specs->typespec_word == cts_auto_type; if (c_parser_next_token_is (parser, CPP_SEMICOLON)) @@ -2144,6 +2197,13 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, c_parser_declaration_or_fndef (parser, false, false, false, true, false, NULL, vNULL); store_parm_decls (); + + if (pass) + { + cfun->pass_startwith = pass; + cfun->startwith = startwith_p; + } + if (omp_declare_simd_clauses.exists () || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE, @@ -2152,6 +2212,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, c_finish_oacc_routine (oacc_routine_data, current_function_decl, true); DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus = c_parser_peek_token (parser)->location; + + if (gimple_body_p && flag_gimple) + { + bool saved = in_late_binary_op; + in_late_binary_op = true; + c_parser_parse_gimple_body (parser); + in_late_binary_op = saved; + cgraph_node::finalize_function (current_function_decl, false); + set_cfun (NULL); + current_function_decl = NULL; + timevar_pop (tv); + return; + } + fnbody = c_parser_compound_statement (parser); if (flag_cilkplus && contains_array_notation_expr (fnbody)) fnbody = expand_array_notation_exprs (fnbody); @@ -18194,4 +18268,1338 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index, return value_tree; } +/* Parse the body of a function declaration marked with "__GIMPLE". */ + +void +c_parser_parse_gimple_body (c_parser *parser) +{ + gimple_seq seq = NULL; + gimple_seq body = NULL; + tree stmt = push_stmt_list (); + push_scope (); + location_t loc1 = c_parser_peek_token (parser)->location; + + init_tree_ssa (cfun); + + if (!c_parser_gimple_compound_statement (parser, &seq)) + { + gimple *ret = gimple_build_return (NULL); + gimple_seq_add_stmt (&seq, ret); + } + + tree block = pop_scope (); + stmt = pop_stmt_list (stmt); + stmt = c_build_bind_expr (loc1, block, stmt); + + block = DECL_INITIAL (current_function_decl); + BLOCK_SUBBLOCKS (block) = NULL_TREE; + BLOCK_CHAIN (block) = NULL_TREE; + TREE_ASM_WRITTEN (block) = 1; + + gbind *bind_stmt = gimple_build_bind (BIND_EXPR_VARS (stmt), NULL, + BIND_EXPR_BLOCK (stmt)); + gimple_bind_set_body (bind_stmt, seq); + gimple_seq_add_stmt (&body, bind_stmt); + gimple_set_body (current_function_decl, body); + cfun->curr_properties = PROP_gimple_any; + + return; +} + +/* Parse a compound statement in gimple function body. + + gimple-statement: + gimple-statement + gimple-declaration-statement + gimple-if-statement + gimple-switch-statement + gimple-labeled-statement + gimple-expression-statement + gimple-goto-statement + gimple-phi-statement + gimple-return-statement +*/ + +static bool +c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq) +{ + bool return_p = false; + + if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) + return false; + + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + { + c_parser_consume_token (parser); + return false; + } + + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + { + c_parser_error (parser, "expected declaration or statement"); + c_parser_consume_token (parser); + return false; + } + + while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE)) + { + + if (parser->error) + { + c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); + return return_p; + } + + if (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_COLON) + c_parser_gimple_label (parser, seq); + + else if (c_parser_next_tokens_start_declaration (parser)) + c_parser_gimple_declaration (parser); + + else if (c_parser_next_token_is (parser, CPP_EOF)) + { + c_parser_error (parser, "expected declaration or statement"); + return return_p; + } + + else + { + switch (c_parser_peek_token (parser)->type) + { + case CPP_KEYWORD: + switch (c_parser_peek_token (parser)->keyword) + { + case RID_IF: + c_parser_gimple_if_stmt (parser, seq); + break; + case RID_SWITCH: + c_parser_gimple_switch_stmt (parser, seq); + break; + case RID_GOTO: + { + location_t loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_NAME)) + { + c_parser_gimple_goto_stmt (loc, + c_parser_peek_token (parser)->value, + seq); + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_SEMICOLON, + "expected %<;%>")) + return return_p; + } + } + break; + case RID_RETURN: + return_p = true; + c_parser_gimple_return_stmt (parser, seq); + if (!c_parser_require (parser, CPP_SEMICOLON, + "expected %<;%>")) + return return_p; + break; + default: + goto expr_stmt; + } + break; + case CPP_SEMICOLON: + c_parser_consume_token (parser); + break; + default: + expr_stmt: + c_parser_gimple_expression (parser, seq); + if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) + return return_p; + } + } + } + c_parser_consume_token (parser); + return return_p; +} + +/* Parse a gimple expression. + + gimple-expression: + gimple-unary-expression + gimple-call-statement + gimple-binary-expression + gimple-assign-expression + gimple-cast-expression + +*/ + +static void +c_parser_gimple_expression (c_parser *parser, gimple_seq *seq) +{ + struct c_expr lhs, rhs; + gimple *assign = NULL; + enum tree_code subcode = NOP_EXPR; + location_t loc; + tree arg = NULL_TREE; + auto_vec<tree> vargs; + + lhs = c_parser_gimple_unary_expression (parser); + rhs.value = error_mark_node; + + if (c_parser_next_token_is (parser, CPP_EQ)) + { + c_parser_consume_token (parser); + } + + loc = EXPR_LOCATION (lhs.value); + + /* gimple call expression. */ + if (c_parser_next_token_is (parser, CPP_SEMICOLON) && + TREE_CODE (lhs.value) == CALL_EXPR) + { + gimple *call; + call = gimple_build_call_from_tree (lhs.value); + gimple_seq_add_stmt (seq, call); + gimple_set_location (call, loc); + return; + } + + /* cast expression. */ + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) + && c_token_starts_typename (c_parser_peek_2nd_token (parser))) + { + rhs = c_parser_cast_expression (parser, NULL); //TODO: have a gimple_cast_expr function + if (lhs.value != error_mark_node && + rhs.value != error_mark_node) + { + assign = gimple_build_assign (lhs.value, rhs.value); + gimple_seq_add_stmt (seq, assign); + gimple_set_location (assign, loc); + return; + } + } + + if (POINTER_TYPE_P (TREE_TYPE (lhs.value))) + { + STRIP_USELESS_TYPE_CONVERSION (rhs.value); + if (!useless_type_conversion_p (TREE_TYPE (lhs.value), + TREE_TYPE (rhs.value))) + rhs.value = fold_convert_loc (loc, TREE_TYPE (lhs.value), rhs.value); + } + + /* pointer expression. */ + if (TREE_CODE (lhs.value) == INDIRECT_REF) + { + tree save_expr = lhs.value; + bool volatilep = TREE_THIS_VOLATILE (lhs.value); + bool notrap = TREE_THIS_NOTRAP (lhs.value); + tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (lhs.value, 0)); + + lhs.value = fold_indirect_ref_loc (loc, lhs.value); + if (lhs.value == save_expr) + { + lhs.value = fold_build2_loc (input_location, MEM_REF, + TREE_TYPE (lhs.value), + TREE_OPERAND (lhs.value, 0), + build_int_cst (saved_ptr_type, 0)); + TREE_THIS_VOLATILE (lhs.value) = volatilep; + TREE_THIS_NOTRAP (lhs.value) = notrap; + } + } + + if (c_parser_next_token_is (parser, CPP_AND) || + c_parser_next_token_is (parser, CPP_MULT) || + c_parser_next_token_is (parser, CPP_PLUS) || + c_parser_next_token_is (parser, CPP_MINUS) || + c_parser_next_token_is (parser, CPP_COMPL) || + c_parser_next_token_is (parser, CPP_NOT)) + { + rhs = c_parser_gimple_unary_expression (parser); + assign = gimple_build_assign (lhs.value, rhs.value); + gimple_set_location (assign, loc); + gimple_seq_add_stmt (seq, assign); + return; + } + + /* gimple PHI expression. */ + if (c_parser_next_token_is_keyword (parser, RID_PHI)) + { + c_parser_consume_token (parser); + + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + return; + } + + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + c_parser_consume_token (parser); + + while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) + { + if (c_parser_next_token_is (parser, CPP_NAME) && + c_parser_peek_2nd_token (parser)->type == CPP_COLON) + { + arg = lookup_label_for_goto (loc, + c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + + if (c_parser_next_token_is (parser, CPP_COLON)) + c_parser_consume_token (parser); + vargs.safe_push (arg); + } + else if (c_parser_next_token_is (parser, CPP_COMMA)) + { + c_parser_consume_token (parser); + } + else + { + arg = c_parser_parse_ssa_names (parser).value; + vargs.safe_push (arg); + } + } + + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + + /* build internal function for PHI. */ + gcall *call_stmt = gimple_build_call_internal_vec (IFN_PHI, vargs); + gimple_call_set_lhs (call_stmt, lhs.value); + gimple_set_location (call_stmt, UNKNOWN_LOCATION); + gimple_seq_add_stmt (seq, call_stmt); + return; + } + + /* gimple call with lhs. */ + if (c_parser_next_token_is (parser, CPP_NAME) && + c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN && + lookup_name (c_parser_peek_token (parser)->value)) + { + rhs = c_parser_gimple_unary_expression (parser); + gimple *call = gimple_build_call_from_tree (rhs.value); + gimple_call_set_lhs (call, lhs.value); + gimple_seq_add_stmt (seq, call); + gimple_set_location (call, loc); + return; + } + + rhs = c_parser_gimple_binary_expression (parser, &subcode); + + if (lhs.value != error_mark_node && + rhs.value != error_mark_node) + { + if (subcode == NOP_EXPR) + assign = gimple_build_assign (lhs.value, rhs.value); + else + assign = gimple_build_assign (lhs.value, subcode, + TREE_OPERAND (rhs.value, 0), + TREE_OPERAND (rhs.value, 1)); + gimple_seq_add_stmt (seq, assign); + gimple_set_location (assign, loc); + } + return; +} + +/* Parse gimple binary expr. + + gimple-multiplicative-expression: + gimple-unary-expression * gimple-unary-expression + gimple-unary-expression / gimple-unary-expression + gimple-unary-expression % gimple-unary-expression + + gimple-additive-expression: + gimple-unary-expression + gimple-unary-expression + gimple-unary-expression - gimple-unary-expression + + gimple-shift-expression: + gimple-unary-expression << gimple-unary-expression + gimple-unary-expression >> gimple-unary-expression + + gimple-relational-expression: + gimple-unary-expression < gimple-unary-expression + gimple-unary-expression > gimple-unary-expression + gimple-unary-expression <= gimple-unary-expression + gimple-unary-expression >= gimple-unary-expression + + gimple-equality-expression: + gimple-unary-expression == gimple-unary-expression + gimple-unary-expression != gimple-unary-expression + + gimple-AND-expression: + gimple-unary-expression & gimple-unary-expression + + gimple-exclusive-OR-expression: + gimple-unary-expression ^ gimple-unary-expression + + gimple-inclusive-OR-expression: + gimple-unary-expression | gimple-unary-expression + + gimple-logical-AND-expression: + gimple-unary-expression && gimple-unary-expression + + gimple-logical-OR-expression: + gimple-unary-expression || gimple-unary-expression + +*/ + +static c_expr +c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode) +{ + struct { + /* The expression at this stack level. */ + struct c_expr expr; + /* The operation on its left. */ + enum tree_code op; + /* The source location of this operation. */ + location_t loc; + } stack[2]; + int sp; + /* Location of the binary operator. */ + location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */ +#define POP \ + do { \ + if (sp == 1 \ + && c_parser_peek_token (parser)->type == CPP_SEMICOLON \ + && (((1 << PREC_BITOR) | (1 << PREC_BITXOR) | (1 << PREC_BITAND) \ + | (1 << PREC_SHIFT) | (1 << PREC_ADD) | (1 << PREC_MULT))) \ + && stack[sp].op != TRUNC_MOD_EXPR \ + && stack[0].expr.value != error_mark_node \ + && stack[1].expr.value != error_mark_node) \ + stack[0].expr.value \ + = build2 (stack[1].op, TREE_TYPE (stack[0].expr.value), \ + stack[0].expr.value, stack[1].expr.value); \ + else \ + stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \ + stack[sp].op, \ + stack[sp - 1].expr, \ + stack[sp].expr); \ + sp--; \ + } while (0) + stack[0].loc = c_parser_peek_token (parser)->location; + stack[0].expr = c_parser_gimple_unary_expression (parser); + sp = 0; + source_range src_range; + if (parser->error) + goto out; + switch (c_parser_peek_token (parser)->type) + { + case CPP_MULT: + *subcode = MULT_EXPR; + break; + case CPP_DIV: + *subcode = TRUNC_DIV_EXPR; + break; + case CPP_MOD: + *subcode = TRUNC_MOD_EXPR; + break; + case CPP_PLUS: + *subcode = PLUS_EXPR; + break; + case CPP_MINUS: + *subcode = MINUS_EXPR; + break; + case CPP_LSHIFT: + *subcode = LSHIFT_EXPR; + break; + case CPP_RSHIFT: + *subcode = RSHIFT_EXPR; + break; + case CPP_LESS: + *subcode = LT_EXPR; + break; + case CPP_GREATER: + *subcode = GT_EXPR; + break; + case CPP_LESS_EQ: + *subcode = LE_EXPR; + break; + case CPP_GREATER_EQ: + *subcode = GE_EXPR; + break; + case CPP_EQ_EQ: + *subcode = EQ_EXPR; + break; + case CPP_NOT_EQ: + *subcode = NE_EXPR; + break; + case CPP_AND: + *subcode = BIT_AND_EXPR; + break; + case CPP_XOR: + *subcode = BIT_XOR_EXPR; + break; + case CPP_OR: + *subcode = BIT_IOR_EXPR; + break; + case CPP_AND_AND: + *subcode = TRUTH_ANDIF_EXPR; + break; + case CPP_OR_OR: + *subcode = TRUTH_ORIF_EXPR; + break; + default: + /* Not a binary operator, so end of the binary + expression. */ + *subcode = NOP_EXPR; + goto out; + } + binary_loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + switch (*subcode) + { + case TRUTH_ANDIF_EXPR: + src_range = stack[sp].expr.src_range; + stack[sp].expr.value = c_objc_common_truthvalue_conversion + (stack[sp].loc, default_conversion (stack[sp].expr.value)); + set_c_expr_source_range (&stack[sp].expr, src_range); + break; + case TRUTH_ORIF_EXPR: + src_range = stack[sp].expr.src_range; + stack[sp].expr.value = c_objc_common_truthvalue_conversion + (stack[sp].loc, default_conversion (stack[sp].expr.value)); + set_c_expr_source_range (&stack[sp].expr, src_range); + break; + default: + break; + } + sp++; + stack[sp].loc = binary_loc; + stack[sp].expr = c_parser_gimple_unary_expression (parser); + stack[sp].op = *subcode; +out: + while (sp > 0) + POP; + return stack[0].expr; +#undef POP + +} + +/* Parse gimple unary expression. + + gimple-unary-expression: + gimple-postfix-expression + unary-operator cast-expression + + unary-operator: one of + & * + - ~ ! +*/ + +static c_expr +c_parser_gimple_unary_expression (c_parser *parser) +{ + struct c_expr ret, op; + if (c_parser_peek_token (parser)->value + && TREE_CODE (c_parser_peek_token (parser)->value) == IDENTIFIER_NODE + && !lookup_name (c_parser_peek_token (parser)->value)) + return c_parser_parse_ssa_names (parser); + + location_t op_loc = c_parser_peek_token (parser)->location; + location_t finish; + ret.original_code = ERROR_MARK; + ret.original_type = NULL; + switch (c_parser_peek_token (parser)->type) + { + case CPP_AND: + c_parser_consume_token (parser); + op = c_parser_cast_expression (parser, NULL); + mark_exp_read (op.value); + return parser_build_unary_op (op_loc, ADDR_EXPR, op); + case CPP_MULT: + { + c_parser_consume_token (parser); + op = c_parser_cast_expression (parser, NULL); + finish = op.get_finish (); + location_t combined_loc = make_location (op_loc, op_loc, finish); + ret.value = build_indirect_ref (combined_loc, op.value, + RO_UNARY_STAR); + ret.src_range.m_start = op_loc; + ret.src_range.m_finish = finish; + return ret; + } + case CPP_PLUS: + c_parser_consume_token (parser); + op = c_parser_cast_expression (parser, NULL); + return parser_build_unary_op (op_loc, CONVERT_EXPR, op); + case CPP_MINUS: + c_parser_consume_token (parser); + op = c_parser_cast_expression (parser, NULL); + return parser_build_unary_op (op_loc, NEGATE_EXPR, op); + case CPP_COMPL: + c_parser_consume_token (parser); + op = c_parser_cast_expression (parser, NULL); + return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op); + case CPP_NOT: + c_parser_consume_token (parser); + op = c_parser_cast_expression (parser, NULL); + return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op); + default: + return c_parser_gimple_postfix_expression (parser); + } +} + +/* Parse gimple ssa names. */ + +static c_expr +c_parser_parse_ssa_names (c_parser *parser) +{ + tree id = NULL_TREE; + c_expr ret; + char *var_name = NULL, *var_version = NULL, *token = NULL; + ret.original_code = ERROR_MARK; + ret.original_type = NULL; + + /* ssa token string. */ + const char *ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + token = new char [strlen (ssa_token)]; + strcpy (token, ssa_token); + + /* seperate var name and version. */ + var_version = strrchr (token, '_'); + if (var_version) + { + var_name = new char[var_version - token + 1]; + memcpy (var_name, token, var_version - token); + var_name[var_version - token] = '\0'; + id = get_identifier (var_name); + + /* lookup for parent decl. */ + if (lookup_name (id)) + { + var_version++; + unsigned int version; + version = atoi (var_version); + if (var_version && version) + { + ret.value = NULL_TREE; + if (version < num_ssa_names) + ret.value = ssa_name (version); + if (!ret.value) + ret.value = make_ssa_name_fn (cfun, lookup_name (id), + gimple_build_nop (), version); + c_parser_consume_token (parser); + } + } + } + + /* for default defination ssa names. */ + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + { + c_parser_consume_token (parser); + ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (!strcmp ("D", ssa_token)) + { + set_ssa_default_def (cfun, lookup_name (id), ret.value); + c_parser_consume_token (parser); + } + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + goto out; + } + + out: + free (var_name); + free (token); + return ret; +} + +/* Parse gimple postfix expression. + + gimple-postfix-expression: + gimple-primary-expression + gimple-primary-xpression [ gimple-primary-expression ] + gimple-primary-expression ( gimple-argument-expression-list[opt] ) + + gimple-argument-expression-list: + gimple-unary-expression + gimple-argument-expression-list , gimple-unary-expression + + gimple-primary-expression: + identifier + constant + string-literal + +*/ + +static struct c_expr +c_parser_gimple_postfix_expression (c_parser *parser) +{ + struct c_expr expr; + location_t loc = c_parser_peek_token (parser)->location; + source_range tok_range = c_parser_peek_token (parser)->get_range (); + expr.original_code = ERROR_MARK; + expr.original_type = NULL; + switch (c_parser_peek_token (parser)->type) + { + case CPP_NUMBER: + expr.value = c_parser_peek_token (parser)->value; + set_c_expr_source_range (&expr, tok_range); + loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + break; + case CPP_CHAR: + case CPP_CHAR16: + case CPP_CHAR32: + case CPP_WCHAR: + expr.value = c_parser_peek_token (parser)->value; + set_c_expr_source_range (&expr, tok_range); + c_parser_consume_token (parser); + break; + case CPP_STRING: + case CPP_STRING16: + case CPP_STRING32: + case CPP_WSTRING: + case CPP_UTF8STRING: + expr.value = c_parser_peek_token (parser)->value; + set_c_expr_source_range (&expr, tok_range); + expr.original_code = STRING_CST; + c_parser_consume_token (parser); + break; + case CPP_NAME: + if (c_parser_peek_token (parser)->id_kind == C_ID_ID) + { + tree id = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + expr.value = build_external_ref (loc, id, + (c_parser_peek_token (parser)->type + == CPP_OPEN_PAREN), + &expr.original_type); + set_c_expr_source_range (&expr, tok_range); + break; + } + else + { + c_parser_error (parser, "expected expression"); + expr.set_error (); + break; + } + break; + default: + c_parser_error (parser, "expected expression"); + expr.set_error (); + break; + } + return c_parser_gimple_postfix_expression_after_primary + (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr); +} + +/* Parse a gimple postfix expression after the initial primary or compound + literal. */ + +static struct c_expr +c_parser_gimple_postfix_expression_after_primary (c_parser *parser, + location_t expr_loc, + struct c_expr expr) +{ + struct c_expr orig_expr; + vec<tree, va_gc> *exprlist; + vec<tree, va_gc> *origtypes = NULL; + vec<location_t> arg_loc = vNULL; + location_t start; + location_t finish; + + location_t op_loc = c_parser_peek_token (parser)->location; + + switch (c_parser_peek_token (parser)->type) + { + case CPP_OPEN_SQUARE: + { + c_parser_consume_token (parser); + tree idx = c_parser_gimple_unary_expression (parser).value; + + if (!c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>")) + break; + + start = expr.get_start (); + finish = parser->tokens_buf[0].location; + expr.value = build_array_ref (op_loc, expr.value, idx); + set_c_expr_source_range (&expr, start, finish); + + expr.original_code = ERROR_MARK; + expr.original_type = NULL; + break; + } + case CPP_OPEN_PAREN: + { + /* Function call */ + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) + exprlist = NULL; + else + exprlist = c_parser_gimple_expr_list (parser, &origtypes, + &arg_loc); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + orig_expr = expr; + start = expr.get_start (); + finish = parser->tokens_buf[0].get_finish (); + expr.value + = c_build_function_call_vec (expr_loc, arg_loc, expr.value, + exprlist, origtypes); + set_c_expr_source_range (&expr, start, finish); + + expr.original_code = ERROR_MARK; + if (TREE_CODE (expr.value) == INTEGER_CST + && TREE_CODE (orig_expr.value) == FUNCTION_DECL + && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P) + expr.original_code = C_MAYBE_CONST_EXPR; + expr.original_type = NULL; + if (exprlist) + { + release_tree_vector (exprlist); + release_tree_vector (origtypes); + } + arg_loc.release (); + break; + default: + return expr; + + } + } + return expr; +} + +/* Parse expression list. + + gimple-expr-list: + gimple-unary-expression + gimple-expr-list , gimple-unary-expression + + */ + +static vec<tree, va_gc> * +c_parser_gimple_expr_list (c_parser *parser, vec<tree, va_gc> **p_orig_types, + vec<location_t> *locations) +{ + vec<tree, va_gc> *ret; + vec<tree, va_gc> *orig_types; + struct c_expr expr; + location_t loc = c_parser_peek_token (parser)->location; + + ret = make_tree_vector (); + if (p_orig_types == NULL) + orig_types = NULL; + else + orig_types = make_tree_vector (); + + expr = c_parser_gimple_unary_expression (parser); + vec_safe_push (ret, expr.value); + if (orig_types) + vec_safe_push (orig_types, expr.original_type); + if (locations) + locations->safe_push (loc); + while (c_parser_next_token_is (parser, CPP_COMMA)) + { + c_parser_consume_token (parser); + loc = c_parser_peek_token (parser)->location; + expr = c_parser_gimple_unary_expression (parser); + vec_safe_push (ret, expr.value); + if (orig_types) + vec_safe_push (orig_types, expr.original_type); + if (locations) + locations->safe_push (loc); + } + if (orig_types) + *p_orig_types = orig_types; + return ret; +} + +/* Parse gimple label. + + gimple-label: + identifier : + case constant-expression : + default : + +*/ + +static void +c_parser_gimple_label (c_parser *parser, gimple_seq *seq) +{ + tree name = c_parser_peek_token (parser)->value; + location_t loc1 = c_parser_peek_token (parser)->location; + gcc_assert (c_parser_next_token_is (parser, CPP_NAME)); + c_parser_consume_token (parser); + gcc_assert (c_parser_next_token_is (parser, CPP_COLON)); + c_parser_consume_token (parser); + tree label = define_label (loc1, name); + gimple_seq_add_stmt (seq, gimple_build_label (label)); + return; +} + +/* Parse gimple pass list. + + gimple-pass-list: + startwith("pass-name") + */ + +static void +c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass, + bool *startwith_p) +{ + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + return; + } + + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) + { + return; + } + + if (c_parser_next_token_is (parser, CPP_NAME)) + { + const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + if (!strcmp (op, "startwith")) + { + *pass = c_parser_gimple_pass_list_params (parser, pass); + if (!(*pass)) + return; + + *startwith_p = true; + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + return; + } + else + { + error_at (c_parser_peek_token (parser)->location, + "invalid operation"); + return; + } + } + else if (c_parser_next_token_is (parser, CPP_EOF)) + { + c_parser_error (parser, "expected parameters"); + return; + } + + return; +} + +/* Support function for c_parser_gimple_pass_list. */ + +static opt_pass * +c_parser_gimple_pass_list_params (c_parser *parser, opt_pass **pass) +{ + opt_pass *pass_start = NULL, *new_pass; + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + return NULL; + } + + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) + { + return NULL; + } + + while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) + { + if (c_parser_next_token_is (parser, CPP_EOF)) + { + error_at (c_parser_peek_token (parser)->location, + "expected pass names"); + return NULL; + } + + if (c_parser_next_token_is (parser, CPP_STRING)) + { + const char *name = NULL; + name = TREE_STRING_POINTER (c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + new_pass = g->get_passes ()->get_pass_by_name (name); + + if (!new_pass) + { + error_at (c_parser_peek_token (parser)->location, + "invalid pass name"); + parser->error = true; + c_parser_consume_token (parser); + return NULL; + } + if (*pass) + { + (*pass)->next = new_pass; + (*pass) = (*pass)->next; + } + else + { + *pass = new_pass; + pass_start = *pass; + } + } + else if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + else + { + error_at (c_parser_peek_token (parser)->location, + "invalid pass name"); + c_parser_consume_token (parser); + return NULL; + } + } + return pass_start; +} + +/* Parse gimple local declaration. + + declaration-specifiers: + storage-class-specifier declaration-specifiers[opt] + type-specifier declaration-specifiers[opt] + type-qualifier declaration-specifiers[opt] + function-specifier declaration-specifiers[opt] + alignment-specifier declaration-specifiers[opt] + + storage-class-specifier: + typedef + extern + static + auto + register + + type-specifier: + void + char + short + int + long + float + double + signed + unsigned + _Bool + _Complex + + type-qualifier: + const + restrict + volatile + address-space-qualifier + _Atomic + + */ + +static void +c_parser_gimple_declaration (c_parser *parser) +{ + struct c_declarator *declarator; + struct c_declspecs *specs = build_null_declspecs (); + c_parser_declspecs (parser, specs, true, true, true, + true, true, cla_nonabstract_decl); + finish_declspecs (specs); + + /* Provide better error recovery. Note that a type name here is usually + better diagnosed as a redeclaration. */ + if (c_parser_next_token_starts_declspecs (parser) + && !c_parser_next_token_is (parser, CPP_NAME)) + { + c_parser_error (parser, "expected %<;%>"); + parser->error = false; + return; + } + + bool dummy = false; + declarator = c_parser_declarator (parser, + specs->typespec_kind != ctsk_none, + C_DTR_NORMAL, &dummy); + + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + { + tree postfix_attrs = NULL_TREE; + tree all_prefix_attrs = specs->attrs; + specs->attrs = NULL; + tree decl = start_decl (declarator, specs, false, + chainon (postfix_attrs, all_prefix_attrs)); + if (decl) + { + finish_decl (decl, UNKNOWN_LOCATION, NULL_TREE, + NULL_TREE, NULL_TREE); + } + } + else + { + c_parser_error (parser, "expected %<;%>"); + return; + } +} + +/* Parse gimple goto statement. */ + +static void +c_parser_gimple_goto_stmt (location_t loc, tree label, gimple_seq *seq) +{ + tree decl = lookup_label_for_goto (loc, label); + gimple_seq_add_stmt (seq, gimple_build_goto (decl)); + return; +} + +/* Parse a parenthesized condition. + gimple-condition: + ( gimple-binary-expression ) */ + +static tree +c_parser_gimple_paren_condition (c_parser *parser) +{ + enum tree_code subcode = NOP_EXPR; + location_t loc = c_parser_peek_token (parser)->location; + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return error_mark_node; + tree cond = c_parser_gimple_binary_expression (parser, &subcode).value; + cond = c_objc_common_truthvalue_conversion (loc, cond); + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + return error_mark_node; + return cond; +} + +/* Parse gimple if-else statement. + + if-statement: + if ( gimple-binary-expression ) gimple-goto-statement + if ( gimple-binary-expression ) gimple-goto-statement \ + else gimple-goto-statement + */ + +static void +c_parser_gimple_if_stmt (c_parser *parser, gimple_seq *seq) +{ + tree t_label, f_label, label; + location_t loc; + c_parser_consume_token (parser); + tree cond = c_parser_gimple_paren_condition (parser); + + if (c_parser_next_token_is_keyword (parser, RID_GOTO)) + { + loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + label = c_parser_peek_token (parser)->value; + t_label = lookup_label_for_goto (loc, label); + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) + return; + } + else + { + c_parser_error (parser, "expected goto expression"); + return; + } + + if (c_parser_next_token_is_keyword (parser, RID_ELSE)) + c_parser_consume_token (parser); + else + { + c_parser_error (parser, "expected else statement"); + return; + } + + if (c_parser_next_token_is_keyword (parser, RID_GOTO)) + { + loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + label = c_parser_peek_token (parser)->value; + f_label = lookup_label_for_goto (loc, label); + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) + return; + } + else + { + c_parser_error (parser, "expected goto expression"); + return; + } + + gimple_seq_add_stmt (seq, gimple_build_cond_from_tree (cond, t_label, + f_label)); +} + +/* Parse gimple switch-statement. + + gimple-switch-statement: + switch (gimple-unary-expression) gimple-case-statement + + gimple-case-statement: + gimple-case-statement + gimple-label-statement : gimple-goto-statment +*/ + +static void +c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq) +{ + c_expr cond_expr; + tree case_label, label; + auto_vec<tree> labels; + tree default_label = NULL_TREE; + gimple_seq switch_body = NULL; + location_t loc; + c_parser_consume_token (parser); + + if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + cond_expr = c_parser_gimple_unary_expression (parser); + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + return; + } + + if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) + { + while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE)) + { + if (c_parser_next_token_is (parser, CPP_EOF)) + { + c_parser_error (parser, "expected statement"); + return; + } + + switch (c_parser_peek_token (parser)->keyword) + { + case RID_CASE: + { + c_expr exp1; + loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + + if (c_parser_next_token_is (parser, CPP_NAME) || + c_parser_peek_token (parser)->type == CPP_NUMBER) + exp1 = c_parser_gimple_unary_expression (parser); + else + c_parser_error (parser, "expected expression"); + + if (c_parser_next_token_is (parser, CPP_COLON)) + { + c_parser_consume_token (parser); + label = create_artificial_label (loc); + case_label = build_case_label (exp1.value, NULL_TREE, + label); + labels.safe_push (case_label); + gimple_seq_add_stmt (&switch_body, + gimple_build_label + (CASE_LABEL (case_label))); + } + else + { + if (!c_parser_require (parser, CPP_SEMICOLON, + "expected %<:%>")) + return; + } + } + break; + case RID_DEFAULT: + { + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_COLON)) + { + c_parser_consume_token (parser); + default_label = build_case_label (NULL_TREE, NULL_TREE, + create_artificial_label + (UNKNOWN_LOCATION)); + gimple_seq_add_stmt (&switch_body, + gimple_build_label + (CASE_LABEL (default_label))); + } + else + { + if (!c_parser_require (parser, CPP_SEMICOLON, + "expected %<:%>")) + return; + } + } + break; + case RID_GOTO: + { + loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_NAME)) + { + c_parser_gimple_goto_stmt (loc, + c_parser_peek_token (parser)->value, + &switch_body); + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + c_parser_consume_token (parser); + else + { + c_parser_error (parser, "expected semicolon"); + return; + } + } + else + { + if (!c_parser_require (parser, CPP_NAME, + "expected label")) + return; + } + } + break; + default: + c_parser_error (parser, "expected case label or goto statement"); + return; + } + + } + } + if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>")) + return; + gimple_seq_add_stmt (seq, gimple_build_switch (cond_expr.value, + default_label, labels)); + gimple_seq_add_seq (seq, switch_body); + labels.release(); +} + +/* Parse gimple return statement. */ + +static void +c_parser_gimple_return_stmt (c_parser *parser, gimple_seq *seq) +{ + location_t loc = c_parser_peek_token (parser)->location; + gimple *ret = NULL; + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + { + c_finish_gimple_return (loc, NULL_TREE); + ret = gimple_build_return (NULL); + gimple_seq_add_stmt (seq, ret); + } + else + { + location_t xloc = c_parser_peek_token (parser)->location; + c_expr expr = c_parser_gimple_unary_expression (parser); + c_finish_gimple_return (xloc, expr.value); + ret = gimple_build_return (expr.value); + gimple_seq_add_stmt (seq, ret); + } +} + +/* Support function for c_parser_gimple_return_stmt. */ + +static void +c_finish_gimple_return (location_t loc, tree retval) +{ + tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)); + + /* Use the expansion point to handle cases such as returning NULL + in a function returning void. */ + source_location xloc = expansion_point_location_if_in_system_header (loc); + + if (TREE_THIS_VOLATILE (current_function_decl)) + warning_at (xloc, 0, + "function declared %<noreturn%> has a %<return%> statement"); + + if (!retval) + { + current_function_returns_null = 1; + } + else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE) + { + current_function_returns_null = 1; + if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE) + { + error_at + (xloc, "%<return%> with a value, in function returning void"); + inform (DECL_SOURCE_LOCATION (current_function_decl), + "declared here"); + } + } + else if (TREE_CODE (valtype) != TREE_CODE (TREE_TYPE (retval))) + { + error_at + (xloc, "invalid conversion in return statement"); + inform (DECL_SOURCE_LOCATION (current_function_decl), + "declared here"); + } + return; +} + #include "gt-c-c-parser.h" diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 6a1d126..cf6728f 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1944,6 +1944,7 @@ cgraph_node::assemble_thunks_and_aliases (void) void cgraph_node::expand (void) { + bool startwith_p = true; location_t saved_loc; /* We ought to not compile any inline clones. */ @@ -1982,7 +1983,7 @@ cgraph_node::expand (void) /* Signal the start of passes. */ invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL); - execute_pass_list (cfun, g->get_passes ()->all_passes); + execute_pass_list (cfun, g->get_passes ()->all_passes, &startwith_p); /* Signal the end of passes. */ invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL); @@ -2035,7 +2036,9 @@ cgraph_node::expand (void) timevar_pop (TV_REST_OF_COMPILATION); /* Make sure that BE didn't give up on compiling. */ - gcc_assert (TREE_ASM_WRITTEN (decl)); + if (!(flag_gimple && cfun->pass_startwith)) /* FIXME : for gimplefe custom_pass_list */ + gcc_assert (TREE_ASM_WRITTEN (decl)); + if (cfun) pop_cfun (); diff --git a/gcc/coretypes.h b/gcc/coretypes.h index fe1e984..ad6e5ac 100644 --- a/gcc/coretypes.h +++ b/gcc/coretypes.h @@ -85,6 +85,7 @@ typedef const union tree_node *const_tree; struct gimple; typedef gimple *gimple_seq; struct gimple_stmt_iterator; +class opt_pass; /* Forward decls for leaf gimple subclasses (for individual gimple codes). Keep this in the same order as the corresponding codes in gimple.def. */ @@ -405,6 +406,8 @@ typedef unsigned char uchar; #include "input.h" #include "is-a.h" #include "memory-block.h" +#include "pass_manager.h" +#include "tree-pass.h" #endif /* GENERATOR_FILE && !USED_FOR_TARGET */ #endif /* coretypes.h */ diff --git a/gcc/function.h b/gcc/function.h index 501ef68..38c00fd 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -228,6 +228,12 @@ struct GTY(()) function { /* GIMPLE body for this function. */ gimple_seq gimple_body; + /* GIMPLEFE pass to start with */ + opt_pass *pass_startwith; + + /* Startwith flag */ + bool startwith; + /* SSA and dataflow information. */ struct gimple_df *gimple_df; diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 12d9a9c..e4416a5 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -838,7 +838,7 @@ dump_gimple_switch (pretty_printer *buffer, gswitch *gs, int spc, { pp_string (buffer, "switch ("); dump_generic_node (buffer, gimple_switch_index (gs), spc, flags, true); - pp_string (buffer, ") <"); + pp_string (buffer, ") {"); } for (i = 0; i < gimple_switch_num_labels (gs); i++) @@ -849,9 +849,9 @@ dump_gimple_switch (pretty_printer *buffer, gswitch *gs, int spc, pp_space (buffer); dump_generic_node (buffer, CASE_LABEL (case_label), spc, flags, false); if (i < gimple_switch_num_labels (gs) - 1) - pp_string (buffer, ", "); + pp_string (buffer, "; "); } - pp_greater (buffer); + pp_string (buffer, "}"); } @@ -907,16 +907,11 @@ dump_gimple_label (pretty_printer *buffer, glabel *gs, int spc, int flags) { tree label = gimple_label_label (gs); if (flags & TDF_RAW) - dump_gimple_fmt (buffer, spc, flags, "%G <%T>", gs, label); + dump_gimple_fmt (buffer, spc, flags, "%T", label); else - { - dump_generic_node (buffer, label, spc, flags, false); - pp_colon (buffer); - } - if (DECL_NONLOCAL (label)) - pp_string (buffer, " [non-local]"); - if ((flags & TDF_EH) && EH_LANDING_PAD_NR (label)) - pp_printf (buffer, " [LP %d]", EH_LANDING_PAD_NR (label)); + dump_generic_node (buffer, label, spc, flags, false); + + pp_colon (buffer); } /* Dump a GIMPLE_GOTO tuple on the pretty_printer BUFFER, SPC @@ -1966,8 +1961,7 @@ dump_ssaname_info_to_file (FILE *file, tree node, int spc) pretty printer. If COMMENT is true, print this after #. */ static void -dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, bool comment, - int flags) +dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, int flags) { size_t i; tree lhs = gimple_phi_result (phi); @@ -1975,30 +1969,27 @@ dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, bool comment, if (flags & TDF_ALIAS) dump_ssaname_info (buffer, lhs, spc); - if (comment) - pp_string (buffer, "# "); - if (flags & TDF_RAW) dump_gimple_fmt (buffer, spc, flags, "%G <%T, ", phi, gimple_phi_result (phi)); else { dump_generic_node (buffer, lhs, spc, flags, false); - pp_string (buffer, " = PHI <"); + pp_string (buffer, " = __PHI ("); } for (i = 0; i < gimple_phi_num_args (phi); i++) { if ((flags & TDF_LINENO) && gimple_phi_arg_has_location (phi, i)) dump_location (buffer, gimple_phi_arg_location (phi, i)); + pp_string (buffer, "bb_"); + pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index); + pp_string (buffer, ": "); dump_generic_node (buffer, gimple_phi_arg_def (phi, i), spc, flags, false); - pp_left_paren (buffer); - pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index); - pp_right_paren (buffer); if (i < gimple_phi_num_args (phi) - 1) pp_string (buffer, ", "); } - pp_greater (buffer); + pp_right_paren (buffer); } @@ -2286,7 +2277,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple *gs, int spc, int flags) break; case GIMPLE_PHI: - dump_gimple_phi (buffer, as_a <gphi *> (gs), spc, false, flags); + dump_gimple_phi (buffer, as_a <gphi *> (gs), spc, flags); break; case GIMPLE_OMP_PARALLEL: @@ -2447,7 +2438,7 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, int indent, int flags) { gimple *stmt = first_stmt (bb); if (!stmt || gimple_code (stmt) != GIMPLE_LABEL) - fprintf (outf, "%*s<bb %d>:\n", indent, "", bb->index); + fprintf (outf, "%*sbb_%d:\n", indent, "", bb->index); } } @@ -2480,7 +2471,7 @@ dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags) if (!virtual_operand_p (gimple_phi_result (phi)) || (flags & TDF_VOPS)) { INDENT (indent); - dump_gimple_phi (buffer, phi, indent, true, flags); + dump_gimple_phi (buffer, phi, indent, flags); pp_newline (buffer); } } @@ -2493,24 +2484,9 @@ dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags) static void pp_cfg_jump (pretty_printer *buffer, basic_block bb) { - gimple *stmt; - - stmt = first_stmt (bb); - - pp_string (buffer, "goto <bb "); + pp_string (buffer, "goto bb_"); pp_decimal_int (buffer, bb->index); - pp_greater (buffer); - if (stmt && gimple_code (stmt) == GIMPLE_LABEL) - { - pp_string (buffer, " ("); - dump_generic_node (buffer, - gimple_label_label (as_a <glabel *> (stmt)), - 0, 0, false); - pp_right_paren (buffer); - pp_semicolon (buffer); - } - else - pp_semicolon (buffer); + pp_semicolon (buffer); } @@ -2627,7 +2603,7 @@ gimple_dump_bb (FILE *file, basic_block bb, int indent, int flags) void gimple_dump_bb_for_graph (pretty_printer *pp, basic_block bb) { - pp_printf (pp, "<bb %d>:\n", bb->index); + pp_printf (pp, "bb_%d:\n", bb->index); pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true); for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi); diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 4715332..12b9ec9 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -11848,7 +11848,22 @@ gimplify_function_tree (tree fndecl) && !needs_to_live_in_memory (ret)) DECL_GIMPLE_REG_P (ret) = 1; - bind = gimplify_body (fndecl, true); + if (!cfun->gimple_body) + bind = gimplify_body (fndecl, true); + else + { + gimple_seq seq; + gimple *outer_stmt; + seq = cfun->gimple_body; + outer_stmt = gimple_seq_first_stmt (seq); + if (gimple_code (outer_stmt) == GIMPLE_BIND + && gimple_seq_first (seq) == gimple_seq_last (seq)) + bind = as_a <gbind *> (outer_stmt); + else + bind = gimple_build_bind (NULL_TREE, seq, NULL); + + DECL_SAVED_TREE (fndecl) = NULL_TREE; + } /* The tree body of the function is no longer needed, replace it with the new GIMPLE body. */ diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index cd4b625..3824fb7 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -2412,3 +2412,9 @@ expand_internal_call (gcall *stmt) { expand_internal_call (gimple_call_internal_fn (stmt), stmt); } + +void +expand_PHI (internal_fn, gcall *) +{ + gcc_unreachable (); +} diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index 6701cd9..a5dd23e 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -169,6 +169,7 @@ DEF_INTERNAL_FN (VA_ARG, ECF_NOTHROW | ECF_LEAF, NULL) other such optimizations. The first argument distinguishes between uses. See internal-fn.h for usage. */ DEF_INTERNAL_FN (UNIQUE, ECF_NOTHROW, NULL) +DEF_INTERNAL_FN (PHI, 0, NULL) /* DIM_SIZE and DIM_POS return the size of a particular compute dimension and the executing thread's position within that diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h index bb31465..9c39dd67 100644 --- a/gcc/internal-fn.h +++ b/gcc/internal-fn.h @@ -174,5 +174,6 @@ extern bool set_edom_supported_p (void); extern void expand_internal_call (gcall *); extern void expand_internal_call (internal_fn, gcall *); +extern void expand_PHI (internal_fn, gcall *); #endif diff --git a/gcc/passes.c b/gcc/passes.c index c7d7dbe..04caf39 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -1685,12 +1685,13 @@ remove_cgraph_node_from_order (cgraph_node *node, void *data) call CALLBACK on the current function. This function is global so that plugins can use it. */ void -do_per_function_toporder (void (*callback) (function *, void *data), void *data) +do_per_function_toporder (void (*callback) (function *, void *data, void *flag), + void *data, void *flag) { int i; if (current_function_decl) - callback (cfun, data); + callback (cfun, data, flag); else { cgraph_node_hook_list *hook; @@ -1725,7 +1726,7 @@ do_per_function_toporder (void (*callback) (function *, void *data), void *data) { struct function *fn = DECL_STRUCT_FUNCTION (node->decl); push_cfun (fn); - callback (fn, data); + callback (fn, data, flag); pop_cfun (); } } @@ -2276,8 +2277,18 @@ override_gate_status (opt_pass *pass, tree func, bool gate_status) /* Execute PASS. */ bool -execute_one_pass (opt_pass *pass) +execute_one_pass (opt_pass *pass, bool startwith_p) { + /* For skipping passes until startwith pass */ + if (cfun && startwith_p && cfun->startwith) + { + if (!strcmp (pass->name, cfun->pass_startwith->name) + || !strcmp (pass->name, "*clean_state")) + cfun->startwith = false; + else + return true; + } + unsigned int todo_after = 0; bool gate_status; @@ -2417,7 +2428,7 @@ execute_one_pass (opt_pass *pass) } static void -execute_pass_list_1 (opt_pass *pass) +execute_pass_list_1 (opt_pass *pass, bool startwith_p) { do { @@ -2426,18 +2437,23 @@ execute_pass_list_1 (opt_pass *pass) if (cfun == NULL) return; - if (execute_one_pass (pass) && pass->sub) - execute_pass_list_1 (pass->sub); + if (execute_one_pass (pass, startwith_p) && pass->sub) + execute_pass_list_1 (pass->sub, startwith_p); pass = pass->next; } while (pass); } void -execute_pass_list (function *fn, opt_pass *pass) +execute_pass_list (function *fn, opt_pass *pass, bool *startwith_p) { gcc_assert (fn == cfun); - execute_pass_list_1 (pass); + + if (startwith_p) + execute_pass_list_1 (pass, *startwith_p); + else + execute_pass_list_1 (pass, false); + if (cfun && fn->cfg) { free_dominance_info (CDI_DOMINATORS); @@ -2767,19 +2783,22 @@ ipa_read_optimization_summaries (void) void execute_ipa_pass_list (opt_pass *pass) { + bool startwith_p = false; do { gcc_assert (!current_function_decl); gcc_assert (!cfun); gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS); - if (execute_one_pass (pass) && pass->sub) + if (!strcmp (pass->name, "opt_local_passes")) + startwith_p = true; + if (execute_one_pass (pass, startwith_p) && pass->sub) { if (pass->sub->type == GIMPLE_PASS) { invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL); - do_per_function_toporder ((void (*)(function *, void *)) + do_per_function_toporder ((void (*)(function *, void *, void *)) execute_pass_list, - pass->sub); + pass->sub, &startwith_p); invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL); } else if (pass->sub->type == SIMPLE_IPA_PASS diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 57c8410..7fe994e 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -170,6 +170,7 @@ static edge find_taken_edge_computed_goto (basic_block, tree); static edge find_taken_edge_cond_expr (basic_block, tree); static edge find_taken_edge_switch_expr (gswitch *, basic_block, tree); static tree find_case_label_for_value (gswitch *, tree); +static void lower_phi_internal_fn (); void init_empty_tree_cfg_for_function (struct function *fn) @@ -244,6 +245,7 @@ build_gimple_cfg (gimple_seq seq) discriminator_per_locus = new hash_table<locus_discrim_hasher> (13); make_edges (); assign_discriminators (); + lower_phi_internal_fn (); cleanup_dead_labels (); delete discriminator_per_locus; discriminator_per_locus = NULL; @@ -345,6 +347,50 @@ replace_loop_annotate (void) } } +/* Lower internal PHI function from GIMPLE FE. */ + +static void +lower_phi_internal_fn () +{ + basic_block bb, pred = NULL; + gimple_stmt_iterator gsi; + tree lhs; + gphi *phi_node; + gimple *stmt; + + /* After edge creation, handle __PHI function from GIMPLE FE. */ + FOR_EACH_BB_FN (bb, cfun) + { + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + stmt = gsi_stmt (gsi); + if (gimple_code (stmt) != GIMPLE_CALL) + continue; + + if (gimple_call_internal_p (stmt) && + gimple_call_internal_fn (stmt) == IFN_PHI) + { + gsi_remove (&gsi, true); + unsigned int i; + lhs = gimple_call_lhs (stmt); + phi_node = create_phi_node (lhs, bb); + + /* Add arguments to the PHI node. */ + for (i = 0; i < gimple_call_num_args (stmt); ++i) + { + tree arg = gimple_call_arg (stmt, i); + if (TREE_CODE (arg) == LABEL_DECL) + pred = label_to_block (arg); + else + { + edge e = find_edge (pred, bb); + add_phi_arg (phi_node, arg, e, UNKNOWN_LOCATION); + } + } + } + } + } +} static unsigned int execute_build_cfg (void) @@ -3340,6 +3386,11 @@ verify_gimple_call (gcall *stmt) debug_generic_stmt (fn); return true; } + /* FIXME : for passing label as arg in internal fn PHI from GIMPLE FE*/ + else if (gimple_call_internal_fn (stmt) == IFN_PHI) + { + return false; + } } else { @@ -7504,7 +7555,8 @@ dump_function_to_file (tree fndecl, FILE *file, int flags) } current_function_decl = fndecl; - fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : ""); + print_generic_expr (file, TREE_TYPE (TREE_TYPE (fndecl)), dump_flags); + fprintf (file, "\n%s %s(", function_name (fun), tmclone ? "[tm-clone] " : ""); arg = DECL_ARGUMENTS (fndecl); while (arg) diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c index ceafa68..ba3dc05 100644 --- a/gcc/tree-into-ssa.c +++ b/gcc/tree-into-ssa.c @@ -1379,12 +1379,19 @@ rewrite_add_phi_arguments (basic_block bb) for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi); gsi_next (&gsi)) { - tree currdef, res; + tree currdef, res, argvar; location_t loc; phi = gsi.phi (); res = gimple_phi_result (phi); - currdef = get_reaching_def (SSA_NAME_VAR (res)); + /* If we have pre-existing PHI its args may be different + vars than existing vars */ + argvar = gimple_phi_arg_def (phi, e->dest_idx); + if (argvar && TREE_CODE (argvar) == SSA_NAME) + continue; + if (!argvar) + argvar = SSA_NAME_VAR (res); + currdef = get_reaching_def (argvar); /* Virtual operand PHI args do not need a location. */ if (virtual_operand_p (res)) loc = UNKNOWN_LOCATION; diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index c0059de..213070b 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -617,8 +617,9 @@ extern gimple_opt_pass *make_pass_lower_vaarg (gcc::context *ctxt); /* Current optimization pass. */ extern opt_pass *current_pass; -extern bool execute_one_pass (opt_pass *); -extern void execute_pass_list (function *, opt_pass *); +extern bool execute_one_pass (opt_pass *, bool startwith_p = false); +extern void execute_pass_list (function *, opt_pass *, + bool *startwith_p = NULL); extern void execute_ipa_pass_list (opt_pass *); extern void execute_ipa_summary_passes (ipa_opt_pass_d *); extern void execute_all_ipa_transforms (void); diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index 734ecda..aa53bd2 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -260,7 +260,7 @@ dump_decl_name (pretty_printer *pp, tree node, int flags) if ((flags & TDF_UID) || DECL_NAME (node) == NULL_TREE) { if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1) - pp_printf (pp, "L.%d", (int) LABEL_DECL_UID (node)); + pp_printf (pp, "L_%d", (int) LABEL_DECL_UID (node)); else if (TREE_CODE (node) == DEBUG_EXPR_DECL) { if (flags & TDF_NOUID) @@ -274,7 +274,7 @@ dump_decl_name (pretty_printer *pp, tree node, int flags) if (flags & TDF_NOUID) pp_printf (pp, "%c.xxxx", c); else - pp_printf (pp, "%c.%u", c, DECL_UID (node)); + pp_printf (pp, "%c_%u", c, DECL_UID (node)); } } if ((flags & TDF_ALIAS) && DECL_PT_UID (node) != DECL_UID (node)) @@ -3965,14 +3965,14 @@ dump_function_header (FILE *dump_file, tree fdecl, int flags) else aname = "<unset-asm-name>"; - fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d", + fprintf (dump_file, "\n/* Function %s (%s, funcdef_no=%d", dname, aname, fun->funcdef_no); if (!(flags & TDF_NOUID)) fprintf (dump_file, ", decl_uid=%d", DECL_UID (fdecl)); if (node) { fprintf (dump_file, ", cgraph_uid=%d", node->uid); - fprintf (dump_file, ", symbol_order=%d)%s\n\n", node->order, + fprintf (dump_file, ", symbol_order=%d)%s", node->order, node->frequency == NODE_FREQUENCY_HOT ? " (hot)" : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED @@ -3982,7 +3982,8 @@ dump_function_header (FILE *dump_file, tree fdecl, int flags) : ""); } else - fprintf (dump_file, ")\n\n"); + fprintf (dump_file, ")"); + fprintf (dump_file, "*/\n\n"); } /* Dump double_int D to pretty_printer PP. UNS is true diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 91a8f97..8b8863b 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -255,7 +255,8 @@ flush_ssaname_freelist (void) used without a preceding definition). */ tree -make_ssa_name_fn (struct function *fn, tree var, gimple *stmt) +make_ssa_name_fn (struct function *fn, tree var, gimple *stmt, + unsigned int version) { tree t; use_operand_p imm; @@ -265,8 +266,19 @@ make_ssa_name_fn (struct function *fn, tree var, gimple *stmt) || TREE_CODE (var) == RESULT_DECL || (TYPE_P (var) && is_gimple_reg_type (var))); + /* parsing ssa names with versions. */ + if (version != 0) + { + t = make_node (SSA_NAME); + SSA_NAME_VERSION (t) = version; + if (version >= SSANAMES (fn)->length ()) + vec_safe_grow_cleared (SSANAMES (fn), version + 1); + gcc_assert ((*SSANAMES (fn))[version] == NULL); + (*SSANAMES (fn))[version] = t; + ssa_name_nodes_created++; + } /* If our free list has an element, then use it. */ - if (!vec_safe_is_empty (FREE_SSANAMES (fn))) + else if (!vec_safe_is_empty (FREE_SSANAMES (fn))) { t = FREE_SSANAMES (fn)->pop (); ssa_name_nodes_reused++; diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h index 8e66ce6..3ce9327 100644 --- a/gcc/tree-ssanames.h +++ b/gcc/tree-ssanames.h @@ -74,7 +74,8 @@ extern bool ssa_name_has_boolean_range (tree); extern void init_ssanames (struct function *, int); extern void fini_ssanames (struct function *); extern void ssanames_print_statistics (void); -extern tree make_ssa_name_fn (struct function *, tree, gimple *); +extern tree make_ssa_name_fn (struct function *, tree, gimple *, + unsigned int version = 0); extern void release_ssa_name_fn (struct function *, tree); extern bool get_ptr_info_alignment (struct ptr_info_def *, unsigned int *, unsigned int *);
diff --git a/gcc/testsuite/gcc.dg/gimplefe-1.c b/gcc/testsuite/gcc.dg/gimplefe-1.c new file mode 100644 index 0000000..0786d47 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-1.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ + +int i; +void __GIMPLE () foo() +{ + i = 1; +} diff --git a/gcc/testsuite/gcc.dg/gimplefe-10.c b/gcc/testsuite/gcc.dg/gimplefe-10.c new file mode 100644 index 0000000..7f63c58 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-10.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ + +int __GIMPLE() bar(int a, int b, int c) +{ + a = 1; + b = a + 1; + c = b * 4; + return b; +} + +void __GIMPLE() foo() +{ + int a; + int b; + int c; + b = bar(a, b, c); +} diff --git a/gcc/testsuite/gcc.dg/gimplefe-11.c b/gcc/testsuite/gcc.dg/gimplefe-11.c new file mode 100644 index 0000000..e1483f4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-11.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ + +void __GIMPLE() bar(int a, int b, int c) +{ + a = 1; + b = a + 1; + c = b * 4; + return; +} + +void __GIMPLE() foo() +{ + int a; + int b; + int c; + bar(a, b, c); +} diff --git a/gcc/testsuite/gcc.dg/gimplefe-12.c b/gcc/testsuite/gcc.dg/gimplefe-12.c new file mode 100644 index 0000000..cbaf8a6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-12.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ + +void __GIMPLE (startwith ("tree-ccp1")) foo () +{ + int a; + int b; + a = b + 2; + return; +} diff --git a/gcc/testsuite/gcc.dg/gimplefe-13.c b/gcc/testsuite/gcc.dg/gimplefe-13.c new file mode 100644 index 0000000..c0da9fa --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-13.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ + +void __GIMPLE (startwith ("tree-dse1")) foo () +{ + int a; + +bb_2: + if (a > 4) + goto bb_3; + else + goto bb_4; + +bb_3: + a_2 = 10; + goto bb_5; + +bb_4: + a_3 = 20; + +bb_5: + a_1 = __PHI (bb_3: a_2, bb_4: a_3); + a_4 = a_1 + 4; + +return; +} diff --git a/gcc/testsuite/gcc.dg/gimplefe-2.c b/gcc/testsuite/gcc.dg/gimplefe-2.c new file mode 100644 index 0000000..e3a23cf --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-2.c @@ -0,0 +1,11 @@ +/* { dg-do compile }*/ +/* { dg-options "-fgimple" } */ + +int a; +void __GIMPLE () foo () +{ + int b; + b = a; + b = b + 1; + a = b; +} diff --git a/gcc/testsuite/gcc.dg/gimplefe-3.c b/gcc/testsuite/gcc.dg/gimplefe-3.c new file mode 100644 index 0000000..595365e --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-3.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ + +void __GIMPLE () foo () +{ + int *b; + *b = 1; +} diff --git a/gcc/testsuite/gcc.dg/gimplefe-4.c b/gcc/testsuite/gcc.dg/gimplefe-4.c new file mode 100644 index 0000000..3600c7c --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-4.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ + +void __GIMPLE () foo () +{ + int a; + char b; + a = (int) b; + return; +} diff --git a/gcc/testsuite/gcc.dg/gimplefe-5.c b/gcc/testsuite/gcc.dg/gimplefe-5.c new file mode 100644 index 0000000..1dab4af --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-5.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ + +int a; +void __GIMPLE () foo () +{ + int b; + int c; + +bb_2: + b = a; + if (b > 3) + goto bb_3; + else + goto bb_4; + +bb_3: + b = c + 4; + goto bb_5; + +bb_4: + b = b + 1; + goto bb_5; + +bb_5: + a = b; + return; +} diff --git a/gcc/testsuite/gcc.dg/gimplefe-6.c b/gcc/testsuite/gcc.dg/gimplefe-6.c new file mode 100644 index 0000000..242e08f --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-6.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ + +void __GIMPLE () foo () +{ + int a; + int b; + int c; + int d; + +bb_2: + a = ~b; + b = a << c; + c = a & b; + d = b | c; + +bb_3: + return; +} diff --git a/gcc/testsuite/gcc.dg/gimplefe-7.c b/gcc/testsuite/gcc.dg/gimplefe-7.c new file mode 100644 index 0000000..6125541 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-7.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ + +void __GIMPLE () foo () +{ + int a; + +bb_2: + if (a > 4) + goto bb_3; + else + goto bb_4; + +bb_3: + a_2 = 10; + goto bb_5; + +bb_4: + a_3 = 20; + +bb_5: + a_1 = __PHI (bb_3: a_2, bb_4: a_3); + a_4 = a_1 + 4; + +return; +} + diff --git a/gcc/testsuite/gcc.dg/gimplefe-8.c b/gcc/testsuite/gcc.dg/gimplefe-8.c new file mode 100644 index 0000000..4936bec --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-8.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ + +int __GIMPLE () foo () +{ + int a; + int b; + +bb_2: + b = a_1(D) + 1; +bb_3: + return b; +} diff --git a/gcc/testsuite/gcc.dg/gimplefe-9.c b/gcc/testsuite/gcc.dg/gimplefe-9.c new file mode 100644 index 0000000..a24be273 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-9.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ + +int __GIMPLE() bar() +{ + int a; + a = a + 1; + return a; +} + +void __GIMPLE() foo() +{ + int b; + b = bar(); +}