OSDN Git Service

* config/s390/s390.c (s390_emit_epilogue): Always restore registers
[pf3gnuchains/gcc-fork.git] / gcc / c-semantics.c
1 /* This file contains the definitions and documentation for the common
2    tree codes used in the GNU C and C++ compilers (see c-common.def
3    for the standard codes).  
4    Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
5    Written by Benjamin Chelf (chelf@codesourcery.com).
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2, or (at your option) any later
12 version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING.  If not, write to the Free
21 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 02111-1307, USA.  */
23
24 #include "config.h"
25 #include "system.h"
26 #include "tree.h"
27 #include "function.h"
28 #include "splay-tree.h"
29 #include "varray.h"
30 #include "c-common.h"
31 #include "except.h"
32 #include "toplev.h"
33 #include "flags.h"
34 #include "ggc.h"
35 #include "rtl.h"
36 #include "expr.h"
37 #include "output.h"
38 #include "timevar.h"
39
40 /* If non-NULL, the address of a language-specific function for
41    expanding statements.  */
42 void (*lang_expand_stmt) PARAMS ((tree));
43
44 /* If non-NULL, the address of a language-specific function for
45    expanding a DECL_STMT.  After the language-independent cases are
46    handled, this function will be called.  If this function is not
47    defined, it is assumed that declarations other than those for
48    variables and labels do not require any RTL generation.  */
49 void (*lang_expand_decl_stmt) PARAMS ((tree));
50
51 /* Create an empty statement tree rooted at T.  */
52
53 void
54 begin_stmt_tree (t)
55      tree *t;
56 {
57   /* We create a trivial EXPR_STMT so that last_tree is never NULL in
58      what follows.  We remove the extraneous statement in
59      finish_stmt_tree.  */
60   *t = build_nt (EXPR_STMT, void_zero_node);
61   last_tree = *t;
62   last_expr_type = NULL_TREE;
63   last_expr_filename = input_filename;
64 }
65
66 /* T is a statement.  Add it to the statement-tree.  */
67
68 tree
69 add_stmt (t)
70      tree t;
71 {
72   if (input_filename != last_expr_filename)
73     {
74       /* If the filename has changed, also add in a FILE_STMT.  Do a string
75          compare first, though, as it might be an equivalent string.  */
76       int add = (strcmp (input_filename, last_expr_filename) != 0);
77       last_expr_filename = input_filename;
78       if (add)
79         {
80           tree pos = build_nt (FILE_STMT, get_identifier (input_filename));
81           add_stmt (pos);
82         }
83     }
84
85   /* Add T to the statement-tree.  */
86   TREE_CHAIN (last_tree) = t;
87   last_tree = t;
88   
89   /* When we expand a statement-tree, we must know whether or not the
90      statements are full-expressions.  We record that fact here.  */
91   STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p ();
92
93   /* Keep track of the number of statements in this function.  */
94   if (current_function_decl)
95     ++DECL_NUM_STMTS (current_function_decl);
96
97   return t;
98 }
99
100 /* Create a declaration statement for the declaration given by the
101    DECL.  */
102
103 void
104 add_decl_stmt (decl)
105      tree decl;
106 {
107   tree decl_stmt;
108
109   /* We need the type to last until instantiation time.  */
110   decl_stmt = build_stmt (DECL_STMT, decl);
111   add_stmt (decl_stmt); 
112 }
113
114 /* Add a scope-statement to the statement-tree.  BEGIN_P indicates
115    whether this statements opens or closes a scope.  PARTIAL_P is true
116    for a partial scope, i.e, the scope that begins after a label when
117    an object that needs a cleanup is created.  If BEGIN_P is nonzero,
118    returns a new TREE_LIST representing the top of the SCOPE_STMT
119    stack.  The TREE_PURPOSE is the new SCOPE_STMT.  If BEGIN_P is
120    zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT,
121    and whose TREE_PURPOSE is the matching SCOPE_STMT with
122    SCOPE_BEGIN_P set.  */
123
124 tree
125 add_scope_stmt (begin_p, partial_p)
126      int begin_p;
127      int partial_p;
128 {
129   tree *stack_ptr = current_scope_stmt_stack ();
130   tree ss;
131   tree top = *stack_ptr;
132
133   /* Build the statement.  */
134   ss = build_stmt (SCOPE_STMT, NULL_TREE);
135   SCOPE_BEGIN_P (ss) = begin_p;
136   SCOPE_PARTIAL_P (ss) = partial_p;
137
138   /* Keep the scope stack up to date.  */
139   if (begin_p)
140     {
141       top = tree_cons (ss, NULL_TREE, top);
142       *stack_ptr = top;
143     }
144   else
145     {
146       TREE_VALUE (top) = ss;
147       *stack_ptr = TREE_CHAIN (top);
148     }
149
150   /* Add the new statement to the statement-tree.  */
151   add_stmt (ss);
152
153   return top;
154 }
155
156 /* Finish the statement tree rooted at T.  */
157
158 void
159 finish_stmt_tree (t)
160      tree *t;
161 {
162   tree stmt;
163   
164   /* Remove the fake extra statement added in begin_stmt_tree.  */
165   stmt = TREE_CHAIN (*t);
166   *t = stmt;
167   last_tree = NULL_TREE;
168
169   if (cfun && stmt)
170     {
171       /* The line-number recorded in the outermost statement in a function
172          is the line number of the end of the function.  */
173       STMT_LINENO (stmt) = lineno;
174       STMT_LINENO_FOR_FN_P (stmt) = 1;
175     }
176 }
177
178 /* Build a generic statement based on the given type of node and
179    arguments. Similar to `build_nt', except that we set
180    STMT_LINENO to be the current line number.  */
181 /* ??? This should be obsolete with the lineno_stmt productions
182    in the grammar.  */
183
184 tree
185 build_stmt VPARAMS ((enum tree_code code, ...))
186 {
187   tree t;
188   int length;
189   int i;
190
191   VA_OPEN (p, code);
192   VA_FIXEDARG (p, enum tree_code, code);
193
194   t = make_node (code);
195   length = TREE_CODE_LENGTH (code);
196   STMT_LINENO (t) = lineno;
197
198   for (i = 0; i < length; i++)
199     TREE_OPERAND (t, i) = va_arg (p, tree);
200
201   VA_CLOSE (p);
202   return t;
203 }
204
205 /* Some statements, like for-statements or if-statements, require a
206    condition.  This condition can be a declaration.  If T is such a
207    declaration it is processed, and an expression appropriate to use
208    as the condition is returned.  Otherwise, T itself is returned.  */
209
210 tree
211 expand_cond (t)
212      tree t;
213 {
214   if (t && TREE_CODE (t) == TREE_LIST)
215     {
216       expand_stmt (TREE_PURPOSE (t));
217       return TREE_VALUE (t);
218     }
219   else 
220     return t;
221 }
222
223 /* Create RTL for the local static variable DECL.  */
224
225 void
226 make_rtl_for_local_static (decl)
227      tree decl;
228 {
229   const char *asmspec = NULL;
230
231   /* If we inlined this variable, we could see it's declaration
232      again.  */
233   if (TREE_ASM_WRITTEN (decl))
234     return;
235
236   /* If the DECL_ASSEMBLER_NAME is not the same as the DECL_NAME, then
237      either we already created RTL for this DECL (and since it was a
238      local variable, its DECL_ASSEMBLER_NAME got hacked up to prevent
239      clashes with other local statics with the same name by a previous
240      call to make_decl_rtl), or the user explicitly requested a
241      particular assembly name for this variable, using the GNU
242      extension for this purpose:
243
244        int i asm ("j");
245
246      There's no way to know which case we're in, here.  But, it turns
247      out we're safe.  If there's already RTL, then
248      rest_of_decl_compilation ignores the ASMSPEC parameter, so we
249      may as well not pass it in.  If there isn't RTL, then we didn't
250      already create RTL, which means that the modification to
251      DECL_ASSEMBLER_NAME came only via the explicit extension.  */
252   if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)
253       && !DECL_RTL_SET_P (decl))
254     asmspec = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
255
256   rest_of_decl_compilation (decl, asmspec, /*top_level=*/0, /*at_end=*/0);
257 }
258
259 /* Let the back-end know about DECL.  */
260
261 void
262 emit_local_var (decl)
263      tree decl;
264 {
265   /* Create RTL for this variable.  */
266   if (!DECL_RTL_SET_P (decl))
267     {
268       if (DECL_C_HARD_REGISTER (decl))
269         /* The user specified an assembler name for this variable.
270            Set that up now.  */
271         rest_of_decl_compilation
272           (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
273            /*top_level=*/0, /*at_end=*/0);
274       else
275         expand_decl (decl);
276     }
277
278   /* Actually do the initialization.  */
279   if (stmts_are_full_exprs_p ())
280     expand_start_target_temps ();
281
282   expand_decl_init (decl);
283
284   if (stmts_are_full_exprs_p ())
285     expand_end_target_temps ();
286 }
287
288 /* Helper for generating the RTL at the beginning of a scope.  */
289
290 void
291 genrtl_do_pushlevel ()
292 {
293   emit_line_note (input_filename, lineno);
294   clear_last_expr ();
295 }
296
297 /* Generate the RTL for DESTINATION, which is a GOTO_STMT.  */
298
299 void
300 genrtl_goto_stmt (destination)
301      tree destination;
302 {
303   if (TREE_CODE (destination) == IDENTIFIER_NODE)
304     abort ();
305   
306   /* We warn about unused labels with -Wunused.  That means we have to
307      mark the used labels as used.  */
308   if (TREE_CODE (destination) == LABEL_DECL)
309     TREE_USED (destination) = 1;
310   
311   emit_line_note (input_filename, lineno);
312   
313   if (TREE_CODE (destination) == LABEL_DECL)
314     {
315       label_rtx (destination);
316       expand_goto (destination); 
317     }
318   else
319     expand_computed_goto (destination);
320 }
321
322 /* Generate the RTL for EXPR, which is an EXPR_STMT.  Provided just
323    for backward compatibility.  genrtl_expr_stmt_value() should be
324    used for new code.  */
325
326 void
327 genrtl_expr_stmt (expr)
328      tree expr;
329 {
330   genrtl_expr_stmt_value (expr, -1, 1);
331 }
332
333 /* Generate the RTL for EXPR, which is an EXPR_STMT.  WANT_VALUE tells
334    whether to (1) save the value of the expression, (0) discard it or
335    (-1) use expr_stmts_for_value to tell.  The use of -1 is
336    deprecated, and retained only for backward compatibility.
337    MAYBE_LAST is non-zero if this EXPR_STMT might be the last statement
338    in expression statement.  */
339
340 void 
341 genrtl_expr_stmt_value (expr, want_value, maybe_last)
342      tree expr;
343      int want_value, maybe_last;
344 {
345   if (expr != NULL_TREE)
346     {
347       emit_line_note (input_filename, lineno);
348       
349       if (stmts_are_full_exprs_p ())
350         expand_start_target_temps ();
351       
352       if (expr != error_mark_node)
353         expand_expr_stmt_value (expr, want_value, maybe_last);
354       
355       if (stmts_are_full_exprs_p ())
356         expand_end_target_temps ();
357     }
358 }
359
360 /* Generate the RTL for T, which is a DECL_STMT.  */
361
362 void
363 genrtl_decl_stmt (t)
364      tree t;
365 {
366   tree decl;
367   emit_line_note (input_filename, lineno);
368   decl = DECL_STMT_DECL (t);
369   /* If this is a declaration for an automatic local
370      variable, initialize it.  Note that we might also see a
371      declaration for a namespace-scope object (declared with
372      `extern').  We don't have to handle the initialization
373      of those objects here; they can only be declarations,
374      rather than definitions.  */
375   if (TREE_CODE (decl) == VAR_DECL 
376       && !TREE_STATIC (decl)
377       && !DECL_EXTERNAL (decl))
378     {
379       /* Let the back-end know about this variable.  */
380       if (!anon_aggr_type_p (TREE_TYPE (decl)))
381         emit_local_var (decl);
382       else
383         expand_anon_union_decl (decl, NULL_TREE, 
384                                 DECL_ANON_UNION_ELEMS (decl));
385     }
386   else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
387     make_rtl_for_local_static (decl);
388   else if (TREE_CODE (decl) == LABEL_DECL 
389            && C_DECLARED_LABEL_FLAG (decl))
390     declare_nonlocal_label (decl);
391   else if (lang_expand_decl_stmt)
392     (*lang_expand_decl_stmt) (t);
393 }
394
395 /* Generate the RTL for T, which is an IF_STMT.  */
396
397 void
398 genrtl_if_stmt (t)
399      tree t;
400 {
401   tree cond;
402   genrtl_do_pushlevel ();
403   cond = expand_cond (IF_COND (t));
404   emit_line_note (input_filename, lineno);
405   expand_start_cond (cond, 0);
406   if (THEN_CLAUSE (t))
407     expand_stmt (THEN_CLAUSE (t));
408   if (ELSE_CLAUSE (t))
409     {
410       expand_start_else ();
411       expand_stmt (ELSE_CLAUSE (t));
412     }
413   expand_end_cond ();
414 }
415
416 /* Generate the RTL for T, which is a WHILE_STMT.  */
417
418 void
419 genrtl_while_stmt (t)
420      tree t;
421 {
422   tree cond;
423   emit_nop ();
424   emit_line_note (input_filename, lineno);
425   expand_start_loop (1); 
426   genrtl_do_pushlevel ();
427
428   cond = expand_cond (WHILE_COND (t));
429   emit_line_note (input_filename, lineno);
430   expand_exit_loop_top_cond (0, cond);
431   genrtl_do_pushlevel ();
432   
433   expand_stmt (WHILE_BODY (t));
434
435   expand_end_loop ();
436 }
437
438 /* Generate the RTL for T, which is a DO_STMT.  */
439
440 void
441 genrtl_do_stmt (t)
442      tree t;
443 {
444   tree cond = DO_COND (t);
445
446   /* Recognize the common special-case of do { ... } while (0) and do
447      not emit the loop widgetry in this case.  In particular this
448      avoids cluttering the rtl with dummy loop notes, which can affect
449      alignment of adjacent labels.  */
450   if (integer_zerop (cond))
451     {
452       expand_start_null_loop ();
453       expand_stmt (DO_BODY (t));
454       expand_end_null_loop ();
455     }
456   else
457     {
458       emit_nop ();
459       emit_line_note (input_filename, lineno);
460       expand_start_loop_continue_elsewhere (1);
461
462       expand_stmt (DO_BODY (t));
463
464       expand_loop_continue_here ();
465       cond = expand_cond (cond);
466       emit_line_note (input_filename, lineno);
467       expand_exit_loop_if_false (0, cond);
468       expand_end_loop ();
469     }
470 }
471
472 /* Build the node for a return statement and return it.  */
473
474 tree
475 build_return_stmt (expr)
476      tree expr;
477 {
478   return (build_stmt (RETURN_STMT, expr));
479 }
480
481 /* Generate the RTL for STMT, which is a RETURN_STMT.  */
482
483 void
484 genrtl_return_stmt (stmt)
485      tree stmt;
486 {
487   tree expr;
488
489   expr = RETURN_EXPR (stmt);
490
491   emit_line_note (input_filename, lineno);
492   if (!expr)
493     expand_null_return ();
494   else
495     {
496       expand_start_target_temps ();
497       expand_return (expr);
498       expand_end_target_temps ();
499     }
500 }
501
502 /* Generate the RTL for T, which is a FOR_STMT.  */
503
504 void
505 genrtl_for_stmt (t)
506      tree t;
507 {
508   tree cond;
509   const char *saved_filename;
510   int saved_lineno;
511
512   if (NEW_FOR_SCOPE_P (t))
513     genrtl_do_pushlevel ();
514
515   expand_stmt (FOR_INIT_STMT (t));
516
517   /* Expand the initialization.  */
518   emit_nop ();
519   emit_line_note (input_filename, lineno);
520   expand_start_loop_continue_elsewhere (1); 
521   genrtl_do_pushlevel ();
522   cond = expand_cond (FOR_COND (t));
523
524   /* Save the filename and line number so that we expand the FOR_EXPR
525      we can reset them back to the saved values.  */
526   saved_filename = input_filename;
527   saved_lineno = lineno;
528
529   /* Expand the condition.  */
530   emit_line_note (input_filename, lineno);
531   if (cond)
532     expand_exit_loop_top_cond (0, cond);
533
534   /* Expand the body.  */
535   genrtl_do_pushlevel ();
536   expand_stmt (FOR_BODY (t));
537
538   /* Expand the increment expression.  */
539   input_filename = saved_filename;
540   lineno = saved_lineno;
541   emit_line_note (input_filename, lineno);
542   expand_loop_continue_here ();
543   if (FOR_EXPR (t))
544     genrtl_expr_stmt (FOR_EXPR (t));
545   expand_end_loop ();
546 }
547
548 /* Build a break statement node and return it.  */
549
550 tree
551 build_break_stmt ()
552 {
553   return (build_stmt (BREAK_STMT));
554 }
555
556 /* Generate the RTL for a BREAK_STMT.  */
557
558 void
559 genrtl_break_stmt ()
560 {
561   emit_line_note (input_filename, lineno);
562   if ( ! expand_exit_something ())
563     error ("break statement not within loop or switch");
564 }
565
566 /* Build a continue statement node and return it.  */
567
568 tree
569 build_continue_stmt ()
570 {
571   return (build_stmt (CONTINUE_STMT));
572 }
573
574 /* Generate the RTL for a CONTINUE_STMT.  */
575
576 void
577 genrtl_continue_stmt ()
578 {
579   emit_line_note (input_filename, lineno);
580   if (! expand_continue_loop (0))
581     error ("continue statement not within a loop");   
582 }
583
584 /* Generate the RTL for T, which is a SCOPE_STMT.  */
585
586 void
587 genrtl_scope_stmt (t)
588      tree t;
589 {
590   tree block = SCOPE_STMT_BLOCK (t);
591
592   if (!SCOPE_NO_CLEANUPS_P (t))
593     {
594       if (SCOPE_BEGIN_P (t))
595         expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t), block);
596       else if (SCOPE_END_P (t))
597         expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), 0);
598     }
599   else if (!SCOPE_NULLIFIED_P (t))
600     {
601       rtx note = emit_note (NULL,
602                             (SCOPE_BEGIN_P (t) 
603                              ? NOTE_INSN_BLOCK_BEG
604                              : NOTE_INSN_BLOCK_END));
605       NOTE_BLOCK (note) = block;
606     }
607
608   /* If we're at the end of a scope that contains inlined nested
609      functions, we have to decide whether or not to write them out.  */
610   if (block && SCOPE_END_P (t))
611     {
612       tree fn;
613
614       for (fn = BLOCK_VARS (block); fn; fn = TREE_CHAIN (fn))
615         {
616           if (TREE_CODE (fn) == FUNCTION_DECL 
617               && DECL_CONTEXT (fn) == current_function_decl
618               && !TREE_ASM_WRITTEN (fn)
619               && TREE_ADDRESSABLE (fn))
620             {
621               push_function_context ();
622               output_inline_function (fn);
623               pop_function_context ();
624             }
625         }
626     }
627 }
628
629 /* Generate the RTL for T, which is a SWITCH_STMT.  */
630
631 void
632 genrtl_switch_stmt (t)
633      tree t;
634 {
635   tree cond;
636   genrtl_do_pushlevel ();
637  
638   cond = expand_cond (SWITCH_COND (t));
639   if (cond == error_mark_node)
640     /* The code is in error, but we don't want expand_end_case to
641        crash.  */
642     cond = boolean_false_node;
643
644   emit_line_note (input_filename, lineno);
645   expand_start_case (1, cond, TREE_TYPE (cond), "switch statement");
646   expand_stmt (SWITCH_BODY (t));
647   expand_end_case_type (cond, SWITCH_TYPE (t));
648 }
649
650 /* Create a CASE_LABEL tree node and return it.  */
651
652 tree
653 build_case_label (low_value, high_value, label_decl)
654      tree low_value;
655      tree high_value;
656      tree label_decl;
657 {
658   return build_stmt (CASE_LABEL, low_value, high_value, label_decl);
659 }
660
661
662 /* Generate the RTL for a CASE_LABEL.  */
663
664 void 
665 genrtl_case_label (case_label)
666      tree case_label;
667 {
668   tree duplicate;
669   tree cleanup;
670
671   cleanup = last_cleanup_this_contour ();
672   if (cleanup)
673     {
674       static int explained = 0;
675       warning_with_decl (TREE_PURPOSE (cleanup), 
676                          "destructor needed for `%#D'");
677       warning ("where case label appears here");
678       if (!explained)
679         {
680           warning ("(enclose actions of previous case statements requiring destructors in their own scope.)");
681           explained = 1;
682         }
683     }
684
685   add_case_node (CASE_LOW (case_label), CASE_HIGH (case_label), 
686                  CASE_LABEL_DECL (case_label), &duplicate);
687 }
688
689 /* Generate the RTL for T, which is a COMPOUND_STMT.  */
690
691 void
692 genrtl_compound_stmt (t)
693     tree t;
694 {
695 #ifdef ENABLE_CHECKING
696   struct nesting *n = current_nesting_level ();
697 #endif
698
699   expand_stmt (COMPOUND_BODY (t));
700
701 #ifdef ENABLE_CHECKING
702   /* Make sure that we've pushed and popped the same number of levels.  */
703   if (!COMPOUND_STMT_NO_SCOPE (t) && n != current_nesting_level ())
704     abort ();
705 #endif
706 }
707
708 /* Generate the RTL for an ASM_STMT.  */
709
710 void
711 genrtl_asm_stmt (cv_qualifier, string, output_operands,
712                  input_operands, clobbers, asm_input_p)
713      tree cv_qualifier;
714      tree string;
715      tree output_operands;
716      tree input_operands;
717      tree clobbers;
718      int asm_input_p;
719 {
720   if (cv_qualifier != NULL_TREE
721       && cv_qualifier != ridpointers[(int) RID_VOLATILE])
722     {
723       warning ("%s qualifier ignored on asm",
724                IDENTIFIER_POINTER (cv_qualifier));
725       cv_qualifier = NULL_TREE;
726     }
727
728   emit_line_note (input_filename, lineno);
729   if (asm_input_p)
730     expand_asm (string);
731   else
732     c_expand_asm_operands (string, output_operands, input_operands, 
733                            clobbers, cv_qualifier != NULL_TREE,
734                            input_filename, lineno);
735 }
736
737 /* Generate the RTL for a DECL_CLEANUP.  */
738
739 void 
740 genrtl_decl_cleanup (t)
741      tree t;
742 {
743   tree decl = CLEANUP_DECL (t);
744   if (!decl || (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node))
745     expand_decl_cleanup_eh (decl, CLEANUP_EXPR (t), CLEANUP_EH_ONLY (t));
746 }
747
748 /* We're about to expand T, a statement.  Set up appropriate context
749    for the substitution.  */
750
751 void
752 prep_stmt (t)
753      tree t;
754 {
755   if (!STMT_LINENO_FOR_FN_P (t))
756     lineno = STMT_LINENO (t);
757   current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
758 }
759
760 /* Generate the RTL for the statement T, its substatements, and any
761    other statements at its nesting level.  */
762
763 void
764 expand_stmt (t)
765      tree t;
766 {
767   while (t && t != error_mark_node)
768     {
769       int saved_stmts_are_full_exprs_p;
770
771       /* Set up context appropriately for handling this statement.  */
772       saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
773       prep_stmt (t);
774
775       switch (TREE_CODE (t))
776         {
777         case FILE_STMT:
778           input_filename = FILE_STMT_FILENAME (t);
779           break;
780
781         case RETURN_STMT:
782           genrtl_return_stmt (t);
783           break;
784
785         case EXPR_STMT:
786           genrtl_expr_stmt_value (EXPR_STMT_EXPR (t), TREE_ADDRESSABLE (t),
787                                   TREE_CHAIN (t) == NULL
788                                   || (TREE_CODE (TREE_CHAIN (t)) == SCOPE_STMT
789                                       && TREE_CHAIN (TREE_CHAIN (t)) == NULL));
790           break;
791
792         case DECL_STMT:
793           genrtl_decl_stmt (t);
794           break;
795
796         case FOR_STMT:
797           genrtl_for_stmt (t);
798           break;
799
800         case WHILE_STMT:
801           genrtl_while_stmt (t);
802           break;
803
804         case DO_STMT:
805           genrtl_do_stmt (t);
806           break;
807
808         case IF_STMT:
809           genrtl_if_stmt (t);
810           break;
811
812         case COMPOUND_STMT:
813           genrtl_compound_stmt (t);
814           break;
815
816         case BREAK_STMT:
817           genrtl_break_stmt ();
818           break;
819
820         case CONTINUE_STMT:
821           genrtl_continue_stmt ();
822           break;
823
824         case SWITCH_STMT:
825           genrtl_switch_stmt (t);
826           break;
827
828         case CASE_LABEL:
829           genrtl_case_label (t);
830           break;
831
832         case LABEL_STMT:
833           expand_label (LABEL_STMT_LABEL (t));
834           break;
835
836         case GOTO_STMT:
837           genrtl_goto_stmt (GOTO_DESTINATION (t));
838           break;
839
840         case ASM_STMT:
841           genrtl_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t),
842                            ASM_OUTPUTS (t), ASM_INPUTS (t),
843                            ASM_CLOBBERS (t), ASM_INPUT_P (t));
844           break;
845
846         case SCOPE_STMT:
847           genrtl_scope_stmt (t);
848           break;
849
850         case CLEANUP_STMT:
851           genrtl_decl_cleanup (t);
852           break;
853
854         default:
855           if (lang_expand_stmt)
856             (*lang_expand_stmt) (t);
857           else 
858             abort ();
859           break;
860         }
861
862       /* Restore saved state.  */
863       current_stmt_tree ()->stmts_are_full_exprs_p
864         = saved_stmts_are_full_exprs_p;
865
866       /* Go on to the next statement in this scope.  */
867       t = TREE_CHAIN (t);
868     }
869 }