1 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
3 Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 Contributed by Jason Merrill <jason@redhat.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 #include "coretypes.h"
31 #include "tree-gimple.h"
33 #include "pointer-set.h"
35 /* Local declarations. */
37 enum bc_t { bc_break = 0, bc_continue = 1 };
39 static struct cp_gimplify_ctx
41 /* Stack of labels which are targets for "break" or "continue",
42 linked through TREE_CHAIN. */
43 tree current_label[2];
50 ctxp = ((struct cp_gimplify_ctx *)
51 xcalloc (1, sizeof (struct cp_gimplify_ctx)));
58 && !ctxp->current_label[0]
59 && !ctxp->current_label[1]);
64 /* Begin a scope which can be exited by a break or continue statement. BC
67 Just creates a label and pushes it into the current context. */
70 begin_bc_block (enum bc_t bc)
72 tree label = create_artificial_label ();
73 TREE_CHAIN (label) = ctxp->current_label[bc];
74 ctxp->current_label[bc] = label;
78 /* Finish a scope which can be exited by a break or continue statement.
79 LABEL was returned from the most recent call to begin_bc_block. BODY is
80 an expression for the contents of the scope.
82 If we saw a break (or continue) in the scope, append a LABEL_EXPR to
83 body. Otherwise, just forget the label. */
86 finish_bc_block (enum bc_t bc, tree label, tree body)
88 gcc_assert (label == ctxp->current_label[bc]);
90 if (TREE_USED (label))
94 t = build1 (LABEL_EXPR, void_type_node, label);
96 append_to_statement_list (body, &sl);
97 append_to_statement_list (t, &sl);
101 ctxp->current_label[bc] = TREE_CHAIN (label);
102 TREE_CHAIN (label) = NULL_TREE;
106 /* Build a GOTO_EXPR to represent a break or continue statement. BC
110 build_bc_goto (enum bc_t bc)
112 tree label = ctxp->current_label[bc];
114 if (label == NULL_TREE)
117 error ("break statement not within loop or switch");
119 error ("continue statement not within loop or switch");
124 /* Mark the label used for finish_bc_block. */
125 TREE_USED (label) = 1;
126 return build1 (GOTO_EXPR, void_type_node, label);
129 /* Genericize a TRY_BLOCK. */
132 genericize_try_block (tree *stmt_p)
134 tree body = TRY_STMTS (*stmt_p);
135 tree cleanup = TRY_HANDLERS (*stmt_p);
137 gimplify_stmt (&body);
139 if (CLEANUP_P (*stmt_p))
140 /* A cleanup is an expression, so it doesn't need to be genericized. */;
142 gimplify_stmt (&cleanup);
144 *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
147 /* Genericize a HANDLER by converting to a CATCH_EXPR. */
150 genericize_catch_block (tree *stmt_p)
152 tree type = HANDLER_TYPE (*stmt_p);
153 tree body = HANDLER_BODY (*stmt_p);
155 gimplify_stmt (&body);
157 /* FIXME should the caught type go in TREE_TYPE? */
158 *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
161 /* Genericize an EH_SPEC_BLOCK by converting it to a
162 TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
165 genericize_eh_spec_block (tree *stmt_p)
167 tree body = EH_SPEC_STMTS (*stmt_p);
168 tree allowed = EH_SPEC_RAISES (*stmt_p);
169 tree failure = build_call (call_unexpected_node,
170 tree_cons (NULL_TREE, build_exc_ptr (),
172 gimplify_stmt (&body);
174 *stmt_p = gimple_build_eh_filter (body, allowed, failure);
177 /* Genericize an IF_STMT by turning it into a COND_EXPR. */
180 gimplify_if_stmt (tree *stmt_p)
182 tree stmt, cond, then_, else_;
185 cond = IF_COND (stmt);
186 then_ = THEN_CLAUSE (stmt);
187 else_ = ELSE_CLAUSE (stmt);
190 then_ = build_empty_stmt ();
192 else_ = build_empty_stmt ();
194 if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
196 else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
199 stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
203 /* Build a generic representation of one of the C loop forms. COND is the
204 loop condition or NULL_TREE. BODY is the (possibly compound) statement
205 controlled by the loop. INCR is the increment expression of a for-loop,
206 or NULL_TREE. COND_IS_FIRST indicates whether the condition is
207 evaluated before the loop body as in while and for loops, or after the
208 loop body as in do-while loops. */
211 gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first)
213 tree top, entry, exit, cont_block, break_block, stmt_list, t;
214 location_t stmt_locus;
216 stmt_locus = input_location;
217 stmt_list = NULL_TREE;
220 break_block = begin_bc_block (bc_break);
221 cont_block = begin_bc_block (bc_continue);
223 /* If condition is zero don't generate a loop construct. */
224 if (cond && integer_zerop (cond))
230 t = build_bc_goto (bc_break);
231 append_to_statement_list (t, &stmt_list);
236 /* If we use a LOOP_EXPR here, we have to feed the whole thing
237 back through the main gimplifier to lower it. Given that we
238 have to gimplify the loop body NOW so that we can resolve
239 break/continue stmts, seems easier to just expand to gotos. */
240 top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
242 /* If we have an exit condition, then we build an IF with gotos either
243 out of the loop, or to the top of it. If there's no exit condition,
244 then we just build a jump back to the top. */
245 exit = build_and_jump (&LABEL_EXPR_LABEL (top));
246 if (cond && !integer_nonzerop (cond))
248 t = build_bc_goto (bc_break);
249 exit = build3 (COND_EXPR, void_type_node, cond, exit, t);
251 gimplify_stmt (&exit);
257 entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
258 t = build_and_jump (&LABEL_EXPR_LABEL (entry));
261 t = build_bc_goto (bc_continue);
262 append_to_statement_list (t, &stmt_list);
267 gimplify_stmt (&body);
268 gimplify_stmt (&incr);
270 body = finish_bc_block (bc_continue, cont_block, body);
272 append_to_statement_list (top, &stmt_list);
273 append_to_statement_list (body, &stmt_list);
274 append_to_statement_list (incr, &stmt_list);
275 append_to_statement_list (entry, &stmt_list);
276 append_to_statement_list (exit, &stmt_list);
278 annotate_all_with_locus (&stmt_list, stmt_locus);
280 return finish_bc_block (bc_break, break_block, stmt_list);
283 /* Gimplify a FOR_STMT node. Move the stuff in the for-init-stmt into the
284 prequeue and hand off to gimplify_cp_loop. */
287 gimplify_for_stmt (tree *stmt_p, tree *pre_p)
291 if (FOR_INIT_STMT (stmt))
292 gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
294 *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
298 /* Gimplify a WHILE_STMT node. */
301 gimplify_while_stmt (tree *stmt_p)
304 *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
308 /* Gimplify a DO_STMT node. */
311 gimplify_do_stmt (tree *stmt_p)
314 *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
318 /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */
321 gimplify_switch_stmt (tree *stmt_p)
324 tree break_block, body;
325 location_t stmt_locus = input_location;
327 break_block = begin_bc_block (bc_break);
329 body = SWITCH_STMT_BODY (stmt);
331 body = build_empty_stmt ();
333 *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
334 SWITCH_STMT_COND (stmt), body, NULL_TREE);
335 SET_EXPR_LOCATION (*stmt_p, stmt_locus);
336 gimplify_stmt (stmt_p);
338 *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p);
341 /* Gimplify initialization from an AGGR_INIT_EXPR. */
344 cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
346 tree from = TREE_OPERAND (*expr_p, 1);
347 tree to = TREE_OPERAND (*expr_p, 0);
350 /* If we are initializing something from a TARGET_EXPR, strip the
351 TARGET_EXPR and initialize it directly. */
352 /* What about code that pulls out the temp and uses it elsewhere? I
353 think that such code never uses the TARGET_EXPR as an initializer. If
354 I'm wrong, we'll abort because the temp won't have any RTL. In that
355 case, I guess we'll need to replace references somehow. */
356 if (TREE_CODE (from) == TARGET_EXPR)
357 from = TARGET_EXPR_INITIAL (from);
358 if (TREE_CODE (from) == CLEANUP_POINT_EXPR)
359 from = TREE_OPERAND (from, 0);
361 /* Look through any COMPOUND_EXPRs. */
362 sub = expr_last (from);
364 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
365 replace the slot operand with our target.
367 Should we add a target parm to gimplify_expr instead? No, as in this
368 case we want to replace the INIT_EXPR. */
369 if (TREE_CODE (sub) == AGGR_INIT_EXPR)
371 gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
372 TREE_OPERAND (sub, 2) = to;
375 /* The initialization is now a side-effect, so the container can
378 TREE_TYPE (from) = void_type_node;
382 /* Gimplify a MUST_NOT_THROW_EXPR. */
385 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
388 tree temp = voidify_wrapper_expr (stmt, NULL);
389 tree body = TREE_OPERAND (stmt, 0);
391 gimplify_stmt (&body);
393 stmt = gimple_build_eh_filter (body, NULL_TREE,
394 build_call (terminate_node, NULL_TREE));
398 append_to_statement_list (stmt, pre_p);
405 /* Do C++-specific gimplification. Args are as for gimplify_expr. */
408 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
410 int saved_stmts_are_full_exprs_p = 0;
411 enum tree_code code = TREE_CODE (*expr_p);
412 enum gimplify_status ret;
414 if (STATEMENT_CODE_P (code))
416 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
417 current_stmt_tree ()->stmts_are_full_exprs_p
418 = STMT_IS_FULL_EXPR_P (*expr_p);
424 *expr_p = cplus_expand_constant (*expr_p);
429 simplify_aggr_init_expr (expr_p);
434 /* FIXME communicate throw type to backend, probably by moving
435 THROW_EXPR into ../tree.def. */
436 *expr_p = TREE_OPERAND (*expr_p, 0);
440 case MUST_NOT_THROW_EXPR:
441 gimplify_must_not_throw_expr (expr_p, pre_p);
447 cp_gimplify_init_expr (expr_p, pre_p, post_p);
451 case EMPTY_CLASS_EXPR:
452 /* We create an INTEGER_CST with RECORD_TYPE and value zero. */
453 *expr_p = build_int_cst (TREE_TYPE (*expr_p), 0);
458 *expr_p = BASELINK_FUNCTIONS (*expr_p);
463 genericize_try_block (expr_p);
468 genericize_catch_block (expr_p);
473 genericize_eh_spec_block (expr_p);
478 /* Just ignore for now. Eventually we will want to pass this on to
480 *expr_p = build_empty_stmt ();
485 gimplify_if_stmt (expr_p);
490 gimplify_for_stmt (expr_p, pre_p);
495 gimplify_while_stmt (expr_p);
500 gimplify_do_stmt (expr_p);
505 gimplify_switch_stmt (expr_p);
510 *expr_p = build_bc_goto (bc_continue);
515 *expr_p = build_bc_goto (bc_break);
520 ret = c_gimplify_expr (expr_p, pre_p, post_p);
524 /* Restore saved state. */
525 if (STATEMENT_CODE_P (code))
526 current_stmt_tree ()->stmts_are_full_exprs_p
527 = saved_stmts_are_full_exprs_p;
533 is_invisiref_parm (tree t)
535 return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
536 && DECL_BY_REFERENCE (t));
539 /* Perform any pre-gimplification lowering of C++ front end trees to
543 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
546 struct pointer_set_t *p_set = (struct pointer_set_t*) data;
548 if (is_invisiref_parm (stmt))
550 *stmt_p = convert_from_reference (stmt);
555 /* Other than invisiref parms, don't walk the same tree twice. */
556 if (pointer_set_contains (p_set, stmt))
562 if (TREE_CODE (stmt) == ADDR_EXPR
563 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
565 *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
568 else if (TREE_CODE (stmt) == RETURN_EXPR
569 && TREE_OPERAND (stmt, 0)
570 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
571 /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */
573 else if (IS_TYPE_OR_DECL_P (stmt))
576 /* Due to the way voidify_wrapper_expr is written, we don't get a chance
577 to lower this construct before scanning it, so we need to lower these
578 before doing anything else. */
579 else if (TREE_CODE (stmt) == CLEANUP_STMT)
580 *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
584 CLEANUP_EXPR (stmt));
586 pointer_set_insert (p_set, *stmt_p);
592 cp_genericize (tree fndecl)
595 struct pointer_set_t *p_set;
597 /* Fix up the types of parms passed by invisible reference. */
598 for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
599 if (TREE_ADDRESSABLE (TREE_TYPE (t)))
601 /* If a function's arguments are copied to create a thunk,
602 then DECL_BY_REFERENCE will be set -- but the type of the
603 argument will be a pointer type, so we will never get
605 gcc_assert (!DECL_BY_REFERENCE (t));
606 gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
607 TREE_TYPE (t) = DECL_ARG_TYPE (t);
608 DECL_BY_REFERENCE (t) = 1;
609 TREE_ADDRESSABLE (t) = 0;
613 /* Do the same for the return value. */
614 if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
616 t = DECL_RESULT (fndecl);
617 TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
618 DECL_BY_REFERENCE (t) = 1;
619 TREE_ADDRESSABLE (t) = 0;
623 /* If we're a clone, the body is already GIMPLE. */
624 if (DECL_CLONED_FUNCTION_P (fndecl))
627 /* We do want to see every occurrence of the parms, so we can't just use
628 walk_tree's hash functionality. */
629 p_set = pointer_set_create ();
630 walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
631 pointer_set_destroy (p_set);
633 /* Do everything else. */
635 c_genericize (fndecl);