Mercurial > hg > CbC > CbC_gcc
diff gcc/c/gimple-parser.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
line wrap: on
line diff
--- a/gcc/c/gimple-parser.c Thu Oct 25 07:37:49 2018 +0900 +++ b/gcc/c/gimple-parser.c Thu Feb 13 11:34:05 2020 +0900 @@ -1,5 +1,5 @@ /* Parser for GIMPLE. - Copyright (C) 2016-2018 Free Software Foundation, Inc. + Copyright (C) 2016-2020 Free Software Foundation, Inc. This file is part of GCC. @@ -54,45 +54,206 @@ #include "gimple-ssa.h" #include "tree-dfa.h" #include "internal-fn.h" +#include "cfg.h" +#include "cfghooks.h" +#include "cfganal.h" +#include "tree-cfg.h" +#include "gimple-iterator.h" +#include "cfgloop.h" +#include "tree-phinodes.h" +#include "tree-into-ssa.h" +#include "bitmap.h" + + +/* GIMPLE parser state. */ + +class gimple_parser +{ +public: + gimple_parser (c_parser *p) : parser (p), edges(), current_bb(NULL) {} + /* c_parser is not visible here, use composition and fake inheritance + via a conversion operator. */ + operator c_parser *() { return parser; } + c_parser *parser; + + /* CFG build state. */ + class gimple_parser_edge + { + public: + int src; + int dest; + int flags; + profile_probability probability; + }; + auto_vec<gimple_parser_edge> edges; + basic_block current_bb; + + void push_edge (int, int, int, profile_probability); +}; + +void +gimple_parser::push_edge (int src, int dest, int flags, + profile_probability prob) +{ + gimple_parser_edge e; + e.src = src; + e.dest = dest; + e.flags = flags; + e.probability = prob; + edges.safe_push (e); +} /* 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_statement (c_parser *, gimple_seq *); -static struct c_expr c_parser_gimple_binary_expression (c_parser *); -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 bool c_parser_gimple_compound_statement (gimple_parser &, gimple_seq *); +static void c_parser_gimple_label (gimple_parser &, gimple_seq *); +static void c_parser_gimple_statement (gimple_parser &, gimple_seq *); +static struct c_expr c_parser_gimple_binary_expression (gimple_parser &); +static struct c_expr c_parser_gimple_unary_expression (gimple_parser &); +static struct c_expr c_parser_gimple_postfix_expression (gimple_parser &); +static struct c_expr c_parser_gimple_postfix_expression_after_primary + (gimple_parser &, location_t, struct c_expr); +static void c_parser_gimple_declaration (gimple_parser &); +static void c_parser_gimple_goto_stmt (gimple_parser &, location_t, + tree, gimple_seq *); +static void c_parser_gimple_try_stmt (gimple_parser &, gimple_seq *); +static void c_parser_gimple_if_stmt (gimple_parser &, gimple_seq *); +static void c_parser_gimple_switch_stmt (gimple_parser &, gimple_seq *); +static void c_parser_gimple_return_stmt (gimple_parser &, gimple_seq *); static void c_finish_gimple_return (location_t, tree); -static tree c_parser_gimple_paren_condition (c_parser *); -static void c_parser_gimple_expr_list (c_parser *, vec<tree> *); +static tree c_parser_gimple_paren_condition (gimple_parser &); +static void c_parser_gimple_expr_list (gimple_parser &, vec<tree> *); + + +/* See if VAL is an identifier matching __BB<num> and return <num> + in *INDEX. */ + +static bool +c_parser_gimple_parse_bb_spec (tree val, int *index) +{ + if (strncmp (IDENTIFIER_POINTER (val), "__BB", 4) != 0) + return false; + for (const char *p = IDENTIFIER_POINTER (val) + 4; *p; ++p) + if (!ISDIGIT (*p)) + return false; + *index = atoi (IDENTIFIER_POINTER (val) + 4); + return *index > 0; +} + +/* See if VAL is an identifier matching __BB<num> and return <num> + in *INDEX. Return true if so and parse also FREQUENCY of + the edge. */ + +static bool +c_parser_gimple_parse_bb_spec_edge_probability (tree val, + gimple_parser &parser, + int *index, + profile_probability *probablity) +{ + bool return_p = c_parser_gimple_parse_bb_spec (val, index); + if (return_p) + { + *probablity = profile_probability::uninitialized (); + /* Parse frequency if provided. */ + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + { + tree f; + c_parser_consume_token (parser); + if (!c_parser_next_token_is (parser, CPP_NAME)) + { + c_parser_error (parser, "expected frequency quality"); + return false; + } + + profile_quality quality; + const char *v + = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (!parse_profile_quality (v, &quality)) + { + c_parser_error (parser, "unknown profile quality"); + return false; + } + + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return false; + + if (!c_parser_next_token_is (parser, CPP_NUMBER) + || (TREE_CODE (f = c_parser_peek_token (parser)->value) + != INTEGER_CST)) + { + c_parser_error (parser, "expected frequency value"); + return false; + } + + unsigned int value = TREE_INT_CST_LOW (f); + *probablity = profile_probability (value, quality); + + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + return false; + + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + return false; + } + + return true; + } + + return false; + +} /* Parse the body of a function declaration marked with "__GIMPLE". */ void -c_parser_parse_gimple_body (c_parser *parser) +c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass, + enum c_declspec_il cdil, + profile_count entry_bb_count) { + gimple_parser parser (cparser); gimple_seq seq = NULL; gimple_seq body = NULL; tree stmt = push_stmt_list (); push_scope (); location_t loc1 = c_parser_peek_token (parser)->location; + cfun->pass_startwith = gimple_pass; init_tree_ssa (cfun); - if (! c_parser_gimple_compound_statement (parser, &seq)) + if (cdil == cdil_gimple) + /* 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; + else + { + /* We have at least cdil_gimple_cfg. */ + gimple_register_cfg_hooks (); + init_empty_tree_cfg (); + parser.current_bb = ENTRY_BLOCK_PTR_FOR_FN (cfun); + /* Initialize the bare loop structure - we are going to only + mark headers and leave the rest to fixup. */ + set_loops_for_fn (cfun, ggc_cleared_alloc<struct loops> ()); + init_loops_structure (cfun, loops_for_fn (cfun), 1); + loops_state_set (cfun, LOOPS_NEED_FIXUP|LOOPS_MAY_HAVE_MULTIPLE_LATCHES); + cfun->curr_properties + |= PROP_gimple_lcf | PROP_gimple_leh | PROP_cfg | PROP_loops; + if (cdil == cdil_gimple_ssa) + { + init_ssa_operands (cfun); + cfun->curr_properties |= PROP_ssa; + } + } + + if (! c_parser_gimple_compound_statement (parser, &seq) + && cdil == cdil_gimple) { gimple *ret = gimple_build_return (NULL); - gimple_seq_add_stmt (&seq, ret); + gimple_seq_add_stmt_without_update (&seq, ret); } tree block = pop_scope (); @@ -104,19 +265,100 @@ 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); + if (cdil == cdil_gimple) + { + 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_without_update (&body, bind_stmt); + gimple_set_body (current_function_decl, body); + } + else + { + /* Control-flow and binds are lowered, record local decls. */ + for (tree var = BIND_EXPR_VARS (stmt); var; var = DECL_CHAIN (var)) + if (VAR_P (var) + && !DECL_EXTERNAL (var)) + add_local_decl (cfun, var); + /* We have a CFG. Build the edges. */ + for (unsigned i = 0; i < parser.edges.length (); ++i) + { + edge e = make_edge (BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].src), + BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].dest), + parser.edges[i].flags); + e->probability = parser.edges[i].probability; + } + /* Add edges for case labels. */ + basic_block bb; + FOR_EACH_BB_FN (bb, cfun) + if (EDGE_COUNT (bb->succs) == 0) + { + gimple *last = last_stmt (bb); + if (gswitch *sw = safe_dyn_cast <gswitch *> (last)) + for (unsigned i = 0; i < gimple_switch_num_labels (sw); ++i) + { + basic_block label_bb = gimple_switch_label_bb (cfun, sw, i); + make_edge (bb, label_bb, 0); + } + } + /* Need those for loop fixup. */ + calculate_dominance_info (CDI_DOMINATORS); + /* With SSA lower PHIs parsed as internal function calls and + update stmts. */ + if (cdil == cdil_gimple_ssa) + { + /* Create PHI nodes, they are parsed into __PHI internal calls. */ + FOR_EACH_BB_FN (bb, cfun) + for (gimple_stmt_iterator gsi = gsi_start_bb (bb); + !gsi_end_p (gsi);) + { + gimple *stmt = gsi_stmt (gsi); + if (!gimple_call_internal_p (stmt, IFN_PHI)) + break; - /* 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; + gphi *phi = create_phi_node (gimple_call_lhs (stmt), bb); + for (unsigned i = 0; i < gimple_call_num_args (stmt); i += 2) + { + int srcidx = TREE_INT_CST_LOW (gimple_call_arg (stmt, i)); + edge e = find_edge (BASIC_BLOCK_FOR_FN (cfun, srcidx), bb); + if (!e) + c_parser_error (parser, "edge not found"); + else + add_phi_arg (phi, gimple_call_arg (stmt, i + 1), e, + UNKNOWN_LOCATION); + } + gsi_remove (&gsi, true); + } + /* Fill SSA name gaps, putting them on the freelist. */ + for (unsigned i = 1; i < num_ssa_names; ++i) + if (!ssa_name (i)) + { + tree name = make_ssa_name_fn (cfun, integer_type_node, NULL, i); + release_ssa_name_fn (cfun, name); + } + /* No explicit virtual operands (yet). */ + bitmap_obstack_initialize (NULL); + update_ssa (TODO_update_ssa_only_virtuals); + bitmap_obstack_release (NULL); + /* ??? By flushing the freelist after virtual operand SSA rewrite + we keep the gaps available for re-use like needed for the + PR89595 testcase but then usually virtual operands would have + taken most of them. The fix is obviously to make virtual + operands explicit in the SSA IL. */ + flush_ssaname_freelist (); + } + fix_loop_structure (NULL); + } + if (cfun->curr_properties & PROP_cfg) + { + ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = entry_bb_count; + gcov_type t = param_gimple_fe_computed_hot_bb_threshold; + set_hot_bb_threshold (t); + update_max_bb_count (); + cgraph_node::get_create (cfun->decl); + cgraph_edge::rebuild_edges (); + } dump_function (TDI_gimple, current_function_decl); } @@ -135,7 +377,7 @@ */ static bool -c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq) +c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq) { bool return_p = false; @@ -168,6 +410,9 @@ case CPP_KEYWORD: switch (c_parser_peek_token (parser)->keyword) { + case RID_AT_TRY: + c_parser_gimple_try_stmt (parser, seq); + break; case RID_IF: c_parser_gimple_if_stmt (parser, seq); break; @@ -180,11 +425,9 @@ 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); + tree label = c_parser_peek_token (parser)->value; c_parser_consume_token (parser); + c_parser_gimple_goto_stmt (parser, loc, label, seq); if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) return return_p; @@ -197,6 +440,9 @@ if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) return return_p; + if (cfun->curr_properties & PROP_cfg) + parser.push_edge (parser.current_bb->index, EXIT_BLOCK, 0, + profile_probability::uninitialized ()); break; default: goto expr_stmt; @@ -208,6 +454,182 @@ c_parser_gimple_label (parser, seq); break; } + if (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_token (parser)->id_kind == C_ID_ID + && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value), + "try") == 0) + { + c_parser_gimple_try_stmt (parser, seq); + break; + } + /* Basic block specification. + __BB (index, ...) */ + if ((cfun->curr_properties & PROP_cfg) + && !strcmp (IDENTIFIER_POINTER + (c_parser_peek_token (parser)->value), "__BB")) + { + c_parser_consume_token (parser); + if (! c_parser_require (parser, CPP_OPEN_PAREN, + "expected %<(%>")) + return return_p; + if (c_parser_next_token_is_not (parser, CPP_NUMBER)) + { + c_parser_error (parser, "expected block index"); + return return_p; + } + tree tnum = c_parser_peek_token (parser)->value; + if (TREE_CODE (tnum) != INTEGER_CST) + { + c_parser_error (parser, "expected block index"); + return return_p; + } + int index = TREE_INT_CST_LOW (tnum); + if (index < NUM_FIXED_BLOCKS + || (index < last_basic_block_for_fn (cfun) + && BASIC_BLOCK_FOR_FN (cfun, index) != NULL)) + { + c_parser_error (parser, "invalid block index"); + return return_p; + } + int is_loop_header_of = -1; + profile_count bb_count = profile_count::uninitialized (); + c_parser_consume_token (parser); + while (c_parser_next_token_is (parser, CPP_COMMA)) + { + c_parser_consume_token (parser); + if (! c_parser_next_token_is (parser, CPP_NAME)) + { + c_parser_error (parser, "expected block specifier"); + return return_p; + } + /* loop_header (NUM) */ + if (!strcmp (IDENTIFIER_POINTER + (c_parser_peek_token (parser)->value), + "loop_header")) + { + c_parser_consume_token (parser); + if (! c_parser_require (parser, CPP_OPEN_PAREN, + "expected %<(%>")) + return return_p; + tree loop_num; + if (! c_parser_next_token_is (parser, CPP_NUMBER) + || TREE_CODE (loop_num + = c_parser_peek_token (parser)->value) + != INTEGER_CST) + { + c_parser_error (parser, "expected loop number"); + return return_p; + } + c_parser_consume_token (parser); + is_loop_header_of = TREE_INT_CST_LOW (loop_num); + if (! c_parser_require (parser, CPP_CLOSE_PAREN, + "expected %<)%>")) + return return_p; + } + /* Parse profile: quality(value) */ + else + { + tree q; + profile_quality quality; + tree v = c_parser_peek_token (parser)->value; + if (!parse_profile_quality (IDENTIFIER_POINTER (v), + &quality)) + { + c_parser_error (parser, "unknown block specifier"); + return false; + } + + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_OPEN_PAREN, + "expected %<(%>")) + return false; + + if (!c_parser_next_token_is (parser, CPP_NUMBER) + || (TREE_CODE (q = c_parser_peek_token (parser)->value) + != INTEGER_CST)) + { + c_parser_error (parser, "expected count value"); + return false; + } + + bb_count + = profile_count::from_gcov_type (TREE_INT_CST_LOW (q), + quality); + c_parser_consume_token (parser); + if (! c_parser_require (parser, CPP_CLOSE_PAREN, + "expected %<)%>")) + return return_p; + } + } + if (! c_parser_require (parser, CPP_CLOSE_PAREN, + "expected %<)%>") + || ! c_parser_require (parser, CPP_COLON, + "expected %<:%>")) + return return_p; + + /* Put stmts parsed in the current block. */ + if (!gimple_seq_empty_p (*seq)) + { + if (!parser.current_bb) + c_parser_error (parser, "stmts without block"); + else + { + gimple_stmt_iterator gsi + = gsi_start_bb (parser.current_bb); + gsi_insert_seq_after (&gsi, *seq, GSI_CONTINUE_LINKING); + } + *seq = NULL; + } + + /* Build an empty block with specified index, linking them + in source order. */ + basic_block bb = alloc_block (); + bb->index = index; + link_block (bb, (parser.current_bb ? parser.current_bb + : ENTRY_BLOCK_PTR_FOR_FN (cfun))); + if (basic_block_info_for_fn (cfun)->length () <= (size_t)index) + vec_safe_grow_cleared (basic_block_info_for_fn (cfun), + index + 1); + SET_BASIC_BLOCK_FOR_FN (cfun, index, bb); + if (last_basic_block_for_fn (cfun) <= index) + last_basic_block_for_fn (cfun) = index + 1; + n_basic_blocks_for_fn (cfun)++; + if (parser.current_bb->index == ENTRY_BLOCK) + parser.push_edge (ENTRY_BLOCK, bb->index, EDGE_FALLTHRU, + profile_probability::always ()); + + /* We leave the proper setting to fixup. */ + class loop *loop_father = loops_for_fn (cfun)->tree_root; + /* If the new block is a loop header, allocate a loop + struct. Fixup will take care of proper placement within + the loop tree. */ + if (is_loop_header_of != -1) + { + if (number_of_loops (cfun) > (unsigned)is_loop_header_of + && get_loop (cfun, is_loop_header_of) != NULL) + { + c_parser_error (parser, "duplicate loop header"); + } + else + { + class loop *loop = alloc_loop (); + loop->num = is_loop_header_of; + loop->header = bb; + vec_safe_grow_cleared (loops_for_fn (cfun)->larray, + is_loop_header_of + 1); + (*loops_for_fn (cfun)->larray)[is_loop_header_of] = loop; + flow_loop_tree_node_add (loops_for_fn (cfun)->tree_root, + loop); + } + loop_father = get_loop (cfun, is_loop_header_of); + } + bb->loop_father = loop_father; + bb->count = bb_count; + + /* Stmts now go to the new block. */ + parser.current_bb = bb; + break; + } goto expr_stmt; case CPP_SEMICOLON: @@ -217,7 +639,7 @@ c_parser_consume_token (parser); gimple *nop = gimple_build_nop (); gimple_set_location (nop, loc); - gimple_seq_add_stmt (seq, nop); + gimple_seq_add_stmt_without_update (seq, nop); break; } @@ -229,6 +651,21 @@ } } c_parser_consume_token (parser); + + /* Put stmts parsed in the current block. */ + if ((cfun->curr_properties & PROP_cfg) + && !gimple_seq_empty_p (*seq)) + { + if (!parser.current_bb) + c_parser_error (parser, "stmts without block"); + else + { + gimple_stmt_iterator gsi = gsi_start_bb (parser.current_bb); + gsi_insert_seq_after (&gsi, *seq, GSI_CONTINUE_LINKING); + } + *seq = NULL; + } + return return_p; } @@ -260,7 +697,7 @@ */ static void -c_parser_gimple_statement (c_parser *parser, gimple_seq *seq) +c_parser_gimple_statement (gimple_parser &parser, gimple_seq *seq) { struct c_expr lhs, rhs; gimple *assign = NULL; @@ -278,7 +715,7 @@ { gimple *call; call = gimple_build_call_from_tree (lhs.value, NULL); - gimple_seq_add_stmt (seq, call); + gimple_seq_add_stmt_without_update (seq, call); gimple_set_location (call, loc); return; } @@ -303,20 +740,14 @@ && rhs.value != error_mark_node) { enum tree_code code = NOP_EXPR; - if (VECTOR_TYPE_P (TREE_TYPE (lhs.value))) - { - code = VIEW_CONVERT_EXPR; - rhs.value = build1 (VIEW_CONVERT_EXPR, - TREE_TYPE (lhs.value), rhs.value); - } - else if (FLOAT_TYPE_P (TREE_TYPE (lhs.value)) - && ! FLOAT_TYPE_P (TREE_TYPE (rhs.value))) + if (FLOAT_TYPE_P (TREE_TYPE (lhs.value)) + && ! FLOAT_TYPE_P (TREE_TYPE (rhs.value))) code = FLOAT_EXPR; else if (! FLOAT_TYPE_P (TREE_TYPE (lhs.value)) && FLOAT_TYPE_P (TREE_TYPE (rhs.value))) code = FIX_TRUNC_EXPR; assign = gimple_build_assign (lhs.value, code, rhs.value); - gimple_seq_add_stmt (seq, assign); + gimple_seq_add_stmt_without_update (seq, assign); gimple_set_location (assign, loc); return; } @@ -329,7 +760,11 @@ { tree id = c_parser_peek_token (parser)->value; if (strcmp (IDENTIFIER_POINTER (id), "__ABS") == 0 - || strcmp (IDENTIFIER_POINTER (id), "__ABSU") == 0) + || strcmp (IDENTIFIER_POINTER (id), "__ABSU") == 0 + || strcmp (IDENTIFIER_POINTER (id), "__MIN") == 0 + || strcmp (IDENTIFIER_POINTER (id), "__MAX") == 0 + || strcmp (IDENTIFIER_POINTER (id), "__BIT_INSERT") == 0 + || strcmp (IDENTIFIER_POINTER (id), "__VEC_PERM") == 0) goto build_unary_expr; break; } @@ -350,7 +785,7 @@ { assign = gimple_build_assign (lhs.value, rhs.value); gimple_set_location (assign, loc); - gimple_seq_add_stmt (seq, assign); + gimple_seq_add_stmt_without_update (seq, assign); } return; @@ -373,13 +808,14 @@ 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); + arg = 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); + int src_index = -1; + if (!c_parser_gimple_parse_bb_spec (arg, &src_index)) + c_parser_error (parser, "invalid source block specification"); + vargs.safe_push (size_int (src_index)); } else if (c_parser_next_token_is (parser, CPP_COMMA)) c_parser_consume_token (parser); @@ -397,7 +833,7 @@ 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); + gimple_seq_add_stmt_without_update (seq, call_stmt); return; } @@ -412,7 +848,7 @@ { gimple *call = gimple_build_call_from_tree (rhs.value, NULL); gimple_call_set_lhs (call, lhs.value); - gimple_seq_add_stmt (seq, call); + gimple_seq_add_stmt_without_update (seq, call); gimple_set_location (call, loc); } return; @@ -440,7 +876,7 @@ rhs.value, trueval.value, falseval.value); } assign = gimple_build_assign (lhs.value, rhs.value); - gimple_seq_add_stmt (seq, assign); + gimple_seq_add_stmt_without_update (seq, assign); gimple_set_location (assign, loc); } return; @@ -470,7 +906,7 @@ */ static c_expr -c_parser_gimple_binary_expression (c_parser *parser) +c_parser_gimple_binary_expression (gimple_parser &parser) { /* Location of the binary operator. */ struct c_expr ret, lhs, rhs; @@ -567,6 +1003,64 @@ return ret; } +/* Parse a gimple parentized binary expression. */ + +static c_expr +c_parser_gimple_parentized_binary_expression (gimple_parser &parser, + location_t op_loc, + tree_code code) +{ + struct c_expr ret; + ret.set_error (); + + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return ret; + c_expr op1 = c_parser_gimple_postfix_expression (parser); + if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) + return ret; + c_expr op2 = c_parser_gimple_postfix_expression (parser); + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + return ret; + + if (op1.value != error_mark_node && op2.value != error_mark_node) + ret.value = build2_loc (op_loc, + code, TREE_TYPE (op1.value), op1.value, op2.value); + return ret; +} + +/* Parse a gimple parentized binary expression. */ + +static c_expr +c_parser_gimple_parentized_ternary_expression (gimple_parser &parser, + location_t op_loc, + tree_code code) +{ + struct c_expr ret; + ret.set_error (); + + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return ret; + c_expr op1 = c_parser_gimple_postfix_expression (parser); + if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) + return ret; + c_expr op2 = c_parser_gimple_postfix_expression (parser); + if (!c_parser_require (parser, CPP_COMMA, "expected %<)%>")) + return ret; + c_expr op3 = c_parser_gimple_postfix_expression (parser); + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + return ret; + + if (op1.value != error_mark_node + && op2.value != error_mark_node + && op3.value != error_mark_node) + ret.value = build3_loc (op_loc, + code, TREE_TYPE (op1.value), + op1.value, op2.value, op3.value); + return ret; +} + /* Parse gimple unary expression. gimple-unary-expression: @@ -578,7 +1072,7 @@ */ static c_expr -c_parser_gimple_unary_expression (c_parser *parser) +c_parser_gimple_unary_expression (gimple_parser &parser) { struct c_expr ret, op; location_t op_loc = c_parser_peek_token (parser)->location; @@ -656,6 +1150,48 @@ op = c_parser_gimple_postfix_expression (parser); return parser_build_unary_op (op_loc, ABSU_EXPR, op); } + else if (strcmp (IDENTIFIER_POINTER (id), "__MIN") == 0) + return c_parser_gimple_parentized_binary_expression (parser, + op_loc, + MIN_EXPR); + else if (strcmp (IDENTIFIER_POINTER (id), "__MAX") == 0) + return c_parser_gimple_parentized_binary_expression (parser, + op_loc, + MAX_EXPR); + else if (strcmp (IDENTIFIER_POINTER (id), "__VEC_PERM") == 0) + return c_parser_gimple_parentized_ternary_expression + (parser, op_loc, VEC_PERM_EXPR); + else if (strcmp (IDENTIFIER_POINTER (id), "__BIT_INSERT") == 0) + { + /* __BIT_INSERT '(' postfix-expression, postfix-expression, + integer ')' */ + location_t loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + c_expr op0 = c_parser_gimple_postfix_expression (parser); + c_parser_skip_until_found (parser, CPP_COMMA, + "expected %<,%>"); + c_expr op1 = c_parser_gimple_postfix_expression (parser); + c_parser_skip_until_found (parser, CPP_COMMA, + "expected %<,%>"); + c_expr op2 = c_parser_gimple_postfix_expression (parser); + if (TREE_CODE (op2.value) != INTEGER_CST + || !int_fits_type_p (op2.value, bitsizetype)) + c_parser_error (parser, "expected constant offset"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + if (op0.value != error_mark_node + && op1.value != error_mark_node + && TREE_CODE (op2.value) == INTEGER_CST) + ret.value = build3_loc (loc, BIT_INSERT_EXPR, + TREE_TYPE (op0.value), + op0.value, op1.value, + fold_convert (bitsizetype, + op2.value)); + } + return ret; + } else return c_parser_gimple_postfix_expression (parser); } @@ -687,7 +1223,7 @@ TYPE is the type if the SSA name is being declared. */ static tree -c_parser_parse_ssa_name (c_parser *parser, +c_parser_parse_ssa_name (gimple_parser &parser, tree id, tree type, unsigned version, unsigned ver_offset) { @@ -752,7 +1288,7 @@ . identifier ( gimple-argument-expression-list[opt] ) */ static struct c_expr -c_parser_gimple_call_internal (c_parser *parser) +c_parser_gimple_call_internal (gimple_parser &parser) { struct c_expr expr; expr.set_error (); @@ -789,6 +1325,36 @@ return expr; } +/* Parse '<' type [',' alignment] '>' and return a type on success + and NULL_TREE on error. */ + +static tree +c_parser_gimple_typespec (gimple_parser &parser) +{ + struct c_type_name *type_name = NULL; + tree alignment = NULL_TREE; + if (c_parser_require (parser, CPP_LESS, "expected %<<%>")) + { + type_name = c_parser_type_name (parser); + /* Optional alignment. */ + if (c_parser_next_token_is (parser, CPP_COMMA)) + { + c_parser_consume_token (parser); + alignment + = c_parser_gimple_postfix_expression (parser).value; + } + c_parser_skip_until_found (parser, + CPP_GREATER, "expected %<>%>"); + } + if (!type_name) + return NULL_TREE; + tree tem; + tree type = groktypename (type_name, &tem, NULL); + if (alignment) + type = build_aligned_type (type, tree_to_uhwi (alignment)); + return type; +} + /* Parse gimple postfix expression. gimple-postfix-expression: @@ -806,12 +1372,13 @@ identifier constant string-literal + constructor gimple-call-internal */ static struct c_expr -c_parser_gimple_postfix_expression (c_parser *parser) +c_parser_gimple_postfix_expression (gimple_parser &parser) { location_t loc = c_parser_peek_token (parser)->location; source_range tok_range = c_parser_peek_token (parser)->get_range (); @@ -828,6 +1395,7 @@ case CPP_CHAR: case CPP_CHAR16: case CPP_CHAR32: + case CPP_UTF8CHAR: case CPP_WCHAR: expr.value = c_parser_peek_token (parser)->value; set_c_expr_source_range (&expr, tok_range); @@ -838,10 +1406,7 @@ 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); + expr = c_parser_string_literal (parser, false, true); break; case CPP_DOT: expr = c_parser_gimple_call_internal (parser); @@ -857,21 +1422,7 @@ [ '+' number ] ')' */ location_t loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); - struct c_type_name *type_name = NULL; - tree alignment = NULL_TREE; - if (c_parser_require (parser, CPP_LESS, "expected %<<%>")) - { - type_name = c_parser_type_name (parser); - /* Optional alignment. */ - if (c_parser_next_token_is (parser, CPP_COMMA)) - { - c_parser_consume_token (parser); - alignment - = c_parser_gimple_postfix_expression (parser).value; - } - c_parser_skip_until_found (parser, - CPP_GREATER, "expected %<>%>"); - } + tree type = c_parser_gimple_typespec (parser); struct c_expr ptr; ptr.value = error_mark_node; tree alias_off = NULL_TREE; @@ -919,22 +1470,73 @@ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } - if (! type_name || c_parser_error (parser)) + if (! type || c_parser_error (parser)) { c_parser_set_error (parser, false); return expr; } - tree tem = NULL_TREE; - tree type = groktypename (type_name, &tem, NULL); - if (alignment) - type = build_aligned_type (type, tree_to_uhwi (alignment)); expr.value = build2_loc (loc, MEM_REF, type, ptr.value, alias_off); break; } + else if (strcmp (IDENTIFIER_POINTER (id), "__VIEW_CONVERT") == 0) + { + /* __VIEW_CONVERT '<' type-name [ ',' number ] '>' + '(' postfix-expression ')' */ + location_t loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + tree type = c_parser_gimple_typespec (parser); + if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + c_expr op = c_parser_gimple_postfix_expression (parser); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + if (type && op.value != error_mark_node) + expr.value = build1_loc (loc, VIEW_CONVERT_EXPR, + type, op.value); + } + break; + } + else if (strcmp (IDENTIFIER_POINTER (id), "__BIT_FIELD_REF") == 0) + { + /* __BIT_FIELD_REF '<' type-name [ ',' number ] '>' + '(' postfix-expression, integer, integer ')' */ + location_t loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + tree type = c_parser_gimple_typespec (parser); + if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + c_expr op0 = c_parser_gimple_postfix_expression (parser); + c_parser_skip_until_found (parser, CPP_COMMA, + "expected %<,%>"); + c_expr op1 = c_parser_gimple_postfix_expression (parser); + if (TREE_CODE (op1.value) != INTEGER_CST + || !int_fits_type_p (op1.value, bitsizetype)) + c_parser_error (parser, "expected constant size"); + c_parser_skip_until_found (parser, CPP_COMMA, + "expected %<,%>"); + c_expr op2 = c_parser_gimple_postfix_expression (parser); + if (TREE_CODE (op2.value) != INTEGER_CST + || !int_fits_type_p (op2.value, bitsizetype)) + c_parser_error (parser, "expected constant offset"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + if (type + && op0.value != error_mark_node + && TREE_CODE (op1.value) == INTEGER_CST + && TREE_CODE (op2.value) == INTEGER_CST) + expr.value = build3_loc (loc, BIT_FIELD_REF, type, + op0.value, + fold_convert (bitsizetype, + op1.value), + fold_convert (bitsizetype, + op2.value)); + } + break; + } else if (strcmp (IDENTIFIER_POINTER (id), "_Literal") == 0) { - /* _Literal '(' type-name ')' [ '-' ] constant */ + /* _Literal '(' type-name ')' ( [ '-' ] constant | constructor ) */ c_parser_consume_token (parser); tree type = NULL_TREE; if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) @@ -946,28 +1548,97 @@ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } - bool neg_p; - if ((neg_p = c_parser_next_token_is (parser, CPP_MINUS))) - c_parser_consume_token (parser); - tree val = c_parser_gimple_postfix_expression (parser).value; - if (! type - || ! val - || val == error_mark_node - || ! CONSTANT_CLASS_P (val)) + if (! type) { c_parser_error (parser, "invalid _Literal"); return expr; } - if (neg_p) + if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) { - val = const_unop (NEGATE_EXPR, TREE_TYPE (val), val); - if (! val) + c_parser_consume_token (parser); + if (!AGGREGATE_TYPE_P (type) + && !VECTOR_TYPE_P (type)) + { + c_parser_error (parser, "invalid type for _Literal with " + "constructor"); + c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, + "expected %<}%>"); + return expr; + } + vec<constructor_elt, va_gc> *v = NULL; + bool constant_p = true; + if (VECTOR_TYPE_P (type) + && !c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + { + vec_alloc (v, TYPE_VECTOR_SUBPARTS (type).to_constant ()); + do + { + tree val + = c_parser_gimple_postfix_expression (parser).value; + if (! val + || val == error_mark_node + || (! CONSTANT_CLASS_P (val) + && ! SSA_VAR_P (val))) + { + c_parser_error (parser, "invalid _Literal"); + return expr; + } + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, val); + if (! CONSTANT_CLASS_P (val)) + constant_p = false; + if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + else + break; + } + while (1); + } + if (c_parser_require (parser, CPP_CLOSE_BRACE, + "expected %<}%>")) + { + if (v && constant_p) + expr.value = build_vector_from_ctor (type, v); + else + expr.value = build_constructor (type, v); + } + else + { + c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, + "expected %<}%>"); + return expr; + } + } + else + { + bool neg_p, addr_p; + if ((neg_p = c_parser_next_token_is (parser, CPP_MINUS))) + c_parser_consume_token (parser); + if ((addr_p = c_parser_next_token_is (parser, CPP_AND))) + c_parser_consume_token (parser); + tree val = c_parser_gimple_postfix_expression (parser).value; + if (! val + || val == error_mark_node + || (!CONSTANT_CLASS_P (val) + && !(addr_p + && (TREE_CODE (val) == STRING_CST + || DECL_P (val))))) { c_parser_error (parser, "invalid _Literal"); return expr; } + if (addr_p) + val = build1 (ADDR_EXPR, type, val); + if (neg_p) + { + val = const_unop (NEGATE_EXPR, TREE_TYPE (val), val); + if (! val) + { + c_parser_error (parser, "invalid _Literal"); + return expr; + } + } + expr.value = fold_convert (type, val); } - expr.value = fold_convert (type, val); return expr; } @@ -1039,7 +1710,7 @@ literal. */ static struct c_expr -c_parser_gimple_postfix_expression_after_primary (c_parser *parser, +c_parser_gimple_postfix_expression_after_primary (gimple_parser &parser, location_t expr_loc, struct c_expr expr) { @@ -1182,7 +1853,7 @@ */ static void -c_parser_gimple_expr_list (c_parser *parser, vec<tree> *ret) +c_parser_gimple_expr_list (gimple_parser &parser, vec<tree> *ret) { struct c_expr expr; @@ -1206,7 +1877,7 @@ */ static void -c_parser_gimple_label (c_parser *parser, gimple_seq *seq) +c_parser_gimple_label (gimple_parser &parser, gimple_seq *seq) { tree name = c_parser_peek_token (parser)->value; location_t loc1 = c_parser_peek_token (parser)->location; @@ -1215,58 +1886,89 @@ 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)); + gimple_seq_add_stmt_without_update (seq, gimple_build_label (label)); return; } /* Parse gimple/RTL pass list. gimple-or-rtl-pass-list: - startwith("pass-name") + startwith("pass-name")[,{cfg,ssa}] */ -char * -c_parser_gimple_or_rtl_pass_list (c_parser *parser) +void +c_parser_gimple_or_rtl_pass_list (c_parser *parser, c_declspecs *specs) { char *pass = NULL; /* Accept __GIMPLE/__RTL. */ if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN)) - return NULL; + return; c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_NAME)) + specs->entry_bb_count = profile_count::uninitialized (); + while (c_parser_next_token_is (parser, CPP_NAME)) { + profile_quality quality; 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; + return; if (c_parser_next_token_is_not (parser, CPP_STRING)) { error_at (c_parser_peek_token (parser)->location, "expected pass name"); - return NULL; + return; } pass = xstrdup (TREE_STRING_POINTER - (c_parser_peek_token (parser)->value)); + (c_parser_string_literal (parser, false, + false).value)); + if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<(%>")) + return; + } + else if (parse_profile_quality (op, &quality)) + { + tree q; + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return; + + if (!c_parser_next_token_is (parser, CPP_NUMBER) + || (TREE_CODE (q = c_parser_peek_token (parser)->value) + != INTEGER_CST)) + { + c_parser_error (parser, "expected count value"); + return; + } + + specs->entry_bb_count + = profile_count::from_gcov_type (TREE_INT_CST_LOW (q), quality); c_parser_consume_token (parser); - if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) - return NULL; + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + return; } + else if (specs->declspec_il != cdil_gimple) + /* Allow only one IL specifier and none on RTL. */ + ; + else if (! strcmp (op, "cfg")) + specs->declspec_il = cdil_gimple_cfg; + else if (! strcmp (op, "ssa")) + specs->declspec_il = cdil_gimple_ssa; else { error_at (c_parser_peek_token (parser)->location, "invalid operation"); - return NULL; + return; } + if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); } if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) - return NULL; + return; - return pass; + specs->gimple_or_rtl_pass = pass; } /* Parse gimple local declaration. @@ -1308,12 +2010,12 @@ */ static void -c_parser_gimple_declaration (c_parser *parser) +c_parser_gimple_declaration (gimple_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); + true, true, true, true, cla_nonabstract_decl); finish_declspecs (specs); /* Provide better error recovery. Note that a type name here is usually @@ -1338,13 +2040,13 @@ unsigned version, ver_offset; if (declarator->kind == cdk_id && is_gimple_reg_type (specs->type) - && c_parser_parse_ssa_name_id (declarator->u.id, + && c_parser_parse_ssa_name_id (declarator->u.id.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, + c_parser_parse_ssa_name (parser, declarator->u.id.id, specs->type, version, ver_offset); else { @@ -1368,11 +2070,23 @@ /* Parse gimple goto statement. */ static void -c_parser_gimple_goto_stmt (location_t loc, tree label, gimple_seq *seq) +c_parser_gimple_goto_stmt (gimple_parser &parser, + location_t loc, tree label, gimple_seq *seq) { + if (cfun->curr_properties & PROP_cfg) + { + int dest_index; + profile_probability prob; + if (c_parser_gimple_parse_bb_spec_edge_probability (label, parser, + &dest_index, &prob)) + { + parser.push_edge (parser.current_bb->index, dest_index, + EDGE_FALLTHRU, prob); + return; + } + } tree decl = lookup_label_for_goto (loc, label); - gimple_seq_add_stmt (seq, gimple_build_goto (decl)); - return; + gimple_seq_add_stmt_without_update (seq, gimple_build_goto (decl)); } /* Parse a parenthesized condition. @@ -1380,7 +2094,7 @@ ( gimple-binary-expression ) */ static tree -c_parser_gimple_paren_condition (c_parser *parser) +c_parser_gimple_paren_condition (gimple_parser &parser) { if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) return error_mark_node; @@ -1390,6 +2104,55 @@ return cond; } +/* Parse gimple try statement. + + try-statement: + try { ... } finally { ... } + try { ... } finally { ... } else { ... } + + This could support try/catch as well, but it's not implemented yet. + */ + +static void +c_parser_gimple_try_stmt (gimple_parser &parser, gimple_seq *seq) +{ + gimple_seq tryseq = NULL; + c_parser_consume_token (parser); + c_parser_gimple_compound_statement (parser, &tryseq); + + if ((c_parser_next_token_is (parser, CPP_KEYWORD) + && c_parser_peek_token (parser)->keyword == RID_AT_FINALLY) + || (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_token (parser)->id_kind == C_ID_ID + && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value), + "finally") == 0)) + { + gimple_seq finseq = NULL; + c_parser_consume_token (parser); + c_parser_gimple_compound_statement (parser, &finseq); + + if (c_parser_next_token_is (parser, CPP_KEYWORD) + && c_parser_peek_token (parser)->keyword == RID_ELSE) + { + gimple_seq elsseq = NULL; + c_parser_consume_token (parser); + c_parser_gimple_compound_statement (parser, &elsseq); + + geh_else *stmt = gimple_build_eh_else (finseq, elsseq); + finseq = NULL; + gimple_seq_add_stmt_without_update (&finseq, stmt); + } + + gtry *stmt = gimple_build_try (tryseq, finseq, GIMPLE_TRY_FINALLY); + gimple_seq_add_stmt_without_update (seq, stmt); + } + else if (c_parser_next_token_is (parser, CPP_KEYWORD) + && c_parser_peek_token (parser)->keyword == RID_AT_CATCH) + c_parser_error (parser, "%<catch%> is not supported"); + else + c_parser_error (parser, "expected %<finally%> or %<catch%>"); +} + /* Parse gimple if-else statement. if-statement: @@ -1399,9 +2162,9 @@ */ static void -c_parser_gimple_if_stmt (c_parser *parser, gimple_seq *seq) +c_parser_gimple_if_stmt (gimple_parser &parser, gimple_seq *seq) { - tree t_label, f_label, label; + tree t_label = NULL_TREE, f_label = NULL_TREE, label; location_t loc; c_parser_consume_token (parser); tree cond = c_parser_gimple_paren_condition (parser); @@ -1417,7 +2180,15 @@ } label = c_parser_peek_token (parser)->value; c_parser_consume_token (parser); - t_label = lookup_label_for_goto (loc, label); + int dest_index; + profile_probability prob; + if ((cfun->curr_properties & PROP_cfg) + && c_parser_gimple_parse_bb_spec_edge_probability (label, parser, + &dest_index, &prob)) + parser.push_edge (parser.current_bb->index, dest_index, + EDGE_TRUE_VALUE, prob); + else + t_label = lookup_label_for_goto (loc, label); if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) return; } @@ -1445,8 +2216,16 @@ return; } label = c_parser_peek_token (parser)->value; - f_label = lookup_label_for_goto (loc, label); c_parser_consume_token (parser); + int dest_index; + profile_probability prob; + if ((cfun->curr_properties & PROP_cfg) + && c_parser_gimple_parse_bb_spec_edge_probability (label, parser, + &dest_index, &prob)) + parser.push_edge (parser.current_bb->index, dest_index, + EDGE_FALSE_VALUE, prob); + else + f_label = lookup_label_for_goto (loc, label); if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) return; } @@ -1457,7 +2236,7 @@ } if (cond != error_mark_node) - gimple_seq_add_stmt (seq, gimple_build_cond_from_tree (cond, t_label, + gimple_seq_add_stmt_without_update (seq, gimple_build_cond_from_tree (cond, t_label, f_label)); } @@ -1472,13 +2251,12 @@ */ static void -c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq) +c_parser_gimple_switch_stmt (gimple_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 %<(%>")) @@ -1566,32 +2344,8 @@ 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"); + c_parser_error (parser, "expected case label"); return; } @@ -1601,16 +2355,15 @@ if (cond_expr.value != error_mark_node) { - gimple_seq_add_stmt (seq, gimple_build_switch (cond_expr.value, - default_label, labels)); - gimple_seq_add_seq (seq, switch_body); + gswitch *s = gimple_build_switch (cond_expr.value, default_label, labels); + gimple_seq_add_stmt_without_update (seq, s); } } /* Parse gimple return statement. */ static void -c_parser_gimple_return_stmt (c_parser *parser, gimple_seq *seq) +c_parser_gimple_return_stmt (gimple_parser &parser, gimple_seq *seq) { location_t loc = c_parser_peek_token (parser)->location; gimple *ret = NULL; @@ -1619,7 +2372,7 @@ { c_finish_gimple_return (loc, NULL_TREE); ret = gimple_build_return (NULL); - gimple_seq_add_stmt (seq, ret); + gimple_seq_add_stmt_without_update (seq, ret); } else { @@ -1629,7 +2382,7 @@ { c_finish_gimple_return (xloc, expr.value); ret = gimple_build_return (expr.value); - gimple_seq_add_stmt (seq, ret); + gimple_seq_add_stmt_without_update (seq, ret); } } } @@ -1643,7 +2396,7 @@ /* 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); + location_t xloc = expansion_point_location_if_in_system_header (loc); if (TREE_THIS_VOLATILE (current_function_decl)) warning_at (xloc, 0,