c-semantics.c revision 117395
1228753Smm/* This file contains the definitions and documentation for the common
2228753Smm   tree codes used in the GNU C and C++ compilers (see c-common.def
3228753Smm   for the standard codes).
4228753Smm   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
5228753Smm   Written by Benjamin Chelf (chelf@codesourcery.com).
6228753Smm
7228753SmmThis file is part of GCC.
8228753Smm
9228753SmmGCC is free software; you can redistribute it and/or modify it under
10228753Smmthe terms of the GNU General Public License as published by the Free
11228753SmmSoftware Foundation; either version 2, or (at your option) any later
12228753Smmversion.
13228753Smm
14228753SmmGCC is distributed in the hope that it will be useful, but WITHOUT ANY
15228753SmmWARRANTY; without even the implied warranty of MERCHANTABILITY or
16228753SmmFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17228753Smmfor more details.
18228753Smm
19228753SmmYou should have received a copy of the GNU General Public License
20228753Smmalong with GCC; see the file COPYING.  If not, write to the Free
21228753SmmSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
22228753Smm02111-1307, USA.  */
23228753Smm
24228753Smm#include "config.h"
25228753Smm#include "system.h"
26228753Smm#include "tree.h"
27228753Smm#include "function.h"
28228753Smm#include "splay-tree.h"
29228753Smm#include "varray.h"
30228753Smm#include "c-common.h"
31228753Smm#include "except.h"
32228753Smm#include "toplev.h"
33228753Smm#include "flags.h"
34228753Smm#include "ggc.h"
35228753Smm#include "rtl.h"
36228753Smm#include "expr.h"
37228753Smm#include "output.h"
38228753Smm#include "timevar.h"
39228753Smm#include "predict.h"
40228753Smm
41228753Smm/* If non-NULL, the address of a language-specific function for
42228753Smm   expanding statements.  */
43228753Smmvoid (*lang_expand_stmt) PARAMS ((tree));
44228753Smm
45228753Smm/* If non-NULL, the address of a language-specific function for
46228753Smm   expanding a DECL_STMT.  After the language-independent cases are
47228753Smm   handled, this function will be called.  If this function is not
48228753Smm   defined, it is assumed that declarations other than those for
49228753Smm   variables and labels do not require any RTL generation.  */
50228753Smmvoid (*lang_expand_decl_stmt) PARAMS ((tree));
51228753Smm
52228753Smm/* Create an empty statement tree rooted at T.  */
53228753Smm
54228753Smmvoid
55228753Smmbegin_stmt_tree (t)
56228753Smm     tree *t;
57228753Smm{
58228753Smm  /* We create a trivial EXPR_STMT so that last_tree is never NULL in
59228753Smm     what follows.  We remove the extraneous statement in
60228753Smm     finish_stmt_tree.  */
61228753Smm  *t = build_nt (EXPR_STMT, void_zero_node);
62228753Smm  last_tree = *t;
63228753Smm  last_expr_type = NULL_TREE;
64228753Smm  last_expr_filename = input_filename;
65228753Smm}
66228753Smm
67228753Smm/* T is a statement.  Add it to the statement-tree.  */
68228753Smm
69228753Smmtree
70228753Smmadd_stmt (t)
71228753Smm     tree t;
72228753Smm{
73228753Smm  if (input_filename != last_expr_filename)
74228753Smm    {
75228753Smm      /* If the filename has changed, also add in a FILE_STMT.  Do a string
76228753Smm	 compare first, though, as it might be an equivalent string.  */
77228753Smm      int add = (strcmp (input_filename, last_expr_filename) != 0);
78228753Smm      last_expr_filename = input_filename;
79228753Smm      if (add)
80228753Smm	{
81228753Smm	  tree pos = build_nt (FILE_STMT, get_identifier (input_filename));
82228753Smm	  add_stmt (pos);
83228753Smm	}
84228753Smm    }
85228753Smm
86228753Smm  /* Add T to the statement-tree.  */
87228753Smm  TREE_CHAIN (last_tree) = t;
88228753Smm  last_tree = t;
89228753Smm
90228753Smm  /* When we expand a statement-tree, we must know whether or not the
91228753Smm     statements are full-expressions.  We record that fact here.  */
92228753Smm  STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p ();
93228753Smm
94228753Smm  /* Keep track of the number of statements in this function.  */
95228753Smm  if (current_function_decl)
96228753Smm    ++DECL_NUM_STMTS (current_function_decl);
97228753Smm
98228753Smm  return t;
99228753Smm}
100228753Smm
101228753Smm/* Create a declaration statement for the declaration given by the
102228753Smm   DECL.  */
103228753Smm
104228753Smmvoid
105228753Smmadd_decl_stmt (decl)
106228753Smm     tree decl;
107228753Smm{
108228753Smm  tree decl_stmt;
109228753Smm
110228753Smm  /* We need the type to last until instantiation time.  */
111228753Smm  decl_stmt = build_stmt (DECL_STMT, decl);
112228753Smm  add_stmt (decl_stmt);
113228753Smm}
114228753Smm
115228753Smm/* Add a scope-statement to the statement-tree.  BEGIN_P indicates
116228753Smm   whether this statements opens or closes a scope.  PARTIAL_P is true
117228753Smm   for a partial scope, i.e, the scope that begins after a label when
118228753Smm   an object that needs a cleanup is created.  If BEGIN_P is nonzero,
119228753Smm   returns a new TREE_LIST representing the top of the SCOPE_STMT
120228753Smm   stack.  The TREE_PURPOSE is the new SCOPE_STMT.  If BEGIN_P is
121228753Smm   zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT,
122228753Smm   and whose TREE_PURPOSE is the matching SCOPE_STMT with
123228753Smm   SCOPE_BEGIN_P set.  */
124228753Smm
125228753Smmtree
126228753Smmadd_scope_stmt (begin_p, partial_p)
127228753Smm     int begin_p;
128228753Smm     int partial_p;
129228753Smm{
130228753Smm  tree *stack_ptr = current_scope_stmt_stack ();
131228753Smm  tree ss;
132228753Smm  tree top = *stack_ptr;
133228753Smm
134228753Smm  /* Build the statement.  */
135228753Smm  ss = build_stmt (SCOPE_STMT, NULL_TREE);
136228753Smm  SCOPE_BEGIN_P (ss) = begin_p;
137228753Smm  SCOPE_PARTIAL_P (ss) = partial_p;
138228753Smm
139228753Smm  /* Keep the scope stack up to date.  */
140228753Smm  if (begin_p)
141228753Smm    {
142228753Smm      top = tree_cons (ss, NULL_TREE, top);
143228753Smm      *stack_ptr = top;
144228753Smm    }
145228753Smm  else
146228753Smm    {
147228753Smm      TREE_VALUE (top) = ss;
148228753Smm      *stack_ptr = TREE_CHAIN (top);
149228753Smm    }
150228753Smm
151228753Smm  /* Add the new statement to the statement-tree.  */
152228753Smm  add_stmt (ss);
153228753Smm
154228753Smm  return top;
155228753Smm}
156228753Smm
157228753Smm/* Finish the statement tree rooted at T.  */
158228753Smm
159228753Smmvoid
160228753Smmfinish_stmt_tree (t)
161228753Smm     tree *t;
162228753Smm{
163228753Smm  tree stmt;
164228753Smm
165228753Smm  /* Remove the fake extra statement added in begin_stmt_tree.  */
166228753Smm  stmt = TREE_CHAIN (*t);
167228753Smm  *t = stmt;
168228753Smm  last_tree = NULL_TREE;
169228753Smm
170228753Smm  if (cfun && stmt)
171228753Smm    {
172228753Smm      /* The line-number recorded in the outermost statement in a function
173228753Smm	 is the line number of the end of the function.  */
174228753Smm      STMT_LINENO (stmt) = lineno;
175228753Smm      STMT_LINENO_FOR_FN_P (stmt) = 1;
176228753Smm    }
177228753Smm}
178228753Smm
179228753Smm/* Build a generic statement based on the given type of node and
180228753Smm   arguments. Similar to `build_nt', except that we set
181228753Smm   STMT_LINENO to be the current line number.  */
182228753Smm/* ??? This should be obsolete with the lineno_stmt productions
183228753Smm   in the grammar.  */
184228753Smm
185228753Smmtree
186228753Smmbuild_stmt VPARAMS ((enum tree_code code, ...))
187228753Smm{
188228753Smm  tree t;
189228753Smm  int length;
190228753Smm  int i;
191228753Smm
192228753Smm  VA_OPEN (p, code);
193228753Smm  VA_FIXEDARG (p, enum tree_code, code);
194228753Smm
195228753Smm  t = make_node (code);
196228753Smm  length = TREE_CODE_LENGTH (code);
197228753Smm  STMT_LINENO (t) = lineno;
198228753Smm
199228753Smm  for (i = 0; i < length; i++)
200228753Smm    TREE_OPERAND (t, i) = va_arg (p, tree);
201228753Smm
202228753Smm  VA_CLOSE (p);
203228753Smm  return t;
204228753Smm}
205228753Smm
206228753Smm/* Some statements, like for-statements or if-statements, require a
207228753Smm   condition.  This condition can be a declaration.  If T is such a
208228753Smm   declaration it is processed, and an expression appropriate to use
209228753Smm   as the condition is returned.  Otherwise, T itself is returned.  */
210228753Smm
211228753Smmtree
212228753Smmexpand_cond (t)
213228753Smm     tree t;
214228753Smm{
215228753Smm  if (t && TREE_CODE (t) == TREE_LIST)
216228753Smm    {
217228753Smm      expand_stmt (TREE_PURPOSE (t));
218228753Smm      return TREE_VALUE (t);
219228753Smm    }
220228753Smm  else
221228753Smm    return t;
222228753Smm}
223228753Smm
224228753Smm/* Create RTL for the local static variable DECL.  */
225228753Smm
226228753Smmvoid
227228753Smmmake_rtl_for_local_static (decl)
228228753Smm     tree decl;
229228753Smm{
230228753Smm  const char *asmspec = NULL;
231228753Smm
232228753Smm  /* If we inlined this variable, we could see it's declaration
233228753Smm     again.  */
234228753Smm  if (TREE_ASM_WRITTEN (decl))
235228753Smm    return;
236228753Smm
237228753Smm  /* If the DECL_ASSEMBLER_NAME is not the same as the DECL_NAME, then
238228753Smm     either we already created RTL for this DECL (and since it was a
239228753Smm     local variable, its DECL_ASSEMBLER_NAME got hacked up to prevent
240228753Smm     clashes with other local statics with the same name by a previous
241228753Smm     call to make_decl_rtl), or the user explicitly requested a
242228753Smm     particular assembly name for this variable, using the GNU
243228753Smm     extension for this purpose:
244228753Smm
245228753Smm       int i asm ("j");
246228753Smm
247228753Smm     There's no way to know which case we're in, here.  But, it turns
248228753Smm     out we're safe.  If there's already RTL, then
249228753Smm     rest_of_decl_compilation ignores the ASMSPEC parameter, so we
250228753Smm     may as well not pass it in.  If there isn't RTL, then we didn't
251228753Smm     already create RTL, which means that the modification to
252228753Smm     DECL_ASSEMBLER_NAME came only via the explicit extension.  */
253228753Smm  if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)
254228753Smm      && !DECL_RTL_SET_P (decl))
255228753Smm    asmspec = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
256228753Smm
257228753Smm  rest_of_decl_compilation (decl, asmspec, /*top_level=*/0, /*at_end=*/0);
258228753Smm}
259228753Smm
260228753Smm/* Let the back-end know about DECL.  */
261228753Smm
262228753Smmvoid
263228753Smmemit_local_var (decl)
264228753Smm     tree decl;
265228753Smm{
266228753Smm  /* Create RTL for this variable.  */
267228753Smm  if (!DECL_RTL_SET_P (decl))
268228753Smm    {
269228753Smm      if (DECL_C_HARD_REGISTER (decl))
270228753Smm	/* The user specified an assembler name for this variable.
271228753Smm	   Set that up now.  */
272228753Smm	rest_of_decl_compilation
273228753Smm	  (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
274228753Smm	   /*top_level=*/0, /*at_end=*/0);
275228753Smm      else
276228753Smm	expand_decl (decl);
277228753Smm    }
278228753Smm
279228753Smm  /* Actually do the initialization.  */
280228753Smm  if (stmts_are_full_exprs_p ())
281228753Smm    expand_start_target_temps ();
282228753Smm
283228753Smm  expand_decl_init (decl);
284228753Smm
285228753Smm  if (stmts_are_full_exprs_p ())
286228753Smm    expand_end_target_temps ();
287228753Smm}
288228753Smm
289228753Smm/* Helper for generating the RTL at the beginning of a scope.  */
290228753Smm
291228753Smmvoid
292228753Smmgenrtl_do_pushlevel ()
293228753Smm{
294228753Smm  emit_line_note (input_filename, lineno);
295228753Smm  clear_last_expr ();
296228753Smm}
297228753Smm
298228753Smm/* Generate the RTL for DESTINATION, which is a GOTO_STMT.  */
299228753Smm
300228753Smmvoid
301228753Smmgenrtl_goto_stmt (destination)
302228753Smm     tree destination;
303228753Smm{
304228753Smm  if (TREE_CODE (destination) == IDENTIFIER_NODE)
305228753Smm    abort ();
306228753Smm
307228753Smm  /* We warn about unused labels with -Wunused.  That means we have to
308228753Smm     mark the used labels as used.  */
309228753Smm  if (TREE_CODE (destination) == LABEL_DECL)
310228753Smm    TREE_USED (destination) = 1;
311228753Smm
312228753Smm  emit_line_note (input_filename, lineno);
313228753Smm
314228753Smm  if (TREE_CODE (destination) == LABEL_DECL)
315228753Smm    {
316228753Smm      label_rtx (destination);
317228753Smm      expand_goto (destination);
318228753Smm    }
319228753Smm  else
320228753Smm    expand_computed_goto (destination);
321228753Smm}
322228753Smm
323228753Smm/* Generate the RTL for EXPR, which is an EXPR_STMT.  Provided just
324228753Smm   for backward compatibility.  genrtl_expr_stmt_value() should be
325228753Smm   used for new code.  */
326228753Smm
327228753Smmvoid
328228753Smmgenrtl_expr_stmt (expr)
329228753Smm     tree expr;
330228753Smm{
331228753Smm  genrtl_expr_stmt_value (expr, -1, 1);
332228753Smm}
333228753Smm
334228753Smm/* Generate the RTL for EXPR, which is an EXPR_STMT.  WANT_VALUE tells
335228753Smm   whether to (1) save the value of the expression, (0) discard it or
336228753Smm   (-1) use expr_stmts_for_value to tell.  The use of -1 is
337228753Smm   deprecated, and retained only for backward compatibility.
338228753Smm   MAYBE_LAST is nonzero if this EXPR_STMT might be the last statement
339228753Smm   in expression statement.  */
340228753Smm
341228753Smmvoid
342228753Smmgenrtl_expr_stmt_value (expr, want_value, maybe_last)
343228753Smm     tree expr;
344228753Smm     int want_value, maybe_last;
345228753Smm{
346228753Smm  if (expr != NULL_TREE)
347228753Smm    {
348228753Smm      emit_line_note (input_filename, lineno);
349228753Smm
350228753Smm      if (stmts_are_full_exprs_p ())
351228753Smm	expand_start_target_temps ();
352228753Smm
353228753Smm      if (expr != error_mark_node)
354228753Smm	expand_expr_stmt_value (expr, want_value, maybe_last);
355228753Smm
356228753Smm      if (stmts_are_full_exprs_p ())
357228753Smm	expand_end_target_temps ();
358228753Smm    }
359228753Smm}
360228753Smm
361228753Smm/* Generate the RTL for T, which is a DECL_STMT.  */
362228753Smm
363228753Smmvoid
364228753Smmgenrtl_decl_stmt (t)
365228753Smm     tree t;
366228753Smm{
367228753Smm  tree decl;
368228753Smm  emit_line_note (input_filename, lineno);
369228753Smm  decl = DECL_STMT_DECL (t);
370228753Smm  /* If this is a declaration for an automatic local
371228753Smm     variable, initialize it.  Note that we might also see a
372228753Smm     declaration for a namespace-scope object (declared with
373228753Smm     `extern').  We don't have to handle the initialization
374228753Smm     of those objects here; they can only be declarations,
375228753Smm     rather than definitions.  */
376228753Smm  if (TREE_CODE (decl) == VAR_DECL
377228753Smm      && !TREE_STATIC (decl)
378228753Smm      && !DECL_EXTERNAL (decl))
379228753Smm    {
380228753Smm      /* Let the back-end know about this variable.  */
381228753Smm      if (!anon_aggr_type_p (TREE_TYPE (decl)))
382228753Smm	emit_local_var (decl);
383228753Smm      else
384228753Smm	expand_anon_union_decl (decl, NULL_TREE,
385228753Smm				DECL_ANON_UNION_ELEMS (decl));
386228753Smm    }
387228753Smm  else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
388228753Smm    make_rtl_for_local_static (decl);
389228753Smm  else if (TREE_CODE (decl) == LABEL_DECL
390228753Smm	   && C_DECLARED_LABEL_FLAG (decl))
391228753Smm    declare_nonlocal_label (decl);
392228753Smm  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