1169689Skan/* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c. 2169689Skan 3169689Skan Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 4169689Skan Contributed by Jason Merrill <jason@redhat.com> 5169689Skan 6169689SkanThis file is part of GCC. 7169689Skan 8169689SkanGCC is free software; you can redistribute it and/or modify it under 9169689Skanthe terms of the GNU General Public License as published by the Free 10169689SkanSoftware Foundation; either version 2, or (at your option) any later 11169689Skanversion. 12169689Skan 13169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY 14169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or 15169689SkanFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16169689Skanfor more details. 17169689Skan 18169689SkanYou should have received a copy of the GNU General Public License 19169689Skanalong with GCC; see the file COPYING. If not, write to the Free 20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21169689Skan02110-1301, USA. */ 22169689Skan 23169689Skan#include "config.h" 24169689Skan#include "system.h" 25169689Skan#include "coretypes.h" 26169689Skan#include "tm.h" 27169689Skan#include "tree.h" 28169689Skan#include "cp-tree.h" 29169689Skan#include "c-common.h" 30169689Skan#include "toplev.h" 31169689Skan#include "tree-gimple.h" 32169689Skan#include "hashtab.h" 33169689Skan#include "pointer-set.h" 34169689Skan#include "flags.h" 35169689Skan 36169689Skan/* Local declarations. */ 37169689Skan 38169689Skanenum bc_t { bc_break = 0, bc_continue = 1 }; 39169689Skan 40169689Skan/* Stack of labels which are targets for "break" or "continue", 41169689Skan linked through TREE_CHAIN. */ 42169689Skanstatic tree bc_label[2]; 43169689Skan 44169689Skan/* Begin a scope which can be exited by a break or continue statement. BC 45169689Skan indicates which. 46169689Skan 47169689Skan Just creates a label and pushes it into the current context. */ 48169689Skan 49169689Skanstatic tree 50169689Skanbegin_bc_block (enum bc_t bc) 51169689Skan{ 52169689Skan tree label = create_artificial_label (); 53169689Skan TREE_CHAIN (label) = bc_label[bc]; 54169689Skan bc_label[bc] = label; 55169689Skan return label; 56169689Skan} 57169689Skan 58169689Skan/* Finish a scope which can be exited by a break or continue statement. 59169689Skan LABEL was returned from the most recent call to begin_bc_block. BODY is 60169689Skan an expression for the contents of the scope. 61169689Skan 62169689Skan If we saw a break (or continue) in the scope, append a LABEL_EXPR to 63169689Skan body. Otherwise, just forget the label. */ 64169689Skan 65169689Skanstatic tree 66169689Skanfinish_bc_block (enum bc_t bc, tree label, tree body) 67169689Skan{ 68169689Skan gcc_assert (label == bc_label[bc]); 69169689Skan 70169689Skan if (TREE_USED (label)) 71169689Skan { 72169689Skan tree t, sl = NULL; 73169689Skan 74169689Skan t = build1 (LABEL_EXPR, void_type_node, label); 75169689Skan 76169689Skan append_to_statement_list (body, &sl); 77169689Skan append_to_statement_list (t, &sl); 78169689Skan body = sl; 79169689Skan } 80169689Skan 81169689Skan bc_label[bc] = TREE_CHAIN (label); 82169689Skan TREE_CHAIN (label) = NULL_TREE; 83169689Skan return body; 84169689Skan} 85169689Skan 86169689Skan/* Build a GOTO_EXPR to represent a break or continue statement. BC 87169689Skan indicates which. */ 88169689Skan 89169689Skanstatic tree 90169689Skanbuild_bc_goto (enum bc_t bc) 91169689Skan{ 92169689Skan tree label = bc_label[bc]; 93169689Skan 94169689Skan if (label == NULL_TREE) 95169689Skan { 96169689Skan if (bc == bc_break) 97169689Skan error ("break statement not within loop or switch"); 98169689Skan else 99169689Skan error ("continue statement not within loop or switch"); 100169689Skan 101169689Skan return NULL_TREE; 102169689Skan } 103169689Skan 104169689Skan /* Mark the label used for finish_bc_block. */ 105169689Skan TREE_USED (label) = 1; 106169689Skan return build1 (GOTO_EXPR, void_type_node, label); 107169689Skan} 108169689Skan 109169689Skan/* Genericize a TRY_BLOCK. */ 110169689Skan 111169689Skanstatic void 112169689Skangenericize_try_block (tree *stmt_p) 113169689Skan{ 114169689Skan tree body = TRY_STMTS (*stmt_p); 115169689Skan tree cleanup = TRY_HANDLERS (*stmt_p); 116169689Skan 117169689Skan gimplify_stmt (&body); 118169689Skan 119169689Skan if (CLEANUP_P (*stmt_p)) 120169689Skan /* A cleanup is an expression, so it doesn't need to be genericized. */; 121169689Skan else 122169689Skan gimplify_stmt (&cleanup); 123169689Skan 124169689Skan *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup); 125169689Skan} 126169689Skan 127169689Skan/* Genericize a HANDLER by converting to a CATCH_EXPR. */ 128169689Skan 129169689Skanstatic void 130169689Skangenericize_catch_block (tree *stmt_p) 131169689Skan{ 132169689Skan tree type = HANDLER_TYPE (*stmt_p); 133169689Skan tree body = HANDLER_BODY (*stmt_p); 134169689Skan 135169689Skan gimplify_stmt (&body); 136169689Skan 137169689Skan /* FIXME should the caught type go in TREE_TYPE? */ 138169689Skan *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body); 139169689Skan} 140169689Skan 141169689Skan/* Genericize an EH_SPEC_BLOCK by converting it to a 142169689Skan TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */ 143169689Skan 144169689Skanstatic void 145169689Skangenericize_eh_spec_block (tree *stmt_p) 146169689Skan{ 147169689Skan tree body = EH_SPEC_STMTS (*stmt_p); 148169689Skan tree allowed = EH_SPEC_RAISES (*stmt_p); 149169689Skan tree failure = build_call (call_unexpected_node, 150169689Skan tree_cons (NULL_TREE, build_exc_ptr (), 151169689Skan NULL_TREE)); 152169689Skan gimplify_stmt (&body); 153169689Skan 154169689Skan *stmt_p = gimple_build_eh_filter (body, allowed, failure); 155169689Skan} 156169689Skan 157169689Skan/* Genericize an IF_STMT by turning it into a COND_EXPR. */ 158169689Skan 159169689Skanstatic void 160169689Skangimplify_if_stmt (tree *stmt_p) 161169689Skan{ 162169689Skan tree stmt, cond, then_, else_; 163169689Skan 164169689Skan stmt = *stmt_p; 165169689Skan cond = IF_COND (stmt); 166169689Skan then_ = THEN_CLAUSE (stmt); 167169689Skan else_ = ELSE_CLAUSE (stmt); 168169689Skan 169169689Skan if (!then_) 170169689Skan then_ = build_empty_stmt (); 171169689Skan if (!else_) 172169689Skan else_ = build_empty_stmt (); 173169689Skan 174169689Skan if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_)) 175169689Skan stmt = then_; 176169689Skan else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_)) 177169689Skan stmt = else_; 178169689Skan else 179169689Skan stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_); 180169689Skan *stmt_p = stmt; 181169689Skan} 182169689Skan 183169689Skan/* Build a generic representation of one of the C loop forms. COND is the 184169689Skan loop condition or NULL_TREE. BODY is the (possibly compound) statement 185169689Skan controlled by the loop. INCR is the increment expression of a for-loop, 186169689Skan or NULL_TREE. COND_IS_FIRST indicates whether the condition is 187169689Skan evaluated before the loop body as in while and for loops, or after the 188169689Skan loop body as in do-while loops. */ 189169689Skan 190169689Skanstatic tree 191260919Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 192260919Spfggimplify_cp_loop (tree cond, tree body, tree incr, tree attrs, 193260919Spfg bool cond_is_first, tree inner_foreach) 194260919Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 195169689Skan{ 196169689Skan tree top, entry, exit, cont_block, break_block, stmt_list, t; 197169689Skan location_t stmt_locus; 198169689Skan 199169689Skan stmt_locus = input_location; 200169689Skan stmt_list = NULL_TREE; 201169689Skan entry = NULL_TREE; 202169689Skan 203169689Skan break_block = begin_bc_block (bc_break); 204169689Skan cont_block = begin_bc_block (bc_continue); 205169689Skan 206169689Skan /* If condition is zero don't generate a loop construct. */ 207169689Skan if (cond && integer_zerop (cond)) 208169689Skan { 209169689Skan top = NULL_TREE; 210169689Skan exit = NULL_TREE; 211169689Skan if (cond_is_first) 212169689Skan { 213169689Skan t = build_bc_goto (bc_break); 214169689Skan append_to_statement_list (t, &stmt_list); 215169689Skan } 216169689Skan } 217169689Skan else 218169689Skan { 219169689Skan /* If we use a LOOP_EXPR here, we have to feed the whole thing 220169689Skan back through the main gimplifier to lower it. Given that we 221169689Skan have to gimplify the loop body NOW so that we can resolve 222169689Skan break/continue stmts, seems easier to just expand to gotos. */ 223169689Skan top = build1 (LABEL_EXPR, void_type_node, NULL_TREE); 224169689Skan 225169689Skan /* If we have an exit condition, then we build an IF with gotos either 226169689Skan out of the loop, or to the top of it. If there's no exit condition, 227169689Skan then we just build a jump back to the top. */ 228169689Skan exit = build_and_jump (&LABEL_EXPR_LABEL (top)); 229260919Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 230260919Spfg 231260919Spfg /* Add the attributes to the 'top' label. */ 232260919Spfg decl_attributes (&LABEL_EXPR_LABEL (top), attrs, 0); 233260919Spfg 234260919Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 235169689Skan if (cond && !integer_nonzerop (cond)) 236169689Skan { 237169689Skan t = build_bc_goto (bc_break); 238169689Skan exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t); 239169689Skan gimplify_stmt (&exit); 240169689Skan 241169689Skan if (cond_is_first) 242169689Skan { 243169689Skan if (incr) 244169689Skan { 245169689Skan entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE); 246169689Skan t = build_and_jump (&LABEL_EXPR_LABEL (entry)); 247169689Skan } 248169689Skan else 249169689Skan t = build_bc_goto (bc_continue); 250169689Skan append_to_statement_list (t, &stmt_list); 251169689Skan } 252169689Skan } 253169689Skan } 254169689Skan 255169689Skan gimplify_stmt (&body); 256169689Skan gimplify_stmt (&incr); 257169689Skan 258169689Skan body = finish_bc_block (bc_continue, cont_block, body); 259169689Skan 260169689Skan append_to_statement_list (top, &stmt_list); 261169689Skan append_to_statement_list (body, &stmt_list); 262169689Skan append_to_statement_list (incr, &stmt_list); 263169689Skan append_to_statement_list (entry, &stmt_list); 264169689Skan append_to_statement_list (exit, &stmt_list); 265169689Skan 266169689Skan annotate_all_with_locus (&stmt_list, stmt_locus); 267169689Skan 268169689Skan return finish_bc_block (bc_break, break_block, stmt_list); 269169689Skan} 270169689Skan 271169689Skan/* Gimplify a FOR_STMT node. Move the stuff in the for-init-stmt into the 272169689Skan prequeue and hand off to gimplify_cp_loop. */ 273169689Skan 274169689Skanstatic void 275169689Skangimplify_for_stmt (tree *stmt_p, tree *pre_p) 276169689Skan{ 277169689Skan tree stmt = *stmt_p; 278169689Skan 279169689Skan if (FOR_INIT_STMT (stmt)) 280169689Skan gimplify_and_add (FOR_INIT_STMT (stmt), pre_p); 281169689Skan 282260919Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 283169689Skan *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt), 284260919Spfg FOR_EXPR (stmt), FOR_ATTRIBUTES (stmt), 1, 285260919Spfg NULL_TREE); 286260919Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 287169689Skan} 288169689Skan 289169689Skan/* Gimplify a WHILE_STMT node. */ 290169689Skan 291169689Skanstatic void 292169689Skangimplify_while_stmt (tree *stmt_p) 293169689Skan{ 294169689Skan tree stmt = *stmt_p; 295260919Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 296169689Skan *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt), 297260919Spfg NULL_TREE, WHILE_ATTRIBUTES (stmt), 1, 298260919Spfg NULL_TREE); 299260919Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 300169689Skan} 301169689Skan 302169689Skan/* Gimplify a DO_STMT node. */ 303169689Skan 304169689Skanstatic void 305169689Skangimplify_do_stmt (tree *stmt_p) 306169689Skan{ 307169689Skan tree stmt = *stmt_p; 308260919Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 309169689Skan *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt), 310260919Spfg NULL_TREE, DO_ATTRIBUTES (stmt), 0, 311260919Spfg DO_FOREACH (stmt)); 312260919Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 313169689Skan} 314169689Skan 315169689Skan/* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */ 316169689Skan 317169689Skanstatic void 318169689Skangimplify_switch_stmt (tree *stmt_p) 319169689Skan{ 320169689Skan tree stmt = *stmt_p; 321169689Skan tree break_block, body; 322169689Skan location_t stmt_locus = input_location; 323169689Skan 324169689Skan break_block = begin_bc_block (bc_break); 325169689Skan 326169689Skan body = SWITCH_STMT_BODY (stmt); 327169689Skan if (!body) 328169689Skan body = build_empty_stmt (); 329169689Skan 330169689Skan *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt), 331169689Skan SWITCH_STMT_COND (stmt), body, NULL_TREE); 332169689Skan SET_EXPR_LOCATION (*stmt_p, stmt_locus); 333169689Skan gimplify_stmt (stmt_p); 334169689Skan 335169689Skan *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p); 336169689Skan} 337169689Skan 338169689Skan/* Hook into the middle of gimplifying an OMP_FOR node. This is required 339169689Skan in order to properly gimplify CONTINUE statements. Here we merely 340169689Skan manage the continue stack; the rest of the job is performed by the 341169689Skan regular gimplifier. */ 342169689Skan 343169689Skanstatic enum gimplify_status 344169689Skancp_gimplify_omp_for (tree *expr_p) 345169689Skan{ 346169689Skan tree for_stmt = *expr_p; 347169689Skan tree cont_block; 348169689Skan 349169689Skan /* Protect ourselves from recursion. */ 350169689Skan if (OMP_FOR_GIMPLIFYING_P (for_stmt)) 351169689Skan return GS_UNHANDLED; 352169689Skan OMP_FOR_GIMPLIFYING_P (for_stmt) = 1; 353169689Skan 354169689Skan /* Note that while technically the continue label is enabled too soon 355169689Skan here, we should have already diagnosed invalid continues nested within 356169689Skan statement expressions within the INIT, COND, or INCR expressions. */ 357169689Skan cont_block = begin_bc_block (bc_continue); 358169689Skan 359169689Skan gimplify_stmt (expr_p); 360169689Skan 361169689Skan OMP_FOR_BODY (for_stmt) 362169689Skan = finish_bc_block (bc_continue, cont_block, OMP_FOR_BODY (for_stmt)); 363169689Skan OMP_FOR_GIMPLIFYING_P (for_stmt) = 0; 364169689Skan 365169689Skan return GS_ALL_DONE; 366169689Skan} 367169689Skan 368169689Skan/* Gimplify an EXPR_STMT node. */ 369169689Skan 370169689Skanstatic void 371169689Skangimplify_expr_stmt (tree *stmt_p) 372169689Skan{ 373169689Skan tree stmt = EXPR_STMT_EXPR (*stmt_p); 374169689Skan 375169689Skan if (stmt == error_mark_node) 376169689Skan stmt = NULL; 377169689Skan 378169689Skan /* Gimplification of a statement expression will nullify the 379169689Skan statement if all its side effects are moved to *PRE_P and *POST_P. 380169689Skan 381169689Skan In this case we will not want to emit the gimplified statement. 382169689Skan However, we may still want to emit a warning, so we do that before 383169689Skan gimplification. */ 384169689Skan if (stmt && (extra_warnings || warn_unused_value)) 385169689Skan { 386169689Skan if (!TREE_SIDE_EFFECTS (stmt)) 387169689Skan { 388169689Skan if (!IS_EMPTY_STMT (stmt) 389169689Skan && !VOID_TYPE_P (TREE_TYPE (stmt)) 390169689Skan && !TREE_NO_WARNING (stmt)) 391169689Skan warning (OPT_Wextra, "statement with no effect"); 392169689Skan } 393169689Skan else if (warn_unused_value) 394169689Skan warn_if_unused_value (stmt, input_location); 395169689Skan } 396169689Skan 397169689Skan if (stmt == NULL_TREE) 398169689Skan stmt = alloc_stmt_list (); 399169689Skan 400169689Skan *stmt_p = stmt; 401169689Skan} 402169689Skan 403169689Skan/* Gimplify initialization from an AGGR_INIT_EXPR. */ 404169689Skan 405169689Skanstatic void 406169689Skancp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p) 407169689Skan{ 408169689Skan tree from = TREE_OPERAND (*expr_p, 1); 409169689Skan tree to = TREE_OPERAND (*expr_p, 0); 410169689Skan tree sub; 411169689Skan 412169689Skan /* What about code that pulls out the temp and uses it elsewhere? I 413169689Skan think that such code never uses the TARGET_EXPR as an initializer. If 414169689Skan I'm wrong, we'll abort because the temp won't have any RTL. In that 415169689Skan case, I guess we'll need to replace references somehow. */ 416169689Skan if (TREE_CODE (from) == TARGET_EXPR) 417169689Skan from = TARGET_EXPR_INITIAL (from); 418169689Skan 419169689Skan /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them 420169689Skan inside the TARGET_EXPR. */ 421169689Skan sub = expr_last (from); 422169689Skan 423169689Skan /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and 424169689Skan replace the slot operand with our target. 425169689Skan 426169689Skan Should we add a target parm to gimplify_expr instead? No, as in this 427169689Skan case we want to replace the INIT_EXPR. */ 428169689Skan if (TREE_CODE (sub) == AGGR_INIT_EXPR) 429169689Skan { 430169689Skan gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue); 431169689Skan TREE_OPERAND (sub, 2) = to; 432169689Skan *expr_p = from; 433169689Skan 434169689Skan /* The initialization is now a side-effect, so the container can 435169689Skan become void. */ 436169689Skan if (from != sub) 437169689Skan TREE_TYPE (from) = void_type_node; 438169689Skan } 439169689Skan} 440169689Skan 441169689Skan/* Gimplify a MUST_NOT_THROW_EXPR. */ 442169689Skan 443169689Skanstatic void 444169689Skangimplify_must_not_throw_expr (tree *expr_p, tree *pre_p) 445169689Skan{ 446169689Skan tree stmt = *expr_p; 447169689Skan tree temp = voidify_wrapper_expr (stmt, NULL); 448169689Skan tree body = TREE_OPERAND (stmt, 0); 449169689Skan 450169689Skan gimplify_stmt (&body); 451169689Skan 452169689Skan stmt = gimple_build_eh_filter (body, NULL_TREE, 453169689Skan build_call (terminate_node, NULL_TREE)); 454169689Skan 455169689Skan if (temp) 456169689Skan { 457169689Skan append_to_statement_list (stmt, pre_p); 458169689Skan *expr_p = temp; 459169689Skan } 460169689Skan else 461169689Skan *expr_p = stmt; 462169689Skan} 463169689Skan 464169689Skan/* Do C++-specific gimplification. Args are as for gimplify_expr. */ 465169689Skan 466169689Skanint 467169689Skancp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p) 468169689Skan{ 469169689Skan int saved_stmts_are_full_exprs_p = 0; 470169689Skan enum tree_code code = TREE_CODE (*expr_p); 471169689Skan enum gimplify_status ret; 472169689Skan 473169689Skan if (STATEMENT_CODE_P (code)) 474169689Skan { 475169689Skan saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); 476169689Skan current_stmt_tree ()->stmts_are_full_exprs_p 477169689Skan = STMT_IS_FULL_EXPR_P (*expr_p); 478169689Skan } 479169689Skan 480169689Skan switch (code) 481169689Skan { 482169689Skan case PTRMEM_CST: 483169689Skan *expr_p = cplus_expand_constant (*expr_p); 484169689Skan ret = GS_OK; 485169689Skan break; 486169689Skan 487169689Skan case AGGR_INIT_EXPR: 488169689Skan simplify_aggr_init_expr (expr_p); 489169689Skan ret = GS_OK; 490169689Skan break; 491169689Skan 492169689Skan case THROW_EXPR: 493169689Skan /* FIXME communicate throw type to backend, probably by moving 494169689Skan THROW_EXPR into ../tree.def. */ 495169689Skan *expr_p = TREE_OPERAND (*expr_p, 0); 496169689Skan ret = GS_OK; 497169689Skan break; 498169689Skan 499169689Skan case MUST_NOT_THROW_EXPR: 500169689Skan gimplify_must_not_throw_expr (expr_p, pre_p); 501169689Skan ret = GS_OK; 502169689Skan break; 503169689Skan 504169689Skan /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the 505169689Skan LHS of an assignment might also be involved in the RHS, as in bug 506169689Skan 25979. */ 507169689Skan case INIT_EXPR: 508169689Skan cp_gimplify_init_expr (expr_p, pre_p, post_p); 509169689Skan ret = GS_OK; 510169689Skan break; 511169689Skan 512169689Skan case EMPTY_CLASS_EXPR: 513169689Skan /* We create an empty CONSTRUCTOR with RECORD_TYPE. */ 514169689Skan *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL); 515169689Skan ret = GS_OK; 516169689Skan break; 517169689Skan 518169689Skan case BASELINK: 519169689Skan *expr_p = BASELINK_FUNCTIONS (*expr_p); 520169689Skan ret = GS_OK; 521169689Skan break; 522169689Skan 523169689Skan case TRY_BLOCK: 524169689Skan genericize_try_block (expr_p); 525169689Skan ret = GS_OK; 526169689Skan break; 527169689Skan 528169689Skan case HANDLER: 529169689Skan genericize_catch_block (expr_p); 530169689Skan ret = GS_OK; 531169689Skan break; 532169689Skan 533169689Skan case EH_SPEC_BLOCK: 534169689Skan genericize_eh_spec_block (expr_p); 535169689Skan ret = GS_OK; 536169689Skan break; 537169689Skan 538169689Skan case USING_STMT: 539169689Skan /* Just ignore for now. Eventually we will want to pass this on to 540169689Skan the debugger. */ 541169689Skan *expr_p = build_empty_stmt (); 542169689Skan ret = GS_ALL_DONE; 543169689Skan break; 544169689Skan 545169689Skan case IF_STMT: 546169689Skan gimplify_if_stmt (expr_p); 547169689Skan ret = GS_OK; 548169689Skan break; 549169689Skan 550169689Skan case FOR_STMT: 551169689Skan gimplify_for_stmt (expr_p, pre_p); 552169689Skan ret = GS_ALL_DONE; 553169689Skan break; 554169689Skan 555169689Skan case WHILE_STMT: 556169689Skan gimplify_while_stmt (expr_p); 557169689Skan ret = GS_ALL_DONE; 558169689Skan break; 559169689Skan 560169689Skan case DO_STMT: 561169689Skan gimplify_do_stmt (expr_p); 562169689Skan ret = GS_ALL_DONE; 563169689Skan break; 564169689Skan 565169689Skan case SWITCH_STMT: 566169689Skan gimplify_switch_stmt (expr_p); 567169689Skan ret = GS_ALL_DONE; 568169689Skan break; 569169689Skan 570169689Skan case OMP_FOR: 571169689Skan ret = cp_gimplify_omp_for (expr_p); 572169689Skan break; 573169689Skan 574169689Skan case CONTINUE_STMT: 575169689Skan *expr_p = build_bc_goto (bc_continue); 576169689Skan ret = GS_ALL_DONE; 577169689Skan break; 578169689Skan 579169689Skan case BREAK_STMT: 580169689Skan *expr_p = build_bc_goto (bc_break); 581169689Skan ret = GS_ALL_DONE; 582169689Skan break; 583169689Skan 584169689Skan case EXPR_STMT: 585169689Skan gimplify_expr_stmt (expr_p); 586169689Skan ret = GS_OK; 587169689Skan break; 588169689Skan 589169689Skan case UNARY_PLUS_EXPR: 590169689Skan { 591169689Skan tree arg = TREE_OPERAND (*expr_p, 0); 592169689Skan tree type = TREE_TYPE (*expr_p); 593169689Skan *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg) 594169689Skan : arg; 595169689Skan ret = GS_OK; 596169689Skan } 597169689Skan break; 598169689Skan 599169689Skan default: 600169689Skan ret = c_gimplify_expr (expr_p, pre_p, post_p); 601169689Skan break; 602169689Skan } 603169689Skan 604169689Skan /* Restore saved state. */ 605169689Skan if (STATEMENT_CODE_P (code)) 606169689Skan current_stmt_tree ()->stmts_are_full_exprs_p 607169689Skan = saved_stmts_are_full_exprs_p; 608169689Skan 609169689Skan return ret; 610169689Skan} 611169689Skan 612169689Skanstatic inline bool 613169689Skanis_invisiref_parm (tree t) 614169689Skan{ 615169689Skan return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL) 616169689Skan && DECL_BY_REFERENCE (t)); 617169689Skan} 618169689Skan 619169689Skan/* Return true if the uid in both int tree maps are equal. */ 620169689Skan 621169689Skanint 622169689Skancxx_int_tree_map_eq (const void *va, const void *vb) 623169689Skan{ 624169689Skan const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va; 625169689Skan const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb; 626169689Skan return (a->uid == b->uid); 627169689Skan} 628169689Skan 629169689Skan/* Hash a UID in a cxx_int_tree_map. */ 630169689Skan 631169689Skanunsigned int 632169689Skancxx_int_tree_map_hash (const void *item) 633169689Skan{ 634169689Skan return ((const struct cxx_int_tree_map *)item)->uid; 635169689Skan} 636169689Skan 637169689Skan/* Perform any pre-gimplification lowering of C++ front end trees to 638169689Skan GENERIC. */ 639169689Skan 640169689Skanstatic tree 641169689Skancp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) 642169689Skan{ 643169689Skan tree stmt = *stmt_p; 644169689Skan struct pointer_set_t *p_set = (struct pointer_set_t*) data; 645169689Skan 646169689Skan if (is_invisiref_parm (stmt) 647169689Skan /* Don't dereference parms in a thunk, pass the references through. */ 648169689Skan && !(DECL_THUNK_P (current_function_decl) 649169689Skan && TREE_CODE (stmt) == PARM_DECL)) 650169689Skan { 651169689Skan *stmt_p = convert_from_reference (stmt); 652169689Skan *walk_subtrees = 0; 653169689Skan return NULL; 654169689Skan } 655169689Skan 656169689Skan /* Map block scope extern declarations to visible declarations with the 657169689Skan same name and type in outer scopes if any. */ 658169689Skan if (cp_function_chain->extern_decl_map 659169689Skan && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL) 660169689Skan && DECL_EXTERNAL (stmt)) 661169689Skan { 662169689Skan struct cxx_int_tree_map *h, in; 663169689Skan in.uid = DECL_UID (stmt); 664169689Skan h = (struct cxx_int_tree_map *) 665169689Skan htab_find_with_hash (cp_function_chain->extern_decl_map, 666169689Skan &in, in.uid); 667169689Skan if (h) 668169689Skan { 669169689Skan *stmt_p = h->to; 670169689Skan *walk_subtrees = 0; 671169689Skan return NULL; 672169689Skan } 673169689Skan } 674169689Skan 675169689Skan /* Other than invisiref parms, don't walk the same tree twice. */ 676169689Skan if (pointer_set_contains (p_set, stmt)) 677169689Skan { 678169689Skan *walk_subtrees = 0; 679169689Skan return NULL_TREE; 680169689Skan } 681169689Skan 682169689Skan if (TREE_CODE (stmt) == ADDR_EXPR 683169689Skan && is_invisiref_parm (TREE_OPERAND (stmt, 0))) 684169689Skan { 685169689Skan *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0)); 686169689Skan *walk_subtrees = 0; 687169689Skan } 688169689Skan else if (TREE_CODE (stmt) == RETURN_EXPR 689169689Skan && TREE_OPERAND (stmt, 0) 690169689Skan && is_invisiref_parm (TREE_OPERAND (stmt, 0))) 691169689Skan /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */ 692169689Skan *walk_subtrees = 0; 693169689Skan else if (TREE_CODE (stmt) == OMP_CLAUSE) 694169689Skan switch (OMP_CLAUSE_CODE (stmt)) 695169689Skan { 696169689Skan case OMP_CLAUSE_PRIVATE: 697169689Skan case OMP_CLAUSE_SHARED: 698169689Skan case OMP_CLAUSE_FIRSTPRIVATE: 699169689Skan case OMP_CLAUSE_LASTPRIVATE: 700169689Skan case OMP_CLAUSE_COPYIN: 701169689Skan case OMP_CLAUSE_COPYPRIVATE: 702169689Skan /* Don't dereference an invisiref in OpenMP clauses. */ 703169689Skan if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) 704169689Skan *walk_subtrees = 0; 705169689Skan break; 706169689Skan case OMP_CLAUSE_REDUCTION: 707169689Skan gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt))); 708169689Skan break; 709169689Skan default: 710169689Skan break; 711169689Skan } 712169689Skan else if (IS_TYPE_OR_DECL_P (stmt)) 713169689Skan *walk_subtrees = 0; 714169689Skan 715169689Skan /* Due to the way voidify_wrapper_expr is written, we don't get a chance 716169689Skan to lower this construct before scanning it, so we need to lower these 717169689Skan before doing anything else. */ 718169689Skan else if (TREE_CODE (stmt) == CLEANUP_STMT) 719169689Skan *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR 720169689Skan : TRY_FINALLY_EXPR, 721169689Skan void_type_node, 722169689Skan CLEANUP_BODY (stmt), 723169689Skan CLEANUP_EXPR (stmt)); 724169689Skan 725169689Skan pointer_set_insert (p_set, *stmt_p); 726169689Skan 727169689Skan return NULL; 728169689Skan} 729169689Skan 730169689Skanvoid 731169689Skancp_genericize (tree fndecl) 732169689Skan{ 733169689Skan tree t; 734169689Skan struct pointer_set_t *p_set; 735169689Skan 736169689Skan /* Fix up the types of parms passed by invisible reference. */ 737169689Skan for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t)) 738169689Skan if (TREE_ADDRESSABLE (TREE_TYPE (t))) 739169689Skan { 740169689Skan /* If a function's arguments are copied to create a thunk, 741169689Skan then DECL_BY_REFERENCE will be set -- but the type of the 742169689Skan argument will be a pointer type, so we will never get 743169689Skan here. */ 744169689Skan gcc_assert (!DECL_BY_REFERENCE (t)); 745169689Skan gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); 746169689Skan TREE_TYPE (t) = DECL_ARG_TYPE (t); 747169689Skan DECL_BY_REFERENCE (t) = 1; 748169689Skan TREE_ADDRESSABLE (t) = 0; 749169689Skan relayout_decl (t); 750169689Skan } 751169689Skan 752169689Skan /* Do the same for the return value. */ 753169689Skan if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl)))) 754169689Skan { 755169689Skan t = DECL_RESULT (fndecl); 756169689Skan TREE_TYPE (t) = build_reference_type (TREE_TYPE (t)); 757169689Skan DECL_BY_REFERENCE (t) = 1; 758169689Skan TREE_ADDRESSABLE (t) = 0; 759169689Skan relayout_decl (t); 760169689Skan } 761169689Skan 762169689Skan /* If we're a clone, the body is already GIMPLE. */ 763169689Skan if (DECL_CLONED_FUNCTION_P (fndecl)) 764169689Skan return; 765169689Skan 766169689Skan /* We do want to see every occurrence of the parms, so we can't just use 767169689Skan walk_tree's hash functionality. */ 768169689Skan p_set = pointer_set_create (); 769169689Skan walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL); 770169689Skan pointer_set_destroy (p_set); 771169689Skan 772169689Skan /* Do everything else. */ 773169689Skan c_genericize (fndecl); 774169689Skan 775169689Skan gcc_assert (bc_label[bc_break] == NULL); 776169689Skan gcc_assert (bc_label[bc_continue] == NULL); 777169689Skan} 778169689Skan 779169689Skan/* Build code to apply FN to each member of ARG1 and ARG2. FN may be 780169689Skan NULL if there is in fact nothing to do. ARG2 may be null if FN 781169689Skan actually only takes one argument. */ 782169689Skan 783169689Skanstatic tree 784169689Skancxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2) 785169689Skan{ 786169689Skan tree defparm, parm; 787169689Skan int i; 788169689Skan 789169689Skan if (fn == NULL) 790169689Skan return NULL; 791169689Skan 792169689Skan defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn))); 793169689Skan if (arg2) 794169689Skan defparm = TREE_CHAIN (defparm); 795169689Skan 796169689Skan if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE) 797169689Skan { 798169689Skan tree inner_type = TREE_TYPE (arg1); 799169689Skan tree start1, end1, p1; 800169689Skan tree start2 = NULL, p2 = NULL; 801169689Skan tree ret = NULL, lab, t; 802169689Skan 803169689Skan start1 = arg1; 804169689Skan start2 = arg2; 805169689Skan do 806169689Skan { 807169689Skan inner_type = TREE_TYPE (inner_type); 808169689Skan start1 = build4 (ARRAY_REF, inner_type, start1, 809169689Skan size_zero_node, NULL, NULL); 810169689Skan if (arg2) 811169689Skan start2 = build4 (ARRAY_REF, inner_type, start2, 812169689Skan size_zero_node, NULL, NULL); 813169689Skan } 814169689Skan while (TREE_CODE (inner_type) == ARRAY_TYPE); 815169689Skan start1 = build_fold_addr_expr (start1); 816169689Skan if (arg2) 817169689Skan start2 = build_fold_addr_expr (start2); 818169689Skan 819169689Skan end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1)); 820169689Skan end1 = fold_convert (TREE_TYPE (start1), end1); 821169689Skan end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1); 822169689Skan 823169689Skan p1 = create_tmp_var (TREE_TYPE (start1), NULL); 824169689Skan t = build2 (MODIFY_EXPR, void_type_node, p1, start1); 825169689Skan append_to_statement_list (t, &ret); 826169689Skan 827169689Skan if (arg2) 828169689Skan { 829169689Skan p2 = create_tmp_var (TREE_TYPE (start2), NULL); 830169689Skan t = build2 (MODIFY_EXPR, void_type_node, p2, start2); 831169689Skan append_to_statement_list (t, &ret); 832169689Skan } 833169689Skan 834169689Skan lab = create_artificial_label (); 835169689Skan t = build1 (LABEL_EXPR, void_type_node, lab); 836169689Skan append_to_statement_list (t, &ret); 837169689Skan 838169689Skan t = tree_cons (NULL, p1, NULL); 839169689Skan if (arg2) 840169689Skan t = tree_cons (NULL, p2, t); 841169689Skan /* Handle default arguments. */ 842169689Skan i = 1 + (arg2 != NULL); 843169689Skan for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm)) 844169689Skan t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm), 845169689Skan TREE_PURPOSE (parm), 846169689Skan fn, i++), t); 847169689Skan t = build_call (fn, nreverse (t)); 848169689Skan append_to_statement_list (t, &ret); 849169689Skan 850169689Skan t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type)); 851169689Skan t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t); 852169689Skan t = build2 (MODIFY_EXPR, void_type_node, p1, t); 853169689Skan append_to_statement_list (t, &ret); 854169689Skan 855169689Skan if (arg2) 856169689Skan { 857169689Skan t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type)); 858169689Skan t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t); 859169689Skan t = build2 (MODIFY_EXPR, void_type_node, p2, t); 860169689Skan append_to_statement_list (t, &ret); 861169689Skan } 862169689Skan 863169689Skan t = build2 (NE_EXPR, boolean_type_node, p1, end1); 864169689Skan t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL); 865169689Skan append_to_statement_list (t, &ret); 866169689Skan 867169689Skan return ret; 868169689Skan } 869169689Skan else 870169689Skan { 871169689Skan tree t = tree_cons (NULL, build_fold_addr_expr (arg1), NULL); 872169689Skan if (arg2) 873169689Skan t = tree_cons (NULL, build_fold_addr_expr (arg2), t); 874169689Skan /* Handle default arguments. */ 875169689Skan i = 1 + (arg2 != NULL); 876169689Skan for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm)) 877169689Skan t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm), 878169689Skan TREE_PURPOSE (parm), 879169689Skan fn, i++), t); 880169689Skan return build_call (fn, nreverse (t)); 881169689Skan } 882169689Skan} 883169689Skan 884169689Skan/* Return code to initialize DECL with its default constructor, or 885169689Skan NULL if there's nothing to do. */ 886169689Skan 887169689Skantree 888169689Skancxx_omp_clause_default_ctor (tree clause, tree decl) 889169689Skan{ 890169689Skan tree info = CP_OMP_CLAUSE_INFO (clause); 891169689Skan tree ret = NULL; 892169689Skan 893169689Skan if (info) 894169689Skan ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL); 895169689Skan 896169689Skan return ret; 897169689Skan} 898169689Skan 899169689Skan/* Return code to initialize DST with a copy constructor from SRC. */ 900169689Skan 901169689Skantree 902169689Skancxx_omp_clause_copy_ctor (tree clause, tree dst, tree src) 903169689Skan{ 904169689Skan tree info = CP_OMP_CLAUSE_INFO (clause); 905169689Skan tree ret = NULL; 906169689Skan 907169689Skan if (info) 908169689Skan ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src); 909169689Skan if (ret == NULL) 910169689Skan ret = build2 (MODIFY_EXPR, void_type_node, dst, src); 911169689Skan 912169689Skan return ret; 913169689Skan} 914169689Skan 915169689Skan/* Similarly, except use an assignment operator instead. */ 916169689Skan 917169689Skantree 918169689Skancxx_omp_clause_assign_op (tree clause, tree dst, tree src) 919169689Skan{ 920169689Skan tree info = CP_OMP_CLAUSE_INFO (clause); 921169689Skan tree ret = NULL; 922169689Skan 923169689Skan if (info) 924169689Skan ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src); 925169689Skan if (ret == NULL) 926169689Skan ret = build2 (MODIFY_EXPR, void_type_node, dst, src); 927169689Skan 928169689Skan return ret; 929169689Skan} 930169689Skan 931169689Skan/* Return code to destroy DECL. */ 932169689Skan 933169689Skantree 934169689Skancxx_omp_clause_dtor (tree clause, tree decl) 935169689Skan{ 936169689Skan tree info = CP_OMP_CLAUSE_INFO (clause); 937169689Skan tree ret = NULL; 938169689Skan 939169689Skan if (info) 940169689Skan ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL); 941169689Skan 942169689Skan return ret; 943169689Skan} 944169689Skan 945169689Skan/* True if OpenMP should privatize what this DECL points to rather 946169689Skan than the DECL itself. */ 947169689Skan 948169689Skanbool 949169689Skancxx_omp_privatize_by_reference (tree decl) 950169689Skan{ 951169689Skan return is_invisiref_parm (decl); 952169689Skan} 953