static enum gimplify_status cp_gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) { tree for_stmt = *expr_p; tree cont_block; gimple stmt; gimple_seq seq = NULL; /* Protect ourselves from recursion. */ if (OMP_FOR_GIMPLIFYING_P (for_stmt)) return GS_UNHANDLED; OMP_FOR_GIMPLIFYING_P (for_stmt) = 1; /* Note that while technically the continue label is enabled too soon here, we should have already diagnosed invalid continues nested within statement expressions within the INIT, COND, or INCR expressions. */ cont_block = begin_bc_block (bc_continue); gimplify_and_add (for_stmt, &seq); stmt = gimple_seq_last_stmt (seq); if (gimple_code (stmt) == GIMPLE_OMP_FOR) gimple_omp_set_body (stmt, finish_bc_block (bc_continue, cont_block, gimple_omp_body (stmt))); else seq = finish_bc_block (bc_continue, cont_block, seq); gimple_seq_add_seq (pre_p, seq); OMP_FOR_GIMPLIFYING_P (for_stmt) = 0; return GS_ALL_DONE; }
static void genericize_omp_for_stmt (tree *stmt_p, int *walk_subtrees, void *data) { tree stmt = *stmt_p; location_t locus = EXPR_LOCATION (stmt); tree clab = begin_bc_block (bc_continue, locus); cp_walk_tree (&OMP_FOR_BODY (stmt), cp_genericize_r, data, NULL); cp_walk_tree (&OMP_FOR_CLAUSES (stmt), cp_genericize_r, data, NULL); cp_walk_tree (&OMP_FOR_INIT (stmt), cp_genericize_r, data, NULL); cp_walk_tree (&OMP_FOR_COND (stmt), cp_genericize_r, data, NULL); cp_walk_tree (&OMP_FOR_INCR (stmt), cp_genericize_r, data, NULL); cp_walk_tree (&OMP_FOR_PRE_BODY (stmt), cp_genericize_r, data, NULL); *walk_subtrees = 0; finish_bc_block (&OMP_FOR_BODY (stmt), bc_continue, clab); }
static void gimplify_switch_stmt (tree *stmt_p) { tree stmt = *stmt_p; tree break_block, body; location_t stmt_locus = input_location; break_block = begin_bc_block (bc_break); body = SWITCH_STMT_BODY (stmt); if (!body) body = build_empty_stmt (); *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt), SWITCH_STMT_COND (stmt), body, NULL_TREE); SET_EXPR_LOCATION (*stmt_p, stmt_locus); gimplify_stmt (stmt_p); *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p); }
static void gimplify_switch_stmt (tree *stmt_p, gimple_seq *pre_p) { tree stmt = *stmt_p; tree break_block, body, t; location_t stmt_locus = input_location; gimple_seq seq = NULL; break_block = begin_bc_block (bc_break); body = SWITCH_STMT_BODY (stmt); if (!body) body = build_empty_stmt (); t = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt), SWITCH_STMT_COND (stmt), body, NULL_TREE); SET_EXPR_LOCATION (t, stmt_locus); gimplify_and_add (t, &seq); seq = finish_bc_block (bc_break, break_block, seq); gimple_seq_add_seq (pre_p, seq); *stmt_p = NULL_TREE; }
static void genericize_switch_stmt (tree *stmt_p, int *walk_subtrees, void *data) { tree stmt = *stmt_p; tree break_block, body, cond, type; location_t stmt_locus = EXPR_LOCATION (stmt); break_block = begin_bc_block (bc_break, stmt_locus); body = SWITCH_STMT_BODY (stmt); if (!body) body = build_empty_stmt (stmt_locus); cond = SWITCH_STMT_COND (stmt); type = SWITCH_STMT_TYPE (stmt); cp_walk_tree (&body, cp_genericize_r, data, NULL); cp_walk_tree (&cond, cp_genericize_r, data, NULL); cp_walk_tree (&type, cp_genericize_r, data, NULL); *walk_subtrees = 0; *stmt_p = build3_loc (stmt_locus, SWITCH_EXPR, type, cond, body, NULL_TREE); finish_bc_block (stmt_p, bc_break, break_block); }
static enum gimplify_status cp_gimplify_omp_for (tree *expr_p) { tree for_stmt = *expr_p; tree cont_block; /* Protect ourselves from recursion. */ if (OMP_FOR_GIMPLIFYING_P (for_stmt)) return GS_UNHANDLED; OMP_FOR_GIMPLIFYING_P (for_stmt) = 1; /* Note that while technically the continue label is enabled too soon here, we should have already diagnosed invalid continues nested within statement expressions within the INIT, COND, or INCR expressions. */ cont_block = begin_bc_block (bc_continue); gimplify_stmt (expr_p); OMP_FOR_BODY (for_stmt) = finish_bc_block (bc_continue, cont_block, OMP_FOR_BODY (for_stmt)); OMP_FOR_GIMPLIFYING_P (for_stmt) = 0; return GS_ALL_DONE; }
static tree gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first) { tree top, entry, exit, cont_block, break_block, stmt_list, t; location_t stmt_locus; stmt_locus = input_location; stmt_list = NULL_TREE; entry = NULL_TREE; break_block = begin_bc_block (bc_break); cont_block = begin_bc_block (bc_continue); /* If condition is zero don't generate a loop construct. */ if (cond && integer_zerop (cond)) { top = NULL_TREE; exit = NULL_TREE; if (cond_is_first) { t = build_bc_goto (bc_break); append_to_statement_list (t, &stmt_list); } } else { /* If we use a LOOP_EXPR here, we have to feed the whole thing back through the main gimplifier to lower it. Given that we have to gimplify the loop body NOW so that we can resolve break/continue stmts, seems easier to just expand to gotos. */ top = build1 (LABEL_EXPR, void_type_node, NULL_TREE); /* If we have an exit condition, then we build an IF with gotos either out of the loop, or to the top of it. If there's no exit condition, then we just build a jump back to the top. */ exit = build_and_jump (&LABEL_EXPR_LABEL (top)); if (cond && !integer_nonzerop (cond)) { t = build_bc_goto (bc_break); exit = build3 (COND_EXPR, void_type_node, cond, exit, t); exit = fold (exit); gimplify_stmt (&exit); if (cond_is_first) { if (incr) { entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE); t = build_and_jump (&LABEL_EXPR_LABEL (entry)); } else t = build_bc_goto (bc_continue); append_to_statement_list (t, &stmt_list); } } } gimplify_stmt (&body); gimplify_stmt (&incr); body = finish_bc_block (bc_continue, cont_block, body); append_to_statement_list (top, &stmt_list); append_to_statement_list (body, &stmt_list); append_to_statement_list (incr, &stmt_list); append_to_statement_list (entry, &stmt_list); append_to_statement_list (exit, &stmt_list); annotate_all_with_locus (&stmt_list, stmt_locus); return finish_bc_block (bc_break, break_block, stmt_list); }
static gimple_seq gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first) { gimple top, entry, stmt; gimple_seq stmt_list, body_seq, incr_seq, exit_seq; tree cont_block, break_block; location_t stmt_locus; stmt_locus = input_location; stmt_list = NULL; body_seq = NULL; incr_seq = NULL; exit_seq = NULL; entry = NULL; break_block = begin_bc_block (bc_break); cont_block = begin_bc_block (bc_continue); /* If condition is zero don't generate a loop construct. */ if (cond && integer_zerop (cond)) { top = NULL; if (cond_is_first) { stmt = gimple_build_goto (get_bc_label (bc_break)); gimple_set_location (stmt, stmt_locus); gimple_seq_add_stmt (&stmt_list, stmt); } } else { /* If we use a LOOP_EXPR here, we have to feed the whole thing back through the main gimplifier to lower it. Given that we have to gimplify the loop body NOW so that we can resolve break/continue stmts, seems easier to just expand to gotos. */ top = gimple_build_label (create_artificial_label ()); /* If we have an exit condition, then we build an IF with gotos either out of the loop, or to the top of it. If there's no exit condition, then we just build a jump back to the top. */ if (cond && !integer_nonzerop (cond)) { if (cond != error_mark_node) { gimplify_expr (&cond, &exit_seq, NULL, is_gimple_val, fb_rvalue); stmt = gimple_build_cond (NE_EXPR, cond, build_int_cst (TREE_TYPE (cond), 0), gimple_label_label (top), get_bc_label (bc_break)); gimple_seq_add_stmt (&exit_seq, stmt); } if (cond_is_first) { if (incr) { entry = gimple_build_label (create_artificial_label ()); stmt = gimple_build_goto (gimple_label_label (entry)); } else stmt = gimple_build_goto (get_bc_label (bc_continue)); gimple_set_location (stmt, stmt_locus); gimple_seq_add_stmt (&stmt_list, stmt); } } else { stmt = gimple_build_goto (gimple_label_label (top)); gimple_seq_add_stmt (&exit_seq, stmt); } } gimplify_stmt (&body, &body_seq); gimplify_stmt (&incr, &incr_seq); body_seq = finish_bc_block (bc_continue, cont_block, body_seq); gimple_seq_add_stmt (&stmt_list, top); gimple_seq_add_seq (&stmt_list, body_seq); gimple_seq_add_seq (&stmt_list, incr_seq); gimple_seq_add_stmt (&stmt_list, entry); gimple_seq_add_seq (&stmt_list, exit_seq); annotate_all_with_location (stmt_list, stmt_locus); return finish_bc_block (bc_break, break_block, stmt_list); }
static void genericize_cp_loop (tree *stmt_p, location_t start_locus, tree cond, tree body, tree incr, bool cond_is_first, int *walk_subtrees, void *data) { tree blab, clab; tree entry = NULL, exit = NULL, t; tree stmt_list = NULL; blab = begin_bc_block (bc_break, start_locus); clab = begin_bc_block (bc_continue, start_locus); if (incr && EXPR_P (incr)) SET_EXPR_LOCATION (incr, start_locus); cp_walk_tree (&cond, cp_genericize_r, data, NULL); cp_walk_tree (&body, cp_genericize_r, data, NULL); cp_walk_tree (&incr, cp_genericize_r, data, NULL); *walk_subtrees = 0; /* If condition is zero don't generate a loop construct. */ if (cond && integer_zerop (cond)) { if (cond_is_first) { t = build1_loc (start_locus, GOTO_EXPR, void_type_node, get_bc_label (bc_break)); append_to_statement_list (t, &stmt_list); } } else { /* Expand to gotos, just like c_finish_loop. TODO: Use LOOP_EXPR. */ tree top = build1 (LABEL_EXPR, void_type_node, create_artificial_label (start_locus)); /* If we have an exit condition, then we build an IF with gotos either out of the loop, or to the top of it. If there's no exit condition, then we just build a jump back to the top. */ exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top)); if (cond && !integer_nonzerop (cond)) { /* Canonicalize the loop condition to the end. This means generating a branch to the loop condition. Reuse the continue label, if possible. */ if (cond_is_first) { if (incr) { entry = build1 (LABEL_EXPR, void_type_node, create_artificial_label (start_locus)); t = build1_loc (start_locus, GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (entry)); } else t = build1_loc (start_locus, GOTO_EXPR, void_type_node, get_bc_label (bc_continue)); append_to_statement_list (t, &stmt_list); } t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break)); exit = fold_build3_loc (start_locus, COND_EXPR, void_type_node, cond, exit, t); } append_to_statement_list (top, &stmt_list); } append_to_statement_list (body, &stmt_list); finish_bc_block (&stmt_list, bc_continue, clab); append_to_statement_list (incr, &stmt_list); append_to_statement_list (entry, &stmt_list); append_to_statement_list (exit, &stmt_list); finish_bc_block (&stmt_list, bc_break, blab); if (stmt_list == NULL_TREE) stmt_list = build1 (NOP_EXPR, void_type_node, integer_zero_node); *stmt_p = stmt_list; }
static tree /* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ gimplify_cp_loop (tree cond, tree body, tree incr, tree attrs, bool cond_is_first, tree inner_foreach) /* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ { tree top, entry, exit, cont_block, break_block, stmt_list, t; location_t stmt_locus; stmt_locus = input_location; stmt_list = NULL_TREE; entry = NULL_TREE; /* APPLE LOCAL begin C* language */ /* Order of label addition to stack is important for objc's foreach-stmt. */ /* APPLE LOCAL radar 4667060 */ if (inner_foreach == integer_zero_node) { cont_block = begin_bc_block (bc_continue); break_block = begin_bc_block (bc_break); } else { break_block = begin_bc_block (bc_break); cont_block = begin_bc_block (bc_continue); } /* APPLE LOCAL end C* language */ /* If condition is zero don't generate a loop construct. */ if (cond && integer_zerop (cond)) { top = NULL_TREE; exit = NULL_TREE; if (cond_is_first) { t = build_bc_goto (bc_break); append_to_statement_list (t, &stmt_list); } } else { /* If we use a LOOP_EXPR here, we have to feed the whole thing back through the main gimplifier to lower it. Given that we have to gimplify the loop body NOW so that we can resolve break/continue stmts, seems easier to just expand to gotos. */ top = build1 (LABEL_EXPR, void_type_node, NULL_TREE); /* If we have an exit condition, then we build an IF with gotos either out of the loop, or to the top of it. If there's no exit condition, then we just build a jump back to the top. */ exit = build_and_jump (&LABEL_EXPR_LABEL (top)); /* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ /* Add the attributes to the 'top' label. */ decl_attributes (&LABEL_EXPR_LABEL (top), attrs, 0); /* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ if (cond && !integer_nonzerop (cond)) { t = build_bc_goto (bc_break); exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t); gimplify_stmt (&exit); if (cond_is_first) { if (incr) { entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE); t = build_and_jump (&LABEL_EXPR_LABEL (entry)); } else t = build_bc_goto (bc_continue); append_to_statement_list (t, &stmt_list); } } } /* APPLE LOCAL begin radar 4547045 */ /* Pop foreach's inner loop break label so outer loop's break label becomes target of inner loop body's break statements. */ t = NULL_TREE; gimplify_stmt (&body); gimplify_stmt (&incr); body = finish_bc_block (bc_continue, cont_block, body); /* APPLE LOCAL begin radar 4547045 */ /* Push back inner loop's own 'break' label so rest of code works seemlessly. */ /* APPLE LOCAL radar 4667060 */ append_to_statement_list (top, &stmt_list); append_to_statement_list (body, &stmt_list); append_to_statement_list (incr, &stmt_list); append_to_statement_list (entry, &stmt_list); append_to_statement_list (exit, &stmt_list); annotate_all_with_locus (&stmt_list, stmt_locus); return finish_bc_block (bc_break, break_block, stmt_list); }