Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / gcc / cp / cp-gimplify.c
blob2eb4ae9f6c0849f96c6668d67cf474db7a4c50a6
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
11 version.
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
16 for more details.
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, 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, USA. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "tree.h"
28 #include "cp-tree.h"
29 #include "c-common.h"
30 #include "toplev.h"
31 #include "tree-gimple.h"
32 #include "hashtab.h"
33 #include "pointer-set.h"
34 #include "flags.h"
36 /* Local declarations. */
38 enum bc_t { bc_break = 0, bc_continue = 1 };
40 static struct cp_gimplify_ctx
42 /* Stack of labels which are targets for "break" or "continue",
43 linked through TREE_CHAIN. */
44 tree current_label[2];
45 } *ctxp;
47 static void
48 push_context (void)
50 gcc_assert (!ctxp);
51 ctxp = ((struct cp_gimplify_ctx *)
52 xcalloc (1, sizeof (struct cp_gimplify_ctx)));
55 static void
56 pop_context (void)
58 gcc_assert (ctxp
59 && !ctxp->current_label[0]
60 && !ctxp->current_label[1]);
61 free (ctxp);
62 ctxp = NULL;
65 /* Begin a scope which can be exited by a break or continue statement. BC
66 indicates which.
68 Just creates a label and pushes it into the current context. */
70 static tree
71 begin_bc_block (enum bc_t bc)
73 tree label = create_artificial_label ();
74 TREE_CHAIN (label) = ctxp->current_label[bc];
75 ctxp->current_label[bc] = label;
76 return label;
79 /* Finish a scope which can be exited by a break or continue statement.
80 LABEL was returned from the most recent call to begin_bc_block. BODY is
81 an expression for the contents of the scope.
83 If we saw a break (or continue) in the scope, append a LABEL_EXPR to
84 body. Otherwise, just forget the label. */
86 static tree
87 finish_bc_block (enum bc_t bc, tree label, tree body)
89 gcc_assert (label == ctxp->current_label[bc]);
91 if (TREE_USED (label))
93 tree t, sl = NULL;
95 t = build1 (LABEL_EXPR, void_type_node, label);
97 append_to_statement_list (body, &sl);
98 append_to_statement_list (t, &sl);
99 body = sl;
102 ctxp->current_label[bc] = TREE_CHAIN (label);
103 TREE_CHAIN (label) = NULL_TREE;
104 return body;
107 /* Build a GOTO_EXPR to represent a break or continue statement. BC
108 indicates which. */
110 static tree
111 build_bc_goto (enum bc_t bc)
113 tree label = ctxp->current_label[bc];
115 if (label == NULL_TREE)
117 if (bc == bc_break)
118 error ("break statement not within loop or switch");
119 else
120 error ("continue statement not within loop or switch");
122 return NULL_TREE;
125 /* Mark the label used for finish_bc_block. */
126 TREE_USED (label) = 1;
127 return build1 (GOTO_EXPR, void_type_node, label);
130 /* Genericize a TRY_BLOCK. */
132 static void
133 genericize_try_block (tree *stmt_p)
135 tree body = TRY_STMTS (*stmt_p);
136 tree cleanup = TRY_HANDLERS (*stmt_p);
138 gimplify_stmt (&body);
140 if (CLEANUP_P (*stmt_p))
141 /* A cleanup is an expression, so it doesn't need to be genericized. */;
142 else
143 gimplify_stmt (&cleanup);
145 *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
148 /* Genericize a HANDLER by converting to a CATCH_EXPR. */
150 static void
151 genericize_catch_block (tree *stmt_p)
153 tree type = HANDLER_TYPE (*stmt_p);
154 tree body = HANDLER_BODY (*stmt_p);
156 gimplify_stmt (&body);
158 /* FIXME should the caught type go in TREE_TYPE? */
159 *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
162 /* Genericize an EH_SPEC_BLOCK by converting it to a
163 TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
165 static void
166 genericize_eh_spec_block (tree *stmt_p)
168 tree body = EH_SPEC_STMTS (*stmt_p);
169 tree allowed = EH_SPEC_RAISES (*stmt_p);
170 tree failure = build_call (call_unexpected_node,
171 tree_cons (NULL_TREE, build_exc_ptr (),
172 NULL_TREE));
173 gimplify_stmt (&body);
175 *stmt_p = gimple_build_eh_filter (body, allowed, failure);
178 /* Genericize an IF_STMT by turning it into a COND_EXPR. */
180 static void
181 gimplify_if_stmt (tree *stmt_p)
183 tree stmt, cond, then_, else_;
185 stmt = *stmt_p;
186 cond = IF_COND (stmt);
187 then_ = THEN_CLAUSE (stmt);
188 else_ = ELSE_CLAUSE (stmt);
190 if (!then_)
191 then_ = build_empty_stmt ();
192 if (!else_)
193 else_ = build_empty_stmt ();
195 if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
196 stmt = then_;
197 else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
198 stmt = else_;
199 else
200 stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
201 *stmt_p = stmt;
204 /* Build a generic representation of one of the C loop forms. COND is the
205 loop condition or NULL_TREE. BODY is the (possibly compound) statement
206 controlled by the loop. INCR is the increment expression of a for-loop,
207 or NULL_TREE. COND_IS_FIRST indicates whether the condition is
208 evaluated before the loop body as in while and for loops, or after the
209 loop body as in do-while loops. */
211 static tree
212 gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first)
214 tree top, entry, exit, cont_block, break_block, stmt_list, t;
215 location_t stmt_locus;
217 stmt_locus = input_location;
218 stmt_list = NULL_TREE;
219 entry = NULL_TREE;
221 break_block = begin_bc_block (bc_break);
222 cont_block = begin_bc_block (bc_continue);
224 /* If condition is zero don't generate a loop construct. */
225 if (cond && integer_zerop (cond))
227 top = NULL_TREE;
228 exit = NULL_TREE;
229 if (cond_is_first)
231 t = build_bc_goto (bc_break);
232 append_to_statement_list (t, &stmt_list);
235 else
237 /* If we use a LOOP_EXPR here, we have to feed the whole thing
238 back through the main gimplifier to lower it. Given that we
239 have to gimplify the loop body NOW so that we can resolve
240 break/continue stmts, seems easier to just expand to gotos. */
241 top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
243 /* If we have an exit condition, then we build an IF with gotos either
244 out of the loop, or to the top of it. If there's no exit condition,
245 then we just build a jump back to the top. */
246 exit = build_and_jump (&LABEL_EXPR_LABEL (top));
247 if (cond && !integer_nonzerop (cond))
249 t = build_bc_goto (bc_break);
250 exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
251 gimplify_stmt (&exit);
253 if (cond_is_first)
255 if (incr)
257 entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
258 t = build_and_jump (&LABEL_EXPR_LABEL (entry));
260 else
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. */
286 static void
287 gimplify_for_stmt (tree *stmt_p, tree *pre_p)
289 tree stmt = *stmt_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),
295 FOR_EXPR (stmt), 1);
298 /* Gimplify a WHILE_STMT node. */
300 static void
301 gimplify_while_stmt (tree *stmt_p)
303 tree stmt = *stmt_p;
304 *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
305 NULL_TREE, 1);
308 /* Gimplify a DO_STMT node. */
310 static void
311 gimplify_do_stmt (tree *stmt_p)
313 tree stmt = *stmt_p;
314 *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
315 NULL_TREE, 0);
318 /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */
320 static void
321 gimplify_switch_stmt (tree *stmt_p)
323 tree stmt = *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);
330 if (!body)
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 an EXPR_STMT node. */
343 static void
344 gimplify_expr_stmt (tree *stmt_p)
346 tree stmt = EXPR_STMT_EXPR (*stmt_p);
348 if (stmt == error_mark_node)
349 stmt = NULL;
351 /* Gimplification of a statement expression will nullify the
352 statement if all its side effects are moved to *PRE_P and *POST_P.
354 In this case we will not want to emit the gimplified statement.
355 However, we may still want to emit a warning, so we do that before
356 gimplification. */
357 if (stmt && (extra_warnings || warn_unused_value))
359 if (!TREE_SIDE_EFFECTS (stmt))
361 if (!IS_EMPTY_STMT (stmt)
362 && !VOID_TYPE_P (TREE_TYPE (stmt))
363 && !TREE_NO_WARNING (stmt))
364 warning (0, "statement with no effect");
366 else if (warn_unused_value)
367 warn_if_unused_value (stmt, input_location);
370 if (stmt == NULL_TREE)
371 stmt = alloc_stmt_list ();
373 *stmt_p = stmt;
376 /* Gimplify initialization from an AGGR_INIT_EXPR. */
378 static void
379 cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
381 tree from = TREE_OPERAND (*expr_p, 1);
382 tree to = TREE_OPERAND (*expr_p, 0);
383 tree sub;
385 /* If we are initializing something from a TARGET_EXPR, strip the
386 TARGET_EXPR and initialize it directly. */
387 /* What about code that pulls out the temp and uses it elsewhere? I
388 think that such code never uses the TARGET_EXPR as an initializer. If
389 I'm wrong, we'll abort because the temp won't have any RTL. In that
390 case, I guess we'll need to replace references somehow. */
391 if (TREE_CODE (from) == TARGET_EXPR)
392 from = TARGET_EXPR_INITIAL (from);
393 if (TREE_CODE (from) == CLEANUP_POINT_EXPR)
394 from = TREE_OPERAND (from, 0);
396 /* Look through any COMPOUND_EXPRs. */
397 sub = expr_last (from);
399 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
400 replace the slot operand with our target.
402 Should we add a target parm to gimplify_expr instead? No, as in this
403 case we want to replace the INIT_EXPR. */
404 if (TREE_CODE (sub) == AGGR_INIT_EXPR)
406 gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
407 TREE_OPERAND (sub, 2) = to;
408 *expr_p = from;
410 /* The initialization is now a side-effect, so the container can
411 become void. */
412 if (from != sub)
413 TREE_TYPE (from) = void_type_node;
417 /* Gimplify a MUST_NOT_THROW_EXPR. */
419 static void
420 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
422 tree stmt = *expr_p;
423 tree temp = voidify_wrapper_expr (stmt, NULL);
424 tree body = TREE_OPERAND (stmt, 0);
426 gimplify_stmt (&body);
428 stmt = gimple_build_eh_filter (body, NULL_TREE,
429 build_call (terminate_node, NULL_TREE));
431 if (temp)
433 append_to_statement_list (stmt, pre_p);
434 *expr_p = temp;
436 else
437 *expr_p = stmt;
440 /* Do C++-specific gimplification. Args are as for gimplify_expr. */
443 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
445 int saved_stmts_are_full_exprs_p = 0;
446 enum tree_code code = TREE_CODE (*expr_p);
447 enum gimplify_status ret;
449 if (STATEMENT_CODE_P (code))
451 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
452 current_stmt_tree ()->stmts_are_full_exprs_p
453 = STMT_IS_FULL_EXPR_P (*expr_p);
456 switch (code)
458 case PTRMEM_CST:
459 *expr_p = cplus_expand_constant (*expr_p);
460 ret = GS_OK;
461 break;
463 case AGGR_INIT_EXPR:
464 simplify_aggr_init_expr (expr_p);
465 ret = GS_OK;
466 break;
468 case THROW_EXPR:
469 /* FIXME communicate throw type to backend, probably by moving
470 THROW_EXPR into ../tree.def. */
471 *expr_p = TREE_OPERAND (*expr_p, 0);
472 ret = GS_OK;
473 break;
475 case MUST_NOT_THROW_EXPR:
476 gimplify_must_not_throw_expr (expr_p, pre_p);
477 ret = GS_OK;
478 break;
480 case INIT_EXPR:
481 case MODIFY_EXPR:
482 cp_gimplify_init_expr (expr_p, pre_p, post_p);
483 ret = GS_OK;
484 break;
486 case EMPTY_CLASS_EXPR:
487 /* We create an empty CONSTRUCTOR with RECORD_TYPE. */
488 *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
489 ret = GS_OK;
490 break;
492 case BASELINK:
493 *expr_p = BASELINK_FUNCTIONS (*expr_p);
494 ret = GS_OK;
495 break;
497 case TRY_BLOCK:
498 genericize_try_block (expr_p);
499 ret = GS_OK;
500 break;
502 case HANDLER:
503 genericize_catch_block (expr_p);
504 ret = GS_OK;
505 break;
507 case EH_SPEC_BLOCK:
508 genericize_eh_spec_block (expr_p);
509 ret = GS_OK;
510 break;
512 case USING_STMT:
513 /* Just ignore for now. Eventually we will want to pass this on to
514 the debugger. */
515 *expr_p = build_empty_stmt ();
516 ret = GS_ALL_DONE;
517 break;
519 case IF_STMT:
520 gimplify_if_stmt (expr_p);
521 ret = GS_OK;
522 break;
524 case FOR_STMT:
525 gimplify_for_stmt (expr_p, pre_p);
526 ret = GS_ALL_DONE;
527 break;
529 case WHILE_STMT:
530 gimplify_while_stmt (expr_p);
531 ret = GS_ALL_DONE;
532 break;
534 case DO_STMT:
535 gimplify_do_stmt (expr_p);
536 ret = GS_ALL_DONE;
537 break;
539 case SWITCH_STMT:
540 gimplify_switch_stmt (expr_p);
541 ret = GS_ALL_DONE;
542 break;
544 case CONTINUE_STMT:
545 *expr_p = build_bc_goto (bc_continue);
546 ret = GS_ALL_DONE;
547 break;
549 case BREAK_STMT:
550 *expr_p = build_bc_goto (bc_break);
551 ret = GS_ALL_DONE;
552 break;
554 case EXPR_STMT:
555 gimplify_expr_stmt (expr_p);
556 ret = GS_OK;
557 break;
559 case UNARY_PLUS_EXPR:
561 tree arg = TREE_OPERAND (*expr_p, 0);
562 tree type = TREE_TYPE (*expr_p);
563 *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
564 : arg;
565 ret = GS_OK;
567 break;
569 default:
570 ret = c_gimplify_expr (expr_p, pre_p, post_p);
571 break;
574 /* Restore saved state. */
575 if (STATEMENT_CODE_P (code))
576 current_stmt_tree ()->stmts_are_full_exprs_p
577 = saved_stmts_are_full_exprs_p;
579 return ret;
582 static inline bool
583 is_invisiref_parm (tree t)
585 return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
586 && DECL_BY_REFERENCE (t));
589 /* Perform any pre-gimplification lowering of C++ front end trees to
590 GENERIC. */
592 static tree
593 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
595 tree stmt = *stmt_p;
596 struct pointer_set_t *p_set = (struct pointer_set_t*) data;
598 if (is_invisiref_parm (stmt)
599 /* Don't dereference parms in a thunk, pass the references through. */
600 && !(DECL_THUNK_P (current_function_decl)
601 && TREE_CODE (stmt) == PARM_DECL))
603 *stmt_p = convert_from_reference (stmt);
604 *walk_subtrees = 0;
605 return NULL;
608 /* Other than invisiref parms, don't walk the same tree twice. */
609 if (pointer_set_contains (p_set, stmt))
611 *walk_subtrees = 0;
612 return NULL_TREE;
615 if (TREE_CODE (stmt) == ADDR_EXPR
616 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
618 *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
619 *walk_subtrees = 0;
621 else if (TREE_CODE (stmt) == RETURN_EXPR
622 && TREE_OPERAND (stmt, 0)
623 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
624 /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */
625 *walk_subtrees = 0;
626 else if (IS_TYPE_OR_DECL_P (stmt))
627 *walk_subtrees = 0;
629 /* Due to the way voidify_wrapper_expr is written, we don't get a chance
630 to lower this construct before scanning it, so we need to lower these
631 before doing anything else. */
632 else if (TREE_CODE (stmt) == CLEANUP_STMT)
633 *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
634 : TRY_FINALLY_EXPR,
635 void_type_node,
636 CLEANUP_BODY (stmt),
637 CLEANUP_EXPR (stmt));
639 pointer_set_insert (p_set, *stmt_p);
641 return NULL;
644 void
645 cp_genericize (tree fndecl)
647 tree t;
648 struct pointer_set_t *p_set;
650 /* Fix up the types of parms passed by invisible reference. */
651 for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
652 if (TREE_ADDRESSABLE (TREE_TYPE (t)))
654 /* If a function's arguments are copied to create a thunk,
655 then DECL_BY_REFERENCE will be set -- but the type of the
656 argument will be a pointer type, so we will never get
657 here. */
658 gcc_assert (!DECL_BY_REFERENCE (t));
659 gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
660 TREE_TYPE (t) = DECL_ARG_TYPE (t);
661 DECL_BY_REFERENCE (t) = 1;
662 TREE_ADDRESSABLE (t) = 0;
663 relayout_decl (t);
666 /* Do the same for the return value. */
667 if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
669 t = DECL_RESULT (fndecl);
670 TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
671 DECL_BY_REFERENCE (t) = 1;
672 TREE_ADDRESSABLE (t) = 0;
673 relayout_decl (t);
676 /* If we're a clone, the body is already GIMPLE. */
677 if (DECL_CLONED_FUNCTION_P (fndecl))
678 return;
680 /* We do want to see every occurrence of the parms, so we can't just use
681 walk_tree's hash functionality. */
682 p_set = pointer_set_create ();
683 walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
684 pointer_set_destroy (p_set);
686 /* Do everything else. */
687 push_context ();
688 c_genericize (fndecl);
689 pop_context ();