#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. */
+
+struct gimple_parser
+{
+ 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. */
+ struct gimple_parser_edge
+ {
+ int src;
+ int dest;
+ int flags;
+ };
+ auto_vec<gimple_parser_edge> edges;
+ basic_block current_bb;
+
+ void push_edge (int, int, int);
+};
+
+void
+gimple_parser::push_edge (int src, int dest, int flags)
+{
+ gimple_parser_edge e;
+ e.src = src;
+ e.dest = dest;
+ e.flags = flags;
+ 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_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. Return true if so. */
+
+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;
+}
+
/* 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)
{
+ 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 ();
+ /* 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 ();
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)
+ make_edge (BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].src),
+ BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].dest),
+ parser.edges[i].flags);
+ /* 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, false);
+ }
+ /* 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);
+ }
dump_function (TDI_gimple, current_function_decl);
}
*/
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;
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_NAME))
{
- c_parser_gimple_goto_stmt (loc,
+ c_parser_gimple_goto_stmt (parser, loc,
c_parser_peek_token
(parser)->value,
seq);
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);
break;
default:
goto expr_stmt;
c_parser_gimple_label (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;
+ 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;
+ }
+ else
+ {
+ c_parser_error (parser, "unknown block specifier");
+ 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)
+ parser.push_edge (ENTRY_BLOCK, bb->index, EDGE_FALLTHRU);
+
+ /* We leave the proper setting to fixup. */
+ struct 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
+ {
+ struct 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;
+
+ /* Stmts now go to the new block. */
+ parser.current_bb = bb;
+ break;
+ }
goto expr_stmt;
case CPP_SEMICOLON:
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;
}
}
}
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;
}
*/
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;
{
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;
}
&& 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;
}
{
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;
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);
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;
}
{
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;
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;
*/
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;
*/
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;
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)
{
. 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 ();
*/
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 ();
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)
{
*/
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;
*/
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;
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))
+ while (c_parser_next_token_is (parser, CPP_NAME))
{
const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
c_parser_consume_token (parser);
if (! strcmp (op, "startwith"))
{
if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- return NULL;
+ 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_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.
*/
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 ();
/* 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;
+ if (c_parser_gimple_parse_bb_spec (label, &dest_index))
+ {
+ parser.push_edge (parser.current_bb->index, dest_index,
+ EDGE_FALLTHRU);
+ 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.
( 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;
*/
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);
}
label = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
- t_label = lookup_label_for_goto (loc, label);
+ int dest_index;
+ if ((cfun->curr_properties & PROP_cfg)
+ && c_parser_gimple_parse_bb_spec (label, &dest_index))
+ parser.push_edge (parser.current_bb->index, dest_index,
+ EDGE_TRUE_VALUE);
+ else
+ t_label = lookup_label_for_goto (loc, label);
if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
return;
}
return;
}
label = c_parser_peek_token (parser)->value;
- f_label = lookup_label_for_goto (loc, label);
+ int dest_index;
+ if ((cfun->curr_properties & PROP_cfg)
+ && c_parser_gimple_parse_bb_spec (label, &dest_index))
+ parser.push_edge (parser.current_bb->index, dest_index,
+ EDGE_FALSE_VALUE);
+ else
+ f_label = lookup_label_for_goto (loc, label);
c_parser_consume_token (parser);
if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
return;
}
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));
}
*/
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 %<(%>"))
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;
}
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;
{
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
{
{
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);
}
}
}