by the C-based front ends. The structure of gimplified, or
language-independent, trees is dictated by the grammar described in this
file.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Lowering of expressions contributed by Sebastian Pop <s.pop@laposte.net>
Re-written to support lowering of whole function trees, documentation
and miscellaneous cleanups by Diego Novillo <dnovillo@redhat.com>
static void
push_context (void)
{
- if (ctxp)
- abort ();
+ gcc_assert (!ctxp);
ctxp = (struct c_gimplify_ctx *) xcalloc (1, sizeof (struct c_gimplify_ctx));
ctxp->bc_id[bc_continue] = get_identifier ("continue");
ctxp->bc_id[bc_break] = get_identifier ("break");
static void
pop_context (void)
{
- if (!ctxp || ctxp->current_bc_label)
- abort ();
+ gcc_assert (ctxp && !ctxp->current_bc_label);
free (ctxp);
ctxp = NULL;
}
body = build_empty_stmt ();
if (decls || block)
{
- bind = build (BIND_EXPR, void_type_node, decls, body, block);
+ bind = build3 (BIND_EXPR, void_type_node, decls, body, block);
TREE_SIDE_EFFECTS (bind) = 1;
}
else
}
if (stmt == NULL_TREE)
- stmt = build_empty_stmt ();
+ stmt = alloc_stmt_list ();
*stmt_p = stmt;
static tree
finish_bc_block (tree label, tree body)
{
- if (label != ctxp->current_bc_label)
- abort ();
+ gcc_assert (label == ctxp->current_bc_label);
if (TREE_USED (label))
{
location_t stmt_locus;
stmt_locus = input_location;
+ stmt_list = NULL_TREE;
+ entry = NULL_TREE;
- /* Detect do { ... } while (0) and don't generate loop construct. */
- if (!cond_is_first && cond && integer_zerop (cond))
- top = cond = 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_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
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)
+ if (cond && !integer_nonzerop (cond))
{
t = build_bc_goto (bc_break);
- exit = build (COND_EXPR, void_type_node, cond, exit, t);
+ 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);
+ }
}
}
- else
- exit = NULL_TREE;
-
- cont_block = begin_bc_block (bc_continue);
gimplify_stmt (&body);
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);
tree stmt = *stmt_p;
if (FOR_INIT_STMT (stmt))
- {
- gimplify_stmt (&FOR_INIT_STMT (stmt));
- append_to_statement_list (FOR_INIT_STMT (stmt), pre_p);
- }
+ gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
+
*stmt_p = gimplify_c_loop (FOR_COND (stmt), FOR_BODY (stmt),
FOR_EXPR (stmt), 1);
break_block = begin_bc_block (bc_break);
- body = SWITCH_BODY (stmt);
+ body = SWITCH_STMT_BODY (stmt);
if (!body)
body = build_empty_stmt ();
- *stmt_p = build (SWITCH_EXPR, SWITCH_TYPE (stmt), SWITCH_COND (stmt),
- body, NULL_TREE);
- annotate_with_locus (*stmt_p, stmt_locus);
+ *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 (break_block, *stmt_p);
return GS_ALL_DONE;
}
-/* Gimplifies a DECL_STMT node *STMT_P by making any necessary allocation
- and initialization explicit. */
-
-static enum gimplify_status
-gimplify_decl_stmt (tree *stmt_p)
-{
- tree stmt = *stmt_p;
- tree decl = DECL_STMT_DECL (stmt);
- tree pre = NULL_TREE;
- tree post = NULL_TREE;
-
- if (TREE_TYPE (decl) == error_mark_node)
- {
- *stmt_p = NULL;
- return GS_ERROR;
- }
-
- if (TREE_CODE (decl) == TYPE_DECL)
- {
- tree type = TREE_TYPE (decl);
- if (TYPE_SIZE_UNIT (type)
- && !TREE_CONSTANT (TYPE_SIZE_UNIT (type)))
- {
- /* This is a variable-sized array type. Simplify its size. */
- tree temp = TYPE_SIZE_UNIT (type);
- gimplify_expr (&temp, &pre, &post, is_gimple_val, fb_rvalue);
- }
- }
-
- if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
- {
- tree init = DECL_INITIAL (decl);
-
- if (!TREE_CONSTANT (DECL_SIZE (decl)))
- {
- tree pt_type = build_pointer_type (TREE_TYPE (decl));
- tree alloc, size;
-
- /* This is a variable-sized decl. Simplify its size and mark it
- for deferred expansion. Note that mudflap depends on the format
- of the emitted code: see mx_register_decls(). */
-
- size = get_initialized_tmp_var (DECL_SIZE_UNIT (decl), &pre, &post);
- DECL_DEFER_OUTPUT (decl) = 1;
- alloc = build_function_call_expr
- (implicit_built_in_decls[BUILT_IN_STACK_ALLOC],
- tree_cons (NULL_TREE,
- build1 (ADDR_EXPR, pt_type, decl),
- tree_cons (NULL_TREE, size, NULL_TREE)));
- append_to_compound_expr (alloc, &pre);
- }
-
- if (init && init != error_mark_node)
- {
- if (!TREE_STATIC (decl))
- {
- /* Do not warn about int x = x; as it is a GCC extension
- to turn off this warning but only if warn_init_self
- is zero. */
- if (init == decl && !warn_init_self)
- TREE_NO_WARNING (decl) = 1;
-
- DECL_INITIAL (decl) = NULL_TREE;
- init = build (MODIFY_EXPR, void_type_node, decl, init);
- append_to_compound_expr (init, &pre);
- }
- else
- {
- /* We must still examine initializers for static variables
- as they may contain a label address. */
- walk_tree (&init, force_labels_r, NULL, NULL);
- }
- }
-
- /* This decl isn't mentioned in the enclosing block, so add it to the
- list of temps. FIXME it seems a bit of a kludge to say that
- anonymous artificial vars aren't pushed, but everything else is. */
- if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
- gimple_add_tmp_var (decl);
- }
-
- append_to_compound_expr (post, &pre);
- *stmt_p = pre;
- return GS_OK;
-}
-
/* Gimplification of expression trees. */
/* Gimplify a C99 compound literal expression. This just means adding the
- DECL_STMT before the current EXPR_STMT and using its anonymous decl
+ DECL_EXPR before the current EXPR_STMT and using its anonymous decl
instead. */
static enum gimplify_status
-gimplify_compound_literal_expr (tree *expr_p)
+gimplify_compound_literal_expr (tree *expr_p, tree *pre_p)
{
tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (*expr_p);
- tree decl = DECL_STMT_DECL (decl_s);
+ tree decl = DECL_EXPR_DECL (decl_s);
/* This decl isn't mentioned in the enclosing block, so add it to the
list of temps. FIXME it seems a bit of a kludge to say that
if (DECL_NAME (decl) == NULL_TREE)
gimple_add_tmp_var (decl);
- gimplify_decl_stmt (&decl_s);
- *expr_p = decl_s ? decl_s : decl;
+ gimplify_and_add (decl_s, pre_p);
+ *expr_p = decl;
return GS_OK;
}
switch (code)
{
+ case DECL_EXPR:
+ /* This is handled mostly by gimplify.c, but we have to deal with
+ not warning about int x = x; as it is a GCC extension to turn off
+ this warning but only if warn_init_self is zero. */
+ if (TREE_CODE (DECL_EXPR_DECL (*expr_p)) == VAR_DECL
+ && !DECL_EXTERNAL (DECL_EXPR_DECL (*expr_p))
+ && !TREE_STATIC (DECL_EXPR_DECL (*expr_p))
+ && (DECL_INITIAL (DECL_EXPR_DECL (*expr_p))
+ == DECL_EXPR_DECL (*expr_p))
+ && !warn_init_self)
+ TREE_NO_WARNING (DECL_EXPR_DECL (*expr_p)) = 1;
+ return GS_UNHANDLED;
+
case COMPOUND_LITERAL_EXPR:
- return gimplify_compound_literal_expr (expr_p);
+ return gimplify_compound_literal_expr (expr_p, pre_p);
case FOR_STMT:
return gimplify_for_stmt (expr_p, pre_p);
case EXPR_STMT:
return gimplify_expr_stmt (expr_p);
- case DECL_STMT:
- return gimplify_decl_stmt (expr_p);
-
case CONTINUE_STMT:
*expr_p = build_bc_goto (bc_continue);
return GS_ALL_DONE;