- body = build_empty_stmt ();
-
- bind = build (BIND_EXPR, void_type_node, decls, body, block);
- TREE_SIDE_EFFECTS (bind) = 1;
-
- return bind;
-}
-
-/* Genericize a syntactic block by removing the bracketing SCOPE_STMTs and
- wrapping the intervening code in a BIND_EXPR. This function assumes
- that matching SCOPE_STMTs will always appear in the same statement
- sequence. */
-
-static enum gimplify_status
-gimplify_block (tree *stmt_p, tree *next_p)
-{
- tree *p;
- tree block;
- tree bind;
- int depth;
- location_t stmt_locus;
-
- if (!SCOPE_BEGIN_P (*stmt_p))
- {
- /* Can wind up mismatched with syntax errors. */
- if (!errorcount && !sorrycount)
- abort ();
- *stmt_p = NULL;
- return GS_ERROR;
- }
-
- block = SCOPE_STMT_BLOCK (*stmt_p);
-
- /* Find the matching ending SCOPE_STMT. */
- depth = 1;
- for (p = &TREE_CHAIN (*stmt_p);; p = &TREE_CHAIN (*p))
- {
- if (*p == NULL)
- break;
- if (TREE_CODE (*p) == SCOPE_STMT)
- {
- if (SCOPE_BEGIN_P (*p))
- ++depth;
- else if (--depth == 0)
- break;
- }
- }
-
- stmt_locus = input_location;
- if (*p)
- {
- if (SCOPE_STMT_BLOCK (*p) != block)
- abort ();
- if (EXPR_LOCUS (*p))
- stmt_locus = *EXPR_LOCUS (*p);
- *next_p = TREE_CHAIN (*p);
- *p = NULL_TREE;
- }
- else
- {
- /* Can wind up mismatched with syntax errors. */
- if (!errorcount && !sorrycount)
- abort ();
- }
-
- bind = c_build_bind_expr (block, TREE_CHAIN (*stmt_p));
- *stmt_p = bind;
- input_location = stmt_locus;
-
- return GS_OK;
-}
-
-/* Genericize a CLEANUP_STMT. Just wrap everything from here to the end of
- the block in a TRY_FINALLY_EXPR. Or a TRY_CATCH_EXPR, if it's an
- EH-only cleanup. */
-
-static enum gimplify_status
-gimplify_cleanup (tree *stmt_p, tree *next_p)
-{
- tree stmt = *stmt_p;
- tree body = TREE_CHAIN (stmt);
- tree cleanup = CLEANUP_EXPR (stmt);
- enum tree_code code
- = (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR);
-
- if (!body)
- body = build_empty_stmt ();
- if (!cleanup)
- cleanup = build_empty_stmt ();
-
- *stmt_p = build (code, void_type_node, body, cleanup);
- *next_p = NULL_TREE;
-
- return GS_OK;
-}
-
-/* Gimplify an EXPR_STMT node.
-
- STMT is the statement node.
-
- PRE_P points to the list where side effects that must happen before
- STMT should be stored.
-
- POST_P points to the list where side effects that must happen after
- STMT should be stored. */
-
-static enum gimplify_status
-gimplify_expr_stmt (tree *stmt_p)
-{
- tree stmt = EXPR_STMT_EXPR (*stmt_p);
-
- if (stmt == error_mark_node)
- stmt = NULL;
-
- /* Gimplification of a statement expression will nullify the
- statement if all its side effects are moved to *PRE_P and *POST_P.
-
- In this case we will not want to emit the gimplified statement.
- However, we may still want to emit a warning, so we do that before
- gimplification. */
- if (stmt && (extra_warnings || warn_unused_value))
- {
- if (!TREE_SIDE_EFFECTS (stmt))
- {
- if (!IS_EMPTY_STMT (stmt)
- && !VOID_TYPE_P (TREE_TYPE (stmt))
- && !TREE_NO_WARNING (stmt))
- warning ("statement with no effect");
- }
- else if (warn_unused_value)
- {
- /* Kludge for 20020220-2.c. warn_if_unused_value shouldn't use
- the stmt file location info. */
- set_file_and_line_for_stmt (input_location);
- warn_if_unused_value (stmt);
- }
- }
-
- if (stmt == NULL_TREE)
- stmt = build_empty_stmt ();
- else if (stmts_are_full_exprs_p ())
- stmt = build1 (CLEANUP_POINT_EXPR, void_type_node, stmt);
-
- *stmt_p = stmt;
-
- return GS_OK;
-}
-
-/* If the condition for a loop (or the like) is a decl, it will be a
- TREE_LIST where the TREE_PURPOSE is a DECL_STMT and the TREE_VALUE is
- a use of the decl. Turn such a thing into a COMPOUND_EXPR. */
-
-static void
-gimplify_condition (tree *cond_p)
-{
- tree cond = *cond_p;
- if (cond && TREE_CODE (cond) == TREE_LIST)
- {
- tree decl = TREE_PURPOSE (cond);
- tree value = TREE_VALUE (cond);
- c_gimplify_stmt (&decl);
- *cond_p = build (COMPOUND_EXPR, TREE_TYPE (value), decl, value);
- }
-}
-
-/* Begin a scope which can be exited by a break or continue statement. BC
- indicates which.
-
- Just creates a label and pushes it into the current context. */
-
-static tree
-begin_bc_block (enum bc_t bc)
-{
- tree label = create_artificial_label ();
- DECL_NAME (label) = ctxp->bc_id[bc];
- TREE_CHAIN (label) = ctxp->current_bc_label;
- ctxp->current_bc_label = label;
- return label;
-}
-
-/* Finish a scope which can be exited by a break or continue statement.
- LABEL was returned from the most recent call to begin_bc_block. BODY is
- an expression for the contents of the scope.
-
- If we saw a break (or continue) in the scope, append a LABEL_EXPR to
- body. Otherwise, just forget the label. */
-
-static tree
-finish_bc_block (tree label, tree body)
-{
- if (label != ctxp->current_bc_label)
- abort ();
-
- if (TREE_USED (label))
- {
- tree t, sl = NULL;
-
- /* Clear the name so flow can delete the label. */
- DECL_NAME (label) = NULL_TREE;
- t = build1 (LABEL_EXPR, void_type_node, label);
-
- append_to_statement_list (body, &sl);
- append_to_statement_list (t, &sl);
- body = sl;
- }
-
- ctxp->current_bc_label = TREE_CHAIN (label);
- TREE_CHAIN (label) = NULL_TREE;
- return body;
-}
-
-/* Build a GOTO_EXPR to represent a break or continue statement. BC
- indicates which. */
-
-static tree
-build_bc_goto (enum bc_t bc)
-{
- tree label;
- tree target_name = ctxp->bc_id[bc];
-
- /* Look for the appropriate type of label. */
- for (label = ctxp->current_bc_label;
- label;
- label = TREE_CHAIN (label))
- if (DECL_NAME (label) == target_name)
- break;
-
- if (label == NULL_TREE)
- {
- if (bc == bc_break)
- error ("break statement not within loop or switch");
- else
- error ("continue statement not within loop or switch");
-
- return NULL_TREE;
- }
-
- /* Mark the label used for finish_bc_block. */
- TREE_USED (label) = 1;
- return build1 (GOTO_EXPR, void_type_node, label);
-}
-
-/* Build a generic representation of one of the C loop forms. COND is the
- loop condition or NULL_TREE. BODY is the (possibly compound) statement
- controlled by the loop. INCR is the increment expression of a for-loop,
- or NULL_TREE. COND_IS_FIRST indicates whether the condition is
- evaluated before the loop body as in while and for loops, or after the
- loop body as in do-while loops. */
-
-static tree
-gimplify_c_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;
-
- /* Detect do { ... } while (0) and don't generate loop construct. */
- if (!cond_is_first && cond && integer_zerop (cond))
- top = cond = NULL;
- 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);
- }
-
- break_block = begin_bc_block (bc_break);
-
- if (top)
- {
- /* 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)
- {
- gimplify_condition (&cond);
- t = build_bc_goto (bc_break);
- exit = build (COND_EXPR, void_type_node, cond, exit, t);
- exit = fold (exit);
- gimplify_stmt (&exit);
- }
- }
- else
- exit = NULL_TREE;
-
- cont_block = begin_bc_block (bc_continue);
-
- gimplify_stmt (&body);
- if (incr && stmts_are_full_exprs_p ())
- incr = fold (build1 (CLEANUP_POINT_EXPR, void_type_node, incr));
- gimplify_stmt (&incr);
-
- body = finish_bc_block (cont_block, body);
-
- stmt_list = NULL;
-
- if (cond_is_first && cond)
- {
- entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
- t = build_and_jump (&LABEL_EXPR_LABEL (entry));
- append_to_statement_list (t, &stmt_list);
- }
- else
- entry = NULL_TREE;
-
- 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 (break_block, stmt_list);
-}
-
-/* Gimplify a FOR_STMT node. Move the stuff in the for-init-stmt into the
- prequeue and hand off to gimplify_c_loop. */
-
-static enum gimplify_status
-gimplify_for_stmt (tree *stmt_p, tree *next_p)
-{
- tree stmt = *stmt_p;
- tree init = FOR_INIT_STMT (stmt);
-
- if (init)