OSDN Git Service

./
[pf3gnuchains/gcc-fork.git] / gcc / cp / cp-gimplify.c
1 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
2
3    Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4    Contributed by Jason Merrill <jason@redhat.com>
5
6 This file is part of GCC.
7
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.
12
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.
17
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
21 02111-1307, USA.  */
22
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
35 /* Local declarations.  */
36
37 enum bc_t { bc_break = 0, bc_continue = 1 };
38
39 static struct cp_gimplify_ctx
40 {
41   /* Stack of labels which are targets for "break" or "continue",
42      linked through TREE_CHAIN.  */
43   tree current_label[2];
44 } *ctxp;
45
46 static void
47 push_context (void)
48 {
49   gcc_assert (!ctxp);
50   ctxp = ((struct cp_gimplify_ctx *)
51           xcalloc (1, sizeof (struct cp_gimplify_ctx)));
52 }
53
54 static void
55 pop_context (void)
56 {
57   gcc_assert (ctxp
58               && !ctxp->current_label[0]
59               && !ctxp->current_label[1]);
60   free (ctxp);
61   ctxp = NULL;
62 }
63
64 /* Begin a scope which can be exited by a break or continue statement.  BC
65    indicates which.
66
67    Just creates a label and pushes it into the current context.  */
68
69 static tree
70 begin_bc_block (enum bc_t bc)
71 {
72   tree label = create_artificial_label ();
73   TREE_CHAIN (label) = ctxp->current_label[bc];
74   ctxp->current_label[bc] = label;
75   return label;
76 }
77
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.
81
82    If we saw a break (or continue) in the scope, append a LABEL_EXPR to
83    body.  Otherwise, just forget the label.  */
84
85 static tree
86 finish_bc_block (enum bc_t bc, tree label, tree body)
87 {
88   gcc_assert (label == ctxp->current_label[bc]);
89
90   if (TREE_USED (label))
91     {
92       tree t, sl = NULL;
93
94       t = build1 (LABEL_EXPR, void_type_node, label);
95
96       append_to_statement_list (body, &sl);
97       append_to_statement_list (t, &sl);
98       body = sl;
99     }
100
101   ctxp->current_label[bc] = TREE_CHAIN (label);
102   TREE_CHAIN (label) = NULL_TREE;
103   return body;
104 }
105
106 /* Build a GOTO_EXPR to represent a break or continue statement.  BC
107    indicates which.  */
108
109 static tree
110 build_bc_goto (enum bc_t bc)
111 {
112   tree label = ctxp->current_label[bc];
113
114   if (label == NULL_TREE)
115     {
116       if (bc == bc_break)
117         error ("break statement not within loop or switch");
118       else
119         error ("continue statement not within loop or switch");
120
121       return NULL_TREE;
122     }
123
124   /* Mark the label used for finish_bc_block.  */
125   TREE_USED (label) = 1;
126   return build1 (GOTO_EXPR, void_type_node, label);
127 }
128
129 /* Genericize a TRY_BLOCK.  */
130
131 static void
132 genericize_try_block (tree *stmt_p)
133 {
134   tree body = TRY_STMTS (*stmt_p);
135   tree cleanup = TRY_HANDLERS (*stmt_p);
136
137   gimplify_stmt (&body);
138
139   if (CLEANUP_P (*stmt_p))
140     /* A cleanup is an expression, so it doesn't need to be genericized.  */;
141   else
142     gimplify_stmt (&cleanup);
143
144   *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
145 }
146
147 /* Genericize a HANDLER by converting to a CATCH_EXPR.  */
148
149 static void
150 genericize_catch_block (tree *stmt_p)
151 {
152   tree type = HANDLER_TYPE (*stmt_p);
153   tree body = HANDLER_BODY (*stmt_p);
154
155   gimplify_stmt (&body);
156
157   /* FIXME should the caught type go in TREE_TYPE?  */
158   *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
159 }
160
161 /* Genericize an EH_SPEC_BLOCK by converting it to a
162    TRY_CATCH_EXPR/EH_FILTER_EXPR pair.  */
163
164 static void
165 genericize_eh_spec_block (tree *stmt_p)
166 {
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 (),
171                                         NULL_TREE));
172   gimplify_stmt (&body);
173
174   *stmt_p = gimple_build_eh_filter (body, allowed, failure);
175 }
176
177 /* Genericize an IF_STMT by turning it into a COND_EXPR.  */
178
179 static void
180 gimplify_if_stmt (tree *stmt_p)
181 {
182   tree stmt, cond, then_, else_;
183
184   stmt = *stmt_p;
185   cond = IF_COND (stmt);
186   then_ = THEN_CLAUSE (stmt);
187   else_ = ELSE_CLAUSE (stmt);
188
189   if (!then_)
190     then_ = build_empty_stmt ();
191   if (!else_)
192     else_ = build_empty_stmt ();
193
194   if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
195     stmt = then_;
196   else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
197     stmt = else_;
198   else
199     stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
200   *stmt_p = stmt;
201 }
202
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.  */
209
210 static tree
211 gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first)
212 {
213   tree top, entry, exit, cont_block, break_block, stmt_list, t;
214   location_t stmt_locus;
215
216   stmt_locus = input_location;
217   stmt_list = NULL_TREE;
218   entry = NULL_TREE;
219
220   break_block = begin_bc_block (bc_break);
221   cont_block = begin_bc_block (bc_continue);
222
223   /* If condition is zero don't generate a loop construct.  */
224   if (cond && integer_zerop (cond))
225     {
226       top = NULL_TREE;
227       exit = NULL_TREE;
228       if (cond_is_first)
229         {
230           t = build_bc_goto (bc_break);
231           append_to_statement_list (t, &stmt_list);
232         }
233     }
234   else
235     {
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);
241
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))
247         {
248           t = build_bc_goto (bc_break);
249           exit = build3 (COND_EXPR, void_type_node, cond, exit, t);
250           exit = fold (exit);
251           gimplify_stmt (&exit);
252
253           if (cond_is_first)
254             {
255               if (incr)
256                 {
257                   entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
258                   t = build_and_jump (&LABEL_EXPR_LABEL (entry));
259                 }
260               else
261                 t = build_bc_goto (bc_continue);
262               append_to_statement_list (t, &stmt_list);
263             }
264         }
265     }
266
267   gimplify_stmt (&body);
268   gimplify_stmt (&incr);
269
270   body = finish_bc_block (bc_continue, cont_block, body);
271
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);
277
278   annotate_all_with_locus (&stmt_list, stmt_locus);
279
280   return finish_bc_block (bc_break, break_block, stmt_list);
281 }
282
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.  */
285
286 static void
287 gimplify_for_stmt (tree *stmt_p, tree *pre_p)
288 {
289   tree stmt = *stmt_p;
290
291   if (FOR_INIT_STMT (stmt))
292     gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
293
294   *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
295                               FOR_EXPR (stmt), 1);
296 }
297
298 /* Gimplify a WHILE_STMT node.  */
299
300 static void
301 gimplify_while_stmt (tree *stmt_p)
302 {
303   tree stmt = *stmt_p;
304   *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
305                               NULL_TREE, 1);
306 }
307
308 /* Gimplify a DO_STMT node.  */
309
310 static void
311 gimplify_do_stmt (tree *stmt_p)
312 {
313   tree stmt = *stmt_p;
314   *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
315                               NULL_TREE, 0);
316 }
317
318 /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
319
320 static void
321 gimplify_switch_stmt (tree *stmt_p)
322 {
323   tree stmt = *stmt_p;
324   tree break_block, body;
325   location_t stmt_locus = input_location;
326
327   break_block = begin_bc_block (bc_break);
328
329   body = SWITCH_STMT_BODY (stmt);
330   if (!body)
331     body = build_empty_stmt ();
332
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);
337
338   *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p);
339 }
340
341 /* Gimplify initialization from an AGGR_INIT_EXPR.  */
342
343 static void
344 cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
345 {
346   tree from = TREE_OPERAND (*expr_p, 1);
347   tree to = TREE_OPERAND (*expr_p, 0);
348   tree sub;
349
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);
360
361   /* Look through any COMPOUND_EXPRs.  */
362   sub = expr_last (from);
363
364   /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
365      replace the slot operand with our target.
366
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)
370     {
371       gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
372       TREE_OPERAND (sub, 2) = to;
373       *expr_p = from;
374
375       /* The initialization is now a side-effect, so the container can
376          become void.  */
377       if (from != sub)
378         TREE_TYPE (from) = void_type_node;
379     }
380 }
381
382 /* Gimplify a MUST_NOT_THROW_EXPR.  */
383
384 static void
385 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
386 {
387   tree stmt = *expr_p;
388   tree temp = voidify_wrapper_expr (stmt, NULL);
389   tree body = TREE_OPERAND (stmt, 0);
390
391   gimplify_stmt (&body);
392
393   stmt = gimple_build_eh_filter (body, NULL_TREE,
394                                  build_call (terminate_node, NULL_TREE));
395
396   if (temp)
397     {
398       append_to_statement_list (stmt, pre_p);
399       *expr_p = temp;
400     }
401   else
402     *expr_p = stmt;
403 }
404
405 /* Do C++-specific gimplification.  Args are as for gimplify_expr.  */
406
407 int
408 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
409 {
410   int saved_stmts_are_full_exprs_p = 0;
411   enum tree_code code = TREE_CODE (*expr_p);
412   enum gimplify_status ret;
413
414   if (STATEMENT_CODE_P (code))
415     {
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);
419     }
420
421   switch (code)
422     {
423     case PTRMEM_CST:
424       *expr_p = cplus_expand_constant (*expr_p);
425       ret = GS_OK;
426       break;
427
428     case AGGR_INIT_EXPR:
429       simplify_aggr_init_expr (expr_p);
430       ret = GS_OK;
431       break;
432
433     case THROW_EXPR:
434       /* FIXME communicate throw type to backend, probably by moving
435          THROW_EXPR into ../tree.def.  */
436       *expr_p = TREE_OPERAND (*expr_p, 0);
437       ret = GS_OK;
438       break;
439
440     case MUST_NOT_THROW_EXPR:
441       gimplify_must_not_throw_expr (expr_p, pre_p);
442       ret = GS_OK;
443       break;
444
445     case INIT_EXPR:
446     case MODIFY_EXPR:
447       cp_gimplify_init_expr (expr_p, pre_p, post_p);
448       ret = GS_OK;
449       break;
450
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);
454       ret = GS_OK;
455       break;
456
457     case BASELINK:
458       *expr_p = BASELINK_FUNCTIONS (*expr_p);
459       ret = GS_OK;
460       break;
461
462     case TRY_BLOCK:
463       genericize_try_block (expr_p);
464       ret = GS_OK;
465       break;
466
467     case HANDLER:
468       genericize_catch_block (expr_p);
469       ret = GS_OK;
470       break;
471
472     case EH_SPEC_BLOCK:
473       genericize_eh_spec_block (expr_p);
474       ret = GS_OK;
475       break;
476
477     case USING_STMT:
478       /* Just ignore for now.  Eventually we will want to pass this on to
479          the debugger.  */
480       *expr_p = build_empty_stmt ();
481       ret = GS_ALL_DONE;
482       break;
483
484     case IF_STMT:
485       gimplify_if_stmt (expr_p);
486       ret = GS_OK;
487       break;
488
489     case FOR_STMT:
490       gimplify_for_stmt (expr_p, pre_p);
491       ret = GS_ALL_DONE;
492       break;
493
494     case WHILE_STMT:
495       gimplify_while_stmt (expr_p);
496       ret = GS_ALL_DONE;
497       break;
498
499     case DO_STMT:
500       gimplify_do_stmt (expr_p);
501       ret = GS_ALL_DONE;
502       break;
503
504     case SWITCH_STMT:
505       gimplify_switch_stmt (expr_p);
506       ret = GS_ALL_DONE;
507       break;
508
509     case CONTINUE_STMT:
510       *expr_p = build_bc_goto (bc_continue);
511       ret = GS_ALL_DONE;
512       break;
513
514     case BREAK_STMT:
515       *expr_p = build_bc_goto (bc_break);
516       ret = GS_ALL_DONE;
517       break;
518
519     default:
520       ret = c_gimplify_expr (expr_p, pre_p, post_p);
521       break;
522     }
523
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;
528
529   return ret;
530 }
531
532 static inline bool
533 is_invisiref_parm (tree t)
534 {
535   return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
536           && DECL_BY_REFERENCE (t));
537 }
538
539 /* Perform any pre-gimplification lowering of C++ front end trees to
540    GENERIC.  */
541
542 static tree
543 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
544 {
545   tree stmt = *stmt_p;
546   struct pointer_set_t *p_set = (struct pointer_set_t*) data;
547
548   if (is_invisiref_parm (stmt))
549     {
550       *stmt_p = convert_from_reference (stmt);
551       *walk_subtrees = 0;
552       return NULL;
553     }
554
555   /* Other than invisiref parms, don't walk the same tree twice.  */
556   if (pointer_set_contains (p_set, stmt))
557     {
558       *walk_subtrees = 0;
559       return NULL_TREE;
560     }
561
562   if (TREE_CODE (stmt) == ADDR_EXPR
563       && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
564     {
565       *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
566       *walk_subtrees = 0;
567     }
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.  */
572     *walk_subtrees = 0;
573   else if (IS_TYPE_OR_DECL_P (stmt))
574     *walk_subtrees = 0;
575
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
581                                              : TRY_FINALLY_EXPR,
582                       void_type_node,
583                       CLEANUP_BODY (stmt),
584                       CLEANUP_EXPR (stmt));
585
586   pointer_set_insert (p_set, *stmt_p);
587   
588   return NULL;
589 }
590
591 void
592 cp_genericize (tree fndecl)
593 {
594   tree t;
595   struct pointer_set_t *p_set;
596
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)))
600       {
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
604            here.  */
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;
610         relayout_decl (t);
611       }
612
613   /* Do the same for the return value.  */
614   if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
615     {
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;
620       relayout_decl (t);
621     }
622
623   /* If we're a clone, the body is already GIMPLE.  */
624   if (DECL_CLONED_FUNCTION_P (fndecl))
625     return;
626
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);
632
633   /* Do everything else.  */
634   push_context ();
635   c_genericize (fndecl);
636   pop_context ();
637 }