1169689Skan/* Nested function decomposition for trees. 2169689Skan Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. 3169689Skan 4169689Skan This file is part of GCC. 5169689Skan 6169689Skan GCC is free software; you can redistribute it and/or modify 7169689Skan it under the terms of the GNU General Public License as published by 8169689Skan the Free Software Foundation; either version 2, or (at your option) 9169689Skan any later version. 10169689Skan 11169689Skan GCC is distributed in the hope that it will be useful, 12169689Skan but WITHOUT ANY WARRANTY; without even the implied warranty of 13169689Skan MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14169689Skan GNU General Public License for more details. 15169689Skan 16169689Skan You should have received a copy of the GNU General Public License 17169689Skan along with GCC; see the file COPYING. If not, write to 18169689Skan the Free Software Foundation, 51 Franklin Street, Fifth Floor, 19169689Skan Boston, MA 02110-1301, USA. */ 20169689Skan 21169689Skan#include "config.h" 22169689Skan#include "system.h" 23169689Skan#include "coretypes.h" 24169689Skan#include "tm.h" 25169689Skan#include "tree.h" 26169689Skan#include "rtl.h" 27169689Skan#include "tm_p.h" 28169689Skan#include "function.h" 29169689Skan#include "tree-dump.h" 30169689Skan#include "tree-inline.h" 31169689Skan#include "tree-gimple.h" 32169689Skan#include "tree-iterator.h" 33169689Skan#include "tree-flow.h" 34169689Skan#include "cgraph.h" 35169689Skan#include "expr.h" 36169689Skan#include "langhooks.h" 37169689Skan#include "ggc.h" 38169689Skan 39169689Skan 40169689Skan/* The object of this pass is to lower the representation of a set of nested 41169689Skan functions in order to expose all of the gory details of the various 42169689Skan nonlocal references. We want to do this sooner rather than later, in 43169689Skan order to give us more freedom in emitting all of the functions in question. 44169689Skan 45169689Skan Back in olden times, when gcc was young, we developed an insanely 46169689Skan complicated scheme whereby variables which were referenced nonlocally 47169689Skan were forced to live in the stack of the declaring function, and then 48169689Skan the nested functions magically discovered where these variables were 49169689Skan placed. In order for this scheme to function properly, it required 50169689Skan that the outer function be partially expanded, then we switch to 51169689Skan compiling the inner function, and once done with those we switch back 52169689Skan to compiling the outer function. Such delicate ordering requirements 53169689Skan makes it difficult to do whole translation unit optimizations 54169689Skan involving such functions. 55169689Skan 56169689Skan The implementation here is much more direct. Everything that can be 57169689Skan referenced by an inner function is a member of an explicitly created 58169689Skan structure herein called the "nonlocal frame struct". The incoming 59169689Skan static chain for a nested function is a pointer to this struct in 60169689Skan the parent. In this way, we settle on known offsets from a known 61169689Skan base, and so are decoupled from the logic that places objects in the 62169689Skan function's stack frame. More importantly, we don't have to wait for 63169689Skan that to happen -- since the compilation of the inner function is no 64169689Skan longer tied to a real stack frame, the nonlocal frame struct can be 65169689Skan allocated anywhere. Which means that the outer function is now 66169689Skan inlinable. 67169689Skan 68169689Skan Theory of operation here is very simple. Iterate over all the 69169689Skan statements in all the functions (depth first) several times, 70169689Skan allocating structures and fields on demand. In general we want to 71169689Skan examine inner functions first, so that we can avoid making changes 72169689Skan to outer functions which are unnecessary. 73169689Skan 74169689Skan The order of the passes matters a bit, in that later passes will be 75169689Skan skipped if it is discovered that the functions don't actually interact 76169689Skan at all. That is, they're nested in the lexical sense but could have 77169689Skan been written as independent functions without change. */ 78169689Skan 79169689Skan 80169689Skanstruct var_map_elt GTY(()) 81169689Skan{ 82169689Skan tree old; 83169689Skan tree new; 84169689Skan}; 85169689Skan 86169689Skanstruct nesting_info GTY ((chain_next ("%h.next"))) 87169689Skan{ 88169689Skan struct nesting_info *outer; 89169689Skan struct nesting_info *inner; 90169689Skan struct nesting_info *next; 91169689Skan 92169689Skan htab_t GTY ((param_is (struct var_map_elt))) field_map; 93169689Skan htab_t GTY ((param_is (struct var_map_elt))) var_map; 94169689Skan bitmap suppress_expansion; 95169689Skan 96169689Skan tree context; 97169689Skan tree new_local_var_chain; 98169689Skan tree debug_var_chain; 99169689Skan tree frame_type; 100169689Skan tree frame_decl; 101169689Skan tree chain_field; 102169689Skan tree chain_decl; 103169689Skan tree nl_goto_field; 104169689Skan 105169689Skan bool any_parm_remapped; 106169689Skan bool any_tramp_created; 107169689Skan char static_chain_added; 108169689Skan}; 109169689Skan 110169689Skan 111169689Skan/* Hashing and equality functions for nesting_info->var_map. */ 112169689Skan 113169689Skanstatic hashval_t 114169689Skanvar_map_hash (const void *x) 115169689Skan{ 116169689Skan const struct var_map_elt *a = (const struct var_map_elt *) x; 117169689Skan return htab_hash_pointer (a->old); 118169689Skan} 119169689Skan 120169689Skanstatic int 121169689Skanvar_map_eq (const void *x, const void *y) 122169689Skan{ 123169689Skan const struct var_map_elt *a = (const struct var_map_elt *) x; 124169689Skan const struct var_map_elt *b = (const struct var_map_elt *) y; 125169689Skan return a->old == b->old; 126169689Skan} 127169689Skan 128169689Skan/* We're working in so many different function contexts simultaneously, 129169689Skan that create_tmp_var is dangerous. Prevent mishap. */ 130169689Skan#define create_tmp_var cant_use_create_tmp_var_here_dummy 131169689Skan 132169689Skan/* Like create_tmp_var, except record the variable for registration at 133169689Skan the given nesting level. */ 134169689Skan 135169689Skanstatic tree 136169689Skancreate_tmp_var_for (struct nesting_info *info, tree type, const char *prefix) 137169689Skan{ 138169689Skan tree tmp_var; 139169689Skan 140169689Skan /* If the type is of variable size or a type which must be created by the 141169689Skan frontend, something is wrong. Note that we explicitly allow 142169689Skan incomplete types here, since we create them ourselves here. */ 143169689Skan gcc_assert (!TREE_ADDRESSABLE (type)); 144169689Skan gcc_assert (!TYPE_SIZE_UNIT (type) 145169689Skan || TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST); 146169689Skan 147169689Skan tmp_var = create_tmp_var_raw (type, prefix); 148169689Skan DECL_CONTEXT (tmp_var) = info->context; 149169689Skan TREE_CHAIN (tmp_var) = info->new_local_var_chain; 150169689Skan DECL_SEEN_IN_BIND_EXPR_P (tmp_var) = 1; 151169689Skan if (TREE_CODE (type) == COMPLEX_TYPE) 152169689Skan DECL_COMPLEX_GIMPLE_REG_P (tmp_var) = 1; 153169689Skan 154169689Skan info->new_local_var_chain = tmp_var; 155169689Skan 156169689Skan return tmp_var; 157169689Skan} 158169689Skan 159169689Skan/* Take the address of EXP to be used within function CONTEXT. 160169689Skan Mark it for addressability as necessary. */ 161169689Skan 162169689Skantree 163169689Skanbuild_addr (tree exp, tree context) 164169689Skan{ 165169689Skan tree base = exp; 166169689Skan tree save_context; 167169689Skan tree retval; 168169689Skan 169169689Skan while (handled_component_p (base)) 170169689Skan base = TREE_OPERAND (base, 0); 171169689Skan 172169689Skan if (DECL_P (base)) 173169689Skan TREE_ADDRESSABLE (base) = 1; 174169689Skan 175169689Skan /* Building the ADDR_EXPR will compute a set of properties for 176169689Skan that ADDR_EXPR. Those properties are unfortunately context 177169689Skan specific. ie, they are dependent on CURRENT_FUNCTION_DECL. 178169689Skan 179169689Skan Temporarily set CURRENT_FUNCTION_DECL to the desired context, 180169689Skan build the ADDR_EXPR, then restore CURRENT_FUNCTION_DECL. That 181169689Skan way the properties are for the ADDR_EXPR are computed properly. */ 182169689Skan save_context = current_function_decl; 183169689Skan current_function_decl = context; 184169689Skan retval = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp); 185169689Skan current_function_decl = save_context;; 186169689Skan return retval; 187169689Skan} 188169689Skan 189169689Skan/* Insert FIELD into TYPE, sorted by alignment requirements. */ 190169689Skan 191169689Skanvoid 192169689Skaninsert_field_into_struct (tree type, tree field) 193169689Skan{ 194169689Skan tree *p; 195169689Skan 196169689Skan DECL_CONTEXT (field) = type; 197169689Skan 198169689Skan for (p = &TYPE_FIELDS (type); *p ; p = &TREE_CHAIN (*p)) 199169689Skan if (DECL_ALIGN (field) >= DECL_ALIGN (*p)) 200169689Skan break; 201169689Skan 202169689Skan TREE_CHAIN (field) = *p; 203169689Skan *p = field; 204169689Skan} 205169689Skan 206169689Skan/* Build or return the RECORD_TYPE that describes the frame state that is 207169689Skan shared between INFO->CONTEXT and its nested functions. This record will 208169689Skan not be complete until finalize_nesting_tree; up until that point we'll 209169689Skan be adding fields as necessary. 210169689Skan 211169689Skan We also build the DECL that represents this frame in the function. */ 212169689Skan 213169689Skanstatic tree 214169689Skanget_frame_type (struct nesting_info *info) 215169689Skan{ 216169689Skan tree type = info->frame_type; 217169689Skan if (!type) 218169689Skan { 219169689Skan char *name; 220169689Skan 221169689Skan type = make_node (RECORD_TYPE); 222169689Skan 223169689Skan name = concat ("FRAME.", 224169689Skan IDENTIFIER_POINTER (DECL_NAME (info->context)), 225169689Skan NULL); 226169689Skan TYPE_NAME (type) = get_identifier (name); 227169689Skan free (name); 228169689Skan 229169689Skan info->frame_type = type; 230169689Skan info->frame_decl = create_tmp_var_for (info, type, "FRAME"); 231169689Skan 232169689Skan /* ??? Always make it addressable for now, since it is meant to 233169689Skan be pointed to by the static chain pointer. This pessimizes 234169689Skan when it turns out that no static chains are needed because 235169689Skan the nested functions referencing non-local variables are not 236169689Skan reachable, but the true pessimization is to create the non- 237169689Skan local frame structure in the first place. */ 238169689Skan TREE_ADDRESSABLE (info->frame_decl) = 1; 239169689Skan } 240169689Skan return type; 241169689Skan} 242169689Skan 243169689Skan/* Return true if DECL should be referenced by pointer in the non-local 244169689Skan frame structure. */ 245169689Skan 246169689Skanstatic bool 247169689Skanuse_pointer_in_frame (tree decl) 248169689Skan{ 249169689Skan if (TREE_CODE (decl) == PARM_DECL) 250169689Skan { 251169689Skan /* It's illegal to copy TREE_ADDRESSABLE, impossible to copy variable 252169689Skan sized decls, and inefficient to copy large aggregates. Don't bother 253169689Skan moving anything but scalar variables. */ 254169689Skan return AGGREGATE_TYPE_P (TREE_TYPE (decl)); 255169689Skan } 256169689Skan else 257169689Skan { 258169689Skan /* Variable sized types make things "interesting" in the frame. */ 259169689Skan return DECL_SIZE (decl) == NULL || !TREE_CONSTANT (DECL_SIZE (decl)); 260169689Skan } 261169689Skan} 262169689Skan 263169689Skan/* Given DECL, a non-locally accessed variable, find or create a field 264169689Skan in the non-local frame structure for the given nesting context. */ 265169689Skan 266169689Skanstatic tree 267169689Skanlookup_field_for_decl (struct nesting_info *info, tree decl, 268169689Skan enum insert_option insert) 269169689Skan{ 270169689Skan struct var_map_elt *elt, dummy; 271169689Skan void **slot; 272169689Skan tree field; 273169689Skan 274169689Skan dummy.old = decl; 275169689Skan slot = htab_find_slot (info->field_map, &dummy, insert); 276169689Skan if (!slot) 277169689Skan { 278169689Skan gcc_assert (insert != INSERT); 279169689Skan return NULL; 280169689Skan } 281169689Skan elt = (struct var_map_elt *) *slot; 282169689Skan 283169689Skan if (!elt && insert == INSERT) 284169689Skan { 285169689Skan field = make_node (FIELD_DECL); 286169689Skan DECL_NAME (field) = DECL_NAME (decl); 287169689Skan 288169689Skan if (use_pointer_in_frame (decl)) 289169689Skan { 290169689Skan TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl)); 291169689Skan DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field)); 292169689Skan DECL_NONADDRESSABLE_P (field) = 1; 293169689Skan } 294169689Skan else 295169689Skan { 296169689Skan TREE_TYPE (field) = TREE_TYPE (decl); 297169689Skan DECL_SOURCE_LOCATION (field) = DECL_SOURCE_LOCATION (decl); 298169689Skan DECL_ALIGN (field) = DECL_ALIGN (decl); 299169689Skan DECL_USER_ALIGN (field) = DECL_USER_ALIGN (decl); 300169689Skan TREE_ADDRESSABLE (field) = TREE_ADDRESSABLE (decl); 301169689Skan DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (decl); 302169689Skan TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (decl); 303169689Skan } 304169689Skan 305169689Skan insert_field_into_struct (get_frame_type (info), field); 306169689Skan 307169689Skan elt = GGC_NEW (struct var_map_elt); 308169689Skan elt->old = decl; 309169689Skan elt->new = field; 310169689Skan *slot = elt; 311169689Skan 312169689Skan if (TREE_CODE (decl) == PARM_DECL) 313169689Skan info->any_parm_remapped = true; 314169689Skan } 315169689Skan else 316169689Skan field = elt ? elt->new : NULL; 317169689Skan 318169689Skan return field; 319169689Skan} 320169689Skan 321169689Skan/* Build or return the variable that holds the static chain within 322169689Skan INFO->CONTEXT. This variable may only be used within INFO->CONTEXT. */ 323169689Skan 324169689Skanstatic tree 325169689Skanget_chain_decl (struct nesting_info *info) 326169689Skan{ 327169689Skan tree decl = info->chain_decl; 328169689Skan if (!decl) 329169689Skan { 330169689Skan tree type; 331169689Skan 332169689Skan type = get_frame_type (info->outer); 333169689Skan type = build_pointer_type (type); 334169689Skan 335169689Skan /* Note that this variable is *not* entered into any BIND_EXPR; 336169689Skan the construction of this variable is handled specially in 337169689Skan expand_function_start and initialize_inlined_parameters. 338169689Skan Note also that it's represented as a parameter. This is more 339169689Skan close to the truth, since the initial value does come from 340169689Skan the caller. */ 341169689Skan decl = build_decl (PARM_DECL, create_tmp_var_name ("CHAIN"), type); 342169689Skan DECL_ARTIFICIAL (decl) = 1; 343169689Skan DECL_IGNORED_P (decl) = 1; 344169689Skan TREE_USED (decl) = 1; 345169689Skan DECL_CONTEXT (decl) = info->context; 346169689Skan DECL_ARG_TYPE (decl) = type; 347169689Skan 348169689Skan /* Tell tree-inline.c that we never write to this variable, so 349169689Skan it can copy-prop the replacement value immediately. */ 350169689Skan TREE_READONLY (decl) = 1; 351169689Skan 352169689Skan info->chain_decl = decl; 353169689Skan } 354169689Skan return decl; 355169689Skan} 356169689Skan 357169689Skan/* Build or return the field within the non-local frame state that holds 358169689Skan the static chain for INFO->CONTEXT. This is the way to walk back up 359169689Skan multiple nesting levels. */ 360169689Skan 361169689Skanstatic tree 362169689Skanget_chain_field (struct nesting_info *info) 363169689Skan{ 364169689Skan tree field = info->chain_field; 365169689Skan if (!field) 366169689Skan { 367169689Skan tree type = build_pointer_type (get_frame_type (info->outer)); 368169689Skan 369169689Skan field = make_node (FIELD_DECL); 370169689Skan DECL_NAME (field) = get_identifier ("__chain"); 371169689Skan TREE_TYPE (field) = type; 372169689Skan DECL_ALIGN (field) = TYPE_ALIGN (type); 373169689Skan DECL_NONADDRESSABLE_P (field) = 1; 374169689Skan 375169689Skan insert_field_into_struct (get_frame_type (info), field); 376169689Skan 377169689Skan info->chain_field = field; 378169689Skan } 379169689Skan return field; 380169689Skan} 381169689Skan 382169689Skan/* Copy EXP into a temporary. Allocate the temporary in the context of 383169689Skan INFO and insert the initialization statement before TSI. */ 384169689Skan 385169689Skanstatic tree 386169689Skaninit_tmp_var (struct nesting_info *info, tree exp, tree_stmt_iterator *tsi) 387169689Skan{ 388169689Skan tree t, stmt; 389169689Skan 390169689Skan t = create_tmp_var_for (info, TREE_TYPE (exp), NULL); 391169689Skan stmt = build2 (MODIFY_EXPR, TREE_TYPE (t), t, exp); 392169689Skan SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi))); 393169689Skan tsi_link_before (tsi, stmt, TSI_SAME_STMT); 394169689Skan 395169689Skan return t; 396169689Skan} 397169689Skan 398169689Skan/* Similarly, but only do so to force EXP to satisfy is_gimple_val. */ 399169689Skan 400169689Skanstatic tree 401169689Skantsi_gimplify_val (struct nesting_info *info, tree exp, tree_stmt_iterator *tsi) 402169689Skan{ 403169689Skan if (is_gimple_val (exp)) 404169689Skan return exp; 405169689Skan else 406169689Skan return init_tmp_var (info, exp, tsi); 407169689Skan} 408169689Skan 409169689Skan/* Similarly, but copy from the temporary and insert the statement 410169689Skan after the iterator. */ 411169689Skan 412169689Skanstatic tree 413169689Skansave_tmp_var (struct nesting_info *info, tree exp, 414169689Skan tree_stmt_iterator *tsi) 415169689Skan{ 416169689Skan tree t, stmt; 417169689Skan 418169689Skan t = create_tmp_var_for (info, TREE_TYPE (exp), NULL); 419169689Skan stmt = build2 (MODIFY_EXPR, TREE_TYPE (t), exp, t); 420169689Skan SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi))); 421169689Skan tsi_link_after (tsi, stmt, TSI_SAME_STMT); 422169689Skan 423169689Skan return t; 424169689Skan} 425169689Skan 426169689Skan/* Build or return the type used to represent a nested function trampoline. */ 427169689Skan 428169689Skanstatic GTY(()) tree trampoline_type; 429169689Skan 430169689Skanstatic tree 431169689Skanget_trampoline_type (void) 432169689Skan{ 433169689Skan tree record, t; 434169689Skan unsigned align, size; 435169689Skan 436169689Skan if (trampoline_type) 437169689Skan return trampoline_type; 438169689Skan 439169689Skan align = TRAMPOLINE_ALIGNMENT; 440169689Skan size = TRAMPOLINE_SIZE; 441169689Skan 442169689Skan /* If we won't be able to guarantee alignment simply via TYPE_ALIGN, 443169689Skan then allocate extra space so that we can do dynamic alignment. */ 444169689Skan if (align > STACK_BOUNDARY) 445169689Skan { 446169689Skan size += ((align/BITS_PER_UNIT) - 1) & -(STACK_BOUNDARY/BITS_PER_UNIT); 447169689Skan align = STACK_BOUNDARY; 448169689Skan } 449169689Skan 450169689Skan t = build_index_type (build_int_cst (NULL_TREE, size - 1)); 451169689Skan t = build_array_type (char_type_node, t); 452169689Skan t = build_decl (FIELD_DECL, get_identifier ("__data"), t); 453169689Skan DECL_ALIGN (t) = align; 454169689Skan DECL_USER_ALIGN (t) = 1; 455169689Skan 456169689Skan record = make_node (RECORD_TYPE); 457169689Skan TYPE_NAME (record) = get_identifier ("__builtin_trampoline"); 458169689Skan TYPE_FIELDS (record) = t; 459169689Skan layout_type (record); 460169689Skan 461169689Skan return record; 462169689Skan} 463169689Skan 464169689Skan/* Given DECL, a nested function, find or create a field in the non-local 465169689Skan frame structure for a trampoline for this function. */ 466169689Skan 467169689Skanstatic tree 468169689Skanlookup_tramp_for_decl (struct nesting_info *info, tree decl, 469169689Skan enum insert_option insert) 470169689Skan{ 471169689Skan struct var_map_elt *elt, dummy; 472169689Skan void **slot; 473169689Skan tree field; 474169689Skan 475169689Skan dummy.old = decl; 476169689Skan slot = htab_find_slot (info->var_map, &dummy, insert); 477169689Skan if (!slot) 478169689Skan { 479169689Skan gcc_assert (insert != INSERT); 480169689Skan return NULL; 481169689Skan } 482169689Skan elt = (struct var_map_elt *) *slot; 483169689Skan 484169689Skan if (!elt && insert == INSERT) 485169689Skan { 486169689Skan field = make_node (FIELD_DECL); 487169689Skan DECL_NAME (field) = DECL_NAME (decl); 488169689Skan TREE_TYPE (field) = get_trampoline_type (); 489169689Skan TREE_ADDRESSABLE (field) = 1; 490169689Skan 491169689Skan insert_field_into_struct (get_frame_type (info), field); 492169689Skan 493169689Skan elt = GGC_NEW (struct var_map_elt); 494169689Skan elt->old = decl; 495169689Skan elt->new = field; 496169689Skan *slot = elt; 497169689Skan 498169689Skan info->any_tramp_created = true; 499169689Skan } 500169689Skan else 501169689Skan field = elt ? elt->new : NULL; 502169689Skan 503169689Skan return field; 504169689Skan} 505169689Skan 506169689Skan/* Build or return the field within the non-local frame state that holds 507169689Skan the non-local goto "jmp_buf". The buffer itself is maintained by the 508169689Skan rtl middle-end as dynamic stack space is allocated. */ 509169689Skan 510169689Skanstatic tree 511169689Skanget_nl_goto_field (struct nesting_info *info) 512169689Skan{ 513169689Skan tree field = info->nl_goto_field; 514169689Skan if (!field) 515169689Skan { 516169689Skan unsigned size; 517169689Skan tree type; 518169689Skan 519169689Skan /* For __builtin_nonlocal_goto, we need N words. The first is the 520169689Skan frame pointer, the rest is for the target's stack pointer save 521169689Skan area. The number of words is controlled by STACK_SAVEAREA_MODE; 522169689Skan not the best interface, but it'll do for now. */ 523169689Skan if (Pmode == ptr_mode) 524169689Skan type = ptr_type_node; 525169689Skan else 526169689Skan type = lang_hooks.types.type_for_mode (Pmode, 1); 527169689Skan 528169689Skan size = GET_MODE_SIZE (STACK_SAVEAREA_MODE (SAVE_NONLOCAL)); 529169689Skan size = size / GET_MODE_SIZE (Pmode); 530169689Skan size = size + 1; 531169689Skan 532169689Skan type = build_array_type 533169689Skan (type, build_index_type (build_int_cst (NULL_TREE, size))); 534169689Skan 535169689Skan field = make_node (FIELD_DECL); 536169689Skan DECL_NAME (field) = get_identifier ("__nl_goto_buf"); 537169689Skan TREE_TYPE (field) = type; 538169689Skan DECL_ALIGN (field) = TYPE_ALIGN (type); 539169689Skan TREE_ADDRESSABLE (field) = 1; 540169689Skan 541169689Skan insert_field_into_struct (get_frame_type (info), field); 542169689Skan 543169689Skan info->nl_goto_field = field; 544169689Skan } 545169689Skan 546169689Skan return field; 547169689Skan} 548169689Skan 549169689Skan/* Helper function for walk_stmts. Walk output operands of an ASM_EXPR. */ 550169689Skan 551169689Skanstatic void 552169689Skanwalk_asm_expr (struct walk_stmt_info *wi, tree stmt) 553169689Skan{ 554169689Skan int noutputs = list_length (ASM_OUTPUTS (stmt)); 555169689Skan const char **oconstraints 556169689Skan = (const char **) alloca ((noutputs) * sizeof (const char *)); 557169689Skan int i; 558169689Skan tree link; 559169689Skan const char *constraint; 560169689Skan bool allows_mem, allows_reg, is_inout; 561169689Skan 562169689Skan wi->is_lhs = true; 563169689Skan for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link)) 564169689Skan { 565169689Skan constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link))); 566169689Skan oconstraints[i] = constraint; 567169689Skan parse_output_constraint (&constraint, i, 0, 0, &allows_mem, 568169689Skan &allows_reg, &is_inout); 569169689Skan 570169689Skan wi->val_only = (allows_reg || !allows_mem); 571169689Skan walk_tree (&TREE_VALUE (link), wi->callback, wi, NULL); 572169689Skan } 573169689Skan 574169689Skan for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link)) 575169689Skan { 576169689Skan constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link))); 577169689Skan parse_input_constraint (&constraint, 0, 0, noutputs, 0, 578169689Skan oconstraints, &allows_mem, &allows_reg); 579169689Skan 580169689Skan wi->val_only = (allows_reg || !allows_mem); 581169689Skan /* Although input "m" is not really a LHS, we need a lvalue. */ 582169689Skan wi->is_lhs = !wi->val_only; 583169689Skan walk_tree (&TREE_VALUE (link), wi->callback, wi, NULL); 584169689Skan } 585169689Skan 586169689Skan wi->is_lhs = false; 587169689Skan wi->val_only = true; 588169689Skan} 589169689Skan 590169689Skan/* Iterate over all sub-statements of *TP calling walk_tree with 591169689Skan WI->CALLBACK for every sub-expression in each statement found. */ 592169689Skan 593169689Skanvoid 594169689Skanwalk_stmts (struct walk_stmt_info *wi, tree *tp) 595169689Skan{ 596169689Skan tree t = *tp; 597169689Skan int walk_subtrees; 598169689Skan 599169689Skan if (!t) 600169689Skan return; 601169689Skan 602169689Skan if (wi->want_locations && EXPR_HAS_LOCATION (t)) 603169689Skan input_location = EXPR_LOCATION (t); 604169689Skan 605169689Skan switch (TREE_CODE (t)) 606169689Skan { 607169689Skan case STATEMENT_LIST: 608169689Skan { 609169689Skan tree_stmt_iterator i; 610169689Skan for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) 611169689Skan { 612169689Skan wi->tsi = i; 613169689Skan walk_stmts (wi, tsi_stmt_ptr (i)); 614169689Skan } 615169689Skan } 616169689Skan break; 617169689Skan 618169689Skan case COND_EXPR: 619169689Skan walk_tree (&COND_EXPR_COND (t), wi->callback, wi, NULL); 620169689Skan walk_stmts (wi, &COND_EXPR_THEN (t)); 621169689Skan walk_stmts (wi, &COND_EXPR_ELSE (t)); 622169689Skan break; 623169689Skan case CATCH_EXPR: 624169689Skan walk_stmts (wi, &CATCH_BODY (t)); 625169689Skan break; 626169689Skan case EH_FILTER_EXPR: 627169689Skan walk_stmts (wi, &EH_FILTER_FAILURE (t)); 628169689Skan break; 629169689Skan case TRY_CATCH_EXPR: 630169689Skan case TRY_FINALLY_EXPR: 631169689Skan walk_stmts (wi, &TREE_OPERAND (t, 0)); 632169689Skan walk_stmts (wi, &TREE_OPERAND (t, 1)); 633169689Skan break; 634169689Skan 635169689Skan case BIND_EXPR: 636169689Skan if (wi->want_bind_expr) 637169689Skan { 638169689Skan walk_subtrees = 1; 639169689Skan wi->callback (tp, &walk_subtrees, wi); 640169689Skan if (!walk_subtrees) 641169689Skan break; 642169689Skan } 643169689Skan walk_stmts (wi, &BIND_EXPR_BODY (t)); 644169689Skan break; 645169689Skan 646169689Skan case RETURN_EXPR: 647169689Skan if (wi->want_return_expr) 648169689Skan { 649169689Skan walk_subtrees = 1; 650169689Skan wi->callback (tp, &walk_subtrees, wi); 651169689Skan if (!walk_subtrees) 652169689Skan break; 653169689Skan } 654169689Skan walk_stmts (wi, &TREE_OPERAND (t, 0)); 655169689Skan break; 656169689Skan 657169689Skan case MODIFY_EXPR: 658169689Skan /* A formal temporary lhs may use a COMPONENT_REF rhs. */ 659169689Skan wi->val_only = !is_gimple_formal_tmp_var (TREE_OPERAND (t, 0)); 660169689Skan walk_tree (&TREE_OPERAND (t, 1), wi->callback, wi, NULL); 661169689Skan 662169689Skan /* If the rhs is appropriate for a memory, we may use a 663169689Skan COMPONENT_REF on the lhs. */ 664169689Skan wi->val_only = !is_gimple_mem_rhs (TREE_OPERAND (t, 1)); 665169689Skan wi->is_lhs = true; 666169689Skan walk_tree (&TREE_OPERAND (t, 0), wi->callback, wi, NULL); 667169689Skan 668169689Skan wi->val_only = true; 669169689Skan wi->is_lhs = false; 670169689Skan break; 671169689Skan 672169689Skan case ASM_EXPR: 673169689Skan walk_asm_expr (wi, *tp); 674169689Skan break; 675169689Skan 676169689Skan default: 677169689Skan wi->val_only = true; 678169689Skan walk_tree (tp, wi->callback, wi, NULL); 679169689Skan break; 680169689Skan } 681169689Skan} 682169689Skan 683169689Skan/* Invoke CALLBACK on all statements of *STMT_P. */ 684169689Skan 685169689Skanstatic void 686169689Skanwalk_body (walk_tree_fn callback, struct nesting_info *info, tree *stmt_p) 687169689Skan{ 688169689Skan struct walk_stmt_info wi; 689169689Skan 690169689Skan memset (&wi, 0, sizeof (wi)); 691169689Skan wi.callback = callback; 692169689Skan wi.info = info; 693169689Skan wi.val_only = true; 694169689Skan 695169689Skan walk_stmts (&wi, stmt_p); 696169689Skan} 697169689Skan 698169689Skan/* Invoke CALLBACK on all statements of INFO->CONTEXT. */ 699169689Skan 700169689Skanstatic inline void 701169689Skanwalk_function (walk_tree_fn callback, struct nesting_info *info) 702169689Skan{ 703169689Skan walk_body (callback, info, &DECL_SAVED_TREE (info->context)); 704169689Skan} 705169689Skan 706169689Skan/* Similarly for ROOT and all functions nested underneath, depth first. */ 707169689Skan 708169689Skanstatic void 709169689Skanwalk_all_functions (walk_tree_fn callback, struct nesting_info *root) 710169689Skan{ 711169689Skan do 712169689Skan { 713169689Skan if (root->inner) 714169689Skan walk_all_functions (callback, root->inner); 715169689Skan walk_function (callback, root); 716169689Skan root = root->next; 717169689Skan } 718169689Skan while (root); 719169689Skan} 720169689Skan 721169689Skan/* We have to check for a fairly pathological case. The operands of function 722169689Skan nested function are to be interpreted in the context of the enclosing 723169689Skan function. So if any are variably-sized, they will get remapped when the 724169689Skan enclosing function is inlined. But that remapping would also have to be 725169689Skan done in the types of the PARM_DECLs of the nested function, meaning the 726169689Skan argument types of that function will disagree with the arguments in the 727169689Skan calls to that function. So we'd either have to make a copy of the nested 728169689Skan function corresponding to each time the enclosing function was inlined or 729169689Skan add a VIEW_CONVERT_EXPR to each such operand for each call to the nested 730169689Skan function. The former is not practical. The latter would still require 731169689Skan detecting this case to know when to add the conversions. So, for now at 732169689Skan least, we don't inline such an enclosing function. 733169689Skan 734169689Skan We have to do that check recursively, so here return indicating whether 735169689Skan FNDECL has such a nested function. ORIG_FN is the function we were 736169689Skan trying to inline to use for checking whether any argument is variably 737169689Skan modified by anything in it. 738169689Skan 739169689Skan It would be better to do this in tree-inline.c so that we could give 740169689Skan the appropriate warning for why a function can't be inlined, but that's 741169689Skan too late since the nesting structure has already been flattened and 742169689Skan adding a flag just to record this fact seems a waste of a flag. */ 743169689Skan 744169689Skanstatic bool 745169689Skancheck_for_nested_with_variably_modified (tree fndecl, tree orig_fndecl) 746169689Skan{ 747169689Skan struct cgraph_node *cgn = cgraph_node (fndecl); 748169689Skan tree arg; 749169689Skan 750169689Skan for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested) 751169689Skan { 752169689Skan for (arg = DECL_ARGUMENTS (cgn->decl); arg; arg = TREE_CHAIN (arg)) 753223715Suqs if (variably_modified_type_p (TREE_TYPE (arg), orig_fndecl)) 754169689Skan return true; 755169689Skan 756169689Skan if (check_for_nested_with_variably_modified (cgn->decl, orig_fndecl)) 757169689Skan return true; 758169689Skan } 759169689Skan 760169689Skan return false; 761169689Skan} 762169689Skan 763169689Skan/* Construct our local datastructure describing the function nesting 764169689Skan tree rooted by CGN. */ 765169689Skan 766169689Skanstatic struct nesting_info * 767169689Skancreate_nesting_tree (struct cgraph_node *cgn) 768169689Skan{ 769169689Skan struct nesting_info *info = GGC_CNEW (struct nesting_info); 770169689Skan info->field_map = htab_create_ggc (7, var_map_hash, var_map_eq, ggc_free); 771169689Skan info->var_map = htab_create_ggc (7, var_map_hash, var_map_eq, ggc_free); 772169689Skan info->suppress_expansion = BITMAP_GGC_ALLOC (); 773169689Skan info->context = cgn->decl; 774169689Skan 775169689Skan for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested) 776169689Skan { 777169689Skan struct nesting_info *sub = create_nesting_tree (cgn); 778169689Skan sub->outer = info; 779169689Skan sub->next = info->inner; 780169689Skan info->inner = sub; 781169689Skan } 782169689Skan 783169689Skan /* See discussion at check_for_nested_with_variably_modified for a 784169689Skan discussion of why this has to be here. */ 785169689Skan if (check_for_nested_with_variably_modified (info->context, info->context)) 786169689Skan DECL_UNINLINABLE (info->context) = true; 787169689Skan 788169689Skan return info; 789169689Skan} 790169689Skan 791169689Skan/* Return an expression computing the static chain for TARGET_CONTEXT 792169689Skan from INFO->CONTEXT. Insert any necessary computations before TSI. */ 793169689Skan 794169689Skanstatic tree 795169689Skanget_static_chain (struct nesting_info *info, tree target_context, 796169689Skan tree_stmt_iterator *tsi) 797169689Skan{ 798169689Skan struct nesting_info *i; 799169689Skan tree x; 800169689Skan 801169689Skan if (info->context == target_context) 802169689Skan { 803169689Skan x = build_addr (info->frame_decl, target_context); 804169689Skan } 805169689Skan else 806169689Skan { 807169689Skan x = get_chain_decl (info); 808169689Skan 809169689Skan for (i = info->outer; i->context != target_context; i = i->outer) 810169689Skan { 811169689Skan tree field = get_chain_field (i); 812169689Skan 813169689Skan x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x); 814169689Skan x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE); 815169689Skan x = init_tmp_var (info, x, tsi); 816169689Skan } 817169689Skan } 818169689Skan 819169689Skan return x; 820169689Skan} 821169689Skan 822169689Skan/* Return an expression referencing FIELD from TARGET_CONTEXT's non-local 823169689Skan frame as seen from INFO->CONTEXT. Insert any necessary computations 824169689Skan before TSI. */ 825169689Skan 826169689Skanstatic tree 827169689Skanget_frame_field (struct nesting_info *info, tree target_context, 828169689Skan tree field, tree_stmt_iterator *tsi) 829169689Skan{ 830169689Skan struct nesting_info *i; 831169689Skan tree x; 832169689Skan 833169689Skan if (info->context == target_context) 834169689Skan { 835169689Skan /* Make sure frame_decl gets created. */ 836169689Skan (void) get_frame_type (info); 837169689Skan x = info->frame_decl; 838169689Skan } 839169689Skan else 840169689Skan { 841169689Skan x = get_chain_decl (info); 842169689Skan 843169689Skan for (i = info->outer; i->context != target_context; i = i->outer) 844169689Skan { 845169689Skan tree field = get_chain_field (i); 846169689Skan 847169689Skan x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x); 848169689Skan x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE); 849169689Skan x = init_tmp_var (info, x, tsi); 850169689Skan } 851169689Skan 852169689Skan x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x); 853169689Skan } 854169689Skan 855169689Skan x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE); 856169689Skan return x; 857169689Skan} 858169689Skan 859169689Skan/* A subroutine of convert_nonlocal_reference. Create a local variable 860169689Skan in the nested function with DECL_VALUE_EXPR set to reference the true 861169689Skan variable in the parent function. This is used both for debug info 862169689Skan and in OpenMP lowering. */ 863169689Skan 864169689Skanstatic tree 865169689Skanget_nonlocal_debug_decl (struct nesting_info *info, tree decl) 866169689Skan{ 867169689Skan struct var_map_elt *elt, dummy; 868169689Skan tree target_context; 869169689Skan struct nesting_info *i; 870169689Skan tree x, field, new_decl; 871169689Skan void **slot; 872169689Skan 873169689Skan dummy.old = decl; 874169689Skan slot = htab_find_slot (info->var_map, &dummy, INSERT); 875169689Skan elt = *slot; 876169689Skan 877169689Skan if (elt) 878169689Skan return elt->new; 879169689Skan 880169689Skan target_context = decl_function_context (decl); 881169689Skan 882169689Skan /* A copy of the code in get_frame_field, but without the temporaries. */ 883169689Skan if (info->context == target_context) 884169689Skan { 885169689Skan /* Make sure frame_decl gets created. */ 886169689Skan (void) get_frame_type (info); 887169689Skan x = info->frame_decl; 888169689Skan i = info; 889169689Skan } 890169689Skan else 891169689Skan { 892169689Skan x = get_chain_decl (info); 893169689Skan for (i = info->outer; i->context != target_context; i = i->outer) 894169689Skan { 895169689Skan field = get_chain_field (i); 896169689Skan x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x); 897169689Skan x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE); 898169689Skan } 899169689Skan x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x); 900169689Skan } 901169689Skan 902169689Skan field = lookup_field_for_decl (i, decl, INSERT); 903169689Skan x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE); 904169689Skan if (use_pointer_in_frame (decl)) 905169689Skan x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x); 906169689Skan 907169689Skan /* ??? We should be remapping types as well, surely. */ 908169689Skan new_decl = build_decl (VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl)); 909169689Skan DECL_CONTEXT (new_decl) = info->context; 910169689Skan DECL_SOURCE_LOCATION (new_decl) = DECL_SOURCE_LOCATION (decl); 911169689Skan DECL_ARTIFICIAL (new_decl) = DECL_ARTIFICIAL (decl); 912169689Skan DECL_IGNORED_P (new_decl) = DECL_IGNORED_P (decl); 913169689Skan TREE_THIS_VOLATILE (new_decl) = TREE_THIS_VOLATILE (decl); 914169689Skan TREE_SIDE_EFFECTS (new_decl) = TREE_SIDE_EFFECTS (decl); 915169689Skan TREE_READONLY (new_decl) = TREE_READONLY (decl); 916169689Skan TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (decl); 917169689Skan DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1; 918169689Skan 919169689Skan SET_DECL_VALUE_EXPR (new_decl, x); 920169689Skan DECL_HAS_VALUE_EXPR_P (new_decl) = 1; 921169689Skan 922169689Skan elt = ggc_alloc (sizeof (*elt)); 923169689Skan elt->old = decl; 924169689Skan elt->new = new_decl; 925169689Skan *slot = elt; 926169689Skan 927169689Skan TREE_CHAIN (new_decl) = info->debug_var_chain; 928169689Skan info->debug_var_chain = new_decl; 929169689Skan 930169689Skan return new_decl; 931169689Skan} 932169689Skan 933169689Skan/* Called via walk_function+walk_tree, rewrite all references to VAR 934169689Skan and PARM_DECLs that belong to outer functions. 935169689Skan 936169689Skan The rewrite will involve some number of structure accesses back up 937169689Skan the static chain. E.g. for a variable FOO up one nesting level it'll 938169689Skan be CHAIN->FOO. For two levels it'll be CHAIN->__chain->FOO. Further 939169689Skan indirections apply to decls for which use_pointer_in_frame is true. */ 940169689Skan 941169689Skanstatic bool convert_nonlocal_omp_clauses (tree *, struct walk_stmt_info *); 942169689Skan 943169689Skanstatic tree 944169689Skanconvert_nonlocal_reference (tree *tp, int *walk_subtrees, void *data) 945169689Skan{ 946169689Skan struct walk_stmt_info *wi = (struct walk_stmt_info *) data; 947169689Skan struct nesting_info *info = wi->info; 948169689Skan tree t = *tp; 949169689Skan tree save_local_var_chain; 950169689Skan bitmap save_suppress; 951169689Skan 952169689Skan *walk_subtrees = 0; 953169689Skan switch (TREE_CODE (t)) 954169689Skan { 955169689Skan case VAR_DECL: 956169689Skan /* Non-automatic variables are never processed. */ 957169689Skan if (TREE_STATIC (t) || DECL_EXTERNAL (t)) 958169689Skan break; 959169689Skan /* FALLTHRU */ 960169689Skan 961169689Skan case PARM_DECL: 962169689Skan if (decl_function_context (t) != info->context) 963169689Skan { 964169689Skan tree x; 965169689Skan wi->changed = true; 966169689Skan 967169689Skan x = get_nonlocal_debug_decl (info, t); 968169689Skan if (!bitmap_bit_p (info->suppress_expansion, DECL_UID (t))) 969169689Skan { 970169689Skan tree target_context = decl_function_context (t); 971169689Skan struct nesting_info *i; 972169689Skan for (i = info->outer; i->context != target_context; i = i->outer) 973169689Skan continue; 974169689Skan x = lookup_field_for_decl (i, t, INSERT); 975169689Skan x = get_frame_field (info, target_context, x, &wi->tsi); 976169689Skan if (use_pointer_in_frame (t)) 977169689Skan { 978169689Skan x = init_tmp_var (info, x, &wi->tsi); 979169689Skan x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x); 980169689Skan } 981169689Skan } 982169689Skan 983169689Skan if (wi->val_only) 984169689Skan { 985169689Skan if (wi->is_lhs) 986169689Skan x = save_tmp_var (info, x, &wi->tsi); 987169689Skan else 988169689Skan x = init_tmp_var (info, x, &wi->tsi); 989169689Skan } 990169689Skan 991169689Skan *tp = x; 992169689Skan } 993169689Skan break; 994169689Skan 995169689Skan case GOTO_EXPR: 996169689Skan /* Don't walk non-local gotos for now. */ 997169689Skan if (TREE_CODE (GOTO_DESTINATION (t)) != LABEL_DECL) 998169689Skan { 999169689Skan *walk_subtrees = 1; 1000169689Skan wi->val_only = true; 1001169689Skan wi->is_lhs = false; 1002169689Skan } 1003169689Skan break; 1004169689Skan 1005169689Skan case LABEL_DECL: 1006169689Skan /* We're taking the address of a label from a parent function, but 1007169689Skan this is not itself a non-local goto. Mark the label such that it 1008169689Skan will not be deleted, much as we would with a label address in 1009169689Skan static storage. */ 1010169689Skan if (decl_function_context (t) != info->context) 1011169689Skan FORCED_LABEL (t) = 1; 1012169689Skan break; 1013169689Skan 1014169689Skan case ADDR_EXPR: 1015169689Skan { 1016169689Skan bool save_val_only = wi->val_only; 1017169689Skan 1018169689Skan wi->val_only = false; 1019169689Skan wi->is_lhs = false; 1020169689Skan wi->changed = false; 1021169689Skan walk_tree (&TREE_OPERAND (t, 0), convert_nonlocal_reference, wi, NULL); 1022169689Skan wi->val_only = true; 1023169689Skan 1024169689Skan if (wi->changed) 1025169689Skan { 1026169689Skan tree save_context; 1027169689Skan 1028169689Skan /* If we changed anything, then TREE_INVARIANT is be wrong, 1029169689Skan since we're no longer directly referencing a decl. */ 1030169689Skan save_context = current_function_decl; 1031169689Skan current_function_decl = info->context; 1032169689Skan recompute_tree_invariant_for_addr_expr (t); 1033169689Skan current_function_decl = save_context; 1034169689Skan 1035169689Skan /* If the callback converted the address argument in a context 1036169689Skan where we only accept variables (and min_invariant, presumably), 1037169689Skan then compute the address into a temporary. */ 1038169689Skan if (save_val_only) 1039169689Skan *tp = tsi_gimplify_val (wi->info, t, &wi->tsi); 1040169689Skan } 1041169689Skan } 1042169689Skan break; 1043169689Skan 1044169689Skan case REALPART_EXPR: 1045169689Skan case IMAGPART_EXPR: 1046169689Skan case COMPONENT_REF: 1047169689Skan case ARRAY_REF: 1048169689Skan case ARRAY_RANGE_REF: 1049169689Skan case BIT_FIELD_REF: 1050169689Skan /* Go down this entire nest and just look at the final prefix and 1051169689Skan anything that describes the references. Otherwise, we lose track 1052169689Skan of whether a NOP_EXPR or VIEW_CONVERT_EXPR needs a simple value. */ 1053169689Skan wi->val_only = true; 1054169689Skan wi->is_lhs = false; 1055169689Skan for (; handled_component_p (t); tp = &TREE_OPERAND (t, 0), t = *tp) 1056169689Skan { 1057169689Skan if (TREE_CODE (t) == COMPONENT_REF) 1058169689Skan walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference, wi, 1059169689Skan NULL); 1060169689Skan else if (TREE_CODE (t) == ARRAY_REF 1061169689Skan || TREE_CODE (t) == ARRAY_RANGE_REF) 1062169689Skan { 1063169689Skan walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference, wi, 1064169689Skan NULL); 1065169689Skan walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference, wi, 1066169689Skan NULL); 1067169689Skan walk_tree (&TREE_OPERAND (t, 3), convert_nonlocal_reference, wi, 1068169689Skan NULL); 1069169689Skan } 1070169689Skan else if (TREE_CODE (t) == BIT_FIELD_REF) 1071169689Skan { 1072169689Skan walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference, wi, 1073169689Skan NULL); 1074169689Skan walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference, wi, 1075169689Skan NULL); 1076169689Skan } 1077169689Skan } 1078169689Skan wi->val_only = false; 1079169689Skan walk_tree (tp, convert_nonlocal_reference, wi, NULL); 1080169689Skan break; 1081169689Skan 1082169689Skan case OMP_PARALLEL: 1083169689Skan save_suppress = info->suppress_expansion; 1084169689Skan if (convert_nonlocal_omp_clauses (&OMP_PARALLEL_CLAUSES (t), wi)) 1085169689Skan { 1086169689Skan tree c, decl; 1087169689Skan decl = get_chain_decl (info); 1088169689Skan c = build_omp_clause (OMP_CLAUSE_FIRSTPRIVATE); 1089169689Skan OMP_CLAUSE_DECL (c) = decl; 1090169689Skan OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t); 1091169689Skan OMP_PARALLEL_CLAUSES (t) = c; 1092169689Skan } 1093169689Skan 1094169689Skan save_local_var_chain = info->new_local_var_chain; 1095169689Skan info->new_local_var_chain = NULL; 1096169689Skan 1097169689Skan walk_body (convert_nonlocal_reference, info, &OMP_PARALLEL_BODY (t)); 1098169689Skan 1099169689Skan if (info->new_local_var_chain) 1100169689Skan declare_vars (info->new_local_var_chain, OMP_PARALLEL_BODY (t), false); 1101169689Skan info->new_local_var_chain = save_local_var_chain; 1102169689Skan info->suppress_expansion = save_suppress; 1103169689Skan break; 1104169689Skan 1105169689Skan case OMP_FOR: 1106169689Skan case OMP_SECTIONS: 1107169689Skan case OMP_SINGLE: 1108169689Skan save_suppress = info->suppress_expansion; 1109169689Skan convert_nonlocal_omp_clauses (&OMP_CLAUSES (t), wi); 1110169689Skan walk_body (convert_nonlocal_reference, info, &OMP_BODY (t)); 1111169689Skan info->suppress_expansion = save_suppress; 1112169689Skan break; 1113169689Skan 1114169689Skan case OMP_SECTION: 1115169689Skan case OMP_MASTER: 1116169689Skan case OMP_ORDERED: 1117169689Skan walk_body (convert_nonlocal_reference, info, &OMP_BODY (t)); 1118169689Skan break; 1119169689Skan 1120169689Skan default: 1121169689Skan if (!IS_TYPE_OR_DECL_P (t)) 1122169689Skan { 1123169689Skan *walk_subtrees = 1; 1124169689Skan wi->val_only = true; 1125169689Skan wi->is_lhs = false; 1126169689Skan } 1127169689Skan break; 1128169689Skan } 1129169689Skan 1130169689Skan return NULL_TREE; 1131169689Skan} 1132169689Skan 1133169689Skanstatic bool 1134169689Skanconvert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) 1135169689Skan{ 1136169689Skan struct nesting_info *info = wi->info; 1137169689Skan bool need_chain = false; 1138169689Skan tree clause, decl; 1139169689Skan int dummy; 1140169689Skan bitmap new_suppress; 1141169689Skan 1142169689Skan new_suppress = BITMAP_GGC_ALLOC (); 1143169689Skan bitmap_copy (new_suppress, info->suppress_expansion); 1144169689Skan 1145169689Skan for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause)) 1146169689Skan { 1147169689Skan switch (OMP_CLAUSE_CODE (clause)) 1148169689Skan { 1149169689Skan case OMP_CLAUSE_PRIVATE: 1150169689Skan case OMP_CLAUSE_FIRSTPRIVATE: 1151169689Skan case OMP_CLAUSE_LASTPRIVATE: 1152169689Skan case OMP_CLAUSE_REDUCTION: 1153169689Skan case OMP_CLAUSE_COPYPRIVATE: 1154169689Skan case OMP_CLAUSE_SHARED: 1155169689Skan decl = OMP_CLAUSE_DECL (clause); 1156169689Skan if (decl_function_context (decl) != info->context) 1157169689Skan { 1158169689Skan bitmap_set_bit (new_suppress, DECL_UID (decl)); 1159169689Skan OMP_CLAUSE_DECL (clause) = get_nonlocal_debug_decl (info, decl); 1160169689Skan need_chain = true; 1161169689Skan } 1162169689Skan break; 1163169689Skan 1164169689Skan case OMP_CLAUSE_SCHEDULE: 1165169689Skan if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL) 1166169689Skan break; 1167169689Skan /* FALLTHRU */ 1168169689Skan case OMP_CLAUSE_IF: 1169169689Skan case OMP_CLAUSE_NUM_THREADS: 1170169689Skan wi->val_only = true; 1171169689Skan wi->is_lhs = false; 1172169689Skan convert_nonlocal_reference (&OMP_CLAUSE_OPERAND (clause, 0), &dummy, 1173169689Skan wi); 1174169689Skan break; 1175169689Skan 1176169689Skan case OMP_CLAUSE_NOWAIT: 1177169689Skan case OMP_CLAUSE_ORDERED: 1178169689Skan case OMP_CLAUSE_DEFAULT: 1179169689Skan case OMP_CLAUSE_COPYIN: 1180169689Skan break; 1181169689Skan 1182169689Skan default: 1183169689Skan gcc_unreachable (); 1184169689Skan } 1185169689Skan } 1186169689Skan 1187169689Skan info->suppress_expansion = new_suppress; 1188169689Skan 1189169689Skan return need_chain; 1190169689Skan} 1191169689Skan 1192169689Skan/* A subroutine of convert_local_reference. Create a local variable 1193169689Skan in the parent function with DECL_VALUE_EXPR set to reference the 1194169689Skan field in FRAME. This is used both for debug info and in OpenMP 1195169689Skan lowering. */ 1196169689Skan 1197169689Skanstatic tree 1198169689Skanget_local_debug_decl (struct nesting_info *info, tree decl, tree field) 1199169689Skan{ 1200169689Skan struct var_map_elt *elt, dummy; 1201169689Skan tree x, new_decl; 1202169689Skan void **slot; 1203169689Skan 1204169689Skan dummy.old = decl; 1205169689Skan slot = htab_find_slot (info->var_map, &dummy, INSERT); 1206169689Skan elt = *slot; 1207169689Skan 1208169689Skan if (elt) 1209169689Skan return elt->new; 1210169689Skan 1211169689Skan /* Make sure frame_decl gets created. */ 1212169689Skan (void) get_frame_type (info); 1213169689Skan x = info->frame_decl; 1214169689Skan x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE); 1215169689Skan 1216169689Skan new_decl = build_decl (VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl)); 1217169689Skan DECL_CONTEXT (new_decl) = info->context; 1218169689Skan DECL_SOURCE_LOCATION (new_decl) = DECL_SOURCE_LOCATION (decl); 1219169689Skan DECL_ARTIFICIAL (new_decl) = DECL_ARTIFICIAL (decl); 1220169689Skan DECL_IGNORED_P (new_decl) = DECL_IGNORED_P (decl); 1221169689Skan TREE_THIS_VOLATILE (new_decl) = TREE_THIS_VOLATILE (decl); 1222169689Skan TREE_SIDE_EFFECTS (new_decl) = TREE_SIDE_EFFECTS (decl); 1223169689Skan TREE_READONLY (new_decl) = TREE_READONLY (decl); 1224169689Skan TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (decl); 1225169689Skan DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1; 1226169689Skan 1227169689Skan SET_DECL_VALUE_EXPR (new_decl, x); 1228169689Skan DECL_HAS_VALUE_EXPR_P (new_decl) = 1; 1229169689Skan 1230169689Skan elt = ggc_alloc (sizeof (*elt)); 1231169689Skan elt->old = decl; 1232169689Skan elt->new = new_decl; 1233169689Skan *slot = elt; 1234169689Skan 1235169689Skan TREE_CHAIN (new_decl) = info->debug_var_chain; 1236169689Skan info->debug_var_chain = new_decl; 1237169689Skan 1238169689Skan /* Do not emit debug info twice. */ 1239169689Skan DECL_IGNORED_P (decl) = 1; 1240169689Skan 1241169689Skan return new_decl; 1242169689Skan} 1243169689Skan 1244169689Skan/* Called via walk_function+walk_tree, rewrite all references to VAR 1245169689Skan and PARM_DECLs that were referenced by inner nested functions. 1246169689Skan The rewrite will be a structure reference to the local frame variable. */ 1247169689Skan 1248169689Skanstatic bool convert_local_omp_clauses (tree *, struct walk_stmt_info *); 1249169689Skan 1250169689Skanstatic tree 1251169689Skanconvert_local_reference (tree *tp, int *walk_subtrees, void *data) 1252169689Skan{ 1253169689Skan struct walk_stmt_info *wi = (struct walk_stmt_info *) data; 1254169689Skan struct nesting_info *info = wi->info; 1255169689Skan tree t = *tp, field, x; 1256169689Skan bool save_val_only; 1257169689Skan tree save_local_var_chain; 1258169689Skan bitmap save_suppress; 1259169689Skan 1260169689Skan *walk_subtrees = 0; 1261169689Skan switch (TREE_CODE (t)) 1262169689Skan { 1263169689Skan case VAR_DECL: 1264169689Skan /* Non-automatic variables are never processed. */ 1265169689Skan if (TREE_STATIC (t) || DECL_EXTERNAL (t)) 1266169689Skan break; 1267169689Skan /* FALLTHRU */ 1268169689Skan 1269169689Skan case PARM_DECL: 1270169689Skan if (decl_function_context (t) == info->context) 1271169689Skan { 1272169689Skan /* If we copied a pointer to the frame, then the original decl 1273169689Skan is used unchanged in the parent function. */ 1274169689Skan if (use_pointer_in_frame (t)) 1275169689Skan break; 1276169689Skan 1277169689Skan /* No need to transform anything if no child references the 1278169689Skan variable. */ 1279169689Skan field = lookup_field_for_decl (info, t, NO_INSERT); 1280169689Skan if (!field) 1281169689Skan break; 1282169689Skan wi->changed = true; 1283169689Skan 1284169689Skan x = get_local_debug_decl (info, t, field); 1285169689Skan if (!bitmap_bit_p (info->suppress_expansion, DECL_UID (t))) 1286169689Skan x = get_frame_field (info, info->context, field, &wi->tsi); 1287169689Skan 1288169689Skan if (wi->val_only) 1289169689Skan { 1290169689Skan if (wi->is_lhs) 1291169689Skan x = save_tmp_var (info, x, &wi->tsi); 1292169689Skan else 1293169689Skan x = init_tmp_var (info, x, &wi->tsi); 1294169689Skan } 1295169689Skan 1296169689Skan *tp = x; 1297169689Skan } 1298169689Skan break; 1299169689Skan 1300169689Skan case ADDR_EXPR: 1301169689Skan save_val_only = wi->val_only; 1302169689Skan wi->val_only = false; 1303169689Skan wi->is_lhs = false; 1304169689Skan wi->changed = false; 1305169689Skan walk_tree (&TREE_OPERAND (t, 0), convert_local_reference, wi, NULL); 1306169689Skan wi->val_only = save_val_only; 1307169689Skan 1308169689Skan /* If we converted anything ... */ 1309169689Skan if (wi->changed) 1310169689Skan { 1311169689Skan tree save_context; 1312169689Skan 1313169689Skan /* Then the frame decl is now addressable. */ 1314169689Skan TREE_ADDRESSABLE (info->frame_decl) = 1; 1315169689Skan 1316169689Skan save_context = current_function_decl; 1317169689Skan current_function_decl = info->context; 1318169689Skan recompute_tree_invariant_for_addr_expr (t); 1319169689Skan current_function_decl = save_context; 1320169689Skan 1321169689Skan /* If we are in a context where we only accept values, then 1322169689Skan compute the address into a temporary. */ 1323169689Skan if (save_val_only) 1324169689Skan *tp = tsi_gimplify_val (wi->info, t, &wi->tsi); 1325169689Skan } 1326169689Skan break; 1327169689Skan 1328169689Skan case REALPART_EXPR: 1329169689Skan case IMAGPART_EXPR: 1330169689Skan case COMPONENT_REF: 1331169689Skan case ARRAY_REF: 1332169689Skan case ARRAY_RANGE_REF: 1333169689Skan case BIT_FIELD_REF: 1334169689Skan /* Go down this entire nest and just look at the final prefix and 1335169689Skan anything that describes the references. Otherwise, we lose track 1336169689Skan of whether a NOP_EXPR or VIEW_CONVERT_EXPR needs a simple value. */ 1337169689Skan save_val_only = wi->val_only; 1338169689Skan wi->val_only = true; 1339169689Skan wi->is_lhs = false; 1340169689Skan for (; handled_component_p (t); tp = &TREE_OPERAND (t, 0), t = *tp) 1341169689Skan { 1342169689Skan if (TREE_CODE (t) == COMPONENT_REF) 1343169689Skan walk_tree (&TREE_OPERAND (t, 2), convert_local_reference, wi, 1344169689Skan NULL); 1345169689Skan else if (TREE_CODE (t) == ARRAY_REF 1346169689Skan || TREE_CODE (t) == ARRAY_RANGE_REF) 1347169689Skan { 1348169689Skan walk_tree (&TREE_OPERAND (t, 1), convert_local_reference, wi, 1349169689Skan NULL); 1350169689Skan walk_tree (&TREE_OPERAND (t, 2), convert_local_reference, wi, 1351169689Skan NULL); 1352169689Skan walk_tree (&TREE_OPERAND (t, 3), convert_local_reference, wi, 1353169689Skan NULL); 1354169689Skan } 1355169689Skan else if (TREE_CODE (t) == BIT_FIELD_REF) 1356169689Skan { 1357169689Skan walk_tree (&TREE_OPERAND (t, 1), convert_local_reference, wi, 1358169689Skan NULL); 1359169689Skan walk_tree (&TREE_OPERAND (t, 2), convert_local_reference, wi, 1360169689Skan NULL); 1361169689Skan } 1362169689Skan } 1363169689Skan wi->val_only = false; 1364169689Skan walk_tree (tp, convert_local_reference, wi, NULL); 1365169689Skan wi->val_only = save_val_only; 1366169689Skan break; 1367169689Skan 1368169689Skan case OMP_PARALLEL: 1369169689Skan save_suppress = info->suppress_expansion; 1370169689Skan if (convert_local_omp_clauses (&OMP_PARALLEL_CLAUSES (t), wi)) 1371169689Skan { 1372169689Skan tree c; 1373169689Skan (void) get_frame_type (info); 1374169689Skan c = build_omp_clause (OMP_CLAUSE_SHARED); 1375169689Skan OMP_CLAUSE_DECL (c) = info->frame_decl; 1376169689Skan OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t); 1377169689Skan OMP_PARALLEL_CLAUSES (t) = c; 1378169689Skan } 1379169689Skan 1380169689Skan save_local_var_chain = info->new_local_var_chain; 1381169689Skan info->new_local_var_chain = NULL; 1382169689Skan 1383169689Skan walk_body (convert_local_reference, info, &OMP_PARALLEL_BODY (t)); 1384169689Skan 1385169689Skan if (info->new_local_var_chain) 1386169689Skan declare_vars (info->new_local_var_chain, OMP_PARALLEL_BODY (t), false); 1387169689Skan info->new_local_var_chain = save_local_var_chain; 1388169689Skan info->suppress_expansion = save_suppress; 1389169689Skan break; 1390169689Skan 1391169689Skan case OMP_FOR: 1392169689Skan case OMP_SECTIONS: 1393169689Skan case OMP_SINGLE: 1394169689Skan save_suppress = info->suppress_expansion; 1395169689Skan convert_local_omp_clauses (&OMP_CLAUSES (t), wi); 1396169689Skan walk_body (convert_local_reference, info, &OMP_BODY (t)); 1397169689Skan info->suppress_expansion = save_suppress; 1398169689Skan break; 1399169689Skan 1400169689Skan case OMP_SECTION: 1401169689Skan case OMP_MASTER: 1402169689Skan case OMP_ORDERED: 1403169689Skan walk_body (convert_local_reference, info, &OMP_BODY (t)); 1404169689Skan break; 1405169689Skan 1406169689Skan default: 1407169689Skan if (!IS_TYPE_OR_DECL_P (t)) 1408169689Skan { 1409169689Skan *walk_subtrees = 1; 1410169689Skan wi->val_only = true; 1411169689Skan wi->is_lhs = false; 1412169689Skan } 1413169689Skan break; 1414169689Skan } 1415169689Skan 1416169689Skan return NULL_TREE; 1417169689Skan} 1418169689Skan 1419169689Skanstatic bool 1420169689Skanconvert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) 1421169689Skan{ 1422169689Skan struct nesting_info *info = wi->info; 1423169689Skan bool need_frame = false; 1424169689Skan tree clause, decl; 1425169689Skan int dummy; 1426169689Skan bitmap new_suppress; 1427169689Skan 1428169689Skan new_suppress = BITMAP_GGC_ALLOC (); 1429169689Skan bitmap_copy (new_suppress, info->suppress_expansion); 1430169689Skan 1431169689Skan for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause)) 1432169689Skan { 1433169689Skan switch (OMP_CLAUSE_CODE (clause)) 1434169689Skan { 1435169689Skan case OMP_CLAUSE_PRIVATE: 1436169689Skan case OMP_CLAUSE_FIRSTPRIVATE: 1437169689Skan case OMP_CLAUSE_LASTPRIVATE: 1438169689Skan case OMP_CLAUSE_REDUCTION: 1439169689Skan case OMP_CLAUSE_COPYPRIVATE: 1440169689Skan case OMP_CLAUSE_SHARED: 1441169689Skan decl = OMP_CLAUSE_DECL (clause); 1442169689Skan if (decl_function_context (decl) == info->context 1443169689Skan && !use_pointer_in_frame (decl)) 1444169689Skan { 1445169689Skan tree field = lookup_field_for_decl (info, decl, NO_INSERT); 1446169689Skan if (field) 1447169689Skan { 1448169689Skan bitmap_set_bit (new_suppress, DECL_UID (decl)); 1449169689Skan OMP_CLAUSE_DECL (clause) 1450169689Skan = get_local_debug_decl (info, decl, field); 1451169689Skan need_frame = true; 1452169689Skan } 1453169689Skan } 1454169689Skan break; 1455169689Skan 1456169689Skan case OMP_CLAUSE_SCHEDULE: 1457169689Skan if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL) 1458169689Skan break; 1459169689Skan /* FALLTHRU */ 1460169689Skan case OMP_CLAUSE_IF: 1461169689Skan case OMP_CLAUSE_NUM_THREADS: 1462169689Skan wi->val_only = true; 1463169689Skan wi->is_lhs = false; 1464169689Skan convert_local_reference (&OMP_CLAUSE_OPERAND (clause, 0), &dummy, wi); 1465169689Skan break; 1466169689Skan 1467169689Skan case OMP_CLAUSE_NOWAIT: 1468169689Skan case OMP_CLAUSE_ORDERED: 1469169689Skan case OMP_CLAUSE_DEFAULT: 1470169689Skan case OMP_CLAUSE_COPYIN: 1471169689Skan break; 1472169689Skan 1473169689Skan default: 1474169689Skan gcc_unreachable (); 1475169689Skan } 1476169689Skan } 1477169689Skan 1478169689Skan info->suppress_expansion = new_suppress; 1479169689Skan 1480169689Skan return need_frame; 1481169689Skan} 1482169689Skan 1483169689Skan/* Called via walk_function+walk_tree, rewrite all GOTO_EXPRs that 1484169689Skan reference labels from outer functions. The rewrite will be a 1485169689Skan call to __builtin_nonlocal_goto. */ 1486169689Skan 1487169689Skanstatic tree 1488169689Skanconvert_nl_goto_reference (tree *tp, int *walk_subtrees, void *data) 1489169689Skan{ 1490169689Skan struct walk_stmt_info *wi = (struct walk_stmt_info *) data; 1491169689Skan struct nesting_info *info = wi->info, *i; 1492169689Skan tree t = *tp, label, new_label, target_context, x, arg, field; 1493169689Skan struct var_map_elt *elt, dummy; 1494169689Skan void **slot; 1495169689Skan 1496169689Skan *walk_subtrees = 0; 1497169689Skan if (TREE_CODE (t) != GOTO_EXPR) 1498169689Skan return NULL_TREE; 1499169689Skan label = GOTO_DESTINATION (t); 1500169689Skan if (TREE_CODE (label) != LABEL_DECL) 1501169689Skan return NULL_TREE; 1502169689Skan target_context = decl_function_context (label); 1503169689Skan if (target_context == info->context) 1504169689Skan return NULL_TREE; 1505169689Skan 1506169689Skan for (i = info->outer; target_context != i->context; i = i->outer) 1507169689Skan continue; 1508169689Skan 1509169689Skan /* The original user label may also be use for a normal goto, therefore 1510169689Skan we must create a new label that will actually receive the abnormal 1511169689Skan control transfer. This new label will be marked LABEL_NONLOCAL; this 1512169689Skan mark will trigger proper behavior in the cfg, as well as cause the 1513169689Skan (hairy target-specific) non-local goto receiver code to be generated 1514169689Skan when we expand rtl. Enter this association into var_map so that we 1515169689Skan can insert the new label into the IL during a second pass. */ 1516169689Skan dummy.old = label; 1517169689Skan slot = htab_find_slot (i->var_map, &dummy, INSERT); 1518169689Skan elt = (struct var_map_elt *) *slot; 1519169689Skan if (elt == NULL) 1520169689Skan { 1521169689Skan new_label = create_artificial_label (); 1522169689Skan DECL_NONLOCAL (new_label) = 1; 1523169689Skan 1524169689Skan elt = GGC_NEW (struct var_map_elt); 1525169689Skan elt->old = label; 1526169689Skan elt->new = new_label; 1527169689Skan *slot = elt; 1528169689Skan } 1529169689Skan else 1530169689Skan new_label = elt->new; 1531169689Skan 1532169689Skan /* Build: __builtin_nl_goto(new_label, &chain->nl_goto_field). */ 1533169689Skan field = get_nl_goto_field (i); 1534169689Skan x = get_frame_field (info, target_context, field, &wi->tsi); 1535169689Skan x = build_addr (x, target_context); 1536169689Skan x = tsi_gimplify_val (info, x, &wi->tsi); 1537169689Skan arg = tree_cons (NULL, x, NULL); 1538169689Skan x = build_addr (new_label, target_context); 1539169689Skan arg = tree_cons (NULL, x, arg); 1540169689Skan x = implicit_built_in_decls[BUILT_IN_NONLOCAL_GOTO]; 1541169689Skan x = build_function_call_expr (x, arg); 1542169689Skan 1543169689Skan SET_EXPR_LOCUS (x, EXPR_LOCUS (tsi_stmt (wi->tsi))); 1544169689Skan *tsi_stmt_ptr (wi->tsi) = x; 1545169689Skan 1546169689Skan return NULL_TREE; 1547169689Skan} 1548169689Skan 1549169689Skan/* Called via walk_function+walk_tree, rewrite all LABEL_EXPRs that 1550169689Skan are referenced via nonlocal goto from a nested function. The rewrite 1551169689Skan will involve installing a newly generated DECL_NONLOCAL label, and 1552169689Skan (potentially) a branch around the rtl gunk that is assumed to be 1553169689Skan attached to such a label. */ 1554169689Skan 1555169689Skanstatic tree 1556169689Skanconvert_nl_goto_receiver (tree *tp, int *walk_subtrees, void *data) 1557169689Skan{ 1558169689Skan struct walk_stmt_info *wi = (struct walk_stmt_info *) data; 1559169689Skan struct nesting_info *info = wi->info; 1560169689Skan tree t = *tp, label, new_label, x; 1561169689Skan struct var_map_elt *elt, dummy; 1562169689Skan tree_stmt_iterator tmp_tsi; 1563169689Skan 1564169689Skan *walk_subtrees = 0; 1565169689Skan if (TREE_CODE (t) != LABEL_EXPR) 1566169689Skan return NULL_TREE; 1567169689Skan label = LABEL_EXPR_LABEL (t); 1568169689Skan 1569169689Skan dummy.old = label; 1570169689Skan elt = (struct var_map_elt *) htab_find (info->var_map, &dummy); 1571169689Skan if (!elt) 1572169689Skan return NULL_TREE; 1573169689Skan new_label = elt->new; 1574169689Skan 1575169689Skan /* If there's any possibility that the previous statement falls through, 1576169689Skan then we must branch around the new non-local label. */ 1577169689Skan tmp_tsi = wi->tsi; 1578169689Skan tsi_prev (&tmp_tsi); 1579169689Skan if (tsi_end_p (tmp_tsi) || block_may_fallthru (tsi_stmt (tmp_tsi))) 1580169689Skan { 1581169689Skan x = build1 (GOTO_EXPR, void_type_node, label); 1582169689Skan tsi_link_before (&wi->tsi, x, TSI_SAME_STMT); 1583169689Skan } 1584169689Skan x = build1 (LABEL_EXPR, void_type_node, new_label); 1585169689Skan tsi_link_before (&wi->tsi, x, TSI_SAME_STMT); 1586169689Skan 1587169689Skan return NULL_TREE; 1588169689Skan} 1589169689Skan 1590169689Skan/* Called via walk_function+walk_tree, rewrite all references to addresses 1591169689Skan of nested functions that require the use of trampolines. The rewrite 1592169689Skan will involve a reference a trampoline generated for the occasion. */ 1593169689Skan 1594169689Skanstatic tree 1595169689Skanconvert_tramp_reference (tree *tp, int *walk_subtrees, void *data) 1596169689Skan{ 1597169689Skan struct walk_stmt_info *wi = (struct walk_stmt_info *) data; 1598169689Skan struct nesting_info *info = wi->info, *i; 1599169689Skan tree t = *tp, decl, target_context, x, arg; 1600169689Skan 1601169689Skan *walk_subtrees = 0; 1602169689Skan switch (TREE_CODE (t)) 1603169689Skan { 1604169689Skan case ADDR_EXPR: 1605169689Skan /* Build 1606169689Skan T.1 = &CHAIN->tramp; 1607169689Skan T.2 = __builtin_adjust_trampoline (T.1); 1608169689Skan T.3 = (func_type)T.2; 1609169689Skan */ 1610169689Skan 1611169689Skan decl = TREE_OPERAND (t, 0); 1612169689Skan if (TREE_CODE (decl) != FUNCTION_DECL) 1613169689Skan break; 1614169689Skan 1615169689Skan /* Only need to process nested functions. */ 1616169689Skan target_context = decl_function_context (decl); 1617169689Skan if (!target_context) 1618169689Skan break; 1619169689Skan 1620169689Skan /* If the nested function doesn't use a static chain, then 1621169689Skan it doesn't need a trampoline. */ 1622169689Skan if (DECL_NO_STATIC_CHAIN (decl)) 1623169689Skan break; 1624223715Suqs if (warn_trampolines) 1625223715Suqs { 1626223715Suqs warning(0, "local function address taken needing trampoline generation"); 1627223715Suqs } 1628169689Skan 1629169689Skan /* Lookup the immediate parent of the callee, as that's where 1630169689Skan we need to insert the trampoline. */ 1631169689Skan for (i = info; i->context != target_context; i = i->outer) 1632169689Skan continue; 1633169689Skan x = lookup_tramp_for_decl (i, decl, INSERT); 1634169689Skan 1635169689Skan /* Compute the address of the field holding the trampoline. */ 1636169689Skan x = get_frame_field (info, target_context, x, &wi->tsi); 1637169689Skan x = build_addr (x, target_context); 1638169689Skan x = tsi_gimplify_val (info, x, &wi->tsi); 1639169689Skan arg = tree_cons (NULL, x, NULL); 1640169689Skan 1641169689Skan /* Do machine-specific ugliness. Normally this will involve 1642169689Skan computing extra alignment, but it can really be anything. */ 1643169689Skan x = implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE]; 1644169689Skan x = build_function_call_expr (x, arg); 1645169689Skan x = init_tmp_var (info, x, &wi->tsi); 1646169689Skan 1647169689Skan /* Cast back to the proper function type. */ 1648169689Skan x = build1 (NOP_EXPR, TREE_TYPE (t), x); 1649169689Skan x = init_tmp_var (info, x, &wi->tsi); 1650169689Skan 1651169689Skan *tp = x; 1652169689Skan break; 1653169689Skan 1654169689Skan case CALL_EXPR: 1655169689Skan /* Only walk call arguments, lest we generate trampolines for 1656169689Skan direct calls. */ 1657169689Skan walk_tree (&TREE_OPERAND (t, 1), convert_tramp_reference, wi, NULL); 1658169689Skan break; 1659169689Skan 1660169689Skan default: 1661169689Skan if (!IS_TYPE_OR_DECL_P (t)) 1662169689Skan *walk_subtrees = 1; 1663169689Skan break; 1664169689Skan } 1665169689Skan 1666169689Skan return NULL_TREE; 1667169689Skan} 1668169689Skan 1669169689Skan/* Called via walk_function+walk_tree, rewrite all CALL_EXPRs that 1670169689Skan reference nested functions to make sure that the static chain is 1671169689Skan set up properly for the call. */ 1672169689Skan 1673169689Skanstatic tree 1674169689Skanconvert_call_expr (tree *tp, int *walk_subtrees, void *data) 1675169689Skan{ 1676169689Skan struct walk_stmt_info *wi = (struct walk_stmt_info *) data; 1677169689Skan struct nesting_info *info = wi->info; 1678169689Skan tree t = *tp, decl, target_context; 1679169689Skan char save_static_chain_added; 1680169689Skan int i; 1681169689Skan 1682169689Skan *walk_subtrees = 0; 1683169689Skan switch (TREE_CODE (t)) 1684169689Skan { 1685169689Skan case CALL_EXPR: 1686169689Skan decl = get_callee_fndecl (t); 1687169689Skan if (!decl) 1688169689Skan break; 1689169689Skan target_context = decl_function_context (decl); 1690169689Skan if (target_context && !DECL_NO_STATIC_CHAIN (decl)) 1691169689Skan { 1692169689Skan TREE_OPERAND (t, 2) 1693169689Skan = get_static_chain (info, target_context, &wi->tsi); 1694169689Skan info->static_chain_added 1695169689Skan |= (1 << (info->context != target_context)); 1696169689Skan } 1697169689Skan break; 1698169689Skan 1699169689Skan case RETURN_EXPR: 1700169689Skan case MODIFY_EXPR: 1701169689Skan case WITH_SIZE_EXPR: 1702169689Skan /* Only return modify and with_size_expr may contain calls. */ 1703169689Skan *walk_subtrees = 1; 1704169689Skan break; 1705169689Skan 1706169689Skan case OMP_PARALLEL: 1707169689Skan save_static_chain_added = info->static_chain_added; 1708169689Skan info->static_chain_added = 0; 1709169689Skan walk_body (convert_call_expr, info, &OMP_PARALLEL_BODY (t)); 1710169689Skan for (i = 0; i < 2; i++) 1711169689Skan { 1712169689Skan tree c, decl; 1713169689Skan if ((info->static_chain_added & (1 << i)) == 0) 1714169689Skan continue; 1715169689Skan decl = i ? get_chain_decl (info) : info->frame_decl; 1716169689Skan /* Don't add CHAIN.* or FRAME.* twice. */ 1717169689Skan for (c = OMP_PARALLEL_CLAUSES (t); c; c = OMP_CLAUSE_CHAIN (c)) 1718169689Skan if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE 1719169689Skan || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED) 1720169689Skan && OMP_CLAUSE_DECL (c) == decl) 1721169689Skan break; 1722169689Skan if (c == NULL) 1723169689Skan { 1724169689Skan c = build_omp_clause (OMP_CLAUSE_FIRSTPRIVATE); 1725169689Skan OMP_CLAUSE_DECL (c) = decl; 1726169689Skan OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t); 1727169689Skan OMP_PARALLEL_CLAUSES (t) = c; 1728169689Skan } 1729169689Skan } 1730169689Skan info->static_chain_added |= save_static_chain_added; 1731169689Skan break; 1732169689Skan 1733169689Skan case OMP_FOR: 1734169689Skan case OMP_SECTIONS: 1735169689Skan case OMP_SECTION: 1736169689Skan case OMP_SINGLE: 1737169689Skan case OMP_MASTER: 1738169689Skan case OMP_ORDERED: 1739169689Skan case OMP_CRITICAL: 1740169689Skan walk_body (convert_call_expr, info, &OMP_BODY (t)); 1741169689Skan break; 1742169689Skan 1743169689Skan default: 1744169689Skan break; 1745169689Skan } 1746169689Skan 1747169689Skan return NULL_TREE; 1748169689Skan} 1749169689Skan 1750169689Skan/* Walk the nesting tree starting with ROOT, depth first. Convert all 1751169689Skan trampolines and call expressions. On the way back up, determine if 1752169689Skan a nested function actually uses its static chain; if not, remember that. */ 1753169689Skan 1754169689Skanstatic void 1755169689Skanconvert_all_function_calls (struct nesting_info *root) 1756169689Skan{ 1757169689Skan do 1758169689Skan { 1759169689Skan if (root->inner) 1760169689Skan convert_all_function_calls (root->inner); 1761169689Skan 1762169689Skan walk_function (convert_tramp_reference, root); 1763169689Skan walk_function (convert_call_expr, root); 1764169689Skan 1765169689Skan /* If the function does not use a static chain, then remember that. */ 1766169689Skan if (root->outer && !root->chain_decl && !root->chain_field) 1767169689Skan DECL_NO_STATIC_CHAIN (root->context) = 1; 1768169689Skan else 1769169689Skan gcc_assert (!DECL_NO_STATIC_CHAIN (root->context)); 1770169689Skan 1771169689Skan root = root->next; 1772169689Skan } 1773169689Skan while (root); 1774169689Skan} 1775169689Skan 1776169689Skan/* Do "everything else" to clean up or complete state collected by the 1777169689Skan various walking passes -- lay out the types and decls, generate code 1778169689Skan to initialize the frame decl, store critical expressions in the 1779169689Skan struct function for rtl to find. */ 1780169689Skan 1781169689Skanstatic void 1782169689Skanfinalize_nesting_tree_1 (struct nesting_info *root) 1783169689Skan{ 1784169689Skan tree stmt_list = NULL; 1785169689Skan tree context = root->context; 1786169689Skan struct function *sf; 1787169689Skan 1788169689Skan /* If we created a non-local frame type or decl, we need to lay them 1789169689Skan out at this time. */ 1790169689Skan if (root->frame_type) 1791169689Skan { 1792169689Skan /* In some cases the frame type will trigger the -Wpadded warning. 1793169689Skan This is not helpful; suppress it. */ 1794169689Skan int save_warn_padded = warn_padded; 1795169689Skan warn_padded = 0; 1796169689Skan layout_type (root->frame_type); 1797169689Skan warn_padded = save_warn_padded; 1798169689Skan layout_decl (root->frame_decl, 0); 1799169689Skan } 1800169689Skan 1801169689Skan /* If any parameters were referenced non-locally, then we need to 1802169689Skan insert a copy. Likewise, if any variables were referenced by 1803169689Skan pointer, we need to initialize the address. */ 1804169689Skan if (root->any_parm_remapped) 1805169689Skan { 1806169689Skan tree p; 1807169689Skan for (p = DECL_ARGUMENTS (context); p ; p = TREE_CHAIN (p)) 1808169689Skan { 1809169689Skan tree field, x, y; 1810169689Skan 1811169689Skan field = lookup_field_for_decl (root, p, NO_INSERT); 1812169689Skan if (!field) 1813169689Skan continue; 1814169689Skan 1815169689Skan if (use_pointer_in_frame (p)) 1816169689Skan x = build_addr (p, context); 1817169689Skan else 1818169689Skan x = p; 1819169689Skan 1820169689Skan y = build3 (COMPONENT_REF, TREE_TYPE (field), 1821169689Skan root->frame_decl, field, NULL_TREE); 1822169689Skan x = build2 (MODIFY_EXPR, TREE_TYPE (field), y, x); 1823169689Skan append_to_statement_list (x, &stmt_list); 1824169689Skan } 1825169689Skan } 1826169689Skan 1827169689Skan /* If a chain_field was created, then it needs to be initialized 1828169689Skan from chain_decl. */ 1829169689Skan if (root->chain_field) 1830169689Skan { 1831169689Skan tree x = build3 (COMPONENT_REF, TREE_TYPE (root->chain_field), 1832169689Skan root->frame_decl, root->chain_field, NULL_TREE); 1833169689Skan x = build2 (MODIFY_EXPR, TREE_TYPE (x), x, get_chain_decl (root)); 1834169689Skan append_to_statement_list (x, &stmt_list); 1835169689Skan } 1836169689Skan 1837169689Skan /* If trampolines were created, then we need to initialize them. */ 1838169689Skan if (root->any_tramp_created) 1839169689Skan { 1840169689Skan struct nesting_info *i; 1841169689Skan for (i = root->inner; i ; i = i->next) 1842169689Skan { 1843169689Skan tree arg, x, field; 1844169689Skan 1845169689Skan field = lookup_tramp_for_decl (root, i->context, NO_INSERT); 1846169689Skan if (!field) 1847169689Skan continue; 1848169689Skan 1849169689Skan if (DECL_NO_STATIC_CHAIN (i->context)) 1850169689Skan x = null_pointer_node; 1851169689Skan else 1852169689Skan x = build_addr (root->frame_decl, context); 1853169689Skan arg = tree_cons (NULL, x, NULL); 1854169689Skan 1855169689Skan x = build_addr (i->context, context); 1856169689Skan arg = tree_cons (NULL, x, arg); 1857169689Skan 1858169689Skan x = build3 (COMPONENT_REF, TREE_TYPE (field), 1859169689Skan root->frame_decl, field, NULL_TREE); 1860169689Skan x = build_addr (x, context); 1861169689Skan arg = tree_cons (NULL, x, arg); 1862169689Skan 1863169689Skan x = implicit_built_in_decls[BUILT_IN_INIT_TRAMPOLINE]; 1864169689Skan x = build_function_call_expr (x, arg); 1865169689Skan 1866169689Skan append_to_statement_list (x, &stmt_list); 1867169689Skan } 1868169689Skan } 1869169689Skan 1870169689Skan /* If we created initialization statements, insert them. */ 1871169689Skan if (stmt_list) 1872169689Skan { 1873169689Skan annotate_all_with_locus (&stmt_list, 1874169689Skan DECL_SOURCE_LOCATION (context)); 1875169689Skan append_to_statement_list (BIND_EXPR_BODY (DECL_SAVED_TREE (context)), 1876169689Skan &stmt_list); 1877169689Skan BIND_EXPR_BODY (DECL_SAVED_TREE (context)) = stmt_list; 1878169689Skan } 1879169689Skan 1880169689Skan /* If a chain_decl was created, then it needs to be registered with 1881169689Skan struct function so that it gets initialized from the static chain 1882169689Skan register at the beginning of the function. */ 1883169689Skan sf = DECL_STRUCT_FUNCTION (root->context); 1884169689Skan sf->static_chain_decl = root->chain_decl; 1885169689Skan 1886169689Skan /* Similarly for the non-local goto save area. */ 1887169689Skan if (root->nl_goto_field) 1888169689Skan { 1889169689Skan sf->nonlocal_goto_save_area 1890169689Skan = get_frame_field (root, context, root->nl_goto_field, NULL); 1891169689Skan sf->has_nonlocal_label = 1; 1892169689Skan } 1893169689Skan 1894169689Skan /* Make sure all new local variables get inserted into the 1895169689Skan proper BIND_EXPR. */ 1896169689Skan if (root->new_local_var_chain) 1897169689Skan declare_vars (root->new_local_var_chain, DECL_SAVED_TREE (root->context), 1898169689Skan false); 1899169689Skan if (root->debug_var_chain) 1900169689Skan declare_vars (root->debug_var_chain, DECL_SAVED_TREE (root->context), 1901169689Skan true); 1902169689Skan 1903169689Skan /* Dump the translated tree function. */ 1904169689Skan dump_function (TDI_nested, root->context); 1905169689Skan} 1906169689Skan 1907169689Skanstatic void 1908169689Skanfinalize_nesting_tree (struct nesting_info *root) 1909169689Skan{ 1910169689Skan do 1911169689Skan { 1912169689Skan if (root->inner) 1913169689Skan finalize_nesting_tree (root->inner); 1914169689Skan finalize_nesting_tree_1 (root); 1915169689Skan root = root->next; 1916169689Skan } 1917169689Skan while (root); 1918169689Skan} 1919169689Skan 1920169689Skan/* Unnest the nodes and pass them to cgraph. */ 1921169689Skan 1922169689Skanstatic void 1923169689Skanunnest_nesting_tree_1 (struct nesting_info *root) 1924169689Skan{ 1925169689Skan struct cgraph_node *node = cgraph_node (root->context); 1926169689Skan 1927169689Skan /* For nested functions update the cgraph to reflect unnesting. 1928169689Skan We also delay finalizing of these functions up to this point. */ 1929169689Skan if (node->origin) 1930169689Skan { 1931169689Skan cgraph_unnest_node (cgraph_node (root->context)); 1932169689Skan cgraph_finalize_function (root->context, true); 1933169689Skan } 1934169689Skan} 1935169689Skan 1936169689Skanstatic void 1937169689Skanunnest_nesting_tree (struct nesting_info *root) 1938169689Skan{ 1939169689Skan do 1940169689Skan { 1941169689Skan if (root->inner) 1942169689Skan unnest_nesting_tree (root->inner); 1943169689Skan unnest_nesting_tree_1 (root); 1944169689Skan root = root->next; 1945169689Skan } 1946169689Skan while (root); 1947169689Skan} 1948169689Skan 1949169689Skan/* Free the data structures allocated during this pass. */ 1950169689Skan 1951169689Skanstatic void 1952169689Skanfree_nesting_tree (struct nesting_info *root) 1953169689Skan{ 1954169689Skan struct nesting_info *next; 1955169689Skan do 1956169689Skan { 1957169689Skan if (root->inner) 1958169689Skan free_nesting_tree (root->inner); 1959169689Skan htab_delete (root->var_map); 1960169689Skan next = root->next; 1961169689Skan ggc_free (root); 1962169689Skan root = next; 1963169689Skan } 1964169689Skan while (root); 1965169689Skan} 1966169689Skan 1967169689Skanstatic GTY(()) struct nesting_info *root; 1968169689Skan 1969169689Skan/* Main entry point for this pass. Process FNDECL and all of its nested 1970169689Skan subroutines and turn them into something less tightly bound. */ 1971169689Skan 1972169689Skanvoid 1973261188Spfg/* APPLE LOCAL radar 6305545 */ 1974261188Spfglower_nested_functions (tree fndecl, bool skip_outermost_fndecl) 1975169689Skan{ 1976169689Skan struct cgraph_node *cgn; 1977169689Skan 1978169689Skan /* If there are no nested functions, there's nothing to do. */ 1979169689Skan cgn = cgraph_node (fndecl); 1980169689Skan if (!cgn->nested) 1981169689Skan return; 1982169689Skan 1983169689Skan root = create_nesting_tree (cgn); 1984261188Spfg /* APPLE LOCAL begin radar 6305545 */ 1985261188Spfg /* If skip_outermost_fndecl is true, we are lowering nested functions of 1986261188Spfg a constructor/destructor which are cloned and thrown away. But we 1987261188Spfg still have to lower their nested functions, but not the outermost function. */ 1988261188Spfg if (skip_outermost_fndecl) 1989261188Spfg root = root->inner; 1990261188Spfg /* APPLE LOCAL end radar 6305545 */ 1991169689Skan walk_all_functions (convert_nonlocal_reference, root); 1992169689Skan walk_all_functions (convert_local_reference, root); 1993169689Skan walk_all_functions (convert_nl_goto_reference, root); 1994169689Skan walk_all_functions (convert_nl_goto_receiver, root); 1995169689Skan convert_all_function_calls (root); 1996169689Skan finalize_nesting_tree (root); 1997169689Skan unnest_nesting_tree (root); 1998169689Skan free_nesting_tree (root); 1999169689Skan root = NULL; 2000169689Skan} 2001169689Skan 2002169689Skan#include "gt-tree-nested.h" 2003