OSDN Git Service

* c-common.c (lang_gimplify_stmt): Remove next_p argument.
[pf3gnuchains/gcc-fork.git] / gcc / c-gimplify.c
1 /* Tree lowering pass.  This pass gimplifies the tree representation built
2    by the C-based front ends.  The structure of gimplified, or
3    language-independent, trees is dictated by the grammar described in this
4    file.
5    Copyright (C) 2002, 2003 Free Software Foundation, Inc.
6    Lowering of expressions contributed by Sebastian Pop <s.pop@laposte.net>
7    Re-written to support lowering of whole function trees, documentation
8    and miscellaneous cleanups by Diego Novillo <dnovillo@redhat.com>
9
10 This file is part of GCC.
11
12 GCC is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free
14 Software Foundation; either version 2, or (at your option) any later
15 version.
16
17 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GCC; see the file COPYING.  If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA.  */
26
27 #include "config.h"
28 #include "system.h"
29 #include "coretypes.h"
30 #include "tm.h"
31 #include "tree.h"
32 #include "errors.h"
33 #include "varray.h"
34 #include "c-tree.h"
35 #include "c-common.h"
36 #include "tree-gimple.h"
37 #include "hard-reg-set.h"
38 #include "basic-block.h"
39 #include "tree-flow.h"
40 #include "tree-inline.h"
41 #include "diagnostic.h"
42 #include "langhooks.h"
43 #include "langhooks-def.h"
44 #include "flags.h"
45 #include "rtl.h"
46 #include "toplev.h"
47 #include "tree-dump.h"
48 #include "c-pretty-print.h"
49 #include "cgraph.h"
50
51
52 /*  The gimplification pass converts the language-dependent trees
53     (ld-trees) emitted by the parser into language-independent trees
54     (li-trees) that are the target of SSA analysis and transformations.
55
56     Language-independent trees are based on the SIMPLE intermediate
57     representation used in the McCAT compiler framework:
58
59     "Designing the McCAT Compiler Based on a Family of Structured
60     Intermediate Representations,"
61     L. Hendren, C. Donawa, M. Emami, G. Gao, Justiani, and B. Sridharan,
62     Proceedings of the 5th International Workshop on Languages and
63     Compilers for Parallel Computing, no. 757 in Lecture Notes in
64     Computer Science, New Haven, Connecticut, pp. 406-420,
65     Springer-Verlag, August 3-5, 1992.
66
67     http://www-acaps.cs.mcgill.ca/info/McCAT/McCAT.html
68
69     Basically, we walk down gimplifying the nodes that we encounter.  As we
70     walk back up, we check that they fit our constraints, and copy them
71     into temporaries if not.  */
72
73 /* Local declarations.  */
74
75 static enum gimplify_status gimplify_expr_stmt (tree *);
76 static enum gimplify_status gimplify_decl_stmt (tree *);
77 static enum gimplify_status gimplify_for_stmt (tree *, tree *);
78 static enum gimplify_status gimplify_while_stmt (tree *);
79 static enum gimplify_status gimplify_do_stmt (tree *);
80 static enum gimplify_status gimplify_if_stmt (tree *);
81 static enum gimplify_status gimplify_switch_stmt (tree *);
82 static enum gimplify_status gimplify_return_stmt (tree *);
83 static enum gimplify_status gimplify_compound_literal_expr (tree *);
84 static void gimplify_cleanup_stmts (tree);
85 static tree gimplify_c_loop (tree, tree, tree, bool);
86 static void push_context (void);
87 static void pop_context (void);
88 static void add_block_to_enclosing (tree);
89 static void gimplify_condition (tree *);
90
91 enum bc_t { bc_break = 0, bc_continue = 1 };
92 static tree begin_bc_block (enum bc_t);
93 static tree finish_bc_block (tree, tree);
94 static tree build_bc_goto (enum bc_t);
95
96 static struct c_gimplify_ctx
97 {
98   /* For handling break and continue.  */
99   tree current_bc_label;
100   tree bc_id[2];
101 } *ctxp;
102
103 static void
104 push_context (void)
105 {
106   if (ctxp)
107     abort ();
108   ctxp = (struct c_gimplify_ctx *) xcalloc (1, sizeof (struct c_gimplify_ctx));
109   ctxp->bc_id[bc_continue] = get_identifier ("continue");
110   ctxp->bc_id[bc_break] = get_identifier ("break");
111 }
112
113 static void
114 pop_context (void)
115 {
116   if (!ctxp || ctxp->current_bc_label)
117     abort ();
118   free (ctxp);
119   ctxp = NULL;
120 }
121
122 /* Gimplification of statement trees.  */
123
124 /* Convert the tree representation of FNDECL from C frontend trees to
125    GENERIC.  */
126
127 void
128 c_genericize (tree fndecl)
129 {
130   FILE *dump_file;
131   int local_dump_flags;
132   struct cgraph_node *cgn;
133
134   /* Dump the C-specific tree IR.  */
135   dump_file = dump_begin (TDI_original, &local_dump_flags);
136   if (dump_file)
137     {
138       fprintf (dump_file, "\n;; Function %s",
139                lang_hooks.decl_printable_name (fndecl, 2));
140       fprintf (dump_file, " (%s)\n",
141                IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
142       fprintf (dump_file, ";; enabled by -%s\n", dump_flag_name (TDI_original));
143       fprintf (dump_file, "\n");
144
145       if (local_dump_flags & TDF_RAW)
146         dump_node (DECL_SAVED_TREE (fndecl),
147                    TDF_SLIM | local_dump_flags, dump_file);
148       else
149         print_c_tree (dump_file, DECL_SAVED_TREE (fndecl));
150       fprintf (dump_file, "\n");
151
152       dump_end (TDI_original, dump_file);
153     }
154
155   /* Go ahead and gimplify for now.  */
156   push_context ();
157   gimplify_cleanup_stmts (fndecl);
158   gimplify_function_tree (fndecl);
159   pop_context ();
160
161   /* Dump the genericized tree IR.  */
162   dump_function (TDI_generic, fndecl);
163
164   /* Genericize all nested functions now.  We do things in this order so
165      that items like VLA sizes are expanded properly in the context of
166      the correct function.  */
167   cgn = cgraph_node (fndecl);
168   for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
169     c_genericize (cgn->decl);
170 }
171
172 /* Genericize a CLEANUP_STMT.  This just turns into a TRY_FINALLY or
173    TRY_CATCH depending on whether it's EH-only.  */
174
175 static tree
176 gimplify_cleanup_stmt (tree *stmt_p, int *walk_subtrees,
177                        void *data ATTRIBUTE_UNUSED)
178 {
179   tree stmt = *stmt_p;
180
181   if (DECL_P (stmt) || TYPE_P (stmt))
182     *walk_subtrees = 0;
183   else if (TREE_CODE (stmt) == CLEANUP_STMT)
184     *stmt_p = build (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR,
185                      void_type_node, CLEANUP_BODY (stmt), CLEANUP_EXPR (stmt));
186
187   return NULL;
188 }
189
190 static void
191 gimplify_cleanup_stmts (tree fndecl)
192 {
193   walk_tree (&DECL_SAVED_TREE (fndecl), gimplify_cleanup_stmt, NULL, NULL);
194 }
195
196 /*  Entry point for the tree lowering pass.  Recursively scan
197     *STMT_P and convert it to a GIMPLE tree.  */
198
199 int
200 c_gimplify_stmt (tree *stmt_p)
201 {
202   tree stmt = *stmt_p;
203   tree pre, post;
204   int saved_stmts_are_full_exprs_p;
205   location_t stmt_locus;
206   enum gimplify_status ret;
207
208   /* PRE and POST are tree chains that contain the side-effects of the
209      gimplified tree.  For instance, given the expression tree:
210
211                 c = ++a * 3 + b++;
212
213      After gimplification, the tree will be re-written as:
214
215                 a = a + 1;
216                 t1 = a * 3;     <-- PRE
217                 c = t1 + b;
218                 b = b + 1;      <-- POST  */
219
220   /* Set up context appropriately for handling this statement.  */
221   saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
222   prep_stmt (stmt);
223   stmt_locus = input_location;
224
225   pre = NULL_TREE;
226   post = NULL_TREE;
227
228   switch (TREE_CODE (stmt))
229     {
230     case COMPOUND_STMT:
231       stmt = COMPOUND_BODY (stmt);
232       ret = GS_OK;
233       break;
234
235     case FOR_STMT:
236       ret = gimplify_for_stmt (&stmt, &pre);
237       break;
238
239     case WHILE_STMT:
240       ret = gimplify_while_stmt (&stmt);
241       break;
242
243     case DO_STMT:
244       ret = gimplify_do_stmt (&stmt);
245       break;
246
247     case IF_STMT:
248       ret = gimplify_if_stmt (&stmt);
249       break;
250
251     case SWITCH_STMT:
252       ret = gimplify_switch_stmt (&stmt);
253       break;
254
255     case EXPR_STMT:
256       ret = gimplify_expr_stmt (&stmt);
257       break;
258
259     case RETURN_STMT:
260       ret = gimplify_return_stmt (&stmt);
261       break;
262
263     case DECL_STMT:
264       ret = gimplify_decl_stmt (&stmt);
265       break;
266
267     case LABEL_STMT:
268       stmt = build1 (LABEL_EXPR, void_type_node, LABEL_STMT_LABEL (stmt));
269       ret = GS_OK;
270       break;
271
272     case GOTO_STMT:
273       stmt = build1 (GOTO_EXPR, void_type_node, GOTO_DESTINATION (stmt));
274       ret = GS_OK;
275       break;
276
277     case CASE_LABEL:
278       {
279         tree label = create_artificial_label ();
280         stmt = build (CASE_LABEL_EXPR, void_type_node,
281                       CASE_LOW (stmt), CASE_HIGH (stmt), label);
282         ret = GS_OK;
283       }
284       break;
285
286     case CONTINUE_STMT:
287       stmt = build_bc_goto (bc_continue);
288       ret = GS_OK;
289       break;
290
291     case BREAK_STMT:
292       stmt = build_bc_goto (bc_break);
293       ret = GS_OK;
294       break;
295
296     case ASM_STMT:
297       {
298         tree new_stmt = build (ASM_EXPR, void_type_node, ASM_STRING (stmt),
299                                ASM_OUTPUTS (stmt), ASM_INPUTS (stmt),
300                                ASM_CLOBBERS (stmt));
301         ASM_INPUT_P (new_stmt) = ASM_INPUT_P (stmt);
302         ASM_VOLATILE_P (new_stmt) = ASM_VOLATILE_P (stmt);
303         stmt = new_stmt;
304         ret = GS_OK;
305       }
306       break;
307
308     default:
309       if (lang_gimplify_stmt && (*lang_gimplify_stmt) (&stmt))
310         {
311           ret = GS_OK;
312           break;
313         }
314
315       fprintf (stderr, "unhandled statement node in c_gimplify_stmt:\n");
316       debug_tree (stmt);
317       abort ();
318       break;
319     }
320
321   switch (ret)
322     {
323     case GS_ERROR:
324       goto cont;
325     case GS_OK:
326       gimplify_stmt (&stmt);
327       break;
328     case GS_ALL_DONE:
329       break;
330     default:
331       abort ();
332     }
333
334   /* PRE and POST now contain a list of statements for all the
335      side-effects in STMT.  */
336
337   append_to_statement_list (stmt, &pre);
338   append_to_statement_list (post, &pre);
339   annotate_all_with_locus (&pre, stmt_locus);
340  cont:
341   /* Restore saved state.  */
342   current_stmt_tree ()->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
343   *stmt_p = pre;
344
345   return GS_ALL_DONE;
346 }
347
348 static void
349 add_block_to_enclosing (tree block)
350 {
351   tree enclosing;
352
353   for (enclosing = gimple_current_bind_expr ();
354        enclosing; enclosing = TREE_CHAIN (enclosing))
355     if (BIND_EXPR_BLOCK (enclosing))
356       break;
357
358   enclosing = BIND_EXPR_BLOCK (enclosing);
359   BLOCK_SUBBLOCKS (enclosing) = chainon (BLOCK_SUBBLOCKS (enclosing), block);
360 }
361
362 /* Genericize a scope by creating a new BIND_EXPR.
363    BLOCK is either a BLOCK representing the scope or a chain of _DECLs.
364      In the latter case, we need to create a new BLOCK and add it to the
365      BLOCK_SUBBLOCKS of the enclosing block.
366    BODY is a chain of C _STMT nodes for the contents of the scope, to be
367      genericized.  */
368
369 tree
370 c_build_bind_expr (tree block, tree body)
371 {
372   tree decls, bind;
373
374   if (block == NULL_TREE)
375     decls = NULL_TREE;
376   else if (TREE_CODE (block) == BLOCK)
377     decls = BLOCK_VARS (block);
378   else
379     {
380       decls = block;
381       if (DECL_ARTIFICIAL (decls))
382         block = NULL_TREE;
383       else
384         {
385           block = make_node (BLOCK);
386           BLOCK_VARS (block) = decls;
387           add_block_to_enclosing (block);
388         }
389     }
390
391   if (!body)
392     body = build_empty_stmt ();
393   if (decls || block)
394     {
395       bind = build (BIND_EXPR, void_type_node, decls, body, block);
396       TREE_SIDE_EFFECTS (bind) = 1;
397     }
398   else
399     bind = body;
400
401   return bind;
402 }
403
404 /*  Gimplify an EXPR_STMT node.
405
406     STMT is the statement node.
407
408     PRE_P points to the list where side effects that must happen before
409         STMT should be stored.
410
411     POST_P points to the list where side effects that must happen after
412         STMT should be stored.  */
413
414 static enum gimplify_status
415 gimplify_expr_stmt (tree *stmt_p)
416 {
417   tree stmt = EXPR_STMT_EXPR (*stmt_p);
418
419   if (stmt == error_mark_node)
420     stmt = NULL;
421
422   /* Gimplification of a statement expression will nullify the
423      statement if all its side effects are moved to *PRE_P and *POST_P.
424
425      In this case we will not want to emit the gimplified statement.
426      However, we may still want to emit a warning, so we do that before
427      gimplification.  */
428   if (stmt && (extra_warnings || warn_unused_value))
429     {
430       if (!TREE_SIDE_EFFECTS (stmt))
431         {
432           if (!IS_EMPTY_STMT (stmt)
433               && !VOID_TYPE_P (TREE_TYPE (stmt))
434               && !TREE_NO_WARNING (stmt))
435             warning ("statement with no effect");
436         }
437       else if (warn_unused_value)
438         {
439           /* Kludge for 20020220-2.c.  warn_if_unused_value shouldn't use
440              the stmt file location info.  */
441           set_file_and_line_for_stmt (input_location);
442           warn_if_unused_value (stmt);
443         }
444     }
445
446   if (stmt == NULL_TREE)
447     stmt = build_empty_stmt ();
448   else if (stmts_are_full_exprs_p ())
449     stmt = build1 (CLEANUP_POINT_EXPR, void_type_node, stmt);
450
451   *stmt_p = stmt;
452
453   return GS_OK;
454 }
455
456 /* If the condition for a loop (or the like) is a decl, it will be a
457    TREE_LIST where the TREE_PURPOSE is a DECL_STMT and the TREE_VALUE is
458    a use of the decl.  Turn such a thing into a COMPOUND_EXPR.  */
459
460 static void
461 gimplify_condition (tree *cond_p)
462 {
463   tree cond = *cond_p;
464   if (cond && TREE_CODE (cond) == TREE_LIST)
465     {
466       tree decl = TREE_PURPOSE (cond);
467       tree value = TREE_VALUE (cond);
468       gimplify_stmt (&decl);
469       *cond_p = build (COMPOUND_EXPR, TREE_TYPE (value), decl, value);
470     }
471 }
472
473 /* Begin a scope which can be exited by a break or continue statement.  BC
474    indicates which.
475
476    Just creates a label and pushes it into the current context.  */
477
478 static tree
479 begin_bc_block (enum bc_t bc)
480 {
481   tree label = create_artificial_label ();
482   DECL_NAME (label) = ctxp->bc_id[bc];
483   TREE_CHAIN (label) = ctxp->current_bc_label;
484   ctxp->current_bc_label = label;
485   return label;
486 }
487
488 /* Finish a scope which can be exited by a break or continue statement.
489    LABEL was returned from the most recent call to begin_bc_block.  BODY is
490    an expression for the contents of the scope.
491
492    If we saw a break (or continue) in the scope, append a LABEL_EXPR to
493    body.  Otherwise, just forget the label.  */
494
495 static tree
496 finish_bc_block (tree label, tree body)
497 {
498   if (label != ctxp->current_bc_label)
499     abort ();
500
501   if (TREE_USED (label))
502     {
503       tree t, sl = NULL;
504
505       /* Clear the name so flow can delete the label.  */
506       DECL_NAME (label) = NULL_TREE;
507       t = build1 (LABEL_EXPR, void_type_node, label);
508
509       append_to_statement_list (body, &sl);
510       append_to_statement_list (t, &sl);
511       body = sl;
512     }
513
514   ctxp->current_bc_label = TREE_CHAIN (label);
515   TREE_CHAIN (label) = NULL_TREE;
516   return body;
517 }
518
519 /* Build a GOTO_EXPR to represent a break or continue statement.  BC
520    indicates which.  */
521
522 static tree
523 build_bc_goto (enum bc_t bc)
524 {
525   tree label;
526   tree target_name = ctxp->bc_id[bc];
527
528   /* Look for the appropriate type of label.  */
529   for (label = ctxp->current_bc_label;
530        label;
531        label = TREE_CHAIN (label))
532     if (DECL_NAME (label) == target_name)
533       break;
534
535   if (label == NULL_TREE)
536     {
537       if (bc == bc_break)
538         error ("break statement not within loop or switch");
539       else
540         error ("continue statement not within loop or switch");
541
542       return NULL_TREE;
543     }
544
545   /* Mark the label used for finish_bc_block.  */
546   TREE_USED (label) = 1;
547   return build1 (GOTO_EXPR, void_type_node, label);
548 }
549
550 /* Build a generic representation of one of the C loop forms.  COND is the
551    loop condition or NULL_TREE.  BODY is the (possibly compound) statement
552    controlled by the loop.  INCR is the increment expression of a for-loop,
553    or NULL_TREE.  COND_IS_FIRST indicates whether the condition is
554    evaluated before the loop body as in while and for loops, or after the
555    loop body as in do-while loops.  */
556
557 static tree
558 gimplify_c_loop (tree cond, tree body, tree incr, bool cond_is_first)
559 {
560   tree top, entry, exit, cont_block, break_block, stmt_list, t;
561   location_t stmt_locus;
562
563   stmt_locus = input_location;
564
565   /* Detect do { ... } while (0) and don't generate loop construct.  */
566   if (!cond_is_first && cond && integer_zerop (cond))
567     top = cond = NULL;
568   else
569     {
570       /* If we use a LOOP_EXPR here, we have to feed the whole thing
571          back through the main gimplifier to lower it.  Given that we
572          have to gimplify the loop body NOW so that we can resolve
573          break/continue stmts, seems easier to just expand to gotos.  */
574       top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
575     }
576
577   break_block = begin_bc_block (bc_break);
578
579   if (top)
580     {
581       /* If we have an exit condition, then we build an IF with gotos either
582          out of the loop, or to the top of it.  If there's no exit condition,
583          then we just build a jump back to the top.  */
584       exit = build_and_jump (&LABEL_EXPR_LABEL (top));
585       if (cond)
586         {
587           gimplify_condition (&cond);
588           t = build_bc_goto (bc_break);
589           exit = build (COND_EXPR, void_type_node, cond, exit, t);
590           exit = fold (exit);
591           gimplify_stmt (&exit);
592         }
593     }
594   else
595     exit = NULL_TREE;
596
597   cont_block = begin_bc_block (bc_continue);
598
599   gimplify_stmt (&body);
600   if (incr && stmts_are_full_exprs_p ())
601     incr = fold (build1 (CLEANUP_POINT_EXPR, void_type_node, incr));
602   gimplify_stmt (&incr);
603
604   body = finish_bc_block (cont_block, body);
605
606   stmt_list = NULL;
607
608   if (cond_is_first && cond)
609     {
610       entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
611       t = build_and_jump (&LABEL_EXPR_LABEL (entry));
612       append_to_statement_list (t, &stmt_list);
613     }
614   else
615     entry = NULL_TREE;
616
617   append_to_statement_list (top, &stmt_list);
618   append_to_statement_list (body, &stmt_list);
619   append_to_statement_list (incr, &stmt_list);
620   append_to_statement_list (entry, &stmt_list);
621   append_to_statement_list (exit, &stmt_list);
622
623   annotate_all_with_locus (&stmt_list, stmt_locus);
624
625   return finish_bc_block (break_block, stmt_list);
626 }
627
628 /* Gimplify a FOR_STMT node.  Move the stuff in the for-init-stmt into the
629    prequeue and hand off to gimplify_c_loop.  */
630
631 static enum gimplify_status
632 gimplify_for_stmt (tree *stmt_p, tree *pre_p)
633 {
634   tree stmt = *stmt_p;
635
636   if (FOR_INIT_STMT (stmt))
637     {
638       gimplify_stmt (&FOR_INIT_STMT (stmt));
639       append_to_statement_list (FOR_INIT_STMT (stmt), pre_p);
640     }
641   *stmt_p = gimplify_c_loop (FOR_COND (stmt), FOR_BODY (stmt),
642                              FOR_EXPR (stmt), 1);
643
644   return GS_ALL_DONE;
645 }
646
647 /* Gimplify a WHILE_STMT node.  */
648
649 static enum gimplify_status
650 gimplify_while_stmt (tree *stmt_p)
651 {
652   tree stmt = *stmt_p;
653   *stmt_p = gimplify_c_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
654                              NULL_TREE, 1);
655   return GS_ALL_DONE;
656 }
657
658 /* Gimplify a DO_STMT node.  */
659
660 static enum gimplify_status
661 gimplify_do_stmt (tree *stmt_p)
662 {
663   tree stmt = *stmt_p;
664   *stmt_p = gimplify_c_loop (DO_COND (stmt), DO_BODY (stmt),
665                              NULL_TREE, 0);
666   return GS_ALL_DONE;
667 }
668
669 /* Genericize an IF_STMT by turning it into a COND_EXPR.  */
670
671 static enum gimplify_status
672 gimplify_if_stmt (tree *stmt_p)
673 {
674   tree stmt, then_, else_;
675
676   stmt = *stmt_p;
677   then_ = THEN_CLAUSE (stmt);
678   else_ = ELSE_CLAUSE (stmt);
679
680   if (!then_)
681     then_ = build_empty_stmt ();
682   if (!else_)
683     else_ = build_empty_stmt ();
684
685   stmt = build (COND_EXPR, void_type_node, IF_COND (stmt), then_, else_);
686   gimplify_condition (& TREE_OPERAND (stmt, 0));
687   *stmt_p = stmt;
688
689   return GS_OK;
690 }
691
692 /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
693
694 static enum gimplify_status
695 gimplify_switch_stmt (tree *stmt_p)
696 {
697   tree stmt = *stmt_p;
698   tree break_block, body;
699   location_t stmt_locus = input_location;
700
701   break_block = begin_bc_block (bc_break);
702
703   gimplify_condition (&SWITCH_COND (stmt));
704
705   body = SWITCH_BODY (stmt);
706   if (!body)
707     body = build_empty_stmt ();
708
709   *stmt_p = build (SWITCH_EXPR, SWITCH_TYPE (stmt), SWITCH_COND (stmt),
710                    body, NULL_TREE);
711   annotate_with_locus (*stmt_p, stmt_locus);
712   gimplify_stmt (stmt_p);
713
714   *stmt_p = finish_bc_block (break_block, *stmt_p);
715   return GS_ALL_DONE;
716 }
717
718 /* Genericize a RETURN_STMT by turning it into a RETURN_EXPR.  */
719
720 static enum gimplify_status
721 gimplify_return_stmt (tree *stmt_p)
722 {
723   tree expr = RETURN_STMT_EXPR (*stmt_p);
724   expr = build1 (RETURN_EXPR, void_type_node, expr);
725   if (stmts_are_full_exprs_p ())
726     expr = build1 (CLEANUP_POINT_EXPR, void_type_node, expr);
727   *stmt_p = expr;
728   return GS_OK;
729 }
730
731 /* Gimplifies a DECL_STMT node *STMT_P by making any necessary allocation
732    and initialization explicit.  */
733
734 static enum gimplify_status
735 gimplify_decl_stmt (tree *stmt_p)
736 {
737   tree stmt = *stmt_p;
738   tree decl = DECL_STMT_DECL (stmt);
739   tree pre = NULL_TREE;
740   tree post = NULL_TREE;
741
742   if (TREE_TYPE (decl) == error_mark_node)
743     {
744       *stmt_p = NULL;
745       return GS_ERROR;
746     }
747     
748   if (TREE_CODE (decl) == TYPE_DECL)
749     {
750       tree type = TREE_TYPE (decl);
751       if (TYPE_SIZE_UNIT (type)
752           && !TREE_CONSTANT (TYPE_SIZE_UNIT (type)))
753         {
754           /* This is a variable-sized array type.  Simplify its size.  */
755           tree temp = TYPE_SIZE_UNIT (type);
756           gimplify_expr (&temp, &pre, &post, is_gimple_val, fb_rvalue);
757         }
758     }
759
760   if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
761     {
762       tree init = DECL_INITIAL (decl);
763
764       if (!TREE_CONSTANT (DECL_SIZE (decl)))
765         {
766           tree pt_type = build_pointer_type (TREE_TYPE (decl));
767           tree alloc, size;
768
769           /* This is a variable-sized decl.  Simplify its size and mark it
770              for deferred expansion.  Note that mudflap depends on the format
771              of the emitted code: see mx_register_decls().  */
772
773           size = get_initialized_tmp_var (DECL_SIZE_UNIT (decl), &pre, &post);
774           DECL_DEFER_OUTPUT (decl) = 1;
775           alloc = build_function_call_expr
776             (implicit_built_in_decls[BUILT_IN_STACK_ALLOC],
777              tree_cons (NULL_TREE,
778                         build1 (ADDR_EXPR, pt_type, decl),
779                         tree_cons (NULL_TREE, size, NULL_TREE)));
780           append_to_compound_expr (alloc, &pre);
781         }
782
783       if (init && init != error_mark_node)
784         {
785           if (!TREE_STATIC (decl))
786             {
787               /* Do not warn about int x = x; as it is a GCC extension
788                  to turn off this warning but only if warn_init_self
789                  is zero.  */
790               if (init == decl && !warn_init_self)
791                 TREE_NO_WARNING (decl) = 1;
792               
793               DECL_INITIAL (decl) = NULL_TREE;
794               init = build (MODIFY_EXPR, void_type_node, decl, init);
795               if (stmts_are_full_exprs_p ())
796                 init = build1 (CLEANUP_POINT_EXPR, void_type_node, init);
797               append_to_compound_expr (init, &pre);
798             }
799           else
800             {
801               /* We must still examine initializers for static variables
802                  as they may contain a label address.  */
803               walk_tree (&init, force_labels_r, NULL, NULL);
804             }
805         }
806
807       /* This decl isn't mentioned in the enclosing block, so add it to the
808          list of temps.  FIXME it seems a bit of a kludge to say that
809          anonymous artificial vars aren't pushed, but everything else is.  */
810       if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
811         gimple_add_tmp_var (decl);
812     }
813
814   append_to_compound_expr (post, &pre);
815   *stmt_p = pre;
816   return GS_OK;
817 }
818
819 /* Gimplification of expression trees.  */
820
821 /* Gimplify a C99 compound literal expression.  This just means adding the
822    DECL_STMT before the current EXPR_STMT and using its anonymous decl
823    instead.  */
824
825 static enum gimplify_status
826 gimplify_compound_literal_expr (tree *expr_p)
827 {
828   tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (*expr_p);
829   tree decl = DECL_STMT_DECL (decl_s);
830
831   /* This decl isn't mentioned in the enclosing block, so add it to the
832      list of temps.  FIXME it seems a bit of a kludge to say that
833      anonymous artificial vars aren't pushed, but everything else is.  */
834   if (DECL_NAME (decl) == NULL_TREE)
835     gimple_add_tmp_var (decl);
836
837   gimplify_decl_stmt (&decl_s);
838   *expr_p = decl_s ? decl_s : decl;
839   return GS_OK;
840 }
841
842 /* Do C-specific gimplification.  Args are as for gimplify_expr.  */
843
844 int
845 c_gimplify_expr (tree *expr_p, tree *pre_p ATTRIBUTE_UNUSED,
846                  tree *post_p ATTRIBUTE_UNUSED)
847 {
848   enum tree_code code = TREE_CODE (*expr_p);
849
850   if (STATEMENT_CODE_P (code))
851     return c_gimplify_stmt (expr_p);
852
853   switch (code)
854     {
855     case COMPOUND_LITERAL_EXPR:
856       return gimplify_compound_literal_expr (expr_p);
857
858     default:
859       return GS_UNHANDLED;
860     }
861 }