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