c-semantics.c revision 132718
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 3132718Skan for the standard codes). 4132718Skan Copyright (C) 2000, 2001, 2002, 2003, 2004 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" 26132718Skan#include "coretypes.h" 27132718Skan#include "tm.h" 2890075Sobrien#include "tree.h" 2990075Sobrien#include "function.h" 3090075Sobrien#include "splay-tree.h" 3190075Sobrien#include "varray.h" 3290075Sobrien#include "c-common.h" 3390075Sobrien#include "except.h" 34132718Skan/* In order for the format checking to accept the C frontend 35132718Skan diagnostic framework extensions, you must define this token before 36132718Skan including toplev.h. */ 37132718Skan#define GCC_DIAG_STYLE __gcc_cdiag__ 3890075Sobrien#include "toplev.h" 3990075Sobrien#include "flags.h" 4090075Sobrien#include "ggc.h" 4190075Sobrien#include "rtl.h" 4290075Sobrien#include "expr.h" 4390075Sobrien#include "output.h" 4490075Sobrien#include "timevar.h" 45117395Skan#include "predict.h" 46132718Skan#include "tree-inline.h" 4790075Sobrien 4890075Sobrien/* If non-NULL, the address of a language-specific function for 4990075Sobrien expanding statements. */ 50132718Skanvoid (*lang_expand_stmt) (tree); 5190075Sobrien 5290075Sobrien/* If non-NULL, the address of a language-specific function for 5390075Sobrien expanding a DECL_STMT. After the language-independent cases are 5490075Sobrien handled, this function will be called. If this function is not 5590075Sobrien defined, it is assumed that declarations other than those for 5690075Sobrien variables and labels do not require any RTL generation. */ 57132718Skanvoid (*lang_expand_decl_stmt) (tree); 5890075Sobrien 59132718Skanstatic tree find_reachable_label_1 (tree *, int *, void *); 60132718Skanstatic tree find_reachable_label (tree); 61132718Skanstatic bool expand_unreachable_if_stmt (tree); 62132718Skanstatic tree expand_unreachable_stmt (tree, int); 63132718Skanstatic void genrtl_do_stmt_1 (tree, tree); 64132718Skan 6590075Sobrien/* Create an empty statement tree rooted at T. */ 6690075Sobrien 6790075Sobrienvoid 68132718Skanbegin_stmt_tree (tree *t) 6990075Sobrien{ 7090075Sobrien /* We create a trivial EXPR_STMT so that last_tree is never NULL in 7190075Sobrien what follows. We remove the extraneous statement in 7290075Sobrien finish_stmt_tree. */ 7390075Sobrien *t = build_nt (EXPR_STMT, void_zero_node); 7490075Sobrien last_tree = *t; 7590075Sobrien last_expr_type = NULL_TREE; 7690075Sobrien last_expr_filename = input_filename; 7790075Sobrien} 7890075Sobrien 7990075Sobrien/* T is a statement. Add it to the statement-tree. */ 8090075Sobrien 8190075Sobrientree 82132718Skanadd_stmt (tree t) 8390075Sobrien{ 8490075Sobrien if (input_filename != last_expr_filename) 8590075Sobrien { 8690075Sobrien /* If the filename has changed, also add in a FILE_STMT. Do a string 8790075Sobrien compare first, though, as it might be an equivalent string. */ 8890075Sobrien int add = (strcmp (input_filename, last_expr_filename) != 0); 8990075Sobrien last_expr_filename = input_filename; 9090075Sobrien if (add) 9190075Sobrien { 9290075Sobrien tree pos = build_nt (FILE_STMT, get_identifier (input_filename)); 9390075Sobrien add_stmt (pos); 9490075Sobrien } 9590075Sobrien } 9690075Sobrien 9790075Sobrien /* Add T to the statement-tree. */ 9890075Sobrien TREE_CHAIN (last_tree) = t; 9990075Sobrien last_tree = t; 100132718Skan 10190075Sobrien /* When we expand a statement-tree, we must know whether or not the 10290075Sobrien statements are full-expressions. We record that fact here. */ 10390075Sobrien STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p (); 10490075Sobrien 10590075Sobrien return t; 10690075Sobrien} 10790075Sobrien 10890075Sobrien/* Create a declaration statement for the declaration given by the 10990075Sobrien DECL. */ 11090075Sobrien 11190075Sobrienvoid 112132718Skanadd_decl_stmt (tree decl) 11390075Sobrien{ 11490075Sobrien tree decl_stmt; 11590075Sobrien 11690075Sobrien /* We need the type to last until instantiation time. */ 11790075Sobrien decl_stmt = build_stmt (DECL_STMT, decl); 118132718Skan add_stmt (decl_stmt); 11990075Sobrien} 12090075Sobrien 12190075Sobrien/* Add a scope-statement to the statement-tree. BEGIN_P indicates 12290075Sobrien whether this statements opens or closes a scope. PARTIAL_P is true 12390075Sobrien for a partial scope, i.e, the scope that begins after a label when 12490075Sobrien an object that needs a cleanup is created. If BEGIN_P is nonzero, 12590075Sobrien returns a new TREE_LIST representing the top of the SCOPE_STMT 12690075Sobrien stack. The TREE_PURPOSE is the new SCOPE_STMT. If BEGIN_P is 12790075Sobrien zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT, 12890075Sobrien and whose TREE_PURPOSE is the matching SCOPE_STMT with 12990075Sobrien SCOPE_BEGIN_P set. */ 13090075Sobrien 13190075Sobrientree 132132718Skanadd_scope_stmt (int begin_p, int partial_p) 13390075Sobrien{ 13490075Sobrien tree *stack_ptr = current_scope_stmt_stack (); 13590075Sobrien tree ss; 13690075Sobrien tree top = *stack_ptr; 13790075Sobrien 13890075Sobrien /* Build the statement. */ 13990075Sobrien ss = build_stmt (SCOPE_STMT, NULL_TREE); 14090075Sobrien SCOPE_BEGIN_P (ss) = begin_p; 14190075Sobrien SCOPE_PARTIAL_P (ss) = partial_p; 14290075Sobrien 14390075Sobrien /* Keep the scope stack up to date. */ 14490075Sobrien if (begin_p) 14590075Sobrien { 14690075Sobrien top = tree_cons (ss, NULL_TREE, top); 14790075Sobrien *stack_ptr = top; 14890075Sobrien } 14990075Sobrien else 15090075Sobrien { 151132718Skan if (partial_p != SCOPE_PARTIAL_P (TREE_PURPOSE (top))) 152132718Skan abort (); 15390075Sobrien TREE_VALUE (top) = ss; 15490075Sobrien *stack_ptr = TREE_CHAIN (top); 15590075Sobrien } 15690075Sobrien 15790075Sobrien /* Add the new statement to the statement-tree. */ 15890075Sobrien add_stmt (ss); 15990075Sobrien 16090075Sobrien return top; 16190075Sobrien} 16290075Sobrien 16390075Sobrien/* Finish the statement tree rooted at T. */ 16490075Sobrien 16590075Sobrienvoid 166132718Skanfinish_stmt_tree (tree *t) 16790075Sobrien{ 16890075Sobrien tree stmt; 169132718Skan 17090075Sobrien /* Remove the fake extra statement added in begin_stmt_tree. */ 17190075Sobrien stmt = TREE_CHAIN (*t); 17290075Sobrien *t = stmt; 17390075Sobrien last_tree = NULL_TREE; 17490075Sobrien 17590075Sobrien if (cfun && stmt) 17690075Sobrien { 17790075Sobrien /* The line-number recorded in the outermost statement in a function 17890075Sobrien is the line number of the end of the function. */ 179132718Skan STMT_LINENO (stmt) = input_line; 18090075Sobrien STMT_LINENO_FOR_FN_P (stmt) = 1; 18190075Sobrien } 18290075Sobrien} 18390075Sobrien 18490075Sobrien/* Build a generic statement based on the given type of node and 18590075Sobrien arguments. Similar to `build_nt', except that we set 18690075Sobrien STMT_LINENO to be the current line number. */ 18790075Sobrien/* ??? This should be obsolete with the lineno_stmt productions 18890075Sobrien in the grammar. */ 18990075Sobrien 19090075Sobrientree 191132718Skanbuild_stmt (enum tree_code code, ...) 19290075Sobrien{ 19390075Sobrien tree t; 19490075Sobrien int length; 19590075Sobrien int i; 196132718Skan va_list p; 19790075Sobrien 198132718Skan va_start (p, code); 19990075Sobrien 20090075Sobrien t = make_node (code); 20190075Sobrien length = TREE_CODE_LENGTH (code); 202132718Skan STMT_LINENO (t) = input_line; 20390075Sobrien 20490075Sobrien for (i = 0; i < length; i++) 20590075Sobrien TREE_OPERAND (t, i) = va_arg (p, tree); 20690075Sobrien 207132718Skan va_end (p); 20890075Sobrien return t; 20990075Sobrien} 21090075Sobrien 21190075Sobrien/* Some statements, like for-statements or if-statements, require a 21290075Sobrien condition. This condition can be a declaration. If T is such a 21390075Sobrien declaration it is processed, and an expression appropriate to use 21490075Sobrien as the condition is returned. Otherwise, T itself is returned. */ 21590075Sobrien 21690075Sobrientree 217132718Skanexpand_cond (tree t) 21890075Sobrien{ 21990075Sobrien if (t && TREE_CODE (t) == TREE_LIST) 22090075Sobrien { 22190075Sobrien expand_stmt (TREE_PURPOSE (t)); 22290075Sobrien return TREE_VALUE (t); 22390075Sobrien } 224132718Skan else 22590075Sobrien return t; 22690075Sobrien} 22790075Sobrien 22890075Sobrien/* Create RTL for the local static variable DECL. */ 22990075Sobrien 23090075Sobrienvoid 231132718Skanmake_rtl_for_local_static (tree decl) 23290075Sobrien{ 23390075Sobrien const char *asmspec = NULL; 23490075Sobrien 23590075Sobrien /* If we inlined this variable, we could see it's declaration 23690075Sobrien again. */ 23790075Sobrien if (TREE_ASM_WRITTEN (decl)) 23890075Sobrien return; 23990075Sobrien 24090075Sobrien /* If the DECL_ASSEMBLER_NAME is not the same as the DECL_NAME, then 24190075Sobrien either we already created RTL for this DECL (and since it was a 24290075Sobrien local variable, its DECL_ASSEMBLER_NAME got hacked up to prevent 24390075Sobrien clashes with other local statics with the same name by a previous 24490075Sobrien call to make_decl_rtl), or the user explicitly requested a 24590075Sobrien particular assembly name for this variable, using the GNU 24690075Sobrien extension for this purpose: 24790075Sobrien 24890075Sobrien int i asm ("j"); 24990075Sobrien 25090075Sobrien There's no way to know which case we're in, here. But, it turns 25190075Sobrien out we're safe. If there's already RTL, then 25290075Sobrien rest_of_decl_compilation ignores the ASMSPEC parameter, so we 25390075Sobrien may as well not pass it in. If there isn't RTL, then we didn't 25490075Sobrien already create RTL, which means that the modification to 25590075Sobrien DECL_ASSEMBLER_NAME came only via the explicit extension. */ 25690075Sobrien if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) 25790075Sobrien && !DECL_RTL_SET_P (decl)) 25890075Sobrien asmspec = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 25990075Sobrien 26090075Sobrien rest_of_decl_compilation (decl, asmspec, /*top_level=*/0, /*at_end=*/0); 26190075Sobrien} 26290075Sobrien 26390075Sobrien/* Let the back-end know about DECL. */ 26490075Sobrien 26590075Sobrienvoid 266132718Skanemit_local_var (tree decl) 26790075Sobrien{ 26890075Sobrien /* Create RTL for this variable. */ 26990075Sobrien if (!DECL_RTL_SET_P (decl)) 27090075Sobrien { 27190075Sobrien if (DECL_C_HARD_REGISTER (decl)) 27290075Sobrien /* The user specified an assembler name for this variable. 27390075Sobrien Set that up now. */ 27490075Sobrien rest_of_decl_compilation 27590075Sobrien (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), 27690075Sobrien /*top_level=*/0, /*at_end=*/0); 27790075Sobrien else 27890075Sobrien expand_decl (decl); 27990075Sobrien } 28090075Sobrien 281132718Skan if (DECL_INITIAL (decl)) 282132718Skan { 283132718Skan /* Actually do the initialization. */ 284132718Skan if (stmts_are_full_exprs_p ()) 285132718Skan expand_start_target_temps (); 28690075Sobrien 287132718Skan expand_decl_init (decl); 28890075Sobrien 289132718Skan if (stmts_are_full_exprs_p ()) 290132718Skan expand_end_target_temps (); 291132718Skan } 29290075Sobrien} 29390075Sobrien 29490075Sobrien/* Helper for generating the RTL at the beginning of a scope. */ 29590075Sobrien 29690075Sobrienvoid 297132718Skangenrtl_do_pushlevel (void) 29890075Sobrien{ 299132718Skan emit_line_note (input_location); 30090075Sobrien clear_last_expr (); 30190075Sobrien} 30290075Sobrien 30390075Sobrien/* Generate the RTL for DESTINATION, which is a GOTO_STMT. */ 30490075Sobrien 30590075Sobrienvoid 306132718Skangenrtl_goto_stmt (tree destination) 30790075Sobrien{ 30890075Sobrien if (TREE_CODE (destination) == IDENTIFIER_NODE) 30990075Sobrien abort (); 310132718Skan 31190075Sobrien /* We warn about unused labels with -Wunused. That means we have to 31290075Sobrien mark the used labels as used. */ 31390075Sobrien if (TREE_CODE (destination) == LABEL_DECL) 31490075Sobrien TREE_USED (destination) = 1; 315132718Skan 316132718Skan emit_line_note (input_location); 317132718Skan 31890075Sobrien if (TREE_CODE (destination) == LABEL_DECL) 31990075Sobrien { 32090075Sobrien label_rtx (destination); 321132718Skan expand_goto (destination); 32290075Sobrien } 32390075Sobrien else 32490075Sobrien expand_computed_goto (destination); 32590075Sobrien} 32690075Sobrien 32790075Sobrien/* Generate the RTL for EXPR, which is an EXPR_STMT. Provided just 32890075Sobrien for backward compatibility. genrtl_expr_stmt_value() should be 32990075Sobrien used for new code. */ 33090075Sobrien 33190075Sobrienvoid 332132718Skangenrtl_expr_stmt (tree expr) 33390075Sobrien{ 33490075Sobrien genrtl_expr_stmt_value (expr, -1, 1); 33590075Sobrien} 33690075Sobrien 33790075Sobrien/* Generate the RTL for EXPR, which is an EXPR_STMT. WANT_VALUE tells 33890075Sobrien whether to (1) save the value of the expression, (0) discard it or 33990075Sobrien (-1) use expr_stmts_for_value to tell. The use of -1 is 34090075Sobrien deprecated, and retained only for backward compatibility. 341117395Skan MAYBE_LAST is nonzero if this EXPR_STMT might be the last statement 34290075Sobrien in expression statement. */ 34390075Sobrien 344132718Skanvoid 345132718Skangenrtl_expr_stmt_value (tree expr, int want_value, int maybe_last) 34690075Sobrien{ 34790075Sobrien if (expr != NULL_TREE) 34890075Sobrien { 349132718Skan emit_line_note (input_location); 350132718Skan 35190075Sobrien if (stmts_are_full_exprs_p ()) 35290075Sobrien expand_start_target_temps (); 353132718Skan 35490075Sobrien if (expr != error_mark_node) 35590075Sobrien expand_expr_stmt_value (expr, want_value, maybe_last); 356132718Skan 35790075Sobrien if (stmts_are_full_exprs_p ()) 35890075Sobrien expand_end_target_temps (); 35990075Sobrien } 36090075Sobrien} 36190075Sobrien 36290075Sobrien/* Generate the RTL for T, which is a DECL_STMT. */ 36390075Sobrien 36490075Sobrienvoid 365132718Skangenrtl_decl_stmt (tree t) 36690075Sobrien{ 36790075Sobrien tree decl; 368132718Skan emit_line_note (input_location); 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. */ 376132718Skan 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 384132718Skan 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); 389132718Skan 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 399132718Skangenrtl_if_stmt (tree t) 40090075Sobrien{ 40190075Sobrien tree cond; 40290075Sobrien genrtl_do_pushlevel (); 40390075Sobrien cond = expand_cond (IF_COND (t)); 404132718Skan emit_line_note (input_location); 40590075Sobrien expand_start_cond (cond, 0); 40690075Sobrien if (THEN_CLAUSE (t)) 407132718Skan { 408132718Skan tree nextt = THEN_CLAUSE (t); 409132718Skan 410132718Skan if (cond && integer_zerop (cond)) 411132718Skan nextt = expand_unreachable_stmt (nextt, warn_notreached); 412132718Skan expand_stmt (nextt); 413132718Skan } 414132718Skan 41590075Sobrien if (ELSE_CLAUSE (t)) 41690075Sobrien { 417132718Skan tree nextt = ELSE_CLAUSE (t); 41890075Sobrien expand_start_else (); 419132718Skan if (cond && integer_nonzerop (cond)) 420132718Skan nextt = expand_unreachable_stmt (nextt, warn_notreached); 421132718Skan expand_stmt (nextt); 42290075Sobrien } 42390075Sobrien expand_end_cond (); 42490075Sobrien} 42590075Sobrien 42690075Sobrien/* Generate the RTL for T, which is a WHILE_STMT. */ 42790075Sobrien 42890075Sobrienvoid 429132718Skangenrtl_while_stmt (tree t) 43090075Sobrien{ 431132718Skan tree cond = WHILE_COND (t); 432132718Skan 433132718Skan emit_line_note (input_location); 434132718Skan expand_start_loop (1); 43590075Sobrien genrtl_do_pushlevel (); 43690075Sobrien 437132718Skan if (cond && !integer_nonzerop (cond)) 438132718Skan { 439132718Skan cond = expand_cond (cond); 440132718Skan emit_line_note (input_location); 441132718Skan expand_exit_loop_top_cond (0, cond); 442132718Skan genrtl_do_pushlevel (); 443132718Skan } 444132718Skan 44590075Sobrien expand_stmt (WHILE_BODY (t)); 44690075Sobrien 44790075Sobrien expand_end_loop (); 44890075Sobrien} 44990075Sobrien 450132718Skan/* Generate the RTL for a DO_STMT with condition COND and loop BODY 451132718Skan body. This is reused for expanding unreachable WHILE_STMTS. */ 45290075Sobrien 453132718Skanstatic void 454132718Skangenrtl_do_stmt_1 (tree cond, tree body) 45590075Sobrien{ 45690075Sobrien /* Recognize the common special-case of do { ... } while (0) and do 45790075Sobrien not emit the loop widgetry in this case. In particular this 45890075Sobrien avoids cluttering the rtl with dummy loop notes, which can affect 459117395Skan alignment of adjacent labels. COND can be NULL due to parse 460117395Skan errors. */ 461117395Skan if (!cond || integer_zerop (cond)) 46290075Sobrien { 46390075Sobrien expand_start_null_loop (); 464132718Skan expand_stmt (body); 46590075Sobrien expand_end_null_loop (); 46690075Sobrien } 467132718Skan else if (integer_nonzerop (cond)) 468132718Skan { 469132718Skan emit_line_note (input_location); 470132718Skan expand_start_loop (1); 471132718Skan 472132718Skan expand_stmt (body); 473132718Skan 474132718Skan emit_line_note (input_location); 475132718Skan expand_end_loop (); 476132718Skan } 47790075Sobrien else 47890075Sobrien { 479132718Skan emit_line_note (input_location); 48090075Sobrien expand_start_loop_continue_elsewhere (1); 48190075Sobrien 482132718Skan expand_stmt (body); 48390075Sobrien 48490075Sobrien expand_loop_continue_here (); 48590075Sobrien cond = expand_cond (cond); 486132718Skan emit_line_note (input_location); 48790075Sobrien expand_exit_loop_if_false (0, cond); 48890075Sobrien expand_end_loop (); 48990075Sobrien } 49090075Sobrien} 49190075Sobrien 492132718Skan/* Generate the RTL for T, which is a DO_STMT. */ 493132718Skan 494132718Skanvoid 495132718Skangenrtl_do_stmt (tree t) 496132718Skan{ 497132718Skan genrtl_do_stmt_1 (DO_COND (t), DO_BODY (t)); 498132718Skan} 499132718Skan 50090075Sobrien/* Build the node for a return statement and return it. */ 50190075Sobrien 50290075Sobrientree 503132718Skanbuild_return_stmt (tree expr) 50490075Sobrien{ 50590075Sobrien return (build_stmt (RETURN_STMT, expr)); 50690075Sobrien} 50790075Sobrien 50890075Sobrien/* Generate the RTL for STMT, which is a RETURN_STMT. */ 50990075Sobrien 51090075Sobrienvoid 511132718Skangenrtl_return_stmt (tree stmt) 51290075Sobrien{ 51390075Sobrien tree expr; 51490075Sobrien 515117395Skan expr = RETURN_STMT_EXPR (stmt); 51690075Sobrien 517132718Skan emit_line_note (input_location); 51890075Sobrien if (!expr) 51990075Sobrien expand_null_return (); 52090075Sobrien else 52190075Sobrien { 52290075Sobrien expand_start_target_temps (); 52390075Sobrien expand_return (expr); 52490075Sobrien expand_end_target_temps (); 52590075Sobrien } 52690075Sobrien} 52790075Sobrien 52890075Sobrien/* Generate the RTL for T, which is a FOR_STMT. */ 52990075Sobrien 53090075Sobrienvoid 531132718Skangenrtl_for_stmt (tree t) 53290075Sobrien{ 533132718Skan tree cond = FOR_COND (t); 534132718Skan location_t saved_loc; 53590075Sobrien 53690075Sobrien if (NEW_FOR_SCOPE_P (t)) 53790075Sobrien genrtl_do_pushlevel (); 53890075Sobrien 53990075Sobrien expand_stmt (FOR_INIT_STMT (t)); 54090075Sobrien 54190075Sobrien /* Expand the initialization. */ 542132718Skan emit_line_note (input_location); 543132718Skan if (FOR_EXPR (t)) 544132718Skan expand_start_loop_continue_elsewhere (1); 545132718Skan else 546132718Skan expand_start_loop (1); 54790075Sobrien genrtl_do_pushlevel (); 54890075Sobrien 54990075Sobrien /* Save the filename and line number so that we expand the FOR_EXPR 55090075Sobrien we can reset them back to the saved values. */ 551132718Skan saved_loc = input_location; 55290075Sobrien 55390075Sobrien /* Expand the condition. */ 554132718Skan if (cond && !integer_nonzerop (cond)) 555132718Skan { 556132718Skan cond = expand_cond (cond); 557132718Skan emit_line_note (input_location); 558132718Skan expand_exit_loop_top_cond (0, cond); 559132718Skan genrtl_do_pushlevel (); 560132718Skan } 56190075Sobrien 56290075Sobrien /* Expand the body. */ 56390075Sobrien expand_stmt (FOR_BODY (t)); 56490075Sobrien 56590075Sobrien /* Expand the increment expression. */ 566132718Skan input_location = saved_loc; 567132718Skan emit_line_note (input_location); 56890075Sobrien if (FOR_EXPR (t)) 569132718Skan { 570132718Skan expand_loop_continue_here (); 571132718Skan genrtl_expr_stmt (FOR_EXPR (t)); 572132718Skan } 57390075Sobrien expand_end_loop (); 57490075Sobrien} 57590075Sobrien 57690075Sobrien/* Build a break statement node and return it. */ 57790075Sobrien 57890075Sobrientree 579132718Skanbuild_break_stmt (void) 58090075Sobrien{ 58190075Sobrien return (build_stmt (BREAK_STMT)); 58290075Sobrien} 58390075Sobrien 58490075Sobrien/* Generate the RTL for a BREAK_STMT. */ 58590075Sobrien 58690075Sobrienvoid 587132718Skangenrtl_break_stmt (void) 58890075Sobrien{ 589132718Skan emit_line_note (input_location); 59090075Sobrien if ( ! expand_exit_something ()) 591132718Skan abort (); 59290075Sobrien} 59390075Sobrien 59490075Sobrien/* Build a continue statement node and return it. */ 59590075Sobrien 59690075Sobrientree 597132718Skanbuild_continue_stmt (void) 59890075Sobrien{ 59990075Sobrien return (build_stmt (CONTINUE_STMT)); 60090075Sobrien} 60190075Sobrien 60290075Sobrien/* Generate the RTL for a CONTINUE_STMT. */ 60390075Sobrien 60490075Sobrienvoid 605132718Skangenrtl_continue_stmt (void) 60690075Sobrien{ 607132718Skan emit_line_note (input_location); 60890075Sobrien if (! expand_continue_loop (0)) 609132718Skan abort (); 61090075Sobrien} 61190075Sobrien 61290075Sobrien/* Generate the RTL for T, which is a SCOPE_STMT. */ 61390075Sobrien 61490075Sobrienvoid 615132718Skangenrtl_scope_stmt (tree t) 61690075Sobrien{ 61790075Sobrien tree block = SCOPE_STMT_BLOCK (t); 61890075Sobrien 61990075Sobrien if (!SCOPE_NO_CLEANUPS_P (t)) 62090075Sobrien { 62190075Sobrien if (SCOPE_BEGIN_P (t)) 62290075Sobrien expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t), block); 62390075Sobrien else if (SCOPE_END_P (t)) 62490075Sobrien expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), 0); 62590075Sobrien } 62690075Sobrien else if (!SCOPE_NULLIFIED_P (t)) 62790075Sobrien { 628132718Skan rtx note = emit_note (SCOPE_BEGIN_P (t) 629132718Skan ? NOTE_INSN_BLOCK_BEG : NOTE_INSN_BLOCK_END); 63090075Sobrien NOTE_BLOCK (note) = block; 63190075Sobrien } 63290075Sobrien 63390075Sobrien /* If we're at the end of a scope that contains inlined nested 63490075Sobrien functions, we have to decide whether or not to write them out. */ 63590075Sobrien if (block && SCOPE_END_P (t)) 63690075Sobrien { 63790075Sobrien tree fn; 63890075Sobrien 63990075Sobrien for (fn = BLOCK_VARS (block); fn; fn = TREE_CHAIN (fn)) 64090075Sobrien { 641132718Skan if (TREE_CODE (fn) == FUNCTION_DECL 64290075Sobrien && DECL_CONTEXT (fn) == current_function_decl 643110611Skan && DECL_SAVED_INSNS (fn) 644132718Skan && DECL_SAVED_INSNS (fn)->saved_for_inline 64590075Sobrien && !TREE_ASM_WRITTEN (fn) 64690075Sobrien && TREE_ADDRESSABLE (fn)) 64790075Sobrien { 64890075Sobrien push_function_context (); 64990075Sobrien output_inline_function (fn); 65090075Sobrien pop_function_context (); 65190075Sobrien } 65290075Sobrien } 65390075Sobrien } 65490075Sobrien} 65590075Sobrien 65690075Sobrien/* Generate the RTL for T, which is a SWITCH_STMT. */ 65790075Sobrien 65890075Sobrienvoid 659132718Skangenrtl_switch_stmt (tree t) 66090075Sobrien{ 66190075Sobrien tree cond; 66290075Sobrien genrtl_do_pushlevel (); 663132718Skan 66490075Sobrien cond = expand_cond (SWITCH_COND (t)); 66590075Sobrien if (cond == error_mark_node) 66690075Sobrien /* The code is in error, but we don't want expand_end_case to 66790075Sobrien crash. */ 668132718Skan cond = truthvalue_false_node; 66990075Sobrien 670132718Skan emit_line_note (input_location); 67190075Sobrien expand_start_case (1, cond, TREE_TYPE (cond), "switch statement"); 672132718Skan expand_stmt (expand_unreachable_stmt (SWITCH_BODY (t), warn_notreached)); 67396263Sobrien expand_end_case_type (cond, SWITCH_TYPE (t)); 67490075Sobrien} 67590075Sobrien 67690075Sobrien/* Create a CASE_LABEL tree node and return it. */ 67790075Sobrien 67890075Sobrientree 679132718Skanbuild_case_label (tree low_value, tree high_value, tree label_decl) 68090075Sobrien{ 68190075Sobrien return build_stmt (CASE_LABEL, low_value, high_value, label_decl); 68290075Sobrien} 68390075Sobrien 68490075Sobrien 68590075Sobrien/* Generate the RTL for a CASE_LABEL. */ 68690075Sobrien 687132718Skanvoid 688132718Skangenrtl_case_label (tree case_label) 68990075Sobrien{ 69090075Sobrien tree duplicate; 69190075Sobrien tree cleanup; 69290075Sobrien 69390075Sobrien cleanup = last_cleanup_this_contour (); 69490075Sobrien if (cleanup) 69590075Sobrien { 69690075Sobrien static int explained = 0; 697132718Skan warning ("destructor needed for `%D'", (TREE_PURPOSE (cleanup))); 69890075Sobrien warning ("where case label appears here"); 69990075Sobrien if (!explained) 70090075Sobrien { 70190075Sobrien warning ("(enclose actions of previous case statements requiring destructors in their own scope.)"); 70290075Sobrien explained = 1; 70390075Sobrien } 70490075Sobrien } 70590075Sobrien 706132718Skan add_case_node (CASE_LOW (case_label), CASE_HIGH (case_label), 70790075Sobrien CASE_LABEL_DECL (case_label), &duplicate); 70890075Sobrien} 70990075Sobrien 71090075Sobrien/* Generate the RTL for T, which is a COMPOUND_STMT. */ 71190075Sobrien 71290075Sobrienvoid 713132718Skangenrtl_compound_stmt (tree t) 71490075Sobrien{ 71590075Sobrien#ifdef ENABLE_CHECKING 71690075Sobrien struct nesting *n = current_nesting_level (); 71790075Sobrien#endif 71890075Sobrien 71990075Sobrien expand_stmt (COMPOUND_BODY (t)); 72090075Sobrien 72190075Sobrien#ifdef ENABLE_CHECKING 72290075Sobrien /* Make sure that we've pushed and popped the same number of levels. */ 72390075Sobrien if (!COMPOUND_STMT_NO_SCOPE (t) && n != current_nesting_level ()) 72490075Sobrien abort (); 72590075Sobrien#endif 72690075Sobrien} 72790075Sobrien 72890075Sobrien/* Generate the RTL for an ASM_STMT. */ 72990075Sobrien 73090075Sobrienvoid 731132718Skangenrtl_asm_stmt (tree cv_qualifier, tree string, tree output_operands, 732132718Skan tree input_operands, tree clobbers, int asm_input_p) 73390075Sobrien{ 73490075Sobrien if (cv_qualifier != NULL_TREE 73590075Sobrien && cv_qualifier != ridpointers[(int) RID_VOLATILE]) 73690075Sobrien { 73790075Sobrien warning ("%s qualifier ignored on asm", 73890075Sobrien IDENTIFIER_POINTER (cv_qualifier)); 73990075Sobrien cv_qualifier = NULL_TREE; 74090075Sobrien } 74190075Sobrien 742132718Skan emit_line_note (input_location); 74390075Sobrien if (asm_input_p) 744110611Skan expand_asm (string, cv_qualifier != NULL_TREE); 74590075Sobrien else 746132718Skan c_expand_asm_operands (string, output_operands, input_operands, 74790075Sobrien clobbers, cv_qualifier != NULL_TREE, 748132718Skan input_location); 74990075Sobrien} 75090075Sobrien 751132718Skan/* Generate the RTL for a CLEANUP_STMT. */ 75290075Sobrien 753132718Skanvoid 754132718Skangenrtl_cleanup_stmt (tree t) 75590075Sobrien{ 75696263Sobrien tree decl = CLEANUP_DECL (t); 757132718Skan if (!decl || !DECL_P (decl) 758132718Skan || (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node)) 75996263Sobrien expand_decl_cleanup_eh (decl, CLEANUP_EXPR (t), CLEANUP_EH_ONLY (t)); 76090075Sobrien} 76190075Sobrien 76290075Sobrien/* We're about to expand T, a statement. Set up appropriate context 76390075Sobrien for the substitution. */ 76490075Sobrien 76590075Sobrienvoid 766132718Skanprep_stmt (tree t) 76790075Sobrien{ 76890075Sobrien if (!STMT_LINENO_FOR_FN_P (t)) 769132718Skan input_line = STMT_LINENO (t); 77090075Sobrien current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t); 77190075Sobrien} 77290075Sobrien 77390075Sobrien/* Generate the RTL for the statement T, its substatements, and any 77490075Sobrien other statements at its nesting level. */ 77590075Sobrien 77690075Sobrienvoid 777132718Skanexpand_stmt (tree t) 77890075Sobrien{ 77990075Sobrien while (t && t != error_mark_node) 78090075Sobrien { 78190075Sobrien int saved_stmts_are_full_exprs_p; 78290075Sobrien 78390075Sobrien /* Set up context appropriately for handling this statement. */ 78490075Sobrien saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); 78590075Sobrien prep_stmt (t); 78690075Sobrien 78790075Sobrien switch (TREE_CODE (t)) 78890075Sobrien { 78990075Sobrien case FILE_STMT: 79090075Sobrien input_filename = FILE_STMT_FILENAME (t); 79190075Sobrien break; 79290075Sobrien 79390075Sobrien case RETURN_STMT: 79490075Sobrien genrtl_return_stmt (t); 795132718Skan t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached); 796132718Skan goto process_t; 79790075Sobrien 79890075Sobrien case EXPR_STMT: 79990075Sobrien genrtl_expr_stmt_value (EXPR_STMT_EXPR (t), TREE_ADDRESSABLE (t), 80090075Sobrien TREE_CHAIN (t) == NULL 80190075Sobrien || (TREE_CODE (TREE_CHAIN (t)) == SCOPE_STMT 80290075Sobrien && TREE_CHAIN (TREE_CHAIN (t)) == NULL)); 80390075Sobrien break; 80490075Sobrien 80590075Sobrien case DECL_STMT: 80690075Sobrien genrtl_decl_stmt (t); 80790075Sobrien break; 80890075Sobrien 80990075Sobrien case FOR_STMT: 81090075Sobrien genrtl_for_stmt (t); 81190075Sobrien break; 81290075Sobrien 81390075Sobrien case WHILE_STMT: 81490075Sobrien genrtl_while_stmt (t); 81590075Sobrien break; 81690075Sobrien 81790075Sobrien case DO_STMT: 81890075Sobrien genrtl_do_stmt (t); 81990075Sobrien break; 82090075Sobrien 82190075Sobrien case IF_STMT: 82290075Sobrien genrtl_if_stmt (t); 82390075Sobrien break; 82490075Sobrien 82590075Sobrien case COMPOUND_STMT: 82690075Sobrien genrtl_compound_stmt (t); 82790075Sobrien break; 82890075Sobrien 82990075Sobrien case BREAK_STMT: 83090075Sobrien genrtl_break_stmt (); 831132718Skan t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached); 832132718Skan goto process_t; 83390075Sobrien 83490075Sobrien case CONTINUE_STMT: 83590075Sobrien genrtl_continue_stmt (); 836132718Skan t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached); 837132718Skan goto process_t; 83890075Sobrien 83990075Sobrien case SWITCH_STMT: 84090075Sobrien genrtl_switch_stmt (t); 84190075Sobrien break; 84290075Sobrien 84390075Sobrien case CASE_LABEL: 84490075Sobrien genrtl_case_label (t); 84590075Sobrien break; 84690075Sobrien 84790075Sobrien case LABEL_STMT: 84890075Sobrien expand_label (LABEL_STMT_LABEL (t)); 84990075Sobrien break; 85090075Sobrien 85190075Sobrien case GOTO_STMT: 852117395Skan /* Emit information for branch prediction. */ 853117395Skan if (!GOTO_FAKE_P (t) 854117395Skan && TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL 855117395Skan && flag_guess_branch_prob) 856117395Skan { 857132718Skan rtx note = emit_note (NOTE_INSN_PREDICTION); 858117395Skan 859117395Skan NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_GOTO, NOT_TAKEN); 860117395Skan } 86190075Sobrien genrtl_goto_stmt (GOTO_DESTINATION (t)); 862132718Skan t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached); 863132718Skan goto process_t; 86490075Sobrien 86590075Sobrien case ASM_STMT: 86690075Sobrien genrtl_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t), 86790075Sobrien ASM_OUTPUTS (t), ASM_INPUTS (t), 86890075Sobrien ASM_CLOBBERS (t), ASM_INPUT_P (t)); 86990075Sobrien break; 87090075Sobrien 87190075Sobrien case SCOPE_STMT: 87290075Sobrien genrtl_scope_stmt (t); 87390075Sobrien break; 87490075Sobrien 87596263Sobrien case CLEANUP_STMT: 876132718Skan genrtl_cleanup_stmt (t); 87796263Sobrien break; 87896263Sobrien 87990075Sobrien default: 88090075Sobrien if (lang_expand_stmt) 88190075Sobrien (*lang_expand_stmt) (t); 882132718Skan else 88390075Sobrien abort (); 88490075Sobrien break; 88590075Sobrien } 88690075Sobrien 887132718Skan /* Go on to the next statement in this scope. */ 888132718Skan t = TREE_CHAIN (t); 889132718Skan 890132718Skan process_t: 89190075Sobrien /* Restore saved state. */ 89290075Sobrien current_stmt_tree ()->stmts_are_full_exprs_p 89390075Sobrien = saved_stmts_are_full_exprs_p; 894132718Skan } 895132718Skan} 896132718Skan 897132718Skan/* If *TP is a potentially reachable label, return nonzero. */ 89890075Sobrien 899132718Skanstatic tree 900132718Skanfind_reachable_label_1 (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, 901132718Skan void *data ATTRIBUTE_UNUSED) 902132718Skan{ 903132718Skan switch (TREE_CODE (*tp)) 904132718Skan { 905132718Skan case LABEL_STMT: 906132718Skan case CASE_LABEL: 907132718Skan return *tp; 908132718Skan 909132718Skan default: 910132718Skan break; 911132718Skan } 912132718Skan return NULL_TREE; 913132718Skan} 914132718Skan 915132718Skan/* Determine whether expression EXP contains a potentially 916132718Skan reachable label. */ 917132718Skanstatic tree 918132718Skanfind_reachable_label (tree exp) 919132718Skan{ 920132718Skan location_t saved_loc = input_location; 921132718Skan tree ret = walk_tree_without_duplicates 922132718Skan (&exp, find_reachable_label_1, NULL); 923132718Skan input_location = saved_loc; 924132718Skan return ret; 925132718Skan} 926132718Skan 927132718Skan/* Expand an unreachable if statement, T. This function returns 928132718Skan true if the IF_STMT contains a potentially reachable code_label. */ 929132718Skanstatic bool 930132718Skanexpand_unreachable_if_stmt (tree t) 931132718Skan{ 932132718Skan tree n; 933132718Skan 934132718Skan if (find_reachable_label (IF_COND (t)) != NULL_TREE) 935132718Skan { 936132718Skan genrtl_if_stmt (t); 937132718Skan return true; 938132718Skan } 939132718Skan 940132718Skan if (THEN_CLAUSE (t) && ELSE_CLAUSE (t)) 941132718Skan { 942132718Skan n = expand_unreachable_stmt (THEN_CLAUSE (t), 0); 943132718Skan 944132718Skan if (n != NULL_TREE) 945132718Skan { 946132718Skan rtx label; 947132718Skan expand_stmt (n); 948132718Skan label = gen_label_rtx (); 949132718Skan emit_jump (label); 950132718Skan expand_stmt (expand_unreachable_stmt (ELSE_CLAUSE (t), 0)); 951132718Skan emit_label (label); 952132718Skan return true; 953132718Skan } 954132718Skan else 955132718Skan n = expand_unreachable_stmt (ELSE_CLAUSE (t), 0); 956132718Skan } 957132718Skan else if (THEN_CLAUSE (t)) 958132718Skan n = expand_unreachable_stmt (THEN_CLAUSE (t), 0); 959132718Skan else if (ELSE_CLAUSE (t)) 960132718Skan n = expand_unreachable_stmt (ELSE_CLAUSE (t), 0); 961132718Skan else 962132718Skan n = NULL_TREE; 963132718Skan 964132718Skan expand_stmt (n); 965132718Skan 966132718Skan return n != NULL_TREE; 967132718Skan} 968132718Skan 969132718Skan/* Expand an unreachable statement list. This function skips all 970132718Skan statements preceding the first potentially reachable label and 971132718Skan then returns the label (or, in same cases, the statement after 972132718Skan one containing the label). */ 973132718Skanstatic tree 974132718Skanexpand_unreachable_stmt (tree t, int warn) 975132718Skan{ 976132718Skan int saved; 977132718Skan 978132718Skan while (t && t != error_mark_node) 979132718Skan { 980132718Skan if (warn) 981132718Skan switch (TREE_CODE (t)) 982132718Skan { 983132718Skan case BREAK_STMT: 984132718Skan case CONTINUE_STMT: 985132718Skan case EXPR_STMT: 986132718Skan case GOTO_STMT: 987132718Skan case IF_STMT: 988132718Skan case RETURN_STMT: 989132718Skan if (!STMT_LINENO_FOR_FN_P (t)) 990132718Skan input_line = STMT_LINENO (t); 991132718Skan warning("will never be executed"); 992132718Skan warn = false; 993132718Skan break; 994132718Skan 995132718Skan default: 996132718Skan break; 997132718Skan } 998132718Skan 999132718Skan switch (TREE_CODE (t)) 1000132718Skan { 1001132718Skan case GOTO_STMT: 1002132718Skan case CONTINUE_STMT: 1003132718Skan case BREAK_STMT: 1004132718Skan break; 1005132718Skan 1006132718Skan case FILE_STMT: 1007132718Skan input_filename = FILE_STMT_FILENAME (t); 1008132718Skan break; 1009132718Skan 1010132718Skan case RETURN_STMT: 1011132718Skan if (find_reachable_label (RETURN_STMT_EXPR (t)) != NULL_TREE) 1012132718Skan return t; 1013132718Skan break; 1014132718Skan 1015132718Skan case EXPR_STMT: 1016132718Skan if (find_reachable_label (EXPR_STMT_EXPR (t)) != NULL_TREE) 1017132718Skan return t; 1018132718Skan break; 1019132718Skan 1020132718Skan case IF_STMT: 1021132718Skan if (expand_unreachable_if_stmt (t)) 1022132718Skan return TREE_CHAIN (t); 1023132718Skan break; 1024132718Skan 1025132718Skan case WHILE_STMT: 1026132718Skan /* If the start of a while statement is unreachable, there is 1027132718Skan no need to rotate the loop, instead the WHILE_STMT can be 1028132718Skan expanded like a DO_STMT. */ 1029132718Skan genrtl_do_stmt_1 (WHILE_COND (t), WHILE_BODY (t)); 1030132718Skan return TREE_CHAIN (t); 1031132718Skan 1032132718Skan case COMPOUND_STMT: 1033132718Skan { 1034132718Skan tree n; 1035132718Skan n = expand_unreachable_stmt (COMPOUND_BODY (t), warn); 1036132718Skan if (n != NULL_TREE) 1037132718Skan { 1038132718Skan expand_stmt (n); 1039132718Skan return TREE_CHAIN (t); 1040132718Skan } 1041132718Skan warn = false; 1042132718Skan break; 1043132718Skan } 1044132718Skan 1045132718Skan case SCOPE_STMT: 1046132718Skan saved = stmts_are_full_exprs_p (); 1047132718Skan prep_stmt (t); 1048132718Skan genrtl_scope_stmt (t); 1049132718Skan current_stmt_tree ()->stmts_are_full_exprs_p = saved; 1050132718Skan break; 1051132718Skan 1052132718Skan default: 1053132718Skan return t; 1054132718Skan } 105590075Sobrien t = TREE_CHAIN (t); 105690075Sobrien } 1057132718Skan return NULL_TREE; 105890075Sobrien} 1059