c-semantics.c revision 117395
190075Sobrien/* This file contains the definitions and documentation for the common
290075Sobrien   tree codes used in the GNU C and C++ compilers (see c-common.def
390075Sobrien   for the standard codes).
490075Sobrien   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
590075Sobrien   Written by Benjamin Chelf (chelf@codesourcery.com).
690075Sobrien
790075SobrienThis file is part of GCC.
890075Sobrien
990075SobrienGCC is free software; you can redistribute it and/or modify it under
1090075Sobrienthe terms of the GNU General Public License as published by the Free
1190075SobrienSoftware Foundation; either version 2, or (at your option) any later
1290075Sobrienversion.
1390075Sobrien
1490075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1590075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1690075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1790075Sobrienfor more details.
1890075Sobrien
1990075SobrienYou should have received a copy of the GNU General Public License
2090075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
2190075SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
2290075Sobrien02111-1307, USA.  */
2390075Sobrien
2490075Sobrien#include "config.h"
2590075Sobrien#include "system.h"
2690075Sobrien#include "tree.h"
2790075Sobrien#include "function.h"
2890075Sobrien#include "splay-tree.h"
2990075Sobrien#include "varray.h"
3090075Sobrien#include "c-common.h"
3190075Sobrien#include "except.h"
3290075Sobrien#include "toplev.h"
3390075Sobrien#include "flags.h"
3490075Sobrien#include "ggc.h"
3590075Sobrien#include "rtl.h"
3690075Sobrien#include "expr.h"
3790075Sobrien#include "output.h"
3890075Sobrien#include "timevar.h"
39117395Skan#include "predict.h"
4090075Sobrien
4190075Sobrien/* If non-NULL, the address of a language-specific function for
4290075Sobrien   expanding statements.  */
4390075Sobrienvoid (*lang_expand_stmt) PARAMS ((tree));
4490075Sobrien
4590075Sobrien/* If non-NULL, the address of a language-specific function for
4690075Sobrien   expanding a DECL_STMT.  After the language-independent cases are
4790075Sobrien   handled, this function will be called.  If this function is not
4890075Sobrien   defined, it is assumed that declarations other than those for
4990075Sobrien   variables and labels do not require any RTL generation.  */
5090075Sobrienvoid (*lang_expand_decl_stmt) PARAMS ((tree));
5190075Sobrien
5290075Sobrien/* Create an empty statement tree rooted at T.  */
5390075Sobrien
5490075Sobrienvoid
5590075Sobrienbegin_stmt_tree (t)
5690075Sobrien     tree *t;
5790075Sobrien{
5890075Sobrien  /* We create a trivial EXPR_STMT so that last_tree is never NULL in
5990075Sobrien     what follows.  We remove the extraneous statement in
6090075Sobrien     finish_stmt_tree.  */
6190075Sobrien  *t = build_nt (EXPR_STMT, void_zero_node);
6290075Sobrien  last_tree = *t;
6390075Sobrien  last_expr_type = NULL_TREE;
6490075Sobrien  last_expr_filename = input_filename;
6590075Sobrien}
6690075Sobrien
6790075Sobrien/* T is a statement.  Add it to the statement-tree.  */
6890075Sobrien
6990075Sobrientree
7090075Sobrienadd_stmt (t)
7190075Sobrien     tree t;
7290075Sobrien{
7390075Sobrien  if (input_filename != last_expr_filename)
7490075Sobrien    {
7590075Sobrien      /* If the filename has changed, also add in a FILE_STMT.  Do a string
7690075Sobrien	 compare first, though, as it might be an equivalent string.  */
7790075Sobrien      int add = (strcmp (input_filename, last_expr_filename) != 0);
7890075Sobrien      last_expr_filename = input_filename;
7990075Sobrien      if (add)
8090075Sobrien	{
8190075Sobrien	  tree pos = build_nt (FILE_STMT, get_identifier (input_filename));
8290075Sobrien	  add_stmt (pos);
8390075Sobrien	}
8490075Sobrien    }
8590075Sobrien
8690075Sobrien  /* Add T to the statement-tree.  */
8790075Sobrien  TREE_CHAIN (last_tree) = t;
8890075Sobrien  last_tree = t;
8990075Sobrien
9090075Sobrien  /* When we expand a statement-tree, we must know whether or not the
9190075Sobrien     statements are full-expressions.  We record that fact here.  */
9290075Sobrien  STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p ();
9390075Sobrien
9490075Sobrien  /* Keep track of the number of statements in this function.  */
9590075Sobrien  if (current_function_decl)
9690075Sobrien    ++DECL_NUM_STMTS (current_function_decl);
9790075Sobrien
9890075Sobrien  return t;
9990075Sobrien}
10090075Sobrien
10190075Sobrien/* Create a declaration statement for the declaration given by the
10290075Sobrien   DECL.  */
10390075Sobrien
10490075Sobrienvoid
10590075Sobrienadd_decl_stmt (decl)
10690075Sobrien     tree decl;
10790075Sobrien{
10890075Sobrien  tree decl_stmt;
10990075Sobrien
11090075Sobrien  /* We need the type to last until instantiation time.  */
11190075Sobrien  decl_stmt = build_stmt (DECL_STMT, decl);
11290075Sobrien  add_stmt (decl_stmt);
11390075Sobrien}
11490075Sobrien
11590075Sobrien/* Add a scope-statement to the statement-tree.  BEGIN_P indicates
11690075Sobrien   whether this statements opens or closes a scope.  PARTIAL_P is true
11790075Sobrien   for a partial scope, i.e, the scope that begins after a label when
11890075Sobrien   an object that needs a cleanup is created.  If BEGIN_P is nonzero,
11990075Sobrien   returns a new TREE_LIST representing the top of the SCOPE_STMT
12090075Sobrien   stack.  The TREE_PURPOSE is the new SCOPE_STMT.  If BEGIN_P is
12190075Sobrien   zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT,
12290075Sobrien   and whose TREE_PURPOSE is the matching SCOPE_STMT with
12390075Sobrien   SCOPE_BEGIN_P set.  */
12490075Sobrien
12590075Sobrientree
12690075Sobrienadd_scope_stmt (begin_p, partial_p)
12790075Sobrien     int begin_p;
12890075Sobrien     int partial_p;
12990075Sobrien{
13090075Sobrien  tree *stack_ptr = current_scope_stmt_stack ();
13190075Sobrien  tree ss;
13290075Sobrien  tree top = *stack_ptr;
13390075Sobrien
13490075Sobrien  /* Build the statement.  */
13590075Sobrien  ss = build_stmt (SCOPE_STMT, NULL_TREE);
13690075Sobrien  SCOPE_BEGIN_P (ss) = begin_p;
13790075Sobrien  SCOPE_PARTIAL_P (ss) = partial_p;
13890075Sobrien
13990075Sobrien  /* Keep the scope stack up to date.  */
14090075Sobrien  if (begin_p)
14190075Sobrien    {
14290075Sobrien      top = tree_cons (ss, NULL_TREE, top);
14390075Sobrien      *stack_ptr = top;
14490075Sobrien    }
14590075Sobrien  else
14690075Sobrien    {
14790075Sobrien      TREE_VALUE (top) = ss;
14890075Sobrien      *stack_ptr = TREE_CHAIN (top);
14990075Sobrien    }
15090075Sobrien
15190075Sobrien  /* Add the new statement to the statement-tree.  */
15290075Sobrien  add_stmt (ss);
15390075Sobrien
15490075Sobrien  return top;
15590075Sobrien}
15690075Sobrien
15790075Sobrien/* Finish the statement tree rooted at T.  */
15890075Sobrien
15990075Sobrienvoid
16090075Sobrienfinish_stmt_tree (t)
16190075Sobrien     tree *t;
16290075Sobrien{
16390075Sobrien  tree stmt;
16490075Sobrien
16590075Sobrien  /* Remove the fake extra statement added in begin_stmt_tree.  */
16690075Sobrien  stmt = TREE_CHAIN (*t);
16790075Sobrien  *t = stmt;
16890075Sobrien  last_tree = NULL_TREE;
16990075Sobrien
17090075Sobrien  if (cfun && stmt)
17190075Sobrien    {
17290075Sobrien      /* The line-number recorded in the outermost statement in a function
17390075Sobrien	 is the line number of the end of the function.  */
17490075Sobrien      STMT_LINENO (stmt) = lineno;
17590075Sobrien      STMT_LINENO_FOR_FN_P (stmt) = 1;
17690075Sobrien    }
17790075Sobrien}
17890075Sobrien
17990075Sobrien/* Build a generic statement based on the given type of node and
18090075Sobrien   arguments. Similar to `build_nt', except that we set
18190075Sobrien   STMT_LINENO to be the current line number.  */
18290075Sobrien/* ??? This should be obsolete with the lineno_stmt productions
18390075Sobrien   in the grammar.  */
18490075Sobrien
18590075Sobrientree
18690075Sobrienbuild_stmt VPARAMS ((enum tree_code code, ...))
18790075Sobrien{
18890075Sobrien  tree t;
18990075Sobrien  int length;
19090075Sobrien  int i;
19190075Sobrien
19290075Sobrien  VA_OPEN (p, code);
19390075Sobrien  VA_FIXEDARG (p, enum tree_code, code);
19490075Sobrien
19590075Sobrien  t = make_node (code);
19690075Sobrien  length = TREE_CODE_LENGTH (code);
19790075Sobrien  STMT_LINENO (t) = lineno;
19890075Sobrien
19990075Sobrien  for (i = 0; i < length; i++)
20090075Sobrien    TREE_OPERAND (t, i) = va_arg (p, tree);
20190075Sobrien
20290075Sobrien  VA_CLOSE (p);
20390075Sobrien  return t;
20490075Sobrien}
20590075Sobrien
20690075Sobrien/* Some statements, like for-statements or if-statements, require a
20790075Sobrien   condition.  This condition can be a declaration.  If T is such a
20890075Sobrien   declaration it is processed, and an expression appropriate to use
20990075Sobrien   as the condition is returned.  Otherwise, T itself is returned.  */
21090075Sobrien
21190075Sobrientree
21290075Sobrienexpand_cond (t)
21390075Sobrien     tree t;
21490075Sobrien{
21590075Sobrien  if (t && TREE_CODE (t) == TREE_LIST)
21690075Sobrien    {
21790075Sobrien      expand_stmt (TREE_PURPOSE (t));
21890075Sobrien      return TREE_VALUE (t);
21990075Sobrien    }
22090075Sobrien  else
22190075Sobrien    return t;
22290075Sobrien}
22390075Sobrien
22490075Sobrien/* Create RTL for the local static variable DECL.  */
22590075Sobrien
22690075Sobrienvoid
22790075Sobrienmake_rtl_for_local_static (decl)
22890075Sobrien     tree decl;
22990075Sobrien{
23090075Sobrien  const char *asmspec = NULL;
23190075Sobrien
23290075Sobrien  /* If we inlined this variable, we could see it's declaration
23390075Sobrien     again.  */
23490075Sobrien  if (TREE_ASM_WRITTEN (decl))
23590075Sobrien    return;
23690075Sobrien
23790075Sobrien  /* If the DECL_ASSEMBLER_NAME is not the same as the DECL_NAME, then
23890075Sobrien     either we already created RTL for this DECL (and since it was a
23990075Sobrien     local variable, its DECL_ASSEMBLER_NAME got hacked up to prevent
24090075Sobrien     clashes with other local statics with the same name by a previous
24190075Sobrien     call to make_decl_rtl), or the user explicitly requested a
24290075Sobrien     particular assembly name for this variable, using the GNU
24390075Sobrien     extension for this purpose:
24490075Sobrien
24590075Sobrien       int i asm ("j");
24690075Sobrien
24790075Sobrien     There's no way to know which case we're in, here.  But, it turns
24890075Sobrien     out we're safe.  If there's already RTL, then
24990075Sobrien     rest_of_decl_compilation ignores the ASMSPEC parameter, so we
25090075Sobrien     may as well not pass it in.  If there isn't RTL, then we didn't
25190075Sobrien     already create RTL, which means that the modification to
25290075Sobrien     DECL_ASSEMBLER_NAME came only via the explicit extension.  */
25390075Sobrien  if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)
25490075Sobrien      && !DECL_RTL_SET_P (decl))
25590075Sobrien    asmspec = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
25690075Sobrien
25790075Sobrien  rest_of_decl_compilation (decl, asmspec, /*top_level=*/0, /*at_end=*/0);
25890075Sobrien}
25990075Sobrien
26090075Sobrien/* Let the back-end know about DECL.  */
26190075Sobrien
26290075Sobrienvoid
26390075Sobrienemit_local_var (decl)
26490075Sobrien     tree decl;
26590075Sobrien{
26690075Sobrien  /* Create RTL for this variable.  */
26790075Sobrien  if (!DECL_RTL_SET_P (decl))
26890075Sobrien    {
26990075Sobrien      if (DECL_C_HARD_REGISTER (decl))
27090075Sobrien	/* The user specified an assembler name for this variable.
27190075Sobrien	   Set that up now.  */
27290075Sobrien	rest_of_decl_compilation
27390075Sobrien	  (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
27490075Sobrien	   /*top_level=*/0, /*at_end=*/0);
27590075Sobrien      else
27690075Sobrien	expand_decl (decl);
27790075Sobrien    }
27890075Sobrien
27990075Sobrien  /* Actually do the initialization.  */
28090075Sobrien  if (stmts_are_full_exprs_p ())
28190075Sobrien    expand_start_target_temps ();
28290075Sobrien
28390075Sobrien  expand_decl_init (decl);
28490075Sobrien
28590075Sobrien  if (stmts_are_full_exprs_p ())
28690075Sobrien    expand_end_target_temps ();
28790075Sobrien}
28890075Sobrien
28990075Sobrien/* Helper for generating the RTL at the beginning of a scope.  */
29090075Sobrien
29190075Sobrienvoid
29290075Sobriengenrtl_do_pushlevel ()
29390075Sobrien{
29490075Sobrien  emit_line_note (input_filename, lineno);
29590075Sobrien  clear_last_expr ();
29690075Sobrien}
29790075Sobrien
29890075Sobrien/* Generate the RTL for DESTINATION, which is a GOTO_STMT.  */
29990075Sobrien
30090075Sobrienvoid
30190075Sobriengenrtl_goto_stmt (destination)
30290075Sobrien     tree destination;
30390075Sobrien{
30490075Sobrien  if (TREE_CODE (destination) == IDENTIFIER_NODE)
30590075Sobrien    abort ();
30690075Sobrien
30790075Sobrien  /* We warn about unused labels with -Wunused.  That means we have to
30890075Sobrien     mark the used labels as used.  */
30990075Sobrien  if (TREE_CODE (destination) == LABEL_DECL)
31090075Sobrien    TREE_USED (destination) = 1;
31190075Sobrien
31290075Sobrien  emit_line_note (input_filename, lineno);
31390075Sobrien
31490075Sobrien  if (TREE_CODE (destination) == LABEL_DECL)
31590075Sobrien    {
31690075Sobrien      label_rtx (destination);
31790075Sobrien      expand_goto (destination);
31890075Sobrien    }
31990075Sobrien  else
32090075Sobrien    expand_computed_goto (destination);
32190075Sobrien}
32290075Sobrien
32390075Sobrien/* Generate the RTL for EXPR, which is an EXPR_STMT.  Provided just
32490075Sobrien   for backward compatibility.  genrtl_expr_stmt_value() should be
32590075Sobrien   used for new code.  */
32690075Sobrien
32790075Sobrienvoid
32890075Sobriengenrtl_expr_stmt (expr)
32990075Sobrien     tree expr;
33090075Sobrien{
33190075Sobrien  genrtl_expr_stmt_value (expr, -1, 1);
33290075Sobrien}
33390075Sobrien
33490075Sobrien/* Generate the RTL for EXPR, which is an EXPR_STMT.  WANT_VALUE tells
33590075Sobrien   whether to (1) save the value of the expression, (0) discard it or
33690075Sobrien   (-1) use expr_stmts_for_value to tell.  The use of -1 is
33790075Sobrien   deprecated, and retained only for backward compatibility.
338117395Skan   MAYBE_LAST is nonzero if this EXPR_STMT might be the last statement
33990075Sobrien   in expression statement.  */
34090075Sobrien
34190075Sobrienvoid
34290075Sobriengenrtl_expr_stmt_value (expr, want_value, maybe_last)
34390075Sobrien     tree expr;
34490075Sobrien     int want_value, maybe_last;
34590075Sobrien{
34690075Sobrien  if (expr != NULL_TREE)
34790075Sobrien    {
34890075Sobrien      emit_line_note (input_filename, lineno);
34990075Sobrien
35090075Sobrien      if (stmts_are_full_exprs_p ())
35190075Sobrien	expand_start_target_temps ();
35290075Sobrien
35390075Sobrien      if (expr != error_mark_node)
35490075Sobrien	expand_expr_stmt_value (expr, want_value, maybe_last);
35590075Sobrien
35690075Sobrien      if (stmts_are_full_exprs_p ())
35790075Sobrien	expand_end_target_temps ();
35890075Sobrien    }
35990075Sobrien}
36090075Sobrien
36190075Sobrien/* Generate the RTL for T, which is a DECL_STMT.  */
36290075Sobrien
36390075Sobrienvoid
36490075Sobriengenrtl_decl_stmt (t)
36590075Sobrien     tree t;
36690075Sobrien{
36790075Sobrien  tree decl;
36890075Sobrien  emit_line_note (input_filename, lineno);
36990075Sobrien  decl = DECL_STMT_DECL (t);
37090075Sobrien  /* If this is a declaration for an automatic local
37190075Sobrien     variable, initialize it.  Note that we might also see a
37290075Sobrien     declaration for a namespace-scope object (declared with
37390075Sobrien     `extern').  We don't have to handle the initialization
37490075Sobrien     of those objects here; they can only be declarations,
37590075Sobrien     rather than definitions.  */
37690075Sobrien  if (TREE_CODE (decl) == VAR_DECL
37790075Sobrien      && !TREE_STATIC (decl)
37890075Sobrien      && !DECL_EXTERNAL (decl))
37990075Sobrien    {
38090075Sobrien      /* Let the back-end know about this variable.  */
38190075Sobrien      if (!anon_aggr_type_p (TREE_TYPE (decl)))
38290075Sobrien	emit_local_var (decl);
38390075Sobrien      else
38490075Sobrien	expand_anon_union_decl (decl, NULL_TREE,
38590075Sobrien				DECL_ANON_UNION_ELEMS (decl));
38690075Sobrien    }
38790075Sobrien  else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
38890075Sobrien    make_rtl_for_local_static (decl);
38990075Sobrien  else if (TREE_CODE (decl) == LABEL_DECL
39090075Sobrien	   && C_DECLARED_LABEL_FLAG (decl))
39190075Sobrien    declare_nonlocal_label (decl);
39290075Sobrien  else if (lang_expand_decl_stmt)
39390075Sobrien    (*lang_expand_decl_stmt) (t);
39490075Sobrien}
39590075Sobrien
39690075Sobrien/* Generate the RTL for T, which is an IF_STMT.  */
39790075Sobrien
39890075Sobrienvoid
39990075Sobriengenrtl_if_stmt (t)
40090075Sobrien     tree t;
40190075Sobrien{
40290075Sobrien  tree cond;
40390075Sobrien  genrtl_do_pushlevel ();
40490075Sobrien  cond = expand_cond (IF_COND (t));
40590075Sobrien  emit_line_note (input_filename, lineno);
40690075Sobrien  expand_start_cond (cond, 0);
40790075Sobrien  if (THEN_CLAUSE (t))
40890075Sobrien    expand_stmt (THEN_CLAUSE (t));
40990075Sobrien  if (ELSE_CLAUSE (t))
41090075Sobrien    {
41190075Sobrien      expand_start_else ();
41290075Sobrien      expand_stmt (ELSE_CLAUSE (t));
41390075Sobrien    }
41490075Sobrien  expand_end_cond ();
41590075Sobrien}
41690075Sobrien
41790075Sobrien/* Generate the RTL for T, which is a WHILE_STMT.  */
41890075Sobrien
41990075Sobrienvoid
42090075Sobriengenrtl_while_stmt (t)
42190075Sobrien     tree t;
42290075Sobrien{
42390075Sobrien  tree cond;
42490075Sobrien  emit_nop ();
42590075Sobrien  emit_line_note (input_filename, lineno);
42690075Sobrien  expand_start_loop (1);
42790075Sobrien  genrtl_do_pushlevel ();
42890075Sobrien
42990075Sobrien  cond = expand_cond (WHILE_COND (t));
43090075Sobrien  emit_line_note (input_filename, lineno);
43190075Sobrien  expand_exit_loop_top_cond (0, cond);
43290075Sobrien  genrtl_do_pushlevel ();
43390075Sobrien
43490075Sobrien  expand_stmt (WHILE_BODY (t));
43590075Sobrien
43690075Sobrien  expand_end_loop ();
43790075Sobrien}
43890075Sobrien
43990075Sobrien/* Generate the RTL for T, which is a DO_STMT.  */
44090075Sobrien
44190075Sobrienvoid
44290075Sobriengenrtl_do_stmt (t)
44390075Sobrien     tree t;
44490075Sobrien{
44590075Sobrien  tree cond = DO_COND (t);
44690075Sobrien
44790075Sobrien  /* Recognize the common special-case of do { ... } while (0) and do
44890075Sobrien     not emit the loop widgetry in this case.  In particular this
44990075Sobrien     avoids cluttering the rtl with dummy loop notes, which can affect
450117395Skan     alignment of adjacent labels.  COND can be NULL due to parse
451117395Skan     errors.  */
452117395Skan  if (!cond || integer_zerop (cond))
45390075Sobrien    {
45490075Sobrien      expand_start_null_loop ();
45590075Sobrien      expand_stmt (DO_BODY (t));
45690075Sobrien      expand_end_null_loop ();
45790075Sobrien    }
45890075Sobrien  else
45990075Sobrien    {
46090075Sobrien      emit_nop ();
46190075Sobrien      emit_line_note (input_filename, lineno);
46290075Sobrien      expand_start_loop_continue_elsewhere (1);
46390075Sobrien
46490075Sobrien      expand_stmt (DO_BODY (t));
46590075Sobrien
46690075Sobrien      expand_loop_continue_here ();
46790075Sobrien      cond = expand_cond (cond);
46890075Sobrien      emit_line_note (input_filename, lineno);
46990075Sobrien      expand_exit_loop_if_false (0, cond);
47090075Sobrien      expand_end_loop ();
47190075Sobrien    }
47290075Sobrien}
47390075Sobrien
47490075Sobrien/* Build the node for a return statement and return it.  */
47590075Sobrien
47690075Sobrientree
47790075Sobrienbuild_return_stmt (expr)
47890075Sobrien     tree expr;
47990075Sobrien{
48090075Sobrien  return (build_stmt (RETURN_STMT, expr));
48190075Sobrien}
48290075Sobrien
48390075Sobrien/* Generate the RTL for STMT, which is a RETURN_STMT.  */
48490075Sobrien
48590075Sobrienvoid
48690075Sobriengenrtl_return_stmt (stmt)
48790075Sobrien     tree stmt;
48890075Sobrien{
48990075Sobrien  tree expr;
49090075Sobrien
491117395Skan  expr = RETURN_STMT_EXPR (stmt);
49290075Sobrien
49390075Sobrien  emit_line_note (input_filename, lineno);
49490075Sobrien  if (!expr)
49590075Sobrien    expand_null_return ();
49690075Sobrien  else
49790075Sobrien    {
49890075Sobrien      expand_start_target_temps ();
49990075Sobrien      expand_return (expr);
50090075Sobrien      expand_end_target_temps ();
50190075Sobrien    }
50290075Sobrien}
50390075Sobrien
50490075Sobrien/* Generate the RTL for T, which is a FOR_STMT.  */
50590075Sobrien
50690075Sobrienvoid
50790075Sobriengenrtl_for_stmt (t)
50890075Sobrien     tree t;
50990075Sobrien{
51090075Sobrien  tree cond;
51190075Sobrien  const char *saved_filename;
51290075Sobrien  int saved_lineno;
51390075Sobrien
51490075Sobrien  if (NEW_FOR_SCOPE_P (t))
51590075Sobrien    genrtl_do_pushlevel ();
51690075Sobrien
51790075Sobrien  expand_stmt (FOR_INIT_STMT (t));
51890075Sobrien
51990075Sobrien  /* Expand the initialization.  */
52090075Sobrien  emit_nop ();
52190075Sobrien  emit_line_note (input_filename, lineno);
52290075Sobrien  expand_start_loop_continue_elsewhere (1);
52390075Sobrien  genrtl_do_pushlevel ();
52490075Sobrien  cond = expand_cond (FOR_COND (t));
52590075Sobrien
52690075Sobrien  /* Save the filename and line number so that we expand the FOR_EXPR
52790075Sobrien     we can reset them back to the saved values.  */
52890075Sobrien  saved_filename = input_filename;
52990075Sobrien  saved_lineno = lineno;
53090075Sobrien
53190075Sobrien  /* Expand the condition.  */
53290075Sobrien  emit_line_note (input_filename, lineno);
53390075Sobrien  if (cond)
53490075Sobrien    expand_exit_loop_top_cond (0, cond);
53590075Sobrien
53690075Sobrien  /* Expand the body.  */
53790075Sobrien  genrtl_do_pushlevel ();
53890075Sobrien  expand_stmt (FOR_BODY (t));
53990075Sobrien
54090075Sobrien  /* Expand the increment expression.  */
54190075Sobrien  input_filename = saved_filename;
54290075Sobrien  lineno = saved_lineno;
54390075Sobrien  emit_line_note (input_filename, lineno);
54490075Sobrien  expand_loop_continue_here ();
54590075Sobrien  if (FOR_EXPR (t))
54690075Sobrien    genrtl_expr_stmt (FOR_EXPR (t));
54790075Sobrien  expand_end_loop ();
54890075Sobrien}
54990075Sobrien
55090075Sobrien/* Build a break statement node and return it.  */
55190075Sobrien
55290075Sobrientree
55390075Sobrienbuild_break_stmt ()
55490075Sobrien{
55590075Sobrien  return (build_stmt (BREAK_STMT));
55690075Sobrien}
55790075Sobrien
55890075Sobrien/* Generate the RTL for a BREAK_STMT.  */
55990075Sobrien
56090075Sobrienvoid
56190075Sobriengenrtl_break_stmt ()
56290075Sobrien{
56390075Sobrien  emit_line_note (input_filename, lineno);
56490075Sobrien  if ( ! expand_exit_something ())
56590075Sobrien    error ("break statement not within loop or switch");
56690075Sobrien}
56790075Sobrien
56890075Sobrien/* Build a continue statement node and return it.  */
56990075Sobrien
57090075Sobrientree
57190075Sobrienbuild_continue_stmt ()
57290075Sobrien{
57390075Sobrien  return (build_stmt (CONTINUE_STMT));
57490075Sobrien}
57590075Sobrien
57690075Sobrien/* Generate the RTL for a CONTINUE_STMT.  */
57790075Sobrien
57890075Sobrienvoid
57990075Sobriengenrtl_continue_stmt ()
58090075Sobrien{
58190075Sobrien  emit_line_note (input_filename, lineno);
58290075Sobrien  if (! expand_continue_loop (0))
58390075Sobrien    error ("continue statement not within a loop");
58490075Sobrien}
58590075Sobrien
58690075Sobrien/* Generate the RTL for T, which is a SCOPE_STMT.  */
58790075Sobrien
58890075Sobrienvoid
58990075Sobriengenrtl_scope_stmt (t)
59090075Sobrien     tree t;
59190075Sobrien{
59290075Sobrien  tree block = SCOPE_STMT_BLOCK (t);
59390075Sobrien
59490075Sobrien  if (!SCOPE_NO_CLEANUPS_P (t))
59590075Sobrien    {
59690075Sobrien      if (SCOPE_BEGIN_P (t))
59790075Sobrien	expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t), block);
59890075Sobrien      else if (SCOPE_END_P (t))
59990075Sobrien	expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), 0);
60090075Sobrien    }
60190075Sobrien  else if (!SCOPE_NULLIFIED_P (t))
60290075Sobrien    {
60390075Sobrien      rtx note = emit_note (NULL,
60490075Sobrien			    (SCOPE_BEGIN_P (t)
60590075Sobrien			     ? NOTE_INSN_BLOCK_BEG
60690075Sobrien			     : NOTE_INSN_BLOCK_END));
60790075Sobrien      NOTE_BLOCK (note) = block;
60890075Sobrien    }
60990075Sobrien
61090075Sobrien  /* If we're at the end of a scope that contains inlined nested
61190075Sobrien     functions, we have to decide whether or not to write them out.  */
61290075Sobrien  if (block && SCOPE_END_P (t))
61390075Sobrien    {
61490075Sobrien      tree fn;
61590075Sobrien
61690075Sobrien      for (fn = BLOCK_VARS (block); fn; fn = TREE_CHAIN (fn))
61790075Sobrien	{
61890075Sobrien	  if (TREE_CODE (fn) == FUNCTION_DECL
61990075Sobrien	      && DECL_CONTEXT (fn) == current_function_decl
620110611Skan	      && DECL_SAVED_INSNS (fn)
62190075Sobrien	      && !TREE_ASM_WRITTEN (fn)
62290075Sobrien	      && TREE_ADDRESSABLE (fn))
62390075Sobrien	    {
62490075Sobrien	      push_function_context ();
62590075Sobrien	      output_inline_function (fn);
62690075Sobrien	      pop_function_context ();
62790075Sobrien	    }
62890075Sobrien	}
62990075Sobrien    }
63090075Sobrien}
63190075Sobrien
63290075Sobrien/* Generate the RTL for T, which is a SWITCH_STMT.  */
63390075Sobrien
63490075Sobrienvoid
63590075Sobriengenrtl_switch_stmt (t)
63690075Sobrien     tree t;
63790075Sobrien{
63890075Sobrien  tree cond;
63990075Sobrien  genrtl_do_pushlevel ();
64090075Sobrien
64190075Sobrien  cond = expand_cond (SWITCH_COND (t));
64290075Sobrien  if (cond == error_mark_node)
64390075Sobrien    /* The code is in error, but we don't want expand_end_case to
64490075Sobrien       crash.  */
64590075Sobrien    cond = boolean_false_node;
64690075Sobrien
64790075Sobrien  emit_line_note (input_filename, lineno);
64890075Sobrien  expand_start_case (1, cond, TREE_TYPE (cond), "switch statement");
64990075Sobrien  expand_stmt (SWITCH_BODY (t));
65096263Sobrien  expand_end_case_type (cond, SWITCH_TYPE (t));
65190075Sobrien}
65290075Sobrien
65390075Sobrien/* Create a CASE_LABEL tree node and return it.  */
65490075Sobrien
65590075Sobrientree
65690075Sobrienbuild_case_label (low_value, high_value, label_decl)
65790075Sobrien     tree low_value;
65890075Sobrien     tree high_value;
65990075Sobrien     tree label_decl;
66090075Sobrien{
66190075Sobrien  return build_stmt (CASE_LABEL, low_value, high_value, label_decl);
66290075Sobrien}
66390075Sobrien
66490075Sobrien
66590075Sobrien/* Generate the RTL for a CASE_LABEL.  */
66690075Sobrien
66790075Sobrienvoid
66890075Sobriengenrtl_case_label (case_label)
66990075Sobrien     tree case_label;
67090075Sobrien{
67190075Sobrien  tree duplicate;
67290075Sobrien  tree cleanup;
67390075Sobrien
67490075Sobrien  cleanup = last_cleanup_this_contour ();
67590075Sobrien  if (cleanup)
67690075Sobrien    {
67790075Sobrien      static int explained = 0;
678117395Skan      warning ("destructor needed for `%#D'", (TREE_PURPOSE (cleanup)));
67990075Sobrien      warning ("where case label appears here");
68090075Sobrien      if (!explained)
68190075Sobrien	{
68290075Sobrien	  warning ("(enclose actions of previous case statements requiring destructors in their own scope.)");
68390075Sobrien	  explained = 1;
68490075Sobrien	}
68590075Sobrien    }
68690075Sobrien
68790075Sobrien  add_case_node (CASE_LOW (case_label), CASE_HIGH (case_label),
68890075Sobrien		 CASE_LABEL_DECL (case_label), &duplicate);
68990075Sobrien}
69090075Sobrien
69190075Sobrien/* Generate the RTL for T, which is a COMPOUND_STMT.  */
69290075Sobrien
69390075Sobrienvoid
69490075Sobriengenrtl_compound_stmt (t)
69590075Sobrien    tree t;
69690075Sobrien{
69790075Sobrien#ifdef ENABLE_CHECKING
69890075Sobrien  struct nesting *n = current_nesting_level ();
69990075Sobrien#endif
70090075Sobrien
70190075Sobrien  expand_stmt (COMPOUND_BODY (t));
70290075Sobrien
70390075Sobrien#ifdef ENABLE_CHECKING
70490075Sobrien  /* Make sure that we've pushed and popped the same number of levels.  */
70590075Sobrien  if (!COMPOUND_STMT_NO_SCOPE (t) && n != current_nesting_level ())
70690075Sobrien    abort ();
70790075Sobrien#endif
70890075Sobrien}
70990075Sobrien
71090075Sobrien/* Generate the RTL for an ASM_STMT.  */
71190075Sobrien
71290075Sobrienvoid
71390075Sobriengenrtl_asm_stmt (cv_qualifier, string, output_operands,
71490075Sobrien		 input_operands, clobbers, asm_input_p)
71590075Sobrien     tree cv_qualifier;
71690075Sobrien     tree string;
71790075Sobrien     tree output_operands;
71890075Sobrien     tree input_operands;
71990075Sobrien     tree clobbers;
72090075Sobrien     int asm_input_p;
72190075Sobrien{
72290075Sobrien  if (cv_qualifier != NULL_TREE
72390075Sobrien      && cv_qualifier != ridpointers[(int) RID_VOLATILE])
72490075Sobrien    {
72590075Sobrien      warning ("%s qualifier ignored on asm",
72690075Sobrien	       IDENTIFIER_POINTER (cv_qualifier));
72790075Sobrien      cv_qualifier = NULL_TREE;
72890075Sobrien    }
72990075Sobrien
73090075Sobrien  emit_line_note (input_filename, lineno);
73190075Sobrien  if (asm_input_p)
732110611Skan    expand_asm (string, cv_qualifier != NULL_TREE);
73390075Sobrien  else
73490075Sobrien    c_expand_asm_operands (string, output_operands, input_operands,
73590075Sobrien			   clobbers, cv_qualifier != NULL_TREE,
73690075Sobrien			   input_filename, lineno);
73790075Sobrien}
73890075Sobrien
73990075Sobrien/* Generate the RTL for a DECL_CLEANUP.  */
74090075Sobrien
74190075Sobrienvoid
74296263Sobriengenrtl_decl_cleanup (t)
74396263Sobrien     tree t;
74490075Sobrien{
74596263Sobrien  tree decl = CLEANUP_DECL (t);
74690075Sobrien  if (!decl || (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node))
74796263Sobrien    expand_decl_cleanup_eh (decl, CLEANUP_EXPR (t), CLEANUP_EH_ONLY (t));
74890075Sobrien}
74990075Sobrien
75090075Sobrien/* We're about to expand T, a statement.  Set up appropriate context
75190075Sobrien   for the substitution.  */
75290075Sobrien
75390075Sobrienvoid
75490075Sobrienprep_stmt (t)
75590075Sobrien     tree t;
75690075Sobrien{
75790075Sobrien  if (!STMT_LINENO_FOR_FN_P (t))
75890075Sobrien    lineno = STMT_LINENO (t);
75990075Sobrien  current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
76090075Sobrien}
76190075Sobrien
76290075Sobrien/* Generate the RTL for the statement T, its substatements, and any
76390075Sobrien   other statements at its nesting level.  */
76490075Sobrien
76590075Sobrienvoid
76690075Sobrienexpand_stmt (t)
76790075Sobrien     tree t;
76890075Sobrien{
76990075Sobrien  while (t && t != error_mark_node)
77090075Sobrien    {
77190075Sobrien      int saved_stmts_are_full_exprs_p;
77290075Sobrien
77390075Sobrien      /* Set up context appropriately for handling this statement.  */
77490075Sobrien      saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
77590075Sobrien      prep_stmt (t);
77690075Sobrien
77790075Sobrien      switch (TREE_CODE (t))
77890075Sobrien	{
77990075Sobrien	case FILE_STMT:
78090075Sobrien	  input_filename = FILE_STMT_FILENAME (t);
78190075Sobrien	  break;
78290075Sobrien
78390075Sobrien	case RETURN_STMT:
78490075Sobrien	  genrtl_return_stmt (t);
78590075Sobrien	  break;
78690075Sobrien
78790075Sobrien	case EXPR_STMT:
78890075Sobrien	  genrtl_expr_stmt_value (EXPR_STMT_EXPR (t), TREE_ADDRESSABLE (t),
78990075Sobrien				  TREE_CHAIN (t) == NULL
79090075Sobrien				  || (TREE_CODE (TREE_CHAIN (t)) == SCOPE_STMT
79190075Sobrien				      && TREE_CHAIN (TREE_CHAIN (t)) == NULL));
79290075Sobrien	  break;
79390075Sobrien
79490075Sobrien	case DECL_STMT:
79590075Sobrien	  genrtl_decl_stmt (t);
79690075Sobrien	  break;
79790075Sobrien
79890075Sobrien	case FOR_STMT:
79990075Sobrien	  genrtl_for_stmt (t);
80090075Sobrien	  break;
80190075Sobrien
80290075Sobrien	case WHILE_STMT:
80390075Sobrien	  genrtl_while_stmt (t);
80490075Sobrien	  break;
80590075Sobrien
80690075Sobrien	case DO_STMT:
80790075Sobrien	  genrtl_do_stmt (t);
80890075Sobrien	  break;
80990075Sobrien
81090075Sobrien	case IF_STMT:
81190075Sobrien	  genrtl_if_stmt (t);
81290075Sobrien	  break;
81390075Sobrien
81490075Sobrien	case COMPOUND_STMT:
81590075Sobrien	  genrtl_compound_stmt (t);
81690075Sobrien	  break;
81790075Sobrien
81890075Sobrien	case BREAK_STMT:
81990075Sobrien	  genrtl_break_stmt ();
82090075Sobrien	  break;
82190075Sobrien
82290075Sobrien	case CONTINUE_STMT:
82390075Sobrien	  genrtl_continue_stmt ();
82490075Sobrien	  break;
82590075Sobrien
82690075Sobrien	case SWITCH_STMT:
82790075Sobrien	  genrtl_switch_stmt (t);
82890075Sobrien	  break;
82990075Sobrien
83090075Sobrien	case CASE_LABEL:
83190075Sobrien	  genrtl_case_label (t);
83290075Sobrien	  break;
83390075Sobrien
83490075Sobrien	case LABEL_STMT:
83590075Sobrien	  expand_label (LABEL_STMT_LABEL (t));
83690075Sobrien	  break;
83790075Sobrien
83890075Sobrien	case GOTO_STMT:
839117395Skan	  /* Emit information for branch prediction.  */
840117395Skan	  if (!GOTO_FAKE_P (t)
841117395Skan	      && TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL
842117395Skan	      && flag_guess_branch_prob)
843117395Skan	    {
844117395Skan	      rtx note = emit_note (NULL, NOTE_INSN_PREDICTION);
845117395Skan
846117395Skan	      NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_GOTO, NOT_TAKEN);
847117395Skan	    }
84890075Sobrien	  genrtl_goto_stmt (GOTO_DESTINATION (t));
84990075Sobrien	  break;
85090075Sobrien
85190075Sobrien	case ASM_STMT:
85290075Sobrien	  genrtl_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t),
85390075Sobrien			   ASM_OUTPUTS (t), ASM_INPUTS (t),
85490075Sobrien			   ASM_CLOBBERS (t), ASM_INPUT_P (t));
85590075Sobrien	  break;
85690075Sobrien
85790075Sobrien	case SCOPE_STMT:
85890075Sobrien	  genrtl_scope_stmt (t);
85990075Sobrien	  break;
86090075Sobrien
86196263Sobrien	case CLEANUP_STMT:
86296263Sobrien	  genrtl_decl_cleanup (t);
86396263Sobrien	  break;
86496263Sobrien
86590075Sobrien	default:
86690075Sobrien	  if (lang_expand_stmt)
86790075Sobrien	    (*lang_expand_stmt) (t);
86890075Sobrien	  else
86990075Sobrien	    abort ();
87090075Sobrien	  break;
87190075Sobrien	}
87290075Sobrien
87390075Sobrien      /* Restore saved state.  */
87490075Sobrien      current_stmt_tree ()->stmts_are_full_exprs_p
87590075Sobrien	= saved_stmts_are_full_exprs_p;
87690075Sobrien
87790075Sobrien      /* Go on to the next statement in this scope.  */
87890075Sobrien      t = TREE_CHAIN (t);
87990075Sobrien    }
88090075Sobrien}
881