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