1*e4b17023SJohn Marino /* Nested function decomposition for GIMPLE. 2*e4b17023SJohn Marino Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 3*e4b17023SJohn Marino Free Software Foundation, Inc. 4*e4b17023SJohn Marino 5*e4b17023SJohn Marino This file is part of GCC. 6*e4b17023SJohn Marino 7*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify 8*e4b17023SJohn Marino it under the terms of the GNU General Public License as published by 9*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option) 10*e4b17023SJohn Marino any later version. 11*e4b17023SJohn Marino 12*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, 13*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of 14*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*e4b17023SJohn Marino GNU General Public License for more details. 16*e4b17023SJohn Marino 17*e4b17023SJohn Marino You should have received a copy of the GNU General Public License 18*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see 19*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */ 20*e4b17023SJohn Marino 21*e4b17023SJohn Marino #include "config.h" 22*e4b17023SJohn Marino #include "system.h" 23*e4b17023SJohn Marino #include "coretypes.h" 24*e4b17023SJohn Marino #include "tm.h" 25*e4b17023SJohn Marino #include "tree.h" 26*e4b17023SJohn Marino #include "tm_p.h" 27*e4b17023SJohn Marino #include "function.h" 28*e4b17023SJohn Marino #include "tree-dump.h" 29*e4b17023SJohn Marino #include "tree-inline.h" 30*e4b17023SJohn Marino #include "gimple.h" 31*e4b17023SJohn Marino #include "tree-iterator.h" 32*e4b17023SJohn Marino #include "tree-flow.h" 33*e4b17023SJohn Marino #include "cgraph.h" 34*e4b17023SJohn Marino #include "expr.h" /* FIXME: For STACK_SAVEAREA_MODE and SAVE_NONLOCAL. */ 35*e4b17023SJohn Marino #include "langhooks.h" 36*e4b17023SJohn Marino #include "pointer-set.h" 37*e4b17023SJohn Marino 38*e4b17023SJohn Marino 39*e4b17023SJohn Marino /* The object of this pass is to lower the representation of a set of nested 40*e4b17023SJohn Marino functions in order to expose all of the gory details of the various 41*e4b17023SJohn Marino nonlocal references. We want to do this sooner rather than later, in 42*e4b17023SJohn Marino order to give us more freedom in emitting all of the functions in question. 43*e4b17023SJohn Marino 44*e4b17023SJohn Marino Back in olden times, when gcc was young, we developed an insanely 45*e4b17023SJohn Marino complicated scheme whereby variables which were referenced nonlocally 46*e4b17023SJohn Marino were forced to live in the stack of the declaring function, and then 47*e4b17023SJohn Marino the nested functions magically discovered where these variables were 48*e4b17023SJohn Marino placed. In order for this scheme to function properly, it required 49*e4b17023SJohn Marino that the outer function be partially expanded, then we switch to 50*e4b17023SJohn Marino compiling the inner function, and once done with those we switch back 51*e4b17023SJohn Marino to compiling the outer function. Such delicate ordering requirements 52*e4b17023SJohn Marino makes it difficult to do whole translation unit optimizations 53*e4b17023SJohn Marino involving such functions. 54*e4b17023SJohn Marino 55*e4b17023SJohn Marino The implementation here is much more direct. Everything that can be 56*e4b17023SJohn Marino referenced by an inner function is a member of an explicitly created 57*e4b17023SJohn Marino structure herein called the "nonlocal frame struct". The incoming 58*e4b17023SJohn Marino static chain for a nested function is a pointer to this struct in 59*e4b17023SJohn Marino the parent. In this way, we settle on known offsets from a known 60*e4b17023SJohn Marino base, and so are decoupled from the logic that places objects in the 61*e4b17023SJohn Marino function's stack frame. More importantly, we don't have to wait for 62*e4b17023SJohn Marino that to happen -- since the compilation of the inner function is no 63*e4b17023SJohn Marino longer tied to a real stack frame, the nonlocal frame struct can be 64*e4b17023SJohn Marino allocated anywhere. Which means that the outer function is now 65*e4b17023SJohn Marino inlinable. 66*e4b17023SJohn Marino 67*e4b17023SJohn Marino Theory of operation here is very simple. Iterate over all the 68*e4b17023SJohn Marino statements in all the functions (depth first) several times, 69*e4b17023SJohn Marino allocating structures and fields on demand. In general we want to 70*e4b17023SJohn Marino examine inner functions first, so that we can avoid making changes 71*e4b17023SJohn Marino to outer functions which are unnecessary. 72*e4b17023SJohn Marino 73*e4b17023SJohn Marino The order of the passes matters a bit, in that later passes will be 74*e4b17023SJohn Marino skipped if it is discovered that the functions don't actually interact 75*e4b17023SJohn Marino at all. That is, they're nested in the lexical sense but could have 76*e4b17023SJohn Marino been written as independent functions without change. */ 77*e4b17023SJohn Marino 78*e4b17023SJohn Marino 79*e4b17023SJohn Marino struct nesting_info 80*e4b17023SJohn Marino { 81*e4b17023SJohn Marino struct nesting_info *outer; 82*e4b17023SJohn Marino struct nesting_info *inner; 83*e4b17023SJohn Marino struct nesting_info *next; 84*e4b17023SJohn Marino 85*e4b17023SJohn Marino struct pointer_map_t *field_map; 86*e4b17023SJohn Marino struct pointer_map_t *var_map; 87*e4b17023SJohn Marino struct pointer_set_t *mem_refs; 88*e4b17023SJohn Marino bitmap suppress_expansion; 89*e4b17023SJohn Marino 90*e4b17023SJohn Marino tree context; 91*e4b17023SJohn Marino tree new_local_var_chain; 92*e4b17023SJohn Marino tree debug_var_chain; 93*e4b17023SJohn Marino tree frame_type; 94*e4b17023SJohn Marino tree frame_decl; 95*e4b17023SJohn Marino tree chain_field; 96*e4b17023SJohn Marino tree chain_decl; 97*e4b17023SJohn Marino tree nl_goto_field; 98*e4b17023SJohn Marino 99*e4b17023SJohn Marino bool any_parm_remapped; 100*e4b17023SJohn Marino bool any_tramp_created; 101*e4b17023SJohn Marino char static_chain_added; 102*e4b17023SJohn Marino }; 103*e4b17023SJohn Marino 104*e4b17023SJohn Marino 105*e4b17023SJohn Marino /* Iterate over the nesting tree, starting with ROOT, depth first. */ 106*e4b17023SJohn Marino 107*e4b17023SJohn Marino static inline struct nesting_info * 108*e4b17023SJohn Marino iter_nestinfo_start (struct nesting_info *root) 109*e4b17023SJohn Marino { 110*e4b17023SJohn Marino while (root->inner) 111*e4b17023SJohn Marino root = root->inner; 112*e4b17023SJohn Marino return root; 113*e4b17023SJohn Marino } 114*e4b17023SJohn Marino 115*e4b17023SJohn Marino static inline struct nesting_info * 116*e4b17023SJohn Marino iter_nestinfo_next (struct nesting_info *node) 117*e4b17023SJohn Marino { 118*e4b17023SJohn Marino if (node->next) 119*e4b17023SJohn Marino return iter_nestinfo_start (node->next); 120*e4b17023SJohn Marino return node->outer; 121*e4b17023SJohn Marino } 122*e4b17023SJohn Marino 123*e4b17023SJohn Marino #define FOR_EACH_NEST_INFO(I, ROOT) \ 124*e4b17023SJohn Marino for ((I) = iter_nestinfo_start (ROOT); (I); (I) = iter_nestinfo_next (I)) 125*e4b17023SJohn Marino 126*e4b17023SJohn Marino /* Obstack used for the bitmaps in the struct above. */ 127*e4b17023SJohn Marino static struct bitmap_obstack nesting_info_bitmap_obstack; 128*e4b17023SJohn Marino 129*e4b17023SJohn Marino 130*e4b17023SJohn Marino /* We're working in so many different function contexts simultaneously, 131*e4b17023SJohn Marino that create_tmp_var is dangerous. Prevent mishap. */ 132*e4b17023SJohn Marino #define create_tmp_var cant_use_create_tmp_var_here_dummy 133*e4b17023SJohn Marino 134*e4b17023SJohn Marino /* Like create_tmp_var, except record the variable for registration at 135*e4b17023SJohn Marino the given nesting level. */ 136*e4b17023SJohn Marino 137*e4b17023SJohn Marino static tree 138*e4b17023SJohn Marino create_tmp_var_for (struct nesting_info *info, tree type, const char *prefix) 139*e4b17023SJohn Marino { 140*e4b17023SJohn Marino tree tmp_var; 141*e4b17023SJohn Marino 142*e4b17023SJohn Marino /* If the type is of variable size or a type which must be created by the 143*e4b17023SJohn Marino frontend, something is wrong. Note that we explicitly allow 144*e4b17023SJohn Marino incomplete types here, since we create them ourselves here. */ 145*e4b17023SJohn Marino gcc_assert (!TREE_ADDRESSABLE (type)); 146*e4b17023SJohn Marino gcc_assert (!TYPE_SIZE_UNIT (type) 147*e4b17023SJohn Marino || TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST); 148*e4b17023SJohn Marino 149*e4b17023SJohn Marino tmp_var = create_tmp_var_raw (type, prefix); 150*e4b17023SJohn Marino DECL_CONTEXT (tmp_var) = info->context; 151*e4b17023SJohn Marino DECL_CHAIN (tmp_var) = info->new_local_var_chain; 152*e4b17023SJohn Marino DECL_SEEN_IN_BIND_EXPR_P (tmp_var) = 1; 153*e4b17023SJohn Marino if (TREE_CODE (type) == COMPLEX_TYPE 154*e4b17023SJohn Marino || TREE_CODE (type) == VECTOR_TYPE) 155*e4b17023SJohn Marino DECL_GIMPLE_REG_P (tmp_var) = 1; 156*e4b17023SJohn Marino 157*e4b17023SJohn Marino info->new_local_var_chain = tmp_var; 158*e4b17023SJohn Marino 159*e4b17023SJohn Marino return tmp_var; 160*e4b17023SJohn Marino } 161*e4b17023SJohn Marino 162*e4b17023SJohn Marino /* Take the address of EXP to be used within function CONTEXT. 163*e4b17023SJohn Marino Mark it for addressability as necessary. */ 164*e4b17023SJohn Marino 165*e4b17023SJohn Marino tree 166*e4b17023SJohn Marino build_addr (tree exp, tree context) 167*e4b17023SJohn Marino { 168*e4b17023SJohn Marino tree base = exp; 169*e4b17023SJohn Marino tree save_context; 170*e4b17023SJohn Marino tree retval; 171*e4b17023SJohn Marino 172*e4b17023SJohn Marino while (handled_component_p (base)) 173*e4b17023SJohn Marino base = TREE_OPERAND (base, 0); 174*e4b17023SJohn Marino 175*e4b17023SJohn Marino if (DECL_P (base)) 176*e4b17023SJohn Marino TREE_ADDRESSABLE (base) = 1; 177*e4b17023SJohn Marino 178*e4b17023SJohn Marino /* Building the ADDR_EXPR will compute a set of properties for 179*e4b17023SJohn Marino that ADDR_EXPR. Those properties are unfortunately context 180*e4b17023SJohn Marino specific, i.e., they are dependent on CURRENT_FUNCTION_DECL. 181*e4b17023SJohn Marino 182*e4b17023SJohn Marino Temporarily set CURRENT_FUNCTION_DECL to the desired context, 183*e4b17023SJohn Marino build the ADDR_EXPR, then restore CURRENT_FUNCTION_DECL. That 184*e4b17023SJohn Marino way the properties are for the ADDR_EXPR are computed properly. */ 185*e4b17023SJohn Marino save_context = current_function_decl; 186*e4b17023SJohn Marino current_function_decl = context; 187*e4b17023SJohn Marino retval = build_fold_addr_expr (exp); 188*e4b17023SJohn Marino current_function_decl = save_context; 189*e4b17023SJohn Marino return retval; 190*e4b17023SJohn Marino } 191*e4b17023SJohn Marino 192*e4b17023SJohn Marino /* Insert FIELD into TYPE, sorted by alignment requirements. */ 193*e4b17023SJohn Marino 194*e4b17023SJohn Marino void 195*e4b17023SJohn Marino insert_field_into_struct (tree type, tree field) 196*e4b17023SJohn Marino { 197*e4b17023SJohn Marino tree *p; 198*e4b17023SJohn Marino 199*e4b17023SJohn Marino DECL_CONTEXT (field) = type; 200*e4b17023SJohn Marino 201*e4b17023SJohn Marino for (p = &TYPE_FIELDS (type); *p ; p = &DECL_CHAIN (*p)) 202*e4b17023SJohn Marino if (DECL_ALIGN (field) >= DECL_ALIGN (*p)) 203*e4b17023SJohn Marino break; 204*e4b17023SJohn Marino 205*e4b17023SJohn Marino DECL_CHAIN (field) = *p; 206*e4b17023SJohn Marino *p = field; 207*e4b17023SJohn Marino 208*e4b17023SJohn Marino /* Set correct alignment for frame struct type. */ 209*e4b17023SJohn Marino if (TYPE_ALIGN (type) < DECL_ALIGN (field)) 210*e4b17023SJohn Marino TYPE_ALIGN (type) = DECL_ALIGN (field); 211*e4b17023SJohn Marino } 212*e4b17023SJohn Marino 213*e4b17023SJohn Marino /* Build or return the RECORD_TYPE that describes the frame state that is 214*e4b17023SJohn Marino shared between INFO->CONTEXT and its nested functions. This record will 215*e4b17023SJohn Marino not be complete until finalize_nesting_tree; up until that point we'll 216*e4b17023SJohn Marino be adding fields as necessary. 217*e4b17023SJohn Marino 218*e4b17023SJohn Marino We also build the DECL that represents this frame in the function. */ 219*e4b17023SJohn Marino 220*e4b17023SJohn Marino static tree 221*e4b17023SJohn Marino get_frame_type (struct nesting_info *info) 222*e4b17023SJohn Marino { 223*e4b17023SJohn Marino tree type = info->frame_type; 224*e4b17023SJohn Marino if (!type) 225*e4b17023SJohn Marino { 226*e4b17023SJohn Marino char *name; 227*e4b17023SJohn Marino 228*e4b17023SJohn Marino type = make_node (RECORD_TYPE); 229*e4b17023SJohn Marino 230*e4b17023SJohn Marino name = concat ("FRAME.", 231*e4b17023SJohn Marino IDENTIFIER_POINTER (DECL_NAME (info->context)), 232*e4b17023SJohn Marino NULL); 233*e4b17023SJohn Marino TYPE_NAME (type) = get_identifier (name); 234*e4b17023SJohn Marino free (name); 235*e4b17023SJohn Marino 236*e4b17023SJohn Marino info->frame_type = type; 237*e4b17023SJohn Marino info->frame_decl = create_tmp_var_for (info, type, "FRAME"); 238*e4b17023SJohn Marino 239*e4b17023SJohn Marino /* ??? Always make it addressable for now, since it is meant to 240*e4b17023SJohn Marino be pointed to by the static chain pointer. This pessimizes 241*e4b17023SJohn Marino when it turns out that no static chains are needed because 242*e4b17023SJohn Marino the nested functions referencing non-local variables are not 243*e4b17023SJohn Marino reachable, but the true pessimization is to create the non- 244*e4b17023SJohn Marino local frame structure in the first place. */ 245*e4b17023SJohn Marino TREE_ADDRESSABLE (info->frame_decl) = 1; 246*e4b17023SJohn Marino } 247*e4b17023SJohn Marino return type; 248*e4b17023SJohn Marino } 249*e4b17023SJohn Marino 250*e4b17023SJohn Marino /* Return true if DECL should be referenced by pointer in the non-local 251*e4b17023SJohn Marino frame structure. */ 252*e4b17023SJohn Marino 253*e4b17023SJohn Marino static bool 254*e4b17023SJohn Marino use_pointer_in_frame (tree decl) 255*e4b17023SJohn Marino { 256*e4b17023SJohn Marino if (TREE_CODE (decl) == PARM_DECL) 257*e4b17023SJohn Marino { 258*e4b17023SJohn Marino /* It's illegal to copy TREE_ADDRESSABLE, impossible to copy variable 259*e4b17023SJohn Marino sized decls, and inefficient to copy large aggregates. Don't bother 260*e4b17023SJohn Marino moving anything but scalar variables. */ 261*e4b17023SJohn Marino return AGGREGATE_TYPE_P (TREE_TYPE (decl)); 262*e4b17023SJohn Marino } 263*e4b17023SJohn Marino else 264*e4b17023SJohn Marino { 265*e4b17023SJohn Marino /* Variable sized types make things "interesting" in the frame. */ 266*e4b17023SJohn Marino return DECL_SIZE (decl) == NULL || !TREE_CONSTANT (DECL_SIZE (decl)); 267*e4b17023SJohn Marino } 268*e4b17023SJohn Marino } 269*e4b17023SJohn Marino 270*e4b17023SJohn Marino /* Given DECL, a non-locally accessed variable, find or create a field 271*e4b17023SJohn Marino in the non-local frame structure for the given nesting context. */ 272*e4b17023SJohn Marino 273*e4b17023SJohn Marino static tree 274*e4b17023SJohn Marino lookup_field_for_decl (struct nesting_info *info, tree decl, 275*e4b17023SJohn Marino enum insert_option insert) 276*e4b17023SJohn Marino { 277*e4b17023SJohn Marino void **slot; 278*e4b17023SJohn Marino 279*e4b17023SJohn Marino if (insert == NO_INSERT) 280*e4b17023SJohn Marino { 281*e4b17023SJohn Marino slot = pointer_map_contains (info->field_map, decl); 282*e4b17023SJohn Marino return slot ? (tree) *slot : NULL_TREE; 283*e4b17023SJohn Marino } 284*e4b17023SJohn Marino 285*e4b17023SJohn Marino slot = pointer_map_insert (info->field_map, decl); 286*e4b17023SJohn Marino if (!*slot) 287*e4b17023SJohn Marino { 288*e4b17023SJohn Marino tree field = make_node (FIELD_DECL); 289*e4b17023SJohn Marino DECL_NAME (field) = DECL_NAME (decl); 290*e4b17023SJohn Marino 291*e4b17023SJohn Marino if (use_pointer_in_frame (decl)) 292*e4b17023SJohn Marino { 293*e4b17023SJohn Marino TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl)); 294*e4b17023SJohn Marino DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field)); 295*e4b17023SJohn Marino DECL_NONADDRESSABLE_P (field) = 1; 296*e4b17023SJohn Marino } 297*e4b17023SJohn Marino else 298*e4b17023SJohn Marino { 299*e4b17023SJohn Marino TREE_TYPE (field) = TREE_TYPE (decl); 300*e4b17023SJohn Marino DECL_SOURCE_LOCATION (field) = DECL_SOURCE_LOCATION (decl); 301*e4b17023SJohn Marino DECL_ALIGN (field) = DECL_ALIGN (decl); 302*e4b17023SJohn Marino DECL_USER_ALIGN (field) = DECL_USER_ALIGN (decl); 303*e4b17023SJohn Marino TREE_ADDRESSABLE (field) = TREE_ADDRESSABLE (decl); 304*e4b17023SJohn Marino DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (decl); 305*e4b17023SJohn Marino TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (decl); 306*e4b17023SJohn Marino } 307*e4b17023SJohn Marino 308*e4b17023SJohn Marino insert_field_into_struct (get_frame_type (info), field); 309*e4b17023SJohn Marino *slot = field; 310*e4b17023SJohn Marino 311*e4b17023SJohn Marino if (TREE_CODE (decl) == PARM_DECL) 312*e4b17023SJohn Marino info->any_parm_remapped = true; 313*e4b17023SJohn Marino } 314*e4b17023SJohn Marino 315*e4b17023SJohn Marino return (tree) *slot; 316*e4b17023SJohn Marino } 317*e4b17023SJohn Marino 318*e4b17023SJohn Marino /* Build or return the variable that holds the static chain within 319*e4b17023SJohn Marino INFO->CONTEXT. This variable may only be used within INFO->CONTEXT. */ 320*e4b17023SJohn Marino 321*e4b17023SJohn Marino static tree 322*e4b17023SJohn Marino get_chain_decl (struct nesting_info *info) 323*e4b17023SJohn Marino { 324*e4b17023SJohn Marino tree decl = info->chain_decl; 325*e4b17023SJohn Marino 326*e4b17023SJohn Marino if (!decl) 327*e4b17023SJohn Marino { 328*e4b17023SJohn Marino tree type; 329*e4b17023SJohn Marino 330*e4b17023SJohn Marino type = get_frame_type (info->outer); 331*e4b17023SJohn Marino type = build_pointer_type (type); 332*e4b17023SJohn Marino 333*e4b17023SJohn Marino /* Note that this variable is *not* entered into any BIND_EXPR; 334*e4b17023SJohn Marino the construction of this variable is handled specially in 335*e4b17023SJohn Marino expand_function_start and initialize_inlined_parameters. 336*e4b17023SJohn Marino Note also that it's represented as a parameter. This is more 337*e4b17023SJohn Marino close to the truth, since the initial value does come from 338*e4b17023SJohn Marino the caller. */ 339*e4b17023SJohn Marino decl = build_decl (DECL_SOURCE_LOCATION (info->context), 340*e4b17023SJohn Marino PARM_DECL, create_tmp_var_name ("CHAIN"), type); 341*e4b17023SJohn Marino DECL_ARTIFICIAL (decl) = 1; 342*e4b17023SJohn Marino DECL_IGNORED_P (decl) = 1; 343*e4b17023SJohn Marino TREE_USED (decl) = 1; 344*e4b17023SJohn Marino DECL_CONTEXT (decl) = info->context; 345*e4b17023SJohn Marino DECL_ARG_TYPE (decl) = type; 346*e4b17023SJohn Marino 347*e4b17023SJohn Marino /* Tell tree-inline.c that we never write to this variable, so 348*e4b17023SJohn Marino it can copy-prop the replacement value immediately. */ 349*e4b17023SJohn Marino TREE_READONLY (decl) = 1; 350*e4b17023SJohn Marino 351*e4b17023SJohn Marino info->chain_decl = decl; 352*e4b17023SJohn Marino 353*e4b17023SJohn Marino if (dump_file 354*e4b17023SJohn Marino && (dump_flags & TDF_DETAILS) 355*e4b17023SJohn Marino && !DECL_STATIC_CHAIN (info->context)) 356*e4b17023SJohn Marino fprintf (dump_file, "Setting static-chain for %s\n", 357*e4b17023SJohn Marino lang_hooks.decl_printable_name (info->context, 2)); 358*e4b17023SJohn Marino 359*e4b17023SJohn Marino DECL_STATIC_CHAIN (info->context) = 1; 360*e4b17023SJohn Marino } 361*e4b17023SJohn Marino return decl; 362*e4b17023SJohn Marino } 363*e4b17023SJohn Marino 364*e4b17023SJohn Marino /* Build or return the field within the non-local frame state that holds 365*e4b17023SJohn Marino the static chain for INFO->CONTEXT. This is the way to walk back up 366*e4b17023SJohn Marino multiple nesting levels. */ 367*e4b17023SJohn Marino 368*e4b17023SJohn Marino static tree 369*e4b17023SJohn Marino get_chain_field (struct nesting_info *info) 370*e4b17023SJohn Marino { 371*e4b17023SJohn Marino tree field = info->chain_field; 372*e4b17023SJohn Marino 373*e4b17023SJohn Marino if (!field) 374*e4b17023SJohn Marino { 375*e4b17023SJohn Marino tree type = build_pointer_type (get_frame_type (info->outer)); 376*e4b17023SJohn Marino 377*e4b17023SJohn Marino field = make_node (FIELD_DECL); 378*e4b17023SJohn Marino DECL_NAME (field) = get_identifier ("__chain"); 379*e4b17023SJohn Marino TREE_TYPE (field) = type; 380*e4b17023SJohn Marino DECL_ALIGN (field) = TYPE_ALIGN (type); 381*e4b17023SJohn Marino DECL_NONADDRESSABLE_P (field) = 1; 382*e4b17023SJohn Marino 383*e4b17023SJohn Marino insert_field_into_struct (get_frame_type (info), field); 384*e4b17023SJohn Marino 385*e4b17023SJohn Marino info->chain_field = field; 386*e4b17023SJohn Marino 387*e4b17023SJohn Marino if (dump_file 388*e4b17023SJohn Marino && (dump_flags & TDF_DETAILS) 389*e4b17023SJohn Marino && !DECL_STATIC_CHAIN (info->context)) 390*e4b17023SJohn Marino fprintf (dump_file, "Setting static-chain for %s\n", 391*e4b17023SJohn Marino lang_hooks.decl_printable_name (info->context, 2)); 392*e4b17023SJohn Marino 393*e4b17023SJohn Marino DECL_STATIC_CHAIN (info->context) = 1; 394*e4b17023SJohn Marino } 395*e4b17023SJohn Marino return field; 396*e4b17023SJohn Marino } 397*e4b17023SJohn Marino 398*e4b17023SJohn Marino /* Initialize a new temporary with the GIMPLE_CALL STMT. */ 399*e4b17023SJohn Marino 400*e4b17023SJohn Marino static tree 401*e4b17023SJohn Marino init_tmp_var_with_call (struct nesting_info *info, gimple_stmt_iterator *gsi, 402*e4b17023SJohn Marino gimple call) 403*e4b17023SJohn Marino { 404*e4b17023SJohn Marino tree t; 405*e4b17023SJohn Marino 406*e4b17023SJohn Marino t = create_tmp_var_for (info, gimple_call_return_type (call), NULL); 407*e4b17023SJohn Marino gimple_call_set_lhs (call, t); 408*e4b17023SJohn Marino if (! gsi_end_p (*gsi)) 409*e4b17023SJohn Marino gimple_set_location (call, gimple_location (gsi_stmt (*gsi))); 410*e4b17023SJohn Marino gsi_insert_before (gsi, call, GSI_SAME_STMT); 411*e4b17023SJohn Marino 412*e4b17023SJohn Marino return t; 413*e4b17023SJohn Marino } 414*e4b17023SJohn Marino 415*e4b17023SJohn Marino 416*e4b17023SJohn Marino /* Copy EXP into a temporary. Allocate the temporary in the context of 417*e4b17023SJohn Marino INFO and insert the initialization statement before GSI. */ 418*e4b17023SJohn Marino 419*e4b17023SJohn Marino static tree 420*e4b17023SJohn Marino init_tmp_var (struct nesting_info *info, tree exp, gimple_stmt_iterator *gsi) 421*e4b17023SJohn Marino { 422*e4b17023SJohn Marino tree t; 423*e4b17023SJohn Marino gimple stmt; 424*e4b17023SJohn Marino 425*e4b17023SJohn Marino t = create_tmp_var_for (info, TREE_TYPE (exp), NULL); 426*e4b17023SJohn Marino stmt = gimple_build_assign (t, exp); 427*e4b17023SJohn Marino if (! gsi_end_p (*gsi)) 428*e4b17023SJohn Marino gimple_set_location (stmt, gimple_location (gsi_stmt (*gsi))); 429*e4b17023SJohn Marino gsi_insert_before_without_update (gsi, stmt, GSI_SAME_STMT); 430*e4b17023SJohn Marino 431*e4b17023SJohn Marino return t; 432*e4b17023SJohn Marino } 433*e4b17023SJohn Marino 434*e4b17023SJohn Marino 435*e4b17023SJohn Marino /* Similarly, but only do so to force EXP to satisfy is_gimple_val. */ 436*e4b17023SJohn Marino 437*e4b17023SJohn Marino static tree 438*e4b17023SJohn Marino gsi_gimplify_val (struct nesting_info *info, tree exp, 439*e4b17023SJohn Marino gimple_stmt_iterator *gsi) 440*e4b17023SJohn Marino { 441*e4b17023SJohn Marino if (is_gimple_val (exp)) 442*e4b17023SJohn Marino return exp; 443*e4b17023SJohn Marino else 444*e4b17023SJohn Marino return init_tmp_var (info, exp, gsi); 445*e4b17023SJohn Marino } 446*e4b17023SJohn Marino 447*e4b17023SJohn Marino /* Similarly, but copy from the temporary and insert the statement 448*e4b17023SJohn Marino after the iterator. */ 449*e4b17023SJohn Marino 450*e4b17023SJohn Marino static tree 451*e4b17023SJohn Marino save_tmp_var (struct nesting_info *info, tree exp, gimple_stmt_iterator *gsi) 452*e4b17023SJohn Marino { 453*e4b17023SJohn Marino tree t; 454*e4b17023SJohn Marino gimple stmt; 455*e4b17023SJohn Marino 456*e4b17023SJohn Marino t = create_tmp_var_for (info, TREE_TYPE (exp), NULL); 457*e4b17023SJohn Marino stmt = gimple_build_assign (exp, t); 458*e4b17023SJohn Marino if (! gsi_end_p (*gsi)) 459*e4b17023SJohn Marino gimple_set_location (stmt, gimple_location (gsi_stmt (*gsi))); 460*e4b17023SJohn Marino gsi_insert_after_without_update (gsi, stmt, GSI_SAME_STMT); 461*e4b17023SJohn Marino 462*e4b17023SJohn Marino return t; 463*e4b17023SJohn Marino } 464*e4b17023SJohn Marino 465*e4b17023SJohn Marino /* Build or return the type used to represent a nested function trampoline. */ 466*e4b17023SJohn Marino 467*e4b17023SJohn Marino static GTY(()) tree trampoline_type; 468*e4b17023SJohn Marino 469*e4b17023SJohn Marino static tree 470*e4b17023SJohn Marino get_trampoline_type (struct nesting_info *info) 471*e4b17023SJohn Marino { 472*e4b17023SJohn Marino unsigned align, size; 473*e4b17023SJohn Marino tree t; 474*e4b17023SJohn Marino 475*e4b17023SJohn Marino if (trampoline_type) 476*e4b17023SJohn Marino return trampoline_type; 477*e4b17023SJohn Marino 478*e4b17023SJohn Marino align = TRAMPOLINE_ALIGNMENT; 479*e4b17023SJohn Marino size = TRAMPOLINE_SIZE; 480*e4b17023SJohn Marino 481*e4b17023SJohn Marino /* If we won't be able to guarantee alignment simply via TYPE_ALIGN, 482*e4b17023SJohn Marino then allocate extra space so that we can do dynamic alignment. */ 483*e4b17023SJohn Marino if (align > STACK_BOUNDARY) 484*e4b17023SJohn Marino { 485*e4b17023SJohn Marino size += ((align/BITS_PER_UNIT) - 1) & -(STACK_BOUNDARY/BITS_PER_UNIT); 486*e4b17023SJohn Marino align = STACK_BOUNDARY; 487*e4b17023SJohn Marino } 488*e4b17023SJohn Marino 489*e4b17023SJohn Marino t = build_index_type (size_int (size - 1)); 490*e4b17023SJohn Marino t = build_array_type (char_type_node, t); 491*e4b17023SJohn Marino t = build_decl (DECL_SOURCE_LOCATION (info->context), 492*e4b17023SJohn Marino FIELD_DECL, get_identifier ("__data"), t); 493*e4b17023SJohn Marino DECL_ALIGN (t) = align; 494*e4b17023SJohn Marino DECL_USER_ALIGN (t) = 1; 495*e4b17023SJohn Marino 496*e4b17023SJohn Marino trampoline_type = make_node (RECORD_TYPE); 497*e4b17023SJohn Marino TYPE_NAME (trampoline_type) = get_identifier ("__builtin_trampoline"); 498*e4b17023SJohn Marino TYPE_FIELDS (trampoline_type) = t; 499*e4b17023SJohn Marino layout_type (trampoline_type); 500*e4b17023SJohn Marino DECL_CONTEXT (t) = trampoline_type; 501*e4b17023SJohn Marino 502*e4b17023SJohn Marino return trampoline_type; 503*e4b17023SJohn Marino } 504*e4b17023SJohn Marino 505*e4b17023SJohn Marino /* Given DECL, a nested function, find or create a field in the non-local 506*e4b17023SJohn Marino frame structure for a trampoline for this function. */ 507*e4b17023SJohn Marino 508*e4b17023SJohn Marino static tree 509*e4b17023SJohn Marino lookup_tramp_for_decl (struct nesting_info *info, tree decl, 510*e4b17023SJohn Marino enum insert_option insert) 511*e4b17023SJohn Marino { 512*e4b17023SJohn Marino void **slot; 513*e4b17023SJohn Marino 514*e4b17023SJohn Marino if (insert == NO_INSERT) 515*e4b17023SJohn Marino { 516*e4b17023SJohn Marino slot = pointer_map_contains (info->var_map, decl); 517*e4b17023SJohn Marino return slot ? (tree) *slot : NULL_TREE; 518*e4b17023SJohn Marino } 519*e4b17023SJohn Marino 520*e4b17023SJohn Marino slot = pointer_map_insert (info->var_map, decl); 521*e4b17023SJohn Marino if (!*slot) 522*e4b17023SJohn Marino { 523*e4b17023SJohn Marino tree field = make_node (FIELD_DECL); 524*e4b17023SJohn Marino DECL_NAME (field) = DECL_NAME (decl); 525*e4b17023SJohn Marino TREE_TYPE (field) = get_trampoline_type (info); 526*e4b17023SJohn Marino TREE_ADDRESSABLE (field) = 1; 527*e4b17023SJohn Marino 528*e4b17023SJohn Marino insert_field_into_struct (get_frame_type (info), field); 529*e4b17023SJohn Marino *slot = field; 530*e4b17023SJohn Marino 531*e4b17023SJohn Marino info->any_tramp_created = true; 532*e4b17023SJohn Marino } 533*e4b17023SJohn Marino 534*e4b17023SJohn Marino return (tree) *slot; 535*e4b17023SJohn Marino } 536*e4b17023SJohn Marino 537*e4b17023SJohn Marino /* Build or return the field within the non-local frame state that holds 538*e4b17023SJohn Marino the non-local goto "jmp_buf". The buffer itself is maintained by the 539*e4b17023SJohn Marino rtl middle-end as dynamic stack space is allocated. */ 540*e4b17023SJohn Marino 541*e4b17023SJohn Marino static tree 542*e4b17023SJohn Marino get_nl_goto_field (struct nesting_info *info) 543*e4b17023SJohn Marino { 544*e4b17023SJohn Marino tree field = info->nl_goto_field; 545*e4b17023SJohn Marino if (!field) 546*e4b17023SJohn Marino { 547*e4b17023SJohn Marino unsigned size; 548*e4b17023SJohn Marino tree type; 549*e4b17023SJohn Marino 550*e4b17023SJohn Marino /* For __builtin_nonlocal_goto, we need N words. The first is the 551*e4b17023SJohn Marino frame pointer, the rest is for the target's stack pointer save 552*e4b17023SJohn Marino area. The number of words is controlled by STACK_SAVEAREA_MODE; 553*e4b17023SJohn Marino not the best interface, but it'll do for now. */ 554*e4b17023SJohn Marino if (Pmode == ptr_mode) 555*e4b17023SJohn Marino type = ptr_type_node; 556*e4b17023SJohn Marino else 557*e4b17023SJohn Marino type = lang_hooks.types.type_for_mode (Pmode, 1); 558*e4b17023SJohn Marino 559*e4b17023SJohn Marino size = GET_MODE_SIZE (STACK_SAVEAREA_MODE (SAVE_NONLOCAL)); 560*e4b17023SJohn Marino size = size / GET_MODE_SIZE (Pmode); 561*e4b17023SJohn Marino size = size + 1; 562*e4b17023SJohn Marino 563*e4b17023SJohn Marino type = build_array_type 564*e4b17023SJohn Marino (type, build_index_type (size_int (size))); 565*e4b17023SJohn Marino 566*e4b17023SJohn Marino field = make_node (FIELD_DECL); 567*e4b17023SJohn Marino DECL_NAME (field) = get_identifier ("__nl_goto_buf"); 568*e4b17023SJohn Marino TREE_TYPE (field) = type; 569*e4b17023SJohn Marino DECL_ALIGN (field) = TYPE_ALIGN (type); 570*e4b17023SJohn Marino TREE_ADDRESSABLE (field) = 1; 571*e4b17023SJohn Marino 572*e4b17023SJohn Marino insert_field_into_struct (get_frame_type (info), field); 573*e4b17023SJohn Marino 574*e4b17023SJohn Marino info->nl_goto_field = field; 575*e4b17023SJohn Marino } 576*e4b17023SJohn Marino 577*e4b17023SJohn Marino return field; 578*e4b17023SJohn Marino } 579*e4b17023SJohn Marino 580*e4b17023SJohn Marino /* Invoke CALLBACK on all statements of GIMPLE sequence SEQ. */ 581*e4b17023SJohn Marino 582*e4b17023SJohn Marino static void 583*e4b17023SJohn Marino walk_body (walk_stmt_fn callback_stmt, walk_tree_fn callback_op, 584*e4b17023SJohn Marino struct nesting_info *info, gimple_seq seq) 585*e4b17023SJohn Marino { 586*e4b17023SJohn Marino struct walk_stmt_info wi; 587*e4b17023SJohn Marino 588*e4b17023SJohn Marino memset (&wi, 0, sizeof (wi)); 589*e4b17023SJohn Marino wi.info = info; 590*e4b17023SJohn Marino wi.val_only = true; 591*e4b17023SJohn Marino walk_gimple_seq (seq, callback_stmt, callback_op, &wi); 592*e4b17023SJohn Marino } 593*e4b17023SJohn Marino 594*e4b17023SJohn Marino 595*e4b17023SJohn Marino /* Invoke CALLBACK_STMT/CALLBACK_OP on all statements of INFO->CONTEXT. */ 596*e4b17023SJohn Marino 597*e4b17023SJohn Marino static inline void 598*e4b17023SJohn Marino walk_function (walk_stmt_fn callback_stmt, walk_tree_fn callback_op, 599*e4b17023SJohn Marino struct nesting_info *info) 600*e4b17023SJohn Marino { 601*e4b17023SJohn Marino walk_body (callback_stmt, callback_op, info, gimple_body (info->context)); 602*e4b17023SJohn Marino } 603*e4b17023SJohn Marino 604*e4b17023SJohn Marino /* Invoke CALLBACK on a GIMPLE_OMP_FOR's init, cond, incr and pre-body. */ 605*e4b17023SJohn Marino 606*e4b17023SJohn Marino static void 607*e4b17023SJohn Marino walk_gimple_omp_for (gimple for_stmt, 608*e4b17023SJohn Marino walk_stmt_fn callback_stmt, walk_tree_fn callback_op, 609*e4b17023SJohn Marino struct nesting_info *info) 610*e4b17023SJohn Marino { 611*e4b17023SJohn Marino struct walk_stmt_info wi; 612*e4b17023SJohn Marino gimple_seq seq; 613*e4b17023SJohn Marino tree t; 614*e4b17023SJohn Marino size_t i; 615*e4b17023SJohn Marino 616*e4b17023SJohn Marino walk_body (callback_stmt, callback_op, info, gimple_omp_for_pre_body (for_stmt)); 617*e4b17023SJohn Marino 618*e4b17023SJohn Marino seq = gimple_seq_alloc (); 619*e4b17023SJohn Marino memset (&wi, 0, sizeof (wi)); 620*e4b17023SJohn Marino wi.info = info; 621*e4b17023SJohn Marino wi.gsi = gsi_last (seq); 622*e4b17023SJohn Marino 623*e4b17023SJohn Marino for (i = 0; i < gimple_omp_for_collapse (for_stmt); i++) 624*e4b17023SJohn Marino { 625*e4b17023SJohn Marino wi.val_only = false; 626*e4b17023SJohn Marino walk_tree (gimple_omp_for_index_ptr (for_stmt, i), callback_op, 627*e4b17023SJohn Marino &wi, NULL); 628*e4b17023SJohn Marino wi.val_only = true; 629*e4b17023SJohn Marino wi.is_lhs = false; 630*e4b17023SJohn Marino walk_tree (gimple_omp_for_initial_ptr (for_stmt, i), callback_op, 631*e4b17023SJohn Marino &wi, NULL); 632*e4b17023SJohn Marino 633*e4b17023SJohn Marino wi.val_only = true; 634*e4b17023SJohn Marino wi.is_lhs = false; 635*e4b17023SJohn Marino walk_tree (gimple_omp_for_final_ptr (for_stmt, i), callback_op, 636*e4b17023SJohn Marino &wi, NULL); 637*e4b17023SJohn Marino 638*e4b17023SJohn Marino t = gimple_omp_for_incr (for_stmt, i); 639*e4b17023SJohn Marino gcc_assert (BINARY_CLASS_P (t)); 640*e4b17023SJohn Marino wi.val_only = false; 641*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 0), callback_op, &wi, NULL); 642*e4b17023SJohn Marino wi.val_only = true; 643*e4b17023SJohn Marino wi.is_lhs = false; 644*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 1), callback_op, &wi, NULL); 645*e4b17023SJohn Marino } 646*e4b17023SJohn Marino 647*e4b17023SJohn Marino if (gimple_seq_empty_p (seq)) 648*e4b17023SJohn Marino gimple_seq_free (seq); 649*e4b17023SJohn Marino else 650*e4b17023SJohn Marino { 651*e4b17023SJohn Marino gimple_seq pre_body = gimple_omp_for_pre_body (for_stmt); 652*e4b17023SJohn Marino annotate_all_with_location (seq, gimple_location (for_stmt)); 653*e4b17023SJohn Marino gimple_seq_add_seq (&pre_body, seq); 654*e4b17023SJohn Marino gimple_omp_for_set_pre_body (for_stmt, pre_body); 655*e4b17023SJohn Marino } 656*e4b17023SJohn Marino } 657*e4b17023SJohn Marino 658*e4b17023SJohn Marino /* Similarly for ROOT and all functions nested underneath, depth first. */ 659*e4b17023SJohn Marino 660*e4b17023SJohn Marino static void 661*e4b17023SJohn Marino walk_all_functions (walk_stmt_fn callback_stmt, walk_tree_fn callback_op, 662*e4b17023SJohn Marino struct nesting_info *root) 663*e4b17023SJohn Marino { 664*e4b17023SJohn Marino struct nesting_info *n; 665*e4b17023SJohn Marino FOR_EACH_NEST_INFO (n, root) 666*e4b17023SJohn Marino walk_function (callback_stmt, callback_op, n); 667*e4b17023SJohn Marino } 668*e4b17023SJohn Marino 669*e4b17023SJohn Marino 670*e4b17023SJohn Marino /* We have to check for a fairly pathological case. The operands of function 671*e4b17023SJohn Marino nested function are to be interpreted in the context of the enclosing 672*e4b17023SJohn Marino function. So if any are variably-sized, they will get remapped when the 673*e4b17023SJohn Marino enclosing function is inlined. But that remapping would also have to be 674*e4b17023SJohn Marino done in the types of the PARM_DECLs of the nested function, meaning the 675*e4b17023SJohn Marino argument types of that function will disagree with the arguments in the 676*e4b17023SJohn Marino calls to that function. So we'd either have to make a copy of the nested 677*e4b17023SJohn Marino function corresponding to each time the enclosing function was inlined or 678*e4b17023SJohn Marino add a VIEW_CONVERT_EXPR to each such operand for each call to the nested 679*e4b17023SJohn Marino function. The former is not practical. The latter would still require 680*e4b17023SJohn Marino detecting this case to know when to add the conversions. So, for now at 681*e4b17023SJohn Marino least, we don't inline such an enclosing function. 682*e4b17023SJohn Marino 683*e4b17023SJohn Marino We have to do that check recursively, so here return indicating whether 684*e4b17023SJohn Marino FNDECL has such a nested function. ORIG_FN is the function we were 685*e4b17023SJohn Marino trying to inline to use for checking whether any argument is variably 686*e4b17023SJohn Marino modified by anything in it. 687*e4b17023SJohn Marino 688*e4b17023SJohn Marino It would be better to do this in tree-inline.c so that we could give 689*e4b17023SJohn Marino the appropriate warning for why a function can't be inlined, but that's 690*e4b17023SJohn Marino too late since the nesting structure has already been flattened and 691*e4b17023SJohn Marino adding a flag just to record this fact seems a waste of a flag. */ 692*e4b17023SJohn Marino 693*e4b17023SJohn Marino static bool 694*e4b17023SJohn Marino check_for_nested_with_variably_modified (tree fndecl, tree orig_fndecl) 695*e4b17023SJohn Marino { 696*e4b17023SJohn Marino struct cgraph_node *cgn = cgraph_get_node (fndecl); 697*e4b17023SJohn Marino tree arg; 698*e4b17023SJohn Marino 699*e4b17023SJohn Marino for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested) 700*e4b17023SJohn Marino { 701*e4b17023SJohn Marino for (arg = DECL_ARGUMENTS (cgn->decl); arg; arg = DECL_CHAIN (arg)) 702*e4b17023SJohn Marino if (variably_modified_type_p (TREE_TYPE (arg), orig_fndecl)) 703*e4b17023SJohn Marino return true; 704*e4b17023SJohn Marino 705*e4b17023SJohn Marino if (check_for_nested_with_variably_modified (cgn->decl, orig_fndecl)) 706*e4b17023SJohn Marino return true; 707*e4b17023SJohn Marino } 708*e4b17023SJohn Marino 709*e4b17023SJohn Marino return false; 710*e4b17023SJohn Marino } 711*e4b17023SJohn Marino 712*e4b17023SJohn Marino /* Construct our local datastructure describing the function nesting 713*e4b17023SJohn Marino tree rooted by CGN. */ 714*e4b17023SJohn Marino 715*e4b17023SJohn Marino static struct nesting_info * 716*e4b17023SJohn Marino create_nesting_tree (struct cgraph_node *cgn) 717*e4b17023SJohn Marino { 718*e4b17023SJohn Marino struct nesting_info *info = XCNEW (struct nesting_info); 719*e4b17023SJohn Marino info->field_map = pointer_map_create (); 720*e4b17023SJohn Marino info->var_map = pointer_map_create (); 721*e4b17023SJohn Marino info->mem_refs = pointer_set_create (); 722*e4b17023SJohn Marino info->suppress_expansion = BITMAP_ALLOC (&nesting_info_bitmap_obstack); 723*e4b17023SJohn Marino info->context = cgn->decl; 724*e4b17023SJohn Marino 725*e4b17023SJohn Marino for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested) 726*e4b17023SJohn Marino { 727*e4b17023SJohn Marino struct nesting_info *sub = create_nesting_tree (cgn); 728*e4b17023SJohn Marino sub->outer = info; 729*e4b17023SJohn Marino sub->next = info->inner; 730*e4b17023SJohn Marino info->inner = sub; 731*e4b17023SJohn Marino } 732*e4b17023SJohn Marino 733*e4b17023SJohn Marino /* See discussion at check_for_nested_with_variably_modified for a 734*e4b17023SJohn Marino discussion of why this has to be here. */ 735*e4b17023SJohn Marino if (check_for_nested_with_variably_modified (info->context, info->context)) 736*e4b17023SJohn Marino DECL_UNINLINABLE (info->context) = true; 737*e4b17023SJohn Marino 738*e4b17023SJohn Marino return info; 739*e4b17023SJohn Marino } 740*e4b17023SJohn Marino 741*e4b17023SJohn Marino /* Return an expression computing the static chain for TARGET_CONTEXT 742*e4b17023SJohn Marino from INFO->CONTEXT. Insert any necessary computations before TSI. */ 743*e4b17023SJohn Marino 744*e4b17023SJohn Marino static tree 745*e4b17023SJohn Marino get_static_chain (struct nesting_info *info, tree target_context, 746*e4b17023SJohn Marino gimple_stmt_iterator *gsi) 747*e4b17023SJohn Marino { 748*e4b17023SJohn Marino struct nesting_info *i; 749*e4b17023SJohn Marino tree x; 750*e4b17023SJohn Marino 751*e4b17023SJohn Marino if (info->context == target_context) 752*e4b17023SJohn Marino { 753*e4b17023SJohn Marino x = build_addr (info->frame_decl, target_context); 754*e4b17023SJohn Marino } 755*e4b17023SJohn Marino else 756*e4b17023SJohn Marino { 757*e4b17023SJohn Marino x = get_chain_decl (info); 758*e4b17023SJohn Marino 759*e4b17023SJohn Marino for (i = info->outer; i->context != target_context; i = i->outer) 760*e4b17023SJohn Marino { 761*e4b17023SJohn Marino tree field = get_chain_field (i); 762*e4b17023SJohn Marino 763*e4b17023SJohn Marino x = build_simple_mem_ref (x); 764*e4b17023SJohn Marino x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE); 765*e4b17023SJohn Marino x = init_tmp_var (info, x, gsi); 766*e4b17023SJohn Marino } 767*e4b17023SJohn Marino } 768*e4b17023SJohn Marino 769*e4b17023SJohn Marino return x; 770*e4b17023SJohn Marino } 771*e4b17023SJohn Marino 772*e4b17023SJohn Marino 773*e4b17023SJohn Marino /* Return an expression referencing FIELD from TARGET_CONTEXT's non-local 774*e4b17023SJohn Marino frame as seen from INFO->CONTEXT. Insert any necessary computations 775*e4b17023SJohn Marino before GSI. */ 776*e4b17023SJohn Marino 777*e4b17023SJohn Marino static tree 778*e4b17023SJohn Marino get_frame_field (struct nesting_info *info, tree target_context, 779*e4b17023SJohn Marino tree field, gimple_stmt_iterator *gsi) 780*e4b17023SJohn Marino { 781*e4b17023SJohn Marino struct nesting_info *i; 782*e4b17023SJohn Marino tree x; 783*e4b17023SJohn Marino 784*e4b17023SJohn Marino if (info->context == target_context) 785*e4b17023SJohn Marino { 786*e4b17023SJohn Marino /* Make sure frame_decl gets created. */ 787*e4b17023SJohn Marino (void) get_frame_type (info); 788*e4b17023SJohn Marino x = info->frame_decl; 789*e4b17023SJohn Marino } 790*e4b17023SJohn Marino else 791*e4b17023SJohn Marino { 792*e4b17023SJohn Marino x = get_chain_decl (info); 793*e4b17023SJohn Marino 794*e4b17023SJohn Marino for (i = info->outer; i->context != target_context; i = i->outer) 795*e4b17023SJohn Marino { 796*e4b17023SJohn Marino tree field = get_chain_field (i); 797*e4b17023SJohn Marino 798*e4b17023SJohn Marino x = build_simple_mem_ref (x); 799*e4b17023SJohn Marino x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE); 800*e4b17023SJohn Marino x = init_tmp_var (info, x, gsi); 801*e4b17023SJohn Marino } 802*e4b17023SJohn Marino 803*e4b17023SJohn Marino x = build_simple_mem_ref (x); 804*e4b17023SJohn Marino } 805*e4b17023SJohn Marino 806*e4b17023SJohn Marino x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE); 807*e4b17023SJohn Marino return x; 808*e4b17023SJohn Marino } 809*e4b17023SJohn Marino 810*e4b17023SJohn Marino static void note_nonlocal_vla_type (struct nesting_info *info, tree type); 811*e4b17023SJohn Marino 812*e4b17023SJohn Marino /* A subroutine of convert_nonlocal_reference_op. Create a local variable 813*e4b17023SJohn Marino in the nested function with DECL_VALUE_EXPR set to reference the true 814*e4b17023SJohn Marino variable in the parent function. This is used both for debug info 815*e4b17023SJohn Marino and in OpenMP lowering. */ 816*e4b17023SJohn Marino 817*e4b17023SJohn Marino static tree 818*e4b17023SJohn Marino get_nonlocal_debug_decl (struct nesting_info *info, tree decl) 819*e4b17023SJohn Marino { 820*e4b17023SJohn Marino tree target_context; 821*e4b17023SJohn Marino struct nesting_info *i; 822*e4b17023SJohn Marino tree x, field, new_decl; 823*e4b17023SJohn Marino void **slot; 824*e4b17023SJohn Marino 825*e4b17023SJohn Marino slot = pointer_map_insert (info->var_map, decl); 826*e4b17023SJohn Marino 827*e4b17023SJohn Marino if (*slot) 828*e4b17023SJohn Marino return (tree) *slot; 829*e4b17023SJohn Marino 830*e4b17023SJohn Marino target_context = decl_function_context (decl); 831*e4b17023SJohn Marino 832*e4b17023SJohn Marino /* A copy of the code in get_frame_field, but without the temporaries. */ 833*e4b17023SJohn Marino if (info->context == target_context) 834*e4b17023SJohn Marino { 835*e4b17023SJohn Marino /* Make sure frame_decl gets created. */ 836*e4b17023SJohn Marino (void) get_frame_type (info); 837*e4b17023SJohn Marino x = info->frame_decl; 838*e4b17023SJohn Marino i = info; 839*e4b17023SJohn Marino } 840*e4b17023SJohn Marino else 841*e4b17023SJohn Marino { 842*e4b17023SJohn Marino x = get_chain_decl (info); 843*e4b17023SJohn Marino for (i = info->outer; i->context != target_context; i = i->outer) 844*e4b17023SJohn Marino { 845*e4b17023SJohn Marino field = get_chain_field (i); 846*e4b17023SJohn Marino x = build_simple_mem_ref (x); 847*e4b17023SJohn Marino x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE); 848*e4b17023SJohn Marino } 849*e4b17023SJohn Marino x = build_simple_mem_ref (x); 850*e4b17023SJohn Marino } 851*e4b17023SJohn Marino 852*e4b17023SJohn Marino field = lookup_field_for_decl (i, decl, INSERT); 853*e4b17023SJohn Marino x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE); 854*e4b17023SJohn Marino if (use_pointer_in_frame (decl)) 855*e4b17023SJohn Marino x = build_simple_mem_ref (x); 856*e4b17023SJohn Marino 857*e4b17023SJohn Marino /* ??? We should be remapping types as well, surely. */ 858*e4b17023SJohn Marino new_decl = build_decl (DECL_SOURCE_LOCATION (decl), 859*e4b17023SJohn Marino VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl)); 860*e4b17023SJohn Marino DECL_CONTEXT (new_decl) = info->context; 861*e4b17023SJohn Marino DECL_ARTIFICIAL (new_decl) = DECL_ARTIFICIAL (decl); 862*e4b17023SJohn Marino DECL_IGNORED_P (new_decl) = DECL_IGNORED_P (decl); 863*e4b17023SJohn Marino TREE_THIS_VOLATILE (new_decl) = TREE_THIS_VOLATILE (decl); 864*e4b17023SJohn Marino TREE_SIDE_EFFECTS (new_decl) = TREE_SIDE_EFFECTS (decl); 865*e4b17023SJohn Marino TREE_READONLY (new_decl) = TREE_READONLY (decl); 866*e4b17023SJohn Marino TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (decl); 867*e4b17023SJohn Marino DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1; 868*e4b17023SJohn Marino if ((TREE_CODE (decl) == PARM_DECL 869*e4b17023SJohn Marino || TREE_CODE (decl) == RESULT_DECL 870*e4b17023SJohn Marino || TREE_CODE (decl) == VAR_DECL) 871*e4b17023SJohn Marino && DECL_BY_REFERENCE (decl)) 872*e4b17023SJohn Marino DECL_BY_REFERENCE (new_decl) = 1; 873*e4b17023SJohn Marino 874*e4b17023SJohn Marino SET_DECL_VALUE_EXPR (new_decl, x); 875*e4b17023SJohn Marino DECL_HAS_VALUE_EXPR_P (new_decl) = 1; 876*e4b17023SJohn Marino 877*e4b17023SJohn Marino *slot = new_decl; 878*e4b17023SJohn Marino DECL_CHAIN (new_decl) = info->debug_var_chain; 879*e4b17023SJohn Marino info->debug_var_chain = new_decl; 880*e4b17023SJohn Marino 881*e4b17023SJohn Marino if (!optimize 882*e4b17023SJohn Marino && info->context != target_context 883*e4b17023SJohn Marino && variably_modified_type_p (TREE_TYPE (decl), NULL)) 884*e4b17023SJohn Marino note_nonlocal_vla_type (info, TREE_TYPE (decl)); 885*e4b17023SJohn Marino 886*e4b17023SJohn Marino return new_decl; 887*e4b17023SJohn Marino } 888*e4b17023SJohn Marino 889*e4b17023SJohn Marino 890*e4b17023SJohn Marino /* Callback for walk_gimple_stmt, rewrite all references to VAR 891*e4b17023SJohn Marino and PARM_DECLs that belong to outer functions. 892*e4b17023SJohn Marino 893*e4b17023SJohn Marino The rewrite will involve some number of structure accesses back up 894*e4b17023SJohn Marino the static chain. E.g. for a variable FOO up one nesting level it'll 895*e4b17023SJohn Marino be CHAIN->FOO. For two levels it'll be CHAIN->__chain->FOO. Further 896*e4b17023SJohn Marino indirections apply to decls for which use_pointer_in_frame is true. */ 897*e4b17023SJohn Marino 898*e4b17023SJohn Marino static tree 899*e4b17023SJohn Marino convert_nonlocal_reference_op (tree *tp, int *walk_subtrees, void *data) 900*e4b17023SJohn Marino { 901*e4b17023SJohn Marino struct walk_stmt_info *wi = (struct walk_stmt_info *) data; 902*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info; 903*e4b17023SJohn Marino tree t = *tp; 904*e4b17023SJohn Marino 905*e4b17023SJohn Marino *walk_subtrees = 0; 906*e4b17023SJohn Marino switch (TREE_CODE (t)) 907*e4b17023SJohn Marino { 908*e4b17023SJohn Marino case VAR_DECL: 909*e4b17023SJohn Marino /* Non-automatic variables are never processed. */ 910*e4b17023SJohn Marino if (TREE_STATIC (t) || DECL_EXTERNAL (t)) 911*e4b17023SJohn Marino break; 912*e4b17023SJohn Marino /* FALLTHRU */ 913*e4b17023SJohn Marino 914*e4b17023SJohn Marino case PARM_DECL: 915*e4b17023SJohn Marino if (decl_function_context (t) != info->context) 916*e4b17023SJohn Marino { 917*e4b17023SJohn Marino tree x; 918*e4b17023SJohn Marino wi->changed = true; 919*e4b17023SJohn Marino 920*e4b17023SJohn Marino x = get_nonlocal_debug_decl (info, t); 921*e4b17023SJohn Marino if (!bitmap_bit_p (info->suppress_expansion, DECL_UID (t))) 922*e4b17023SJohn Marino { 923*e4b17023SJohn Marino tree target_context = decl_function_context (t); 924*e4b17023SJohn Marino struct nesting_info *i; 925*e4b17023SJohn Marino for (i = info->outer; i->context != target_context; i = i->outer) 926*e4b17023SJohn Marino continue; 927*e4b17023SJohn Marino x = lookup_field_for_decl (i, t, INSERT); 928*e4b17023SJohn Marino x = get_frame_field (info, target_context, x, &wi->gsi); 929*e4b17023SJohn Marino if (use_pointer_in_frame (t)) 930*e4b17023SJohn Marino { 931*e4b17023SJohn Marino x = init_tmp_var (info, x, &wi->gsi); 932*e4b17023SJohn Marino x = build_simple_mem_ref (x); 933*e4b17023SJohn Marino } 934*e4b17023SJohn Marino } 935*e4b17023SJohn Marino 936*e4b17023SJohn Marino if (wi->val_only) 937*e4b17023SJohn Marino { 938*e4b17023SJohn Marino if (wi->is_lhs) 939*e4b17023SJohn Marino x = save_tmp_var (info, x, &wi->gsi); 940*e4b17023SJohn Marino else 941*e4b17023SJohn Marino x = init_tmp_var (info, x, &wi->gsi); 942*e4b17023SJohn Marino } 943*e4b17023SJohn Marino 944*e4b17023SJohn Marino *tp = x; 945*e4b17023SJohn Marino } 946*e4b17023SJohn Marino break; 947*e4b17023SJohn Marino 948*e4b17023SJohn Marino case LABEL_DECL: 949*e4b17023SJohn Marino /* We're taking the address of a label from a parent function, but 950*e4b17023SJohn Marino this is not itself a non-local goto. Mark the label such that it 951*e4b17023SJohn Marino will not be deleted, much as we would with a label address in 952*e4b17023SJohn Marino static storage. */ 953*e4b17023SJohn Marino if (decl_function_context (t) != info->context) 954*e4b17023SJohn Marino FORCED_LABEL (t) = 1; 955*e4b17023SJohn Marino break; 956*e4b17023SJohn Marino 957*e4b17023SJohn Marino case ADDR_EXPR: 958*e4b17023SJohn Marino { 959*e4b17023SJohn Marino bool save_val_only = wi->val_only; 960*e4b17023SJohn Marino 961*e4b17023SJohn Marino wi->val_only = false; 962*e4b17023SJohn Marino wi->is_lhs = false; 963*e4b17023SJohn Marino wi->changed = false; 964*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 0), convert_nonlocal_reference_op, wi, 0); 965*e4b17023SJohn Marino wi->val_only = true; 966*e4b17023SJohn Marino 967*e4b17023SJohn Marino if (wi->changed) 968*e4b17023SJohn Marino { 969*e4b17023SJohn Marino tree save_context; 970*e4b17023SJohn Marino 971*e4b17023SJohn Marino /* If we changed anything, we might no longer be directly 972*e4b17023SJohn Marino referencing a decl. */ 973*e4b17023SJohn Marino save_context = current_function_decl; 974*e4b17023SJohn Marino current_function_decl = info->context; 975*e4b17023SJohn Marino recompute_tree_invariant_for_addr_expr (t); 976*e4b17023SJohn Marino current_function_decl = save_context; 977*e4b17023SJohn Marino 978*e4b17023SJohn Marino /* If the callback converted the address argument in a context 979*e4b17023SJohn Marino where we only accept variables (and min_invariant, presumably), 980*e4b17023SJohn Marino then compute the address into a temporary. */ 981*e4b17023SJohn Marino if (save_val_only) 982*e4b17023SJohn Marino *tp = gsi_gimplify_val ((struct nesting_info *) wi->info, 983*e4b17023SJohn Marino t, &wi->gsi); 984*e4b17023SJohn Marino } 985*e4b17023SJohn Marino } 986*e4b17023SJohn Marino break; 987*e4b17023SJohn Marino 988*e4b17023SJohn Marino case REALPART_EXPR: 989*e4b17023SJohn Marino case IMAGPART_EXPR: 990*e4b17023SJohn Marino case COMPONENT_REF: 991*e4b17023SJohn Marino case ARRAY_REF: 992*e4b17023SJohn Marino case ARRAY_RANGE_REF: 993*e4b17023SJohn Marino case BIT_FIELD_REF: 994*e4b17023SJohn Marino /* Go down this entire nest and just look at the final prefix and 995*e4b17023SJohn Marino anything that describes the references. Otherwise, we lose track 996*e4b17023SJohn Marino of whether a NOP_EXPR or VIEW_CONVERT_EXPR needs a simple value. */ 997*e4b17023SJohn Marino wi->val_only = true; 998*e4b17023SJohn Marino wi->is_lhs = false; 999*e4b17023SJohn Marino for (; handled_component_p (t); tp = &TREE_OPERAND (t, 0), t = *tp) 1000*e4b17023SJohn Marino { 1001*e4b17023SJohn Marino if (TREE_CODE (t) == COMPONENT_REF) 1002*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference_op, wi, 1003*e4b17023SJohn Marino NULL); 1004*e4b17023SJohn Marino else if (TREE_CODE (t) == ARRAY_REF 1005*e4b17023SJohn Marino || TREE_CODE (t) == ARRAY_RANGE_REF) 1006*e4b17023SJohn Marino { 1007*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference_op, 1008*e4b17023SJohn Marino wi, NULL); 1009*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference_op, 1010*e4b17023SJohn Marino wi, NULL); 1011*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 3), convert_nonlocal_reference_op, 1012*e4b17023SJohn Marino wi, NULL); 1013*e4b17023SJohn Marino } 1014*e4b17023SJohn Marino else if (TREE_CODE (t) == BIT_FIELD_REF) 1015*e4b17023SJohn Marino { 1016*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference_op, 1017*e4b17023SJohn Marino wi, NULL); 1018*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference_op, 1019*e4b17023SJohn Marino wi, NULL); 1020*e4b17023SJohn Marino } 1021*e4b17023SJohn Marino } 1022*e4b17023SJohn Marino wi->val_only = false; 1023*e4b17023SJohn Marino walk_tree (tp, convert_nonlocal_reference_op, wi, NULL); 1024*e4b17023SJohn Marino break; 1025*e4b17023SJohn Marino 1026*e4b17023SJohn Marino case VIEW_CONVERT_EXPR: 1027*e4b17023SJohn Marino /* Just request to look at the subtrees, leaving val_only and lhs 1028*e4b17023SJohn Marino untouched. This might actually be for !val_only + lhs, in which 1029*e4b17023SJohn Marino case we don't want to force a replacement by a temporary. */ 1030*e4b17023SJohn Marino *walk_subtrees = 1; 1031*e4b17023SJohn Marino break; 1032*e4b17023SJohn Marino 1033*e4b17023SJohn Marino default: 1034*e4b17023SJohn Marino if (!IS_TYPE_OR_DECL_P (t)) 1035*e4b17023SJohn Marino { 1036*e4b17023SJohn Marino *walk_subtrees = 1; 1037*e4b17023SJohn Marino wi->val_only = true; 1038*e4b17023SJohn Marino wi->is_lhs = false; 1039*e4b17023SJohn Marino } 1040*e4b17023SJohn Marino break; 1041*e4b17023SJohn Marino } 1042*e4b17023SJohn Marino 1043*e4b17023SJohn Marino return NULL_TREE; 1044*e4b17023SJohn Marino } 1045*e4b17023SJohn Marino 1046*e4b17023SJohn Marino static tree convert_nonlocal_reference_stmt (gimple_stmt_iterator *, bool *, 1047*e4b17023SJohn Marino struct walk_stmt_info *); 1048*e4b17023SJohn Marino 1049*e4b17023SJohn Marino /* Helper for convert_nonlocal_references, rewrite all references to VAR 1050*e4b17023SJohn Marino and PARM_DECLs that belong to outer functions. */ 1051*e4b17023SJohn Marino 1052*e4b17023SJohn Marino static bool 1053*e4b17023SJohn Marino convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) 1054*e4b17023SJohn Marino { 1055*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info; 1056*e4b17023SJohn Marino bool need_chain = false, need_stmts = false; 1057*e4b17023SJohn Marino tree clause, decl; 1058*e4b17023SJohn Marino int dummy; 1059*e4b17023SJohn Marino bitmap new_suppress; 1060*e4b17023SJohn Marino 1061*e4b17023SJohn Marino new_suppress = BITMAP_GGC_ALLOC (); 1062*e4b17023SJohn Marino bitmap_copy (new_suppress, info->suppress_expansion); 1063*e4b17023SJohn Marino 1064*e4b17023SJohn Marino for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause)) 1065*e4b17023SJohn Marino { 1066*e4b17023SJohn Marino switch (OMP_CLAUSE_CODE (clause)) 1067*e4b17023SJohn Marino { 1068*e4b17023SJohn Marino case OMP_CLAUSE_REDUCTION: 1069*e4b17023SJohn Marino if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause)) 1070*e4b17023SJohn Marino need_stmts = true; 1071*e4b17023SJohn Marino goto do_decl_clause; 1072*e4b17023SJohn Marino 1073*e4b17023SJohn Marino case OMP_CLAUSE_LASTPRIVATE: 1074*e4b17023SJohn Marino if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause)) 1075*e4b17023SJohn Marino need_stmts = true; 1076*e4b17023SJohn Marino goto do_decl_clause; 1077*e4b17023SJohn Marino 1078*e4b17023SJohn Marino case OMP_CLAUSE_PRIVATE: 1079*e4b17023SJohn Marino case OMP_CLAUSE_FIRSTPRIVATE: 1080*e4b17023SJohn Marino case OMP_CLAUSE_COPYPRIVATE: 1081*e4b17023SJohn Marino case OMP_CLAUSE_SHARED: 1082*e4b17023SJohn Marino do_decl_clause: 1083*e4b17023SJohn Marino decl = OMP_CLAUSE_DECL (clause); 1084*e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL 1085*e4b17023SJohn Marino && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) 1086*e4b17023SJohn Marino break; 1087*e4b17023SJohn Marino if (decl_function_context (decl) != info->context) 1088*e4b17023SJohn Marino { 1089*e4b17023SJohn Marino bitmap_set_bit (new_suppress, DECL_UID (decl)); 1090*e4b17023SJohn Marino OMP_CLAUSE_DECL (clause) = get_nonlocal_debug_decl (info, decl); 1091*e4b17023SJohn Marino if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_PRIVATE) 1092*e4b17023SJohn Marino need_chain = true; 1093*e4b17023SJohn Marino } 1094*e4b17023SJohn Marino break; 1095*e4b17023SJohn Marino 1096*e4b17023SJohn Marino case OMP_CLAUSE_SCHEDULE: 1097*e4b17023SJohn Marino if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL) 1098*e4b17023SJohn Marino break; 1099*e4b17023SJohn Marino /* FALLTHRU */ 1100*e4b17023SJohn Marino case OMP_CLAUSE_FINAL: 1101*e4b17023SJohn Marino case OMP_CLAUSE_IF: 1102*e4b17023SJohn Marino case OMP_CLAUSE_NUM_THREADS: 1103*e4b17023SJohn Marino wi->val_only = true; 1104*e4b17023SJohn Marino wi->is_lhs = false; 1105*e4b17023SJohn Marino convert_nonlocal_reference_op (&OMP_CLAUSE_OPERAND (clause, 0), 1106*e4b17023SJohn Marino &dummy, wi); 1107*e4b17023SJohn Marino break; 1108*e4b17023SJohn Marino 1109*e4b17023SJohn Marino case OMP_CLAUSE_NOWAIT: 1110*e4b17023SJohn Marino case OMP_CLAUSE_ORDERED: 1111*e4b17023SJohn Marino case OMP_CLAUSE_DEFAULT: 1112*e4b17023SJohn Marino case OMP_CLAUSE_COPYIN: 1113*e4b17023SJohn Marino case OMP_CLAUSE_COLLAPSE: 1114*e4b17023SJohn Marino case OMP_CLAUSE_UNTIED: 1115*e4b17023SJohn Marino case OMP_CLAUSE_MERGEABLE: 1116*e4b17023SJohn Marino break; 1117*e4b17023SJohn Marino 1118*e4b17023SJohn Marino default: 1119*e4b17023SJohn Marino gcc_unreachable (); 1120*e4b17023SJohn Marino } 1121*e4b17023SJohn Marino } 1122*e4b17023SJohn Marino 1123*e4b17023SJohn Marino info->suppress_expansion = new_suppress; 1124*e4b17023SJohn Marino 1125*e4b17023SJohn Marino if (need_stmts) 1126*e4b17023SJohn Marino for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause)) 1127*e4b17023SJohn Marino switch (OMP_CLAUSE_CODE (clause)) 1128*e4b17023SJohn Marino { 1129*e4b17023SJohn Marino case OMP_CLAUSE_REDUCTION: 1130*e4b17023SJohn Marino if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause)) 1131*e4b17023SJohn Marino { 1132*e4b17023SJohn Marino tree old_context 1133*e4b17023SJohn Marino = DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause)); 1134*e4b17023SJohn Marino DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause)) 1135*e4b17023SJohn Marino = info->context; 1136*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt, 1137*e4b17023SJohn Marino convert_nonlocal_reference_op, info, 1138*e4b17023SJohn Marino OMP_CLAUSE_REDUCTION_GIMPLE_INIT (clause)); 1139*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt, 1140*e4b17023SJohn Marino convert_nonlocal_reference_op, info, 1141*e4b17023SJohn Marino OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (clause)); 1142*e4b17023SJohn Marino DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause)) 1143*e4b17023SJohn Marino = old_context; 1144*e4b17023SJohn Marino } 1145*e4b17023SJohn Marino break; 1146*e4b17023SJohn Marino 1147*e4b17023SJohn Marino case OMP_CLAUSE_LASTPRIVATE: 1148*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt, 1149*e4b17023SJohn Marino convert_nonlocal_reference_op, info, 1150*e4b17023SJohn Marino OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause)); 1151*e4b17023SJohn Marino break; 1152*e4b17023SJohn Marino 1153*e4b17023SJohn Marino default: 1154*e4b17023SJohn Marino break; 1155*e4b17023SJohn Marino } 1156*e4b17023SJohn Marino 1157*e4b17023SJohn Marino return need_chain; 1158*e4b17023SJohn Marino } 1159*e4b17023SJohn Marino 1160*e4b17023SJohn Marino /* Create nonlocal debug decls for nonlocal VLA array bounds. */ 1161*e4b17023SJohn Marino 1162*e4b17023SJohn Marino static void 1163*e4b17023SJohn Marino note_nonlocal_vla_type (struct nesting_info *info, tree type) 1164*e4b17023SJohn Marino { 1165*e4b17023SJohn Marino while (POINTER_TYPE_P (type) && !TYPE_NAME (type)) 1166*e4b17023SJohn Marino type = TREE_TYPE (type); 1167*e4b17023SJohn Marino 1168*e4b17023SJohn Marino if (TYPE_NAME (type) 1169*e4b17023SJohn Marino && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL 1170*e4b17023SJohn Marino && DECL_ORIGINAL_TYPE (TYPE_NAME (type))) 1171*e4b17023SJohn Marino type = DECL_ORIGINAL_TYPE (TYPE_NAME (type)); 1172*e4b17023SJohn Marino 1173*e4b17023SJohn Marino while (POINTER_TYPE_P (type) 1174*e4b17023SJohn Marino || TREE_CODE (type) == VECTOR_TYPE 1175*e4b17023SJohn Marino || TREE_CODE (type) == FUNCTION_TYPE 1176*e4b17023SJohn Marino || TREE_CODE (type) == METHOD_TYPE) 1177*e4b17023SJohn Marino type = TREE_TYPE (type); 1178*e4b17023SJohn Marino 1179*e4b17023SJohn Marino if (TREE_CODE (type) == ARRAY_TYPE) 1180*e4b17023SJohn Marino { 1181*e4b17023SJohn Marino tree domain, t; 1182*e4b17023SJohn Marino 1183*e4b17023SJohn Marino note_nonlocal_vla_type (info, TREE_TYPE (type)); 1184*e4b17023SJohn Marino domain = TYPE_DOMAIN (type); 1185*e4b17023SJohn Marino if (domain) 1186*e4b17023SJohn Marino { 1187*e4b17023SJohn Marino t = TYPE_MIN_VALUE (domain); 1188*e4b17023SJohn Marino if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL) 1189*e4b17023SJohn Marino && decl_function_context (t) != info->context) 1190*e4b17023SJohn Marino get_nonlocal_debug_decl (info, t); 1191*e4b17023SJohn Marino t = TYPE_MAX_VALUE (domain); 1192*e4b17023SJohn Marino if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL) 1193*e4b17023SJohn Marino && decl_function_context (t) != info->context) 1194*e4b17023SJohn Marino get_nonlocal_debug_decl (info, t); 1195*e4b17023SJohn Marino } 1196*e4b17023SJohn Marino } 1197*e4b17023SJohn Marino } 1198*e4b17023SJohn Marino 1199*e4b17023SJohn Marino /* Create nonlocal debug decls for nonlocal VLA array bounds for VLAs 1200*e4b17023SJohn Marino in BLOCK. */ 1201*e4b17023SJohn Marino 1202*e4b17023SJohn Marino static void 1203*e4b17023SJohn Marino note_nonlocal_block_vlas (struct nesting_info *info, tree block) 1204*e4b17023SJohn Marino { 1205*e4b17023SJohn Marino tree var; 1206*e4b17023SJohn Marino 1207*e4b17023SJohn Marino for (var = BLOCK_VARS (block); var; var = DECL_CHAIN (var)) 1208*e4b17023SJohn Marino if (TREE_CODE (var) == VAR_DECL 1209*e4b17023SJohn Marino && variably_modified_type_p (TREE_TYPE (var), NULL) 1210*e4b17023SJohn Marino && DECL_HAS_VALUE_EXPR_P (var) 1211*e4b17023SJohn Marino && decl_function_context (var) != info->context) 1212*e4b17023SJohn Marino note_nonlocal_vla_type (info, TREE_TYPE (var)); 1213*e4b17023SJohn Marino } 1214*e4b17023SJohn Marino 1215*e4b17023SJohn Marino /* Callback for walk_gimple_stmt. Rewrite all references to VAR and 1216*e4b17023SJohn Marino PARM_DECLs that belong to outer functions. This handles statements 1217*e4b17023SJohn Marino that are not handled via the standard recursion done in 1218*e4b17023SJohn Marino walk_gimple_stmt. STMT is the statement to examine, DATA is as in 1219*e4b17023SJohn Marino convert_nonlocal_reference_op. Set *HANDLED_OPS_P to true if all the 1220*e4b17023SJohn Marino operands of STMT have been handled by this function. */ 1221*e4b17023SJohn Marino 1222*e4b17023SJohn Marino static tree 1223*e4b17023SJohn Marino convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, 1224*e4b17023SJohn Marino struct walk_stmt_info *wi) 1225*e4b17023SJohn Marino { 1226*e4b17023SJohn Marino struct nesting_info *info = (struct nesting_info *) wi->info; 1227*e4b17023SJohn Marino tree save_local_var_chain; 1228*e4b17023SJohn Marino bitmap save_suppress; 1229*e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsi); 1230*e4b17023SJohn Marino 1231*e4b17023SJohn Marino switch (gimple_code (stmt)) 1232*e4b17023SJohn Marino { 1233*e4b17023SJohn Marino case GIMPLE_GOTO: 1234*e4b17023SJohn Marino /* Don't walk non-local gotos for now. */ 1235*e4b17023SJohn Marino if (TREE_CODE (gimple_goto_dest (stmt)) != LABEL_DECL) 1236*e4b17023SJohn Marino { 1237*e4b17023SJohn Marino wi->val_only = true; 1238*e4b17023SJohn Marino wi->is_lhs = false; 1239*e4b17023SJohn Marino *handled_ops_p = true; 1240*e4b17023SJohn Marino return NULL_TREE; 1241*e4b17023SJohn Marino } 1242*e4b17023SJohn Marino break; 1243*e4b17023SJohn Marino 1244*e4b17023SJohn Marino case GIMPLE_OMP_PARALLEL: 1245*e4b17023SJohn Marino case GIMPLE_OMP_TASK: 1246*e4b17023SJohn Marino save_suppress = info->suppress_expansion; 1247*e4b17023SJohn Marino if (convert_nonlocal_omp_clauses (gimple_omp_taskreg_clauses_ptr (stmt), 1248*e4b17023SJohn Marino wi)) 1249*e4b17023SJohn Marino { 1250*e4b17023SJohn Marino tree c, decl; 1251*e4b17023SJohn Marino decl = get_chain_decl (info); 1252*e4b17023SJohn Marino c = build_omp_clause (gimple_location (stmt), 1253*e4b17023SJohn Marino OMP_CLAUSE_FIRSTPRIVATE); 1254*e4b17023SJohn Marino OMP_CLAUSE_DECL (c) = decl; 1255*e4b17023SJohn Marino OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt); 1256*e4b17023SJohn Marino gimple_omp_taskreg_set_clauses (stmt, c); 1257*e4b17023SJohn Marino } 1258*e4b17023SJohn Marino 1259*e4b17023SJohn Marino save_local_var_chain = info->new_local_var_chain; 1260*e4b17023SJohn Marino info->new_local_var_chain = NULL; 1261*e4b17023SJohn Marino 1262*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op, 1263*e4b17023SJohn Marino info, gimple_omp_body (stmt)); 1264*e4b17023SJohn Marino 1265*e4b17023SJohn Marino if (info->new_local_var_chain) 1266*e4b17023SJohn Marino declare_vars (info->new_local_var_chain, 1267*e4b17023SJohn Marino gimple_seq_first_stmt (gimple_omp_body (stmt)), 1268*e4b17023SJohn Marino false); 1269*e4b17023SJohn Marino info->new_local_var_chain = save_local_var_chain; 1270*e4b17023SJohn Marino info->suppress_expansion = save_suppress; 1271*e4b17023SJohn Marino break; 1272*e4b17023SJohn Marino 1273*e4b17023SJohn Marino case GIMPLE_OMP_FOR: 1274*e4b17023SJohn Marino save_suppress = info->suppress_expansion; 1275*e4b17023SJohn Marino convert_nonlocal_omp_clauses (gimple_omp_for_clauses_ptr (stmt), wi); 1276*e4b17023SJohn Marino walk_gimple_omp_for (stmt, convert_nonlocal_reference_stmt, 1277*e4b17023SJohn Marino convert_nonlocal_reference_op, info); 1278*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt, 1279*e4b17023SJohn Marino convert_nonlocal_reference_op, info, gimple_omp_body (stmt)); 1280*e4b17023SJohn Marino info->suppress_expansion = save_suppress; 1281*e4b17023SJohn Marino break; 1282*e4b17023SJohn Marino 1283*e4b17023SJohn Marino case GIMPLE_OMP_SECTIONS: 1284*e4b17023SJohn Marino save_suppress = info->suppress_expansion; 1285*e4b17023SJohn Marino convert_nonlocal_omp_clauses (gimple_omp_sections_clauses_ptr (stmt), wi); 1286*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op, 1287*e4b17023SJohn Marino info, gimple_omp_body (stmt)); 1288*e4b17023SJohn Marino info->suppress_expansion = save_suppress; 1289*e4b17023SJohn Marino break; 1290*e4b17023SJohn Marino 1291*e4b17023SJohn Marino case GIMPLE_OMP_SINGLE: 1292*e4b17023SJohn Marino save_suppress = info->suppress_expansion; 1293*e4b17023SJohn Marino convert_nonlocal_omp_clauses (gimple_omp_single_clauses_ptr (stmt), wi); 1294*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op, 1295*e4b17023SJohn Marino info, gimple_omp_body (stmt)); 1296*e4b17023SJohn Marino info->suppress_expansion = save_suppress; 1297*e4b17023SJohn Marino break; 1298*e4b17023SJohn Marino 1299*e4b17023SJohn Marino case GIMPLE_OMP_SECTION: 1300*e4b17023SJohn Marino case GIMPLE_OMP_MASTER: 1301*e4b17023SJohn Marino case GIMPLE_OMP_ORDERED: 1302*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op, 1303*e4b17023SJohn Marino info, gimple_omp_body (stmt)); 1304*e4b17023SJohn Marino break; 1305*e4b17023SJohn Marino 1306*e4b17023SJohn Marino case GIMPLE_BIND: 1307*e4b17023SJohn Marino if (!optimize && gimple_bind_block (stmt)) 1308*e4b17023SJohn Marino note_nonlocal_block_vlas (info, gimple_bind_block (stmt)); 1309*e4b17023SJohn Marino 1310*e4b17023SJohn Marino *handled_ops_p = false; 1311*e4b17023SJohn Marino return NULL_TREE; 1312*e4b17023SJohn Marino 1313*e4b17023SJohn Marino case GIMPLE_COND: 1314*e4b17023SJohn Marino wi->val_only = true; 1315*e4b17023SJohn Marino wi->is_lhs = false; 1316*e4b17023SJohn Marino *handled_ops_p = false; 1317*e4b17023SJohn Marino return NULL_TREE; 1318*e4b17023SJohn Marino 1319*e4b17023SJohn Marino default: 1320*e4b17023SJohn Marino /* For every other statement that we are not interested in 1321*e4b17023SJohn Marino handling here, let the walker traverse the operands. */ 1322*e4b17023SJohn Marino *handled_ops_p = false; 1323*e4b17023SJohn Marino return NULL_TREE; 1324*e4b17023SJohn Marino } 1325*e4b17023SJohn Marino 1326*e4b17023SJohn Marino /* We have handled all of STMT operands, no need to traverse the operands. */ 1327*e4b17023SJohn Marino *handled_ops_p = true; 1328*e4b17023SJohn Marino return NULL_TREE; 1329*e4b17023SJohn Marino } 1330*e4b17023SJohn Marino 1331*e4b17023SJohn Marino 1332*e4b17023SJohn Marino /* A subroutine of convert_local_reference. Create a local variable 1333*e4b17023SJohn Marino in the parent function with DECL_VALUE_EXPR set to reference the 1334*e4b17023SJohn Marino field in FRAME. This is used both for debug info and in OpenMP 1335*e4b17023SJohn Marino lowering. */ 1336*e4b17023SJohn Marino 1337*e4b17023SJohn Marino static tree 1338*e4b17023SJohn Marino get_local_debug_decl (struct nesting_info *info, tree decl, tree field) 1339*e4b17023SJohn Marino { 1340*e4b17023SJohn Marino tree x, new_decl; 1341*e4b17023SJohn Marino void **slot; 1342*e4b17023SJohn Marino 1343*e4b17023SJohn Marino slot = pointer_map_insert (info->var_map, decl); 1344*e4b17023SJohn Marino if (*slot) 1345*e4b17023SJohn Marino return (tree) *slot; 1346*e4b17023SJohn Marino 1347*e4b17023SJohn Marino /* Make sure frame_decl gets created. */ 1348*e4b17023SJohn Marino (void) get_frame_type (info); 1349*e4b17023SJohn Marino x = info->frame_decl; 1350*e4b17023SJohn Marino x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE); 1351*e4b17023SJohn Marino 1352*e4b17023SJohn Marino new_decl = build_decl (DECL_SOURCE_LOCATION (decl), 1353*e4b17023SJohn Marino VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl)); 1354*e4b17023SJohn Marino DECL_CONTEXT (new_decl) = info->context; 1355*e4b17023SJohn Marino DECL_ARTIFICIAL (new_decl) = DECL_ARTIFICIAL (decl); 1356*e4b17023SJohn Marino DECL_IGNORED_P (new_decl) = DECL_IGNORED_P (decl); 1357*e4b17023SJohn Marino TREE_THIS_VOLATILE (new_decl) = TREE_THIS_VOLATILE (decl); 1358*e4b17023SJohn Marino TREE_SIDE_EFFECTS (new_decl) = TREE_SIDE_EFFECTS (decl); 1359*e4b17023SJohn Marino TREE_READONLY (new_decl) = TREE_READONLY (decl); 1360*e4b17023SJohn Marino TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (decl); 1361*e4b17023SJohn Marino DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1; 1362*e4b17023SJohn Marino if ((TREE_CODE (decl) == PARM_DECL 1363*e4b17023SJohn Marino || TREE_CODE (decl) == RESULT_DECL 1364*e4b17023SJohn Marino || TREE_CODE (decl) == VAR_DECL) 1365*e4b17023SJohn Marino && DECL_BY_REFERENCE (decl)) 1366*e4b17023SJohn Marino DECL_BY_REFERENCE (new_decl) = 1; 1367*e4b17023SJohn Marino 1368*e4b17023SJohn Marino SET_DECL_VALUE_EXPR (new_decl, x); 1369*e4b17023SJohn Marino DECL_HAS_VALUE_EXPR_P (new_decl) = 1; 1370*e4b17023SJohn Marino *slot = new_decl; 1371*e4b17023SJohn Marino 1372*e4b17023SJohn Marino DECL_CHAIN (new_decl) = info->debug_var_chain; 1373*e4b17023SJohn Marino info->debug_var_chain = new_decl; 1374*e4b17023SJohn Marino 1375*e4b17023SJohn Marino /* Do not emit debug info twice. */ 1376*e4b17023SJohn Marino DECL_IGNORED_P (decl) = 1; 1377*e4b17023SJohn Marino 1378*e4b17023SJohn Marino return new_decl; 1379*e4b17023SJohn Marino } 1380*e4b17023SJohn Marino 1381*e4b17023SJohn Marino 1382*e4b17023SJohn Marino /* Called via walk_function+walk_gimple_stmt, rewrite all references to VAR 1383*e4b17023SJohn Marino and PARM_DECLs that were referenced by inner nested functions. 1384*e4b17023SJohn Marino The rewrite will be a structure reference to the local frame variable. */ 1385*e4b17023SJohn Marino 1386*e4b17023SJohn Marino static bool convert_local_omp_clauses (tree *, struct walk_stmt_info *); 1387*e4b17023SJohn Marino 1388*e4b17023SJohn Marino static tree 1389*e4b17023SJohn Marino convert_local_reference_op (tree *tp, int *walk_subtrees, void *data) 1390*e4b17023SJohn Marino { 1391*e4b17023SJohn Marino struct walk_stmt_info *wi = (struct walk_stmt_info *) data; 1392*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info; 1393*e4b17023SJohn Marino tree t = *tp, field, x; 1394*e4b17023SJohn Marino bool save_val_only; 1395*e4b17023SJohn Marino 1396*e4b17023SJohn Marino *walk_subtrees = 0; 1397*e4b17023SJohn Marino switch (TREE_CODE (t)) 1398*e4b17023SJohn Marino { 1399*e4b17023SJohn Marino case VAR_DECL: 1400*e4b17023SJohn Marino /* Non-automatic variables are never processed. */ 1401*e4b17023SJohn Marino if (TREE_STATIC (t) || DECL_EXTERNAL (t)) 1402*e4b17023SJohn Marino break; 1403*e4b17023SJohn Marino /* FALLTHRU */ 1404*e4b17023SJohn Marino 1405*e4b17023SJohn Marino case PARM_DECL: 1406*e4b17023SJohn Marino if (decl_function_context (t) == info->context) 1407*e4b17023SJohn Marino { 1408*e4b17023SJohn Marino /* If we copied a pointer to the frame, then the original decl 1409*e4b17023SJohn Marino is used unchanged in the parent function. */ 1410*e4b17023SJohn Marino if (use_pointer_in_frame (t)) 1411*e4b17023SJohn Marino break; 1412*e4b17023SJohn Marino 1413*e4b17023SJohn Marino /* No need to transform anything if no child references the 1414*e4b17023SJohn Marino variable. */ 1415*e4b17023SJohn Marino field = lookup_field_for_decl (info, t, NO_INSERT); 1416*e4b17023SJohn Marino if (!field) 1417*e4b17023SJohn Marino break; 1418*e4b17023SJohn Marino wi->changed = true; 1419*e4b17023SJohn Marino 1420*e4b17023SJohn Marino x = get_local_debug_decl (info, t, field); 1421*e4b17023SJohn Marino if (!bitmap_bit_p (info->suppress_expansion, DECL_UID (t))) 1422*e4b17023SJohn Marino x = get_frame_field (info, info->context, field, &wi->gsi); 1423*e4b17023SJohn Marino 1424*e4b17023SJohn Marino if (wi->val_only) 1425*e4b17023SJohn Marino { 1426*e4b17023SJohn Marino if (wi->is_lhs) 1427*e4b17023SJohn Marino x = save_tmp_var (info, x, &wi->gsi); 1428*e4b17023SJohn Marino else 1429*e4b17023SJohn Marino x = init_tmp_var (info, x, &wi->gsi); 1430*e4b17023SJohn Marino } 1431*e4b17023SJohn Marino 1432*e4b17023SJohn Marino *tp = x; 1433*e4b17023SJohn Marino } 1434*e4b17023SJohn Marino break; 1435*e4b17023SJohn Marino 1436*e4b17023SJohn Marino case ADDR_EXPR: 1437*e4b17023SJohn Marino save_val_only = wi->val_only; 1438*e4b17023SJohn Marino wi->val_only = false; 1439*e4b17023SJohn Marino wi->is_lhs = false; 1440*e4b17023SJohn Marino wi->changed = false; 1441*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 0), convert_local_reference_op, wi, NULL); 1442*e4b17023SJohn Marino wi->val_only = save_val_only; 1443*e4b17023SJohn Marino 1444*e4b17023SJohn Marino /* If we converted anything ... */ 1445*e4b17023SJohn Marino if (wi->changed) 1446*e4b17023SJohn Marino { 1447*e4b17023SJohn Marino tree save_context; 1448*e4b17023SJohn Marino 1449*e4b17023SJohn Marino /* Then the frame decl is now addressable. */ 1450*e4b17023SJohn Marino TREE_ADDRESSABLE (info->frame_decl) = 1; 1451*e4b17023SJohn Marino 1452*e4b17023SJohn Marino save_context = current_function_decl; 1453*e4b17023SJohn Marino current_function_decl = info->context; 1454*e4b17023SJohn Marino recompute_tree_invariant_for_addr_expr (t); 1455*e4b17023SJohn Marino current_function_decl = save_context; 1456*e4b17023SJohn Marino 1457*e4b17023SJohn Marino /* If we are in a context where we only accept values, then 1458*e4b17023SJohn Marino compute the address into a temporary. */ 1459*e4b17023SJohn Marino if (save_val_only) 1460*e4b17023SJohn Marino *tp = gsi_gimplify_val ((struct nesting_info *) wi->info, 1461*e4b17023SJohn Marino t, &wi->gsi); 1462*e4b17023SJohn Marino } 1463*e4b17023SJohn Marino break; 1464*e4b17023SJohn Marino 1465*e4b17023SJohn Marino case REALPART_EXPR: 1466*e4b17023SJohn Marino case IMAGPART_EXPR: 1467*e4b17023SJohn Marino case COMPONENT_REF: 1468*e4b17023SJohn Marino case ARRAY_REF: 1469*e4b17023SJohn Marino case ARRAY_RANGE_REF: 1470*e4b17023SJohn Marino case BIT_FIELD_REF: 1471*e4b17023SJohn Marino /* Go down this entire nest and just look at the final prefix and 1472*e4b17023SJohn Marino anything that describes the references. Otherwise, we lose track 1473*e4b17023SJohn Marino of whether a NOP_EXPR or VIEW_CONVERT_EXPR needs a simple value. */ 1474*e4b17023SJohn Marino save_val_only = wi->val_only; 1475*e4b17023SJohn Marino wi->val_only = true; 1476*e4b17023SJohn Marino wi->is_lhs = false; 1477*e4b17023SJohn Marino for (; handled_component_p (t); tp = &TREE_OPERAND (t, 0), t = *tp) 1478*e4b17023SJohn Marino { 1479*e4b17023SJohn Marino if (TREE_CODE (t) == COMPONENT_REF) 1480*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 2), convert_local_reference_op, wi, 1481*e4b17023SJohn Marino NULL); 1482*e4b17023SJohn Marino else if (TREE_CODE (t) == ARRAY_REF 1483*e4b17023SJohn Marino || TREE_CODE (t) == ARRAY_RANGE_REF) 1484*e4b17023SJohn Marino { 1485*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 1), convert_local_reference_op, wi, 1486*e4b17023SJohn Marino NULL); 1487*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 2), convert_local_reference_op, wi, 1488*e4b17023SJohn Marino NULL); 1489*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 3), convert_local_reference_op, wi, 1490*e4b17023SJohn Marino NULL); 1491*e4b17023SJohn Marino } 1492*e4b17023SJohn Marino else if (TREE_CODE (t) == BIT_FIELD_REF) 1493*e4b17023SJohn Marino { 1494*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 1), convert_local_reference_op, wi, 1495*e4b17023SJohn Marino NULL); 1496*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 2), convert_local_reference_op, wi, 1497*e4b17023SJohn Marino NULL); 1498*e4b17023SJohn Marino } 1499*e4b17023SJohn Marino } 1500*e4b17023SJohn Marino wi->val_only = false; 1501*e4b17023SJohn Marino walk_tree (tp, convert_local_reference_op, wi, NULL); 1502*e4b17023SJohn Marino wi->val_only = save_val_only; 1503*e4b17023SJohn Marino break; 1504*e4b17023SJohn Marino 1505*e4b17023SJohn Marino case MEM_REF: 1506*e4b17023SJohn Marino save_val_only = wi->val_only; 1507*e4b17023SJohn Marino wi->val_only = true; 1508*e4b17023SJohn Marino wi->is_lhs = false; 1509*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 0), convert_local_reference_op, 1510*e4b17023SJohn Marino wi, NULL); 1511*e4b17023SJohn Marino /* We need to re-fold the MEM_REF as component references as 1512*e4b17023SJohn Marino part of a ADDR_EXPR address are not allowed. But we cannot 1513*e4b17023SJohn Marino fold here, as the chain record type is not yet finalized. */ 1514*e4b17023SJohn Marino if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR 1515*e4b17023SJohn Marino && !DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0))) 1516*e4b17023SJohn Marino pointer_set_insert (info->mem_refs, tp); 1517*e4b17023SJohn Marino wi->val_only = save_val_only; 1518*e4b17023SJohn Marino break; 1519*e4b17023SJohn Marino 1520*e4b17023SJohn Marino case VIEW_CONVERT_EXPR: 1521*e4b17023SJohn Marino /* Just request to look at the subtrees, leaving val_only and lhs 1522*e4b17023SJohn Marino untouched. This might actually be for !val_only + lhs, in which 1523*e4b17023SJohn Marino case we don't want to force a replacement by a temporary. */ 1524*e4b17023SJohn Marino *walk_subtrees = 1; 1525*e4b17023SJohn Marino break; 1526*e4b17023SJohn Marino 1527*e4b17023SJohn Marino default: 1528*e4b17023SJohn Marino if (!IS_TYPE_OR_DECL_P (t)) 1529*e4b17023SJohn Marino { 1530*e4b17023SJohn Marino *walk_subtrees = 1; 1531*e4b17023SJohn Marino wi->val_only = true; 1532*e4b17023SJohn Marino wi->is_lhs = false; 1533*e4b17023SJohn Marino } 1534*e4b17023SJohn Marino break; 1535*e4b17023SJohn Marino } 1536*e4b17023SJohn Marino 1537*e4b17023SJohn Marino return NULL_TREE; 1538*e4b17023SJohn Marino } 1539*e4b17023SJohn Marino 1540*e4b17023SJohn Marino static tree convert_local_reference_stmt (gimple_stmt_iterator *, bool *, 1541*e4b17023SJohn Marino struct walk_stmt_info *); 1542*e4b17023SJohn Marino 1543*e4b17023SJohn Marino /* Helper for convert_local_reference. Convert all the references in 1544*e4b17023SJohn Marino the chain of clauses at *PCLAUSES. WI is as in convert_local_reference. */ 1545*e4b17023SJohn Marino 1546*e4b17023SJohn Marino static bool 1547*e4b17023SJohn Marino convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) 1548*e4b17023SJohn Marino { 1549*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info; 1550*e4b17023SJohn Marino bool need_frame = false, need_stmts = false; 1551*e4b17023SJohn Marino tree clause, decl; 1552*e4b17023SJohn Marino int dummy; 1553*e4b17023SJohn Marino bitmap new_suppress; 1554*e4b17023SJohn Marino 1555*e4b17023SJohn Marino new_suppress = BITMAP_GGC_ALLOC (); 1556*e4b17023SJohn Marino bitmap_copy (new_suppress, info->suppress_expansion); 1557*e4b17023SJohn Marino 1558*e4b17023SJohn Marino for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause)) 1559*e4b17023SJohn Marino { 1560*e4b17023SJohn Marino switch (OMP_CLAUSE_CODE (clause)) 1561*e4b17023SJohn Marino { 1562*e4b17023SJohn Marino case OMP_CLAUSE_REDUCTION: 1563*e4b17023SJohn Marino if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause)) 1564*e4b17023SJohn Marino need_stmts = true; 1565*e4b17023SJohn Marino goto do_decl_clause; 1566*e4b17023SJohn Marino 1567*e4b17023SJohn Marino case OMP_CLAUSE_LASTPRIVATE: 1568*e4b17023SJohn Marino if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause)) 1569*e4b17023SJohn Marino need_stmts = true; 1570*e4b17023SJohn Marino goto do_decl_clause; 1571*e4b17023SJohn Marino 1572*e4b17023SJohn Marino case OMP_CLAUSE_PRIVATE: 1573*e4b17023SJohn Marino case OMP_CLAUSE_FIRSTPRIVATE: 1574*e4b17023SJohn Marino case OMP_CLAUSE_COPYPRIVATE: 1575*e4b17023SJohn Marino case OMP_CLAUSE_SHARED: 1576*e4b17023SJohn Marino do_decl_clause: 1577*e4b17023SJohn Marino decl = OMP_CLAUSE_DECL (clause); 1578*e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL 1579*e4b17023SJohn Marino && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) 1580*e4b17023SJohn Marino break; 1581*e4b17023SJohn Marino if (decl_function_context (decl) == info->context 1582*e4b17023SJohn Marino && !use_pointer_in_frame (decl)) 1583*e4b17023SJohn Marino { 1584*e4b17023SJohn Marino tree field = lookup_field_for_decl (info, decl, NO_INSERT); 1585*e4b17023SJohn Marino if (field) 1586*e4b17023SJohn Marino { 1587*e4b17023SJohn Marino bitmap_set_bit (new_suppress, DECL_UID (decl)); 1588*e4b17023SJohn Marino OMP_CLAUSE_DECL (clause) 1589*e4b17023SJohn Marino = get_local_debug_decl (info, decl, field); 1590*e4b17023SJohn Marino need_frame = true; 1591*e4b17023SJohn Marino } 1592*e4b17023SJohn Marino } 1593*e4b17023SJohn Marino break; 1594*e4b17023SJohn Marino 1595*e4b17023SJohn Marino case OMP_CLAUSE_SCHEDULE: 1596*e4b17023SJohn Marino if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL) 1597*e4b17023SJohn Marino break; 1598*e4b17023SJohn Marino /* FALLTHRU */ 1599*e4b17023SJohn Marino case OMP_CLAUSE_FINAL: 1600*e4b17023SJohn Marino case OMP_CLAUSE_IF: 1601*e4b17023SJohn Marino case OMP_CLAUSE_NUM_THREADS: 1602*e4b17023SJohn Marino wi->val_only = true; 1603*e4b17023SJohn Marino wi->is_lhs = false; 1604*e4b17023SJohn Marino convert_local_reference_op (&OMP_CLAUSE_OPERAND (clause, 0), &dummy, 1605*e4b17023SJohn Marino wi); 1606*e4b17023SJohn Marino break; 1607*e4b17023SJohn Marino 1608*e4b17023SJohn Marino case OMP_CLAUSE_NOWAIT: 1609*e4b17023SJohn Marino case OMP_CLAUSE_ORDERED: 1610*e4b17023SJohn Marino case OMP_CLAUSE_DEFAULT: 1611*e4b17023SJohn Marino case OMP_CLAUSE_COPYIN: 1612*e4b17023SJohn Marino case OMP_CLAUSE_COLLAPSE: 1613*e4b17023SJohn Marino case OMP_CLAUSE_UNTIED: 1614*e4b17023SJohn Marino case OMP_CLAUSE_MERGEABLE: 1615*e4b17023SJohn Marino break; 1616*e4b17023SJohn Marino 1617*e4b17023SJohn Marino default: 1618*e4b17023SJohn Marino gcc_unreachable (); 1619*e4b17023SJohn Marino } 1620*e4b17023SJohn Marino } 1621*e4b17023SJohn Marino 1622*e4b17023SJohn Marino info->suppress_expansion = new_suppress; 1623*e4b17023SJohn Marino 1624*e4b17023SJohn Marino if (need_stmts) 1625*e4b17023SJohn Marino for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause)) 1626*e4b17023SJohn Marino switch (OMP_CLAUSE_CODE (clause)) 1627*e4b17023SJohn Marino { 1628*e4b17023SJohn Marino case OMP_CLAUSE_REDUCTION: 1629*e4b17023SJohn Marino if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause)) 1630*e4b17023SJohn Marino { 1631*e4b17023SJohn Marino tree old_context 1632*e4b17023SJohn Marino = DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause)); 1633*e4b17023SJohn Marino DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause)) 1634*e4b17023SJohn Marino = info->context; 1635*e4b17023SJohn Marino walk_body (convert_local_reference_stmt, 1636*e4b17023SJohn Marino convert_local_reference_op, info, 1637*e4b17023SJohn Marino OMP_CLAUSE_REDUCTION_GIMPLE_INIT (clause)); 1638*e4b17023SJohn Marino walk_body (convert_local_reference_stmt, 1639*e4b17023SJohn Marino convert_local_reference_op, info, 1640*e4b17023SJohn Marino OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (clause)); 1641*e4b17023SJohn Marino DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause)) 1642*e4b17023SJohn Marino = old_context; 1643*e4b17023SJohn Marino } 1644*e4b17023SJohn Marino break; 1645*e4b17023SJohn Marino 1646*e4b17023SJohn Marino case OMP_CLAUSE_LASTPRIVATE: 1647*e4b17023SJohn Marino walk_body (convert_local_reference_stmt, 1648*e4b17023SJohn Marino convert_local_reference_op, info, 1649*e4b17023SJohn Marino OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause)); 1650*e4b17023SJohn Marino break; 1651*e4b17023SJohn Marino 1652*e4b17023SJohn Marino default: 1653*e4b17023SJohn Marino break; 1654*e4b17023SJohn Marino } 1655*e4b17023SJohn Marino 1656*e4b17023SJohn Marino return need_frame; 1657*e4b17023SJohn Marino } 1658*e4b17023SJohn Marino 1659*e4b17023SJohn Marino 1660*e4b17023SJohn Marino /* Called via walk_function+walk_gimple_stmt, rewrite all references to VAR 1661*e4b17023SJohn Marino and PARM_DECLs that were referenced by inner nested functions. 1662*e4b17023SJohn Marino The rewrite will be a structure reference to the local frame variable. */ 1663*e4b17023SJohn Marino 1664*e4b17023SJohn Marino static tree 1665*e4b17023SJohn Marino convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, 1666*e4b17023SJohn Marino struct walk_stmt_info *wi) 1667*e4b17023SJohn Marino { 1668*e4b17023SJohn Marino struct nesting_info *info = (struct nesting_info *) wi->info; 1669*e4b17023SJohn Marino tree save_local_var_chain; 1670*e4b17023SJohn Marino bitmap save_suppress; 1671*e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsi); 1672*e4b17023SJohn Marino 1673*e4b17023SJohn Marino switch (gimple_code (stmt)) 1674*e4b17023SJohn Marino { 1675*e4b17023SJohn Marino case GIMPLE_OMP_PARALLEL: 1676*e4b17023SJohn Marino case GIMPLE_OMP_TASK: 1677*e4b17023SJohn Marino save_suppress = info->suppress_expansion; 1678*e4b17023SJohn Marino if (convert_local_omp_clauses (gimple_omp_taskreg_clauses_ptr (stmt), 1679*e4b17023SJohn Marino wi)) 1680*e4b17023SJohn Marino { 1681*e4b17023SJohn Marino tree c; 1682*e4b17023SJohn Marino (void) get_frame_type (info); 1683*e4b17023SJohn Marino c = build_omp_clause (gimple_location (stmt), 1684*e4b17023SJohn Marino OMP_CLAUSE_SHARED); 1685*e4b17023SJohn Marino OMP_CLAUSE_DECL (c) = info->frame_decl; 1686*e4b17023SJohn Marino OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt); 1687*e4b17023SJohn Marino gimple_omp_taskreg_set_clauses (stmt, c); 1688*e4b17023SJohn Marino } 1689*e4b17023SJohn Marino 1690*e4b17023SJohn Marino save_local_var_chain = info->new_local_var_chain; 1691*e4b17023SJohn Marino info->new_local_var_chain = NULL; 1692*e4b17023SJohn Marino 1693*e4b17023SJohn Marino walk_body (convert_local_reference_stmt, convert_local_reference_op, info, 1694*e4b17023SJohn Marino gimple_omp_body (stmt)); 1695*e4b17023SJohn Marino 1696*e4b17023SJohn Marino if (info->new_local_var_chain) 1697*e4b17023SJohn Marino declare_vars (info->new_local_var_chain, 1698*e4b17023SJohn Marino gimple_seq_first_stmt (gimple_omp_body (stmt)), false); 1699*e4b17023SJohn Marino info->new_local_var_chain = save_local_var_chain; 1700*e4b17023SJohn Marino info->suppress_expansion = save_suppress; 1701*e4b17023SJohn Marino break; 1702*e4b17023SJohn Marino 1703*e4b17023SJohn Marino case GIMPLE_OMP_FOR: 1704*e4b17023SJohn Marino save_suppress = info->suppress_expansion; 1705*e4b17023SJohn Marino convert_local_omp_clauses (gimple_omp_for_clauses_ptr (stmt), wi); 1706*e4b17023SJohn Marino walk_gimple_omp_for (stmt, convert_local_reference_stmt, 1707*e4b17023SJohn Marino convert_local_reference_op, info); 1708*e4b17023SJohn Marino walk_body (convert_local_reference_stmt, convert_local_reference_op, 1709*e4b17023SJohn Marino info, gimple_omp_body (stmt)); 1710*e4b17023SJohn Marino info->suppress_expansion = save_suppress; 1711*e4b17023SJohn Marino break; 1712*e4b17023SJohn Marino 1713*e4b17023SJohn Marino case GIMPLE_OMP_SECTIONS: 1714*e4b17023SJohn Marino save_suppress = info->suppress_expansion; 1715*e4b17023SJohn Marino convert_local_omp_clauses (gimple_omp_sections_clauses_ptr (stmt), wi); 1716*e4b17023SJohn Marino walk_body (convert_local_reference_stmt, convert_local_reference_op, 1717*e4b17023SJohn Marino info, gimple_omp_body (stmt)); 1718*e4b17023SJohn Marino info->suppress_expansion = save_suppress; 1719*e4b17023SJohn Marino break; 1720*e4b17023SJohn Marino 1721*e4b17023SJohn Marino case GIMPLE_OMP_SINGLE: 1722*e4b17023SJohn Marino save_suppress = info->suppress_expansion; 1723*e4b17023SJohn Marino convert_local_omp_clauses (gimple_omp_single_clauses_ptr (stmt), wi); 1724*e4b17023SJohn Marino walk_body (convert_local_reference_stmt, convert_local_reference_op, 1725*e4b17023SJohn Marino info, gimple_omp_body (stmt)); 1726*e4b17023SJohn Marino info->suppress_expansion = save_suppress; 1727*e4b17023SJohn Marino break; 1728*e4b17023SJohn Marino 1729*e4b17023SJohn Marino case GIMPLE_OMP_SECTION: 1730*e4b17023SJohn Marino case GIMPLE_OMP_MASTER: 1731*e4b17023SJohn Marino case GIMPLE_OMP_ORDERED: 1732*e4b17023SJohn Marino walk_body (convert_local_reference_stmt, convert_local_reference_op, 1733*e4b17023SJohn Marino info, gimple_omp_body (stmt)); 1734*e4b17023SJohn Marino break; 1735*e4b17023SJohn Marino 1736*e4b17023SJohn Marino case GIMPLE_COND: 1737*e4b17023SJohn Marino wi->val_only = true; 1738*e4b17023SJohn Marino wi->is_lhs = false; 1739*e4b17023SJohn Marino *handled_ops_p = false; 1740*e4b17023SJohn Marino return NULL_TREE; 1741*e4b17023SJohn Marino 1742*e4b17023SJohn Marino default: 1743*e4b17023SJohn Marino /* For every other statement that we are not interested in 1744*e4b17023SJohn Marino handling here, let the walker traverse the operands. */ 1745*e4b17023SJohn Marino *handled_ops_p = false; 1746*e4b17023SJohn Marino return NULL_TREE; 1747*e4b17023SJohn Marino } 1748*e4b17023SJohn Marino 1749*e4b17023SJohn Marino /* Indicate that we have handled all the operands ourselves. */ 1750*e4b17023SJohn Marino *handled_ops_p = true; 1751*e4b17023SJohn Marino return NULL_TREE; 1752*e4b17023SJohn Marino } 1753*e4b17023SJohn Marino 1754*e4b17023SJohn Marino 1755*e4b17023SJohn Marino /* Called via walk_function+walk_gimple_stmt, rewrite all GIMPLE_GOTOs 1756*e4b17023SJohn Marino that reference labels from outer functions. The rewrite will be a 1757*e4b17023SJohn Marino call to __builtin_nonlocal_goto. */ 1758*e4b17023SJohn Marino 1759*e4b17023SJohn Marino static tree 1760*e4b17023SJohn Marino convert_nl_goto_reference (gimple_stmt_iterator *gsi, bool *handled_ops_p, 1761*e4b17023SJohn Marino struct walk_stmt_info *wi) 1762*e4b17023SJohn Marino { 1763*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info, *i; 1764*e4b17023SJohn Marino tree label, new_label, target_context, x, field; 1765*e4b17023SJohn Marino void **slot; 1766*e4b17023SJohn Marino gimple call; 1767*e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsi); 1768*e4b17023SJohn Marino 1769*e4b17023SJohn Marino if (gimple_code (stmt) != GIMPLE_GOTO) 1770*e4b17023SJohn Marino { 1771*e4b17023SJohn Marino *handled_ops_p = false; 1772*e4b17023SJohn Marino return NULL_TREE; 1773*e4b17023SJohn Marino } 1774*e4b17023SJohn Marino 1775*e4b17023SJohn Marino label = gimple_goto_dest (stmt); 1776*e4b17023SJohn Marino if (TREE_CODE (label) != LABEL_DECL) 1777*e4b17023SJohn Marino { 1778*e4b17023SJohn Marino *handled_ops_p = false; 1779*e4b17023SJohn Marino return NULL_TREE; 1780*e4b17023SJohn Marino } 1781*e4b17023SJohn Marino 1782*e4b17023SJohn Marino target_context = decl_function_context (label); 1783*e4b17023SJohn Marino if (target_context == info->context) 1784*e4b17023SJohn Marino { 1785*e4b17023SJohn Marino *handled_ops_p = false; 1786*e4b17023SJohn Marino return NULL_TREE; 1787*e4b17023SJohn Marino } 1788*e4b17023SJohn Marino 1789*e4b17023SJohn Marino for (i = info->outer; target_context != i->context; i = i->outer) 1790*e4b17023SJohn Marino continue; 1791*e4b17023SJohn Marino 1792*e4b17023SJohn Marino /* The original user label may also be use for a normal goto, therefore 1793*e4b17023SJohn Marino we must create a new label that will actually receive the abnormal 1794*e4b17023SJohn Marino control transfer. This new label will be marked LABEL_NONLOCAL; this 1795*e4b17023SJohn Marino mark will trigger proper behavior in the cfg, as well as cause the 1796*e4b17023SJohn Marino (hairy target-specific) non-local goto receiver code to be generated 1797*e4b17023SJohn Marino when we expand rtl. Enter this association into var_map so that we 1798*e4b17023SJohn Marino can insert the new label into the IL during a second pass. */ 1799*e4b17023SJohn Marino slot = pointer_map_insert (i->var_map, label); 1800*e4b17023SJohn Marino if (*slot == NULL) 1801*e4b17023SJohn Marino { 1802*e4b17023SJohn Marino new_label = create_artificial_label (UNKNOWN_LOCATION); 1803*e4b17023SJohn Marino DECL_NONLOCAL (new_label) = 1; 1804*e4b17023SJohn Marino *slot = new_label; 1805*e4b17023SJohn Marino } 1806*e4b17023SJohn Marino else 1807*e4b17023SJohn Marino new_label = (tree) *slot; 1808*e4b17023SJohn Marino 1809*e4b17023SJohn Marino /* Build: __builtin_nl_goto(new_label, &chain->nl_goto_field). */ 1810*e4b17023SJohn Marino field = get_nl_goto_field (i); 1811*e4b17023SJohn Marino x = get_frame_field (info, target_context, field, &wi->gsi); 1812*e4b17023SJohn Marino x = build_addr (x, target_context); 1813*e4b17023SJohn Marino x = gsi_gimplify_val (info, x, &wi->gsi); 1814*e4b17023SJohn Marino call = gimple_build_call (builtin_decl_implicit (BUILT_IN_NONLOCAL_GOTO), 1815*e4b17023SJohn Marino 2, build_addr (new_label, target_context), x); 1816*e4b17023SJohn Marino gsi_replace (&wi->gsi, call, false); 1817*e4b17023SJohn Marino 1818*e4b17023SJohn Marino /* We have handled all of STMT's operands, no need to keep going. */ 1819*e4b17023SJohn Marino *handled_ops_p = true; 1820*e4b17023SJohn Marino return NULL_TREE; 1821*e4b17023SJohn Marino } 1822*e4b17023SJohn Marino 1823*e4b17023SJohn Marino 1824*e4b17023SJohn Marino /* Called via walk_function+walk_tree, rewrite all GIMPLE_LABELs whose labels 1825*e4b17023SJohn Marino are referenced via nonlocal goto from a nested function. The rewrite 1826*e4b17023SJohn Marino will involve installing a newly generated DECL_NONLOCAL label, and 1827*e4b17023SJohn Marino (potentially) a branch around the rtl gunk that is assumed to be 1828*e4b17023SJohn Marino attached to such a label. */ 1829*e4b17023SJohn Marino 1830*e4b17023SJohn Marino static tree 1831*e4b17023SJohn Marino convert_nl_goto_receiver (gimple_stmt_iterator *gsi, bool *handled_ops_p, 1832*e4b17023SJohn Marino struct walk_stmt_info *wi) 1833*e4b17023SJohn Marino { 1834*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info; 1835*e4b17023SJohn Marino tree label, new_label; 1836*e4b17023SJohn Marino gimple_stmt_iterator tmp_gsi; 1837*e4b17023SJohn Marino void **slot; 1838*e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsi); 1839*e4b17023SJohn Marino 1840*e4b17023SJohn Marino if (gimple_code (stmt) != GIMPLE_LABEL) 1841*e4b17023SJohn Marino { 1842*e4b17023SJohn Marino *handled_ops_p = false; 1843*e4b17023SJohn Marino return NULL_TREE; 1844*e4b17023SJohn Marino } 1845*e4b17023SJohn Marino 1846*e4b17023SJohn Marino label = gimple_label_label (stmt); 1847*e4b17023SJohn Marino 1848*e4b17023SJohn Marino slot = pointer_map_contains (info->var_map, label); 1849*e4b17023SJohn Marino if (!slot) 1850*e4b17023SJohn Marino { 1851*e4b17023SJohn Marino *handled_ops_p = false; 1852*e4b17023SJohn Marino return NULL_TREE; 1853*e4b17023SJohn Marino } 1854*e4b17023SJohn Marino 1855*e4b17023SJohn Marino /* If there's any possibility that the previous statement falls through, 1856*e4b17023SJohn Marino then we must branch around the new non-local label. */ 1857*e4b17023SJohn Marino tmp_gsi = wi->gsi; 1858*e4b17023SJohn Marino gsi_prev (&tmp_gsi); 1859*e4b17023SJohn Marino if (gsi_end_p (tmp_gsi) || gimple_stmt_may_fallthru (gsi_stmt (tmp_gsi))) 1860*e4b17023SJohn Marino { 1861*e4b17023SJohn Marino gimple stmt = gimple_build_goto (label); 1862*e4b17023SJohn Marino gsi_insert_before (gsi, stmt, GSI_SAME_STMT); 1863*e4b17023SJohn Marino } 1864*e4b17023SJohn Marino 1865*e4b17023SJohn Marino new_label = (tree) *slot; 1866*e4b17023SJohn Marino stmt = gimple_build_label (new_label); 1867*e4b17023SJohn Marino gsi_insert_before (gsi, stmt, GSI_SAME_STMT); 1868*e4b17023SJohn Marino 1869*e4b17023SJohn Marino *handled_ops_p = true; 1870*e4b17023SJohn Marino return NULL_TREE; 1871*e4b17023SJohn Marino } 1872*e4b17023SJohn Marino 1873*e4b17023SJohn Marino 1874*e4b17023SJohn Marino /* Called via walk_function+walk_stmt, rewrite all references to addresses 1875*e4b17023SJohn Marino of nested functions that require the use of trampolines. The rewrite 1876*e4b17023SJohn Marino will involve a reference a trampoline generated for the occasion. */ 1877*e4b17023SJohn Marino 1878*e4b17023SJohn Marino static tree 1879*e4b17023SJohn Marino convert_tramp_reference_op (tree *tp, int *walk_subtrees, void *data) 1880*e4b17023SJohn Marino { 1881*e4b17023SJohn Marino struct walk_stmt_info *wi = (struct walk_stmt_info *) data; 1882*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info, *i; 1883*e4b17023SJohn Marino tree t = *tp, decl, target_context, x, builtin; 1884*e4b17023SJohn Marino gimple call; 1885*e4b17023SJohn Marino 1886*e4b17023SJohn Marino *walk_subtrees = 0; 1887*e4b17023SJohn Marino switch (TREE_CODE (t)) 1888*e4b17023SJohn Marino { 1889*e4b17023SJohn Marino case ADDR_EXPR: 1890*e4b17023SJohn Marino /* Build 1891*e4b17023SJohn Marino T.1 = &CHAIN->tramp; 1892*e4b17023SJohn Marino T.2 = __builtin_adjust_trampoline (T.1); 1893*e4b17023SJohn Marino T.3 = (func_type)T.2; 1894*e4b17023SJohn Marino */ 1895*e4b17023SJohn Marino 1896*e4b17023SJohn Marino decl = TREE_OPERAND (t, 0); 1897*e4b17023SJohn Marino if (TREE_CODE (decl) != FUNCTION_DECL) 1898*e4b17023SJohn Marino break; 1899*e4b17023SJohn Marino 1900*e4b17023SJohn Marino /* Only need to process nested functions. */ 1901*e4b17023SJohn Marino target_context = decl_function_context (decl); 1902*e4b17023SJohn Marino if (!target_context) 1903*e4b17023SJohn Marino break; 1904*e4b17023SJohn Marino 1905*e4b17023SJohn Marino /* If the nested function doesn't use a static chain, then 1906*e4b17023SJohn Marino it doesn't need a trampoline. */ 1907*e4b17023SJohn Marino if (!DECL_STATIC_CHAIN (decl)) 1908*e4b17023SJohn Marino break; 1909*e4b17023SJohn Marino 1910*e4b17023SJohn Marino /* If we don't want a trampoline, then don't build one. */ 1911*e4b17023SJohn Marino if (TREE_NO_TRAMPOLINE (t)) 1912*e4b17023SJohn Marino break; 1913*e4b17023SJohn Marino 1914*e4b17023SJohn Marino /* Lookup the immediate parent of the callee, as that's where 1915*e4b17023SJohn Marino we need to insert the trampoline. */ 1916*e4b17023SJohn Marino for (i = info; i->context != target_context; i = i->outer) 1917*e4b17023SJohn Marino continue; 1918*e4b17023SJohn Marino x = lookup_tramp_for_decl (i, decl, INSERT); 1919*e4b17023SJohn Marino 1920*e4b17023SJohn Marino /* Compute the address of the field holding the trampoline. */ 1921*e4b17023SJohn Marino x = get_frame_field (info, target_context, x, &wi->gsi); 1922*e4b17023SJohn Marino x = build_addr (x, target_context); 1923*e4b17023SJohn Marino x = gsi_gimplify_val (info, x, &wi->gsi); 1924*e4b17023SJohn Marino 1925*e4b17023SJohn Marino /* Do machine-specific ugliness. Normally this will involve 1926*e4b17023SJohn Marino computing extra alignment, but it can really be anything. */ 1927*e4b17023SJohn Marino builtin = builtin_decl_implicit (BUILT_IN_ADJUST_TRAMPOLINE); 1928*e4b17023SJohn Marino call = gimple_build_call (builtin, 1, x); 1929*e4b17023SJohn Marino x = init_tmp_var_with_call (info, &wi->gsi, call); 1930*e4b17023SJohn Marino 1931*e4b17023SJohn Marino /* Cast back to the proper function type. */ 1932*e4b17023SJohn Marino x = build1 (NOP_EXPR, TREE_TYPE (t), x); 1933*e4b17023SJohn Marino x = init_tmp_var (info, x, &wi->gsi); 1934*e4b17023SJohn Marino 1935*e4b17023SJohn Marino *tp = x; 1936*e4b17023SJohn Marino break; 1937*e4b17023SJohn Marino 1938*e4b17023SJohn Marino default: 1939*e4b17023SJohn Marino if (!IS_TYPE_OR_DECL_P (t)) 1940*e4b17023SJohn Marino *walk_subtrees = 1; 1941*e4b17023SJohn Marino break; 1942*e4b17023SJohn Marino } 1943*e4b17023SJohn Marino 1944*e4b17023SJohn Marino return NULL_TREE; 1945*e4b17023SJohn Marino } 1946*e4b17023SJohn Marino 1947*e4b17023SJohn Marino 1948*e4b17023SJohn Marino /* Called via walk_function+walk_gimple_stmt, rewrite all references 1949*e4b17023SJohn Marino to addresses of nested functions that require the use of 1950*e4b17023SJohn Marino trampolines. The rewrite will involve a reference a trampoline 1951*e4b17023SJohn Marino generated for the occasion. */ 1952*e4b17023SJohn Marino 1953*e4b17023SJohn Marino static tree 1954*e4b17023SJohn Marino convert_tramp_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, 1955*e4b17023SJohn Marino struct walk_stmt_info *wi) 1956*e4b17023SJohn Marino { 1957*e4b17023SJohn Marino struct nesting_info *info = (struct nesting_info *) wi->info; 1958*e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsi); 1959*e4b17023SJohn Marino 1960*e4b17023SJohn Marino switch (gimple_code (stmt)) 1961*e4b17023SJohn Marino { 1962*e4b17023SJohn Marino case GIMPLE_CALL: 1963*e4b17023SJohn Marino { 1964*e4b17023SJohn Marino /* Only walk call arguments, lest we generate trampolines for 1965*e4b17023SJohn Marino direct calls. */ 1966*e4b17023SJohn Marino unsigned long i, nargs = gimple_call_num_args (stmt); 1967*e4b17023SJohn Marino for (i = 0; i < nargs; i++) 1968*e4b17023SJohn Marino walk_tree (gimple_call_arg_ptr (stmt, i), convert_tramp_reference_op, 1969*e4b17023SJohn Marino wi, NULL); 1970*e4b17023SJohn Marino break; 1971*e4b17023SJohn Marino } 1972*e4b17023SJohn Marino 1973*e4b17023SJohn Marino case GIMPLE_OMP_PARALLEL: 1974*e4b17023SJohn Marino case GIMPLE_OMP_TASK: 1975*e4b17023SJohn Marino { 1976*e4b17023SJohn Marino tree save_local_var_chain; 1977*e4b17023SJohn Marino walk_gimple_op (stmt, convert_tramp_reference_op, wi); 1978*e4b17023SJohn Marino save_local_var_chain = info->new_local_var_chain; 1979*e4b17023SJohn Marino info->new_local_var_chain = NULL; 1980*e4b17023SJohn Marino walk_body (convert_tramp_reference_stmt, convert_tramp_reference_op, 1981*e4b17023SJohn Marino info, gimple_omp_body (stmt)); 1982*e4b17023SJohn Marino if (info->new_local_var_chain) 1983*e4b17023SJohn Marino declare_vars (info->new_local_var_chain, 1984*e4b17023SJohn Marino gimple_seq_first_stmt (gimple_omp_body (stmt)), 1985*e4b17023SJohn Marino false); 1986*e4b17023SJohn Marino info->new_local_var_chain = save_local_var_chain; 1987*e4b17023SJohn Marino } 1988*e4b17023SJohn Marino break; 1989*e4b17023SJohn Marino 1990*e4b17023SJohn Marino default: 1991*e4b17023SJohn Marino *handled_ops_p = false; 1992*e4b17023SJohn Marino return NULL_TREE; 1993*e4b17023SJohn Marino break; 1994*e4b17023SJohn Marino } 1995*e4b17023SJohn Marino 1996*e4b17023SJohn Marino *handled_ops_p = true; 1997*e4b17023SJohn Marino return NULL_TREE; 1998*e4b17023SJohn Marino } 1999*e4b17023SJohn Marino 2000*e4b17023SJohn Marino 2001*e4b17023SJohn Marino 2002*e4b17023SJohn Marino /* Called via walk_function+walk_gimple_stmt, rewrite all GIMPLE_CALLs 2003*e4b17023SJohn Marino that reference nested functions to make sure that the static chain 2004*e4b17023SJohn Marino is set up properly for the call. */ 2005*e4b17023SJohn Marino 2006*e4b17023SJohn Marino static tree 2007*e4b17023SJohn Marino convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p, 2008*e4b17023SJohn Marino struct walk_stmt_info *wi) 2009*e4b17023SJohn Marino { 2010*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info; 2011*e4b17023SJohn Marino tree decl, target_context; 2012*e4b17023SJohn Marino char save_static_chain_added; 2013*e4b17023SJohn Marino int i; 2014*e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsi); 2015*e4b17023SJohn Marino 2016*e4b17023SJohn Marino switch (gimple_code (stmt)) 2017*e4b17023SJohn Marino { 2018*e4b17023SJohn Marino case GIMPLE_CALL: 2019*e4b17023SJohn Marino if (gimple_call_chain (stmt)) 2020*e4b17023SJohn Marino break; 2021*e4b17023SJohn Marino decl = gimple_call_fndecl (stmt); 2022*e4b17023SJohn Marino if (!decl) 2023*e4b17023SJohn Marino break; 2024*e4b17023SJohn Marino target_context = decl_function_context (decl); 2025*e4b17023SJohn Marino if (target_context && DECL_STATIC_CHAIN (decl)) 2026*e4b17023SJohn Marino { 2027*e4b17023SJohn Marino gimple_call_set_chain (stmt, get_static_chain (info, target_context, 2028*e4b17023SJohn Marino &wi->gsi)); 2029*e4b17023SJohn Marino info->static_chain_added |= (1 << (info->context != target_context)); 2030*e4b17023SJohn Marino } 2031*e4b17023SJohn Marino break; 2032*e4b17023SJohn Marino 2033*e4b17023SJohn Marino case GIMPLE_OMP_PARALLEL: 2034*e4b17023SJohn Marino case GIMPLE_OMP_TASK: 2035*e4b17023SJohn Marino save_static_chain_added = info->static_chain_added; 2036*e4b17023SJohn Marino info->static_chain_added = 0; 2037*e4b17023SJohn Marino walk_body (convert_gimple_call, NULL, info, gimple_omp_body (stmt)); 2038*e4b17023SJohn Marino for (i = 0; i < 2; i++) 2039*e4b17023SJohn Marino { 2040*e4b17023SJohn Marino tree c, decl; 2041*e4b17023SJohn Marino if ((info->static_chain_added & (1 << i)) == 0) 2042*e4b17023SJohn Marino continue; 2043*e4b17023SJohn Marino decl = i ? get_chain_decl (info) : info->frame_decl; 2044*e4b17023SJohn Marino /* Don't add CHAIN.* or FRAME.* twice. */ 2045*e4b17023SJohn Marino for (c = gimple_omp_taskreg_clauses (stmt); 2046*e4b17023SJohn Marino c; 2047*e4b17023SJohn Marino c = OMP_CLAUSE_CHAIN (c)) 2048*e4b17023SJohn Marino if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE 2049*e4b17023SJohn Marino || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED) 2050*e4b17023SJohn Marino && OMP_CLAUSE_DECL (c) == decl) 2051*e4b17023SJohn Marino break; 2052*e4b17023SJohn Marino if (c == NULL) 2053*e4b17023SJohn Marino { 2054*e4b17023SJohn Marino c = build_omp_clause (gimple_location (stmt), 2055*e4b17023SJohn Marino i ? OMP_CLAUSE_FIRSTPRIVATE 2056*e4b17023SJohn Marino : OMP_CLAUSE_SHARED); 2057*e4b17023SJohn Marino OMP_CLAUSE_DECL (c) = decl; 2058*e4b17023SJohn Marino OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt); 2059*e4b17023SJohn Marino gimple_omp_taskreg_set_clauses (stmt, c); 2060*e4b17023SJohn Marino } 2061*e4b17023SJohn Marino } 2062*e4b17023SJohn Marino info->static_chain_added |= save_static_chain_added; 2063*e4b17023SJohn Marino break; 2064*e4b17023SJohn Marino 2065*e4b17023SJohn Marino case GIMPLE_OMP_FOR: 2066*e4b17023SJohn Marino walk_body (convert_gimple_call, NULL, info, 2067*e4b17023SJohn Marino gimple_omp_for_pre_body (stmt)); 2068*e4b17023SJohn Marino /* FALLTHRU */ 2069*e4b17023SJohn Marino case GIMPLE_OMP_SECTIONS: 2070*e4b17023SJohn Marino case GIMPLE_OMP_SECTION: 2071*e4b17023SJohn Marino case GIMPLE_OMP_SINGLE: 2072*e4b17023SJohn Marino case GIMPLE_OMP_MASTER: 2073*e4b17023SJohn Marino case GIMPLE_OMP_ORDERED: 2074*e4b17023SJohn Marino case GIMPLE_OMP_CRITICAL: 2075*e4b17023SJohn Marino walk_body (convert_gimple_call, NULL, info, gimple_omp_body (stmt)); 2076*e4b17023SJohn Marino break; 2077*e4b17023SJohn Marino 2078*e4b17023SJohn Marino default: 2079*e4b17023SJohn Marino /* Keep looking for other operands. */ 2080*e4b17023SJohn Marino *handled_ops_p = false; 2081*e4b17023SJohn Marino return NULL_TREE; 2082*e4b17023SJohn Marino } 2083*e4b17023SJohn Marino 2084*e4b17023SJohn Marino *handled_ops_p = true; 2085*e4b17023SJohn Marino return NULL_TREE; 2086*e4b17023SJohn Marino } 2087*e4b17023SJohn Marino 2088*e4b17023SJohn Marino /* Walk the nesting tree starting with ROOT. Convert all trampolines and 2089*e4b17023SJohn Marino call expressions. At the same time, determine if a nested function 2090*e4b17023SJohn Marino actually uses its static chain; if not, remember that. */ 2091*e4b17023SJohn Marino 2092*e4b17023SJohn Marino static void 2093*e4b17023SJohn Marino convert_all_function_calls (struct nesting_info *root) 2094*e4b17023SJohn Marino { 2095*e4b17023SJohn Marino unsigned int chain_count = 0, old_chain_count, iter_count; 2096*e4b17023SJohn Marino struct nesting_info *n; 2097*e4b17023SJohn Marino 2098*e4b17023SJohn Marino /* First, optimistically clear static_chain for all decls that haven't 2099*e4b17023SJohn Marino used the static chain already for variable access. */ 2100*e4b17023SJohn Marino FOR_EACH_NEST_INFO (n, root) 2101*e4b17023SJohn Marino { 2102*e4b17023SJohn Marino tree decl = n->context; 2103*e4b17023SJohn Marino if (!n->outer || (!n->chain_decl && !n->chain_field)) 2104*e4b17023SJohn Marino { 2105*e4b17023SJohn Marino DECL_STATIC_CHAIN (decl) = 0; 2106*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 2107*e4b17023SJohn Marino fprintf (dump_file, "Guessing no static-chain for %s\n", 2108*e4b17023SJohn Marino lang_hooks.decl_printable_name (decl, 2)); 2109*e4b17023SJohn Marino } 2110*e4b17023SJohn Marino else 2111*e4b17023SJohn Marino DECL_STATIC_CHAIN (decl) = 1; 2112*e4b17023SJohn Marino chain_count += DECL_STATIC_CHAIN (decl); 2113*e4b17023SJohn Marino } 2114*e4b17023SJohn Marino 2115*e4b17023SJohn Marino /* Walk the functions and perform transformations. Note that these 2116*e4b17023SJohn Marino transformations can induce new uses of the static chain, which in turn 2117*e4b17023SJohn Marino require re-examining all users of the decl. */ 2118*e4b17023SJohn Marino /* ??? It would make sense to try to use the call graph to speed this up, 2119*e4b17023SJohn Marino but the call graph hasn't really been built yet. Even if it did, we 2120*e4b17023SJohn Marino would still need to iterate in this loop since address-of references 2121*e4b17023SJohn Marino wouldn't show up in the callgraph anyway. */ 2122*e4b17023SJohn Marino iter_count = 0; 2123*e4b17023SJohn Marino do 2124*e4b17023SJohn Marino { 2125*e4b17023SJohn Marino old_chain_count = chain_count; 2126*e4b17023SJohn Marino chain_count = 0; 2127*e4b17023SJohn Marino iter_count++; 2128*e4b17023SJohn Marino 2129*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 2130*e4b17023SJohn Marino fputc ('\n', dump_file); 2131*e4b17023SJohn Marino 2132*e4b17023SJohn Marino FOR_EACH_NEST_INFO (n, root) 2133*e4b17023SJohn Marino { 2134*e4b17023SJohn Marino tree decl = n->context; 2135*e4b17023SJohn Marino walk_function (convert_tramp_reference_stmt, 2136*e4b17023SJohn Marino convert_tramp_reference_op, n); 2137*e4b17023SJohn Marino walk_function (convert_gimple_call, NULL, n); 2138*e4b17023SJohn Marino chain_count += DECL_STATIC_CHAIN (decl); 2139*e4b17023SJohn Marino } 2140*e4b17023SJohn Marino } 2141*e4b17023SJohn Marino while (chain_count != old_chain_count); 2142*e4b17023SJohn Marino 2143*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 2144*e4b17023SJohn Marino fprintf (dump_file, "convert_all_function_calls iterations: %u\n\n", 2145*e4b17023SJohn Marino iter_count); 2146*e4b17023SJohn Marino } 2147*e4b17023SJohn Marino 2148*e4b17023SJohn Marino struct nesting_copy_body_data 2149*e4b17023SJohn Marino { 2150*e4b17023SJohn Marino copy_body_data cb; 2151*e4b17023SJohn Marino struct nesting_info *root; 2152*e4b17023SJohn Marino }; 2153*e4b17023SJohn Marino 2154*e4b17023SJohn Marino /* A helper subroutine for debug_var_chain type remapping. */ 2155*e4b17023SJohn Marino 2156*e4b17023SJohn Marino static tree 2157*e4b17023SJohn Marino nesting_copy_decl (tree decl, copy_body_data *id) 2158*e4b17023SJohn Marino { 2159*e4b17023SJohn Marino struct nesting_copy_body_data *nid = (struct nesting_copy_body_data *) id; 2160*e4b17023SJohn Marino void **slot = pointer_map_contains (nid->root->var_map, decl); 2161*e4b17023SJohn Marino 2162*e4b17023SJohn Marino if (slot) 2163*e4b17023SJohn Marino return (tree) *slot; 2164*e4b17023SJohn Marino 2165*e4b17023SJohn Marino if (TREE_CODE (decl) == TYPE_DECL && DECL_ORIGINAL_TYPE (decl)) 2166*e4b17023SJohn Marino { 2167*e4b17023SJohn Marino tree new_decl = copy_decl_no_change (decl, id); 2168*e4b17023SJohn Marino DECL_ORIGINAL_TYPE (new_decl) 2169*e4b17023SJohn Marino = remap_type (DECL_ORIGINAL_TYPE (decl), id); 2170*e4b17023SJohn Marino return new_decl; 2171*e4b17023SJohn Marino } 2172*e4b17023SJohn Marino 2173*e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL 2174*e4b17023SJohn Marino || TREE_CODE (decl) == PARM_DECL 2175*e4b17023SJohn Marino || TREE_CODE (decl) == RESULT_DECL) 2176*e4b17023SJohn Marino return decl; 2177*e4b17023SJohn Marino 2178*e4b17023SJohn Marino return copy_decl_no_change (decl, id); 2179*e4b17023SJohn Marino } 2180*e4b17023SJohn Marino 2181*e4b17023SJohn Marino /* A helper function for remap_vla_decls. See if *TP contains 2182*e4b17023SJohn Marino some remapped variables. */ 2183*e4b17023SJohn Marino 2184*e4b17023SJohn Marino static tree 2185*e4b17023SJohn Marino contains_remapped_vars (tree *tp, int *walk_subtrees, void *data) 2186*e4b17023SJohn Marino { 2187*e4b17023SJohn Marino struct nesting_info *root = (struct nesting_info *) data; 2188*e4b17023SJohn Marino tree t = *tp; 2189*e4b17023SJohn Marino void **slot; 2190*e4b17023SJohn Marino 2191*e4b17023SJohn Marino if (DECL_P (t)) 2192*e4b17023SJohn Marino { 2193*e4b17023SJohn Marino *walk_subtrees = 0; 2194*e4b17023SJohn Marino slot = pointer_map_contains (root->var_map, t); 2195*e4b17023SJohn Marino 2196*e4b17023SJohn Marino if (slot) 2197*e4b17023SJohn Marino return (tree) *slot; 2198*e4b17023SJohn Marino } 2199*e4b17023SJohn Marino return NULL; 2200*e4b17023SJohn Marino } 2201*e4b17023SJohn Marino 2202*e4b17023SJohn Marino /* Remap VLA decls in BLOCK and subblocks if remapped variables are 2203*e4b17023SJohn Marino involved. */ 2204*e4b17023SJohn Marino 2205*e4b17023SJohn Marino static void 2206*e4b17023SJohn Marino remap_vla_decls (tree block, struct nesting_info *root) 2207*e4b17023SJohn Marino { 2208*e4b17023SJohn Marino tree var, subblock, val, type; 2209*e4b17023SJohn Marino struct nesting_copy_body_data id; 2210*e4b17023SJohn Marino 2211*e4b17023SJohn Marino for (subblock = BLOCK_SUBBLOCKS (block); 2212*e4b17023SJohn Marino subblock; 2213*e4b17023SJohn Marino subblock = BLOCK_CHAIN (subblock)) 2214*e4b17023SJohn Marino remap_vla_decls (subblock, root); 2215*e4b17023SJohn Marino 2216*e4b17023SJohn Marino for (var = BLOCK_VARS (block); var; var = DECL_CHAIN (var)) 2217*e4b17023SJohn Marino if (TREE_CODE (var) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (var)) 2218*e4b17023SJohn Marino { 2219*e4b17023SJohn Marino val = DECL_VALUE_EXPR (var); 2220*e4b17023SJohn Marino type = TREE_TYPE (var); 2221*e4b17023SJohn Marino 2222*e4b17023SJohn Marino if (!(TREE_CODE (val) == INDIRECT_REF 2223*e4b17023SJohn Marino && TREE_CODE (TREE_OPERAND (val, 0)) == VAR_DECL 2224*e4b17023SJohn Marino && variably_modified_type_p (type, NULL))) 2225*e4b17023SJohn Marino continue; 2226*e4b17023SJohn Marino 2227*e4b17023SJohn Marino if (pointer_map_contains (root->var_map, TREE_OPERAND (val, 0)) 2228*e4b17023SJohn Marino || walk_tree (&type, contains_remapped_vars, root, NULL)) 2229*e4b17023SJohn Marino break; 2230*e4b17023SJohn Marino } 2231*e4b17023SJohn Marino 2232*e4b17023SJohn Marino if (var == NULL_TREE) 2233*e4b17023SJohn Marino return; 2234*e4b17023SJohn Marino 2235*e4b17023SJohn Marino memset (&id, 0, sizeof (id)); 2236*e4b17023SJohn Marino id.cb.copy_decl = nesting_copy_decl; 2237*e4b17023SJohn Marino id.cb.decl_map = pointer_map_create (); 2238*e4b17023SJohn Marino id.root = root; 2239*e4b17023SJohn Marino 2240*e4b17023SJohn Marino for (; var; var = DECL_CHAIN (var)) 2241*e4b17023SJohn Marino if (TREE_CODE (var) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (var)) 2242*e4b17023SJohn Marino { 2243*e4b17023SJohn Marino struct nesting_info *i; 2244*e4b17023SJohn Marino tree newt, context; 2245*e4b17023SJohn Marino void **slot; 2246*e4b17023SJohn Marino 2247*e4b17023SJohn Marino val = DECL_VALUE_EXPR (var); 2248*e4b17023SJohn Marino type = TREE_TYPE (var); 2249*e4b17023SJohn Marino 2250*e4b17023SJohn Marino if (!(TREE_CODE (val) == INDIRECT_REF 2251*e4b17023SJohn Marino && TREE_CODE (TREE_OPERAND (val, 0)) == VAR_DECL 2252*e4b17023SJohn Marino && variably_modified_type_p (type, NULL))) 2253*e4b17023SJohn Marino continue; 2254*e4b17023SJohn Marino 2255*e4b17023SJohn Marino slot = pointer_map_contains (root->var_map, TREE_OPERAND (val, 0)); 2256*e4b17023SJohn Marino if (!slot && !walk_tree (&type, contains_remapped_vars, root, NULL)) 2257*e4b17023SJohn Marino continue; 2258*e4b17023SJohn Marino 2259*e4b17023SJohn Marino context = decl_function_context (var); 2260*e4b17023SJohn Marino for (i = root; i; i = i->outer) 2261*e4b17023SJohn Marino if (i->context == context) 2262*e4b17023SJohn Marino break; 2263*e4b17023SJohn Marino 2264*e4b17023SJohn Marino if (i == NULL) 2265*e4b17023SJohn Marino continue; 2266*e4b17023SJohn Marino 2267*e4b17023SJohn Marino /* Fully expand value expressions. This avoids having debug variables 2268*e4b17023SJohn Marino only referenced from them and that can be swept during GC. */ 2269*e4b17023SJohn Marino if (slot) 2270*e4b17023SJohn Marino { 2271*e4b17023SJohn Marino tree t = (tree) *slot; 2272*e4b17023SJohn Marino gcc_assert (DECL_P (t) && DECL_HAS_VALUE_EXPR_P (t)); 2273*e4b17023SJohn Marino val = build1 (INDIRECT_REF, TREE_TYPE (val), DECL_VALUE_EXPR (t)); 2274*e4b17023SJohn Marino } 2275*e4b17023SJohn Marino 2276*e4b17023SJohn Marino id.cb.src_fn = i->context; 2277*e4b17023SJohn Marino id.cb.dst_fn = i->context; 2278*e4b17023SJohn Marino id.cb.src_cfun = DECL_STRUCT_FUNCTION (root->context); 2279*e4b17023SJohn Marino 2280*e4b17023SJohn Marino TREE_TYPE (var) = newt = remap_type (type, &id.cb); 2281*e4b17023SJohn Marino while (POINTER_TYPE_P (newt) && !TYPE_NAME (newt)) 2282*e4b17023SJohn Marino { 2283*e4b17023SJohn Marino newt = TREE_TYPE (newt); 2284*e4b17023SJohn Marino type = TREE_TYPE (type); 2285*e4b17023SJohn Marino } 2286*e4b17023SJohn Marino if (TYPE_NAME (newt) 2287*e4b17023SJohn Marino && TREE_CODE (TYPE_NAME (newt)) == TYPE_DECL 2288*e4b17023SJohn Marino && DECL_ORIGINAL_TYPE (TYPE_NAME (newt)) 2289*e4b17023SJohn Marino && newt != type 2290*e4b17023SJohn Marino && TYPE_NAME (newt) == TYPE_NAME (type)) 2291*e4b17023SJohn Marino TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb); 2292*e4b17023SJohn Marino 2293*e4b17023SJohn Marino walk_tree (&val, copy_tree_body_r, &id.cb, NULL); 2294*e4b17023SJohn Marino if (val != DECL_VALUE_EXPR (var)) 2295*e4b17023SJohn Marino SET_DECL_VALUE_EXPR (var, val); 2296*e4b17023SJohn Marino } 2297*e4b17023SJohn Marino 2298*e4b17023SJohn Marino pointer_map_destroy (id.cb.decl_map); 2299*e4b17023SJohn Marino } 2300*e4b17023SJohn Marino 2301*e4b17023SJohn Marino /* Fold the MEM_REF *E. */ 2302*e4b17023SJohn Marino static bool 2303*e4b17023SJohn Marino fold_mem_refs (const void *e, void *data ATTRIBUTE_UNUSED) 2304*e4b17023SJohn Marino { 2305*e4b17023SJohn Marino tree *ref_p = CONST_CAST2(tree *, const tree *, (const tree *)e); 2306*e4b17023SJohn Marino *ref_p = fold (*ref_p); 2307*e4b17023SJohn Marino return true; 2308*e4b17023SJohn Marino } 2309*e4b17023SJohn Marino 2310*e4b17023SJohn Marino /* Do "everything else" to clean up or complete state collected by the 2311*e4b17023SJohn Marino various walking passes -- lay out the types and decls, generate code 2312*e4b17023SJohn Marino to initialize the frame decl, store critical expressions in the 2313*e4b17023SJohn Marino struct function for rtl to find. */ 2314*e4b17023SJohn Marino 2315*e4b17023SJohn Marino static void 2316*e4b17023SJohn Marino finalize_nesting_tree_1 (struct nesting_info *root) 2317*e4b17023SJohn Marino { 2318*e4b17023SJohn Marino gimple_seq stmt_list; 2319*e4b17023SJohn Marino gimple stmt; 2320*e4b17023SJohn Marino tree context = root->context; 2321*e4b17023SJohn Marino struct function *sf; 2322*e4b17023SJohn Marino 2323*e4b17023SJohn Marino stmt_list = NULL; 2324*e4b17023SJohn Marino 2325*e4b17023SJohn Marino /* If we created a non-local frame type or decl, we need to lay them 2326*e4b17023SJohn Marino out at this time. */ 2327*e4b17023SJohn Marino if (root->frame_type) 2328*e4b17023SJohn Marino { 2329*e4b17023SJohn Marino /* In some cases the frame type will trigger the -Wpadded warning. 2330*e4b17023SJohn Marino This is not helpful; suppress it. */ 2331*e4b17023SJohn Marino int save_warn_padded = warn_padded; 2332*e4b17023SJohn Marino tree *adjust; 2333*e4b17023SJohn Marino 2334*e4b17023SJohn Marino warn_padded = 0; 2335*e4b17023SJohn Marino layout_type (root->frame_type); 2336*e4b17023SJohn Marino warn_padded = save_warn_padded; 2337*e4b17023SJohn Marino layout_decl (root->frame_decl, 0); 2338*e4b17023SJohn Marino 2339*e4b17023SJohn Marino /* Remove root->frame_decl from root->new_local_var_chain, so 2340*e4b17023SJohn Marino that we can declare it also in the lexical blocks, which 2341*e4b17023SJohn Marino helps ensure virtual regs that end up appearing in its RTL 2342*e4b17023SJohn Marino expression get substituted in instantiate_virtual_regs(). */ 2343*e4b17023SJohn Marino for (adjust = &root->new_local_var_chain; 2344*e4b17023SJohn Marino *adjust != root->frame_decl; 2345*e4b17023SJohn Marino adjust = &DECL_CHAIN (*adjust)) 2346*e4b17023SJohn Marino gcc_assert (DECL_CHAIN (*adjust)); 2347*e4b17023SJohn Marino *adjust = DECL_CHAIN (*adjust); 2348*e4b17023SJohn Marino 2349*e4b17023SJohn Marino DECL_CHAIN (root->frame_decl) = NULL_TREE; 2350*e4b17023SJohn Marino declare_vars (root->frame_decl, 2351*e4b17023SJohn Marino gimple_seq_first_stmt (gimple_body (context)), true); 2352*e4b17023SJohn Marino } 2353*e4b17023SJohn Marino 2354*e4b17023SJohn Marino /* If any parameters were referenced non-locally, then we need to 2355*e4b17023SJohn Marino insert a copy. Likewise, if any variables were referenced by 2356*e4b17023SJohn Marino pointer, we need to initialize the address. */ 2357*e4b17023SJohn Marino if (root->any_parm_remapped) 2358*e4b17023SJohn Marino { 2359*e4b17023SJohn Marino tree p; 2360*e4b17023SJohn Marino for (p = DECL_ARGUMENTS (context); p ; p = DECL_CHAIN (p)) 2361*e4b17023SJohn Marino { 2362*e4b17023SJohn Marino tree field, x, y; 2363*e4b17023SJohn Marino 2364*e4b17023SJohn Marino field = lookup_field_for_decl (root, p, NO_INSERT); 2365*e4b17023SJohn Marino if (!field) 2366*e4b17023SJohn Marino continue; 2367*e4b17023SJohn Marino 2368*e4b17023SJohn Marino if (use_pointer_in_frame (p)) 2369*e4b17023SJohn Marino x = build_addr (p, context); 2370*e4b17023SJohn Marino else 2371*e4b17023SJohn Marino x = p; 2372*e4b17023SJohn Marino 2373*e4b17023SJohn Marino y = build3 (COMPONENT_REF, TREE_TYPE (field), 2374*e4b17023SJohn Marino root->frame_decl, field, NULL_TREE); 2375*e4b17023SJohn Marino stmt = gimple_build_assign (y, x); 2376*e4b17023SJohn Marino gimple_seq_add_stmt (&stmt_list, stmt); 2377*e4b17023SJohn Marino /* If the assignment is from a non-register the stmt is 2378*e4b17023SJohn Marino not valid gimple. Make it so by using a temporary instead. */ 2379*e4b17023SJohn Marino if (!is_gimple_reg (x) 2380*e4b17023SJohn Marino && is_gimple_reg_type (TREE_TYPE (x))) 2381*e4b17023SJohn Marino { 2382*e4b17023SJohn Marino gimple_stmt_iterator gsi = gsi_last (stmt_list); 2383*e4b17023SJohn Marino x = init_tmp_var (root, x, &gsi); 2384*e4b17023SJohn Marino gimple_assign_set_rhs1 (stmt, x); 2385*e4b17023SJohn Marino } 2386*e4b17023SJohn Marino } 2387*e4b17023SJohn Marino } 2388*e4b17023SJohn Marino 2389*e4b17023SJohn Marino /* If a chain_field was created, then it needs to be initialized 2390*e4b17023SJohn Marino from chain_decl. */ 2391*e4b17023SJohn Marino if (root->chain_field) 2392*e4b17023SJohn Marino { 2393*e4b17023SJohn Marino tree x = build3 (COMPONENT_REF, TREE_TYPE (root->chain_field), 2394*e4b17023SJohn Marino root->frame_decl, root->chain_field, NULL_TREE); 2395*e4b17023SJohn Marino stmt = gimple_build_assign (x, get_chain_decl (root)); 2396*e4b17023SJohn Marino gimple_seq_add_stmt (&stmt_list, stmt); 2397*e4b17023SJohn Marino } 2398*e4b17023SJohn Marino 2399*e4b17023SJohn Marino /* If trampolines were created, then we need to initialize them. */ 2400*e4b17023SJohn Marino if (root->any_tramp_created) 2401*e4b17023SJohn Marino { 2402*e4b17023SJohn Marino struct nesting_info *i; 2403*e4b17023SJohn Marino for (i = root->inner; i ; i = i->next) 2404*e4b17023SJohn Marino { 2405*e4b17023SJohn Marino tree arg1, arg2, arg3, x, field; 2406*e4b17023SJohn Marino 2407*e4b17023SJohn Marino field = lookup_tramp_for_decl (root, i->context, NO_INSERT); 2408*e4b17023SJohn Marino if (!field) 2409*e4b17023SJohn Marino continue; 2410*e4b17023SJohn Marino 2411*e4b17023SJohn Marino gcc_assert (DECL_STATIC_CHAIN (i->context)); 2412*e4b17023SJohn Marino arg3 = build_addr (root->frame_decl, context); 2413*e4b17023SJohn Marino 2414*e4b17023SJohn Marino arg2 = build_addr (i->context, context); 2415*e4b17023SJohn Marino 2416*e4b17023SJohn Marino x = build3 (COMPONENT_REF, TREE_TYPE (field), 2417*e4b17023SJohn Marino root->frame_decl, field, NULL_TREE); 2418*e4b17023SJohn Marino arg1 = build_addr (x, context); 2419*e4b17023SJohn Marino 2420*e4b17023SJohn Marino x = builtin_decl_implicit (BUILT_IN_INIT_TRAMPOLINE); 2421*e4b17023SJohn Marino stmt = gimple_build_call (x, 3, arg1, arg2, arg3); 2422*e4b17023SJohn Marino gimple_seq_add_stmt (&stmt_list, stmt); 2423*e4b17023SJohn Marino } 2424*e4b17023SJohn Marino } 2425*e4b17023SJohn Marino 2426*e4b17023SJohn Marino /* If we created initialization statements, insert them. */ 2427*e4b17023SJohn Marino if (stmt_list) 2428*e4b17023SJohn Marino { 2429*e4b17023SJohn Marino gimple bind; 2430*e4b17023SJohn Marino annotate_all_with_location (stmt_list, DECL_SOURCE_LOCATION (context)); 2431*e4b17023SJohn Marino bind = gimple_seq_first_stmt (gimple_body (context)); 2432*e4b17023SJohn Marino gimple_seq_add_seq (&stmt_list, gimple_bind_body (bind)); 2433*e4b17023SJohn Marino gimple_bind_set_body (bind, stmt_list); 2434*e4b17023SJohn Marino } 2435*e4b17023SJohn Marino 2436*e4b17023SJohn Marino /* If a chain_decl was created, then it needs to be registered with 2437*e4b17023SJohn Marino struct function so that it gets initialized from the static chain 2438*e4b17023SJohn Marino register at the beginning of the function. */ 2439*e4b17023SJohn Marino sf = DECL_STRUCT_FUNCTION (root->context); 2440*e4b17023SJohn Marino sf->static_chain_decl = root->chain_decl; 2441*e4b17023SJohn Marino 2442*e4b17023SJohn Marino /* Similarly for the non-local goto save area. */ 2443*e4b17023SJohn Marino if (root->nl_goto_field) 2444*e4b17023SJohn Marino { 2445*e4b17023SJohn Marino sf->nonlocal_goto_save_area 2446*e4b17023SJohn Marino = get_frame_field (root, context, root->nl_goto_field, NULL); 2447*e4b17023SJohn Marino sf->has_nonlocal_label = 1; 2448*e4b17023SJohn Marino } 2449*e4b17023SJohn Marino 2450*e4b17023SJohn Marino /* Make sure all new local variables get inserted into the 2451*e4b17023SJohn Marino proper BIND_EXPR. */ 2452*e4b17023SJohn Marino if (root->new_local_var_chain) 2453*e4b17023SJohn Marino declare_vars (root->new_local_var_chain, 2454*e4b17023SJohn Marino gimple_seq_first_stmt (gimple_body (root->context)), 2455*e4b17023SJohn Marino false); 2456*e4b17023SJohn Marino 2457*e4b17023SJohn Marino if (root->debug_var_chain) 2458*e4b17023SJohn Marino { 2459*e4b17023SJohn Marino tree debug_var; 2460*e4b17023SJohn Marino gimple scope; 2461*e4b17023SJohn Marino 2462*e4b17023SJohn Marino remap_vla_decls (DECL_INITIAL (root->context), root); 2463*e4b17023SJohn Marino 2464*e4b17023SJohn Marino for (debug_var = root->debug_var_chain; debug_var; 2465*e4b17023SJohn Marino debug_var = DECL_CHAIN (debug_var)) 2466*e4b17023SJohn Marino if (variably_modified_type_p (TREE_TYPE (debug_var), NULL)) 2467*e4b17023SJohn Marino break; 2468*e4b17023SJohn Marino 2469*e4b17023SJohn Marino /* If there are any debug decls with variable length types, 2470*e4b17023SJohn Marino remap those types using other debug_var_chain variables. */ 2471*e4b17023SJohn Marino if (debug_var) 2472*e4b17023SJohn Marino { 2473*e4b17023SJohn Marino struct nesting_copy_body_data id; 2474*e4b17023SJohn Marino 2475*e4b17023SJohn Marino memset (&id, 0, sizeof (id)); 2476*e4b17023SJohn Marino id.cb.copy_decl = nesting_copy_decl; 2477*e4b17023SJohn Marino id.cb.decl_map = pointer_map_create (); 2478*e4b17023SJohn Marino id.root = root; 2479*e4b17023SJohn Marino 2480*e4b17023SJohn Marino for (; debug_var; debug_var = DECL_CHAIN (debug_var)) 2481*e4b17023SJohn Marino if (variably_modified_type_p (TREE_TYPE (debug_var), NULL)) 2482*e4b17023SJohn Marino { 2483*e4b17023SJohn Marino tree type = TREE_TYPE (debug_var); 2484*e4b17023SJohn Marino tree newt, t = type; 2485*e4b17023SJohn Marino struct nesting_info *i; 2486*e4b17023SJohn Marino 2487*e4b17023SJohn Marino for (i = root; i; i = i->outer) 2488*e4b17023SJohn Marino if (variably_modified_type_p (type, i->context)) 2489*e4b17023SJohn Marino break; 2490*e4b17023SJohn Marino 2491*e4b17023SJohn Marino if (i == NULL) 2492*e4b17023SJohn Marino continue; 2493*e4b17023SJohn Marino 2494*e4b17023SJohn Marino id.cb.src_fn = i->context; 2495*e4b17023SJohn Marino id.cb.dst_fn = i->context; 2496*e4b17023SJohn Marino id.cb.src_cfun = DECL_STRUCT_FUNCTION (root->context); 2497*e4b17023SJohn Marino 2498*e4b17023SJohn Marino TREE_TYPE (debug_var) = newt = remap_type (type, &id.cb); 2499*e4b17023SJohn Marino while (POINTER_TYPE_P (newt) && !TYPE_NAME (newt)) 2500*e4b17023SJohn Marino { 2501*e4b17023SJohn Marino newt = TREE_TYPE (newt); 2502*e4b17023SJohn Marino t = TREE_TYPE (t); 2503*e4b17023SJohn Marino } 2504*e4b17023SJohn Marino if (TYPE_NAME (newt) 2505*e4b17023SJohn Marino && TREE_CODE (TYPE_NAME (newt)) == TYPE_DECL 2506*e4b17023SJohn Marino && DECL_ORIGINAL_TYPE (TYPE_NAME (newt)) 2507*e4b17023SJohn Marino && newt != t 2508*e4b17023SJohn Marino && TYPE_NAME (newt) == TYPE_NAME (t)) 2509*e4b17023SJohn Marino TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb); 2510*e4b17023SJohn Marino } 2511*e4b17023SJohn Marino 2512*e4b17023SJohn Marino pointer_map_destroy (id.cb.decl_map); 2513*e4b17023SJohn Marino } 2514*e4b17023SJohn Marino 2515*e4b17023SJohn Marino scope = gimple_seq_first_stmt (gimple_body (root->context)); 2516*e4b17023SJohn Marino if (gimple_bind_block (scope)) 2517*e4b17023SJohn Marino declare_vars (root->debug_var_chain, scope, true); 2518*e4b17023SJohn Marino else 2519*e4b17023SJohn Marino BLOCK_VARS (DECL_INITIAL (root->context)) 2520*e4b17023SJohn Marino = chainon (BLOCK_VARS (DECL_INITIAL (root->context)), 2521*e4b17023SJohn Marino root->debug_var_chain); 2522*e4b17023SJohn Marino } 2523*e4b17023SJohn Marino 2524*e4b17023SJohn Marino /* Fold the rewritten MEM_REF trees. */ 2525*e4b17023SJohn Marino pointer_set_traverse (root->mem_refs, fold_mem_refs, NULL); 2526*e4b17023SJohn Marino 2527*e4b17023SJohn Marino /* Dump the translated tree function. */ 2528*e4b17023SJohn Marino if (dump_file) 2529*e4b17023SJohn Marino { 2530*e4b17023SJohn Marino fputs ("\n\n", dump_file); 2531*e4b17023SJohn Marino dump_function_to_file (root->context, dump_file, dump_flags); 2532*e4b17023SJohn Marino } 2533*e4b17023SJohn Marino } 2534*e4b17023SJohn Marino 2535*e4b17023SJohn Marino static void 2536*e4b17023SJohn Marino finalize_nesting_tree (struct nesting_info *root) 2537*e4b17023SJohn Marino { 2538*e4b17023SJohn Marino struct nesting_info *n; 2539*e4b17023SJohn Marino FOR_EACH_NEST_INFO (n, root) 2540*e4b17023SJohn Marino finalize_nesting_tree_1 (n); 2541*e4b17023SJohn Marino } 2542*e4b17023SJohn Marino 2543*e4b17023SJohn Marino /* Unnest the nodes and pass them to cgraph. */ 2544*e4b17023SJohn Marino 2545*e4b17023SJohn Marino static void 2546*e4b17023SJohn Marino unnest_nesting_tree_1 (struct nesting_info *root) 2547*e4b17023SJohn Marino { 2548*e4b17023SJohn Marino struct cgraph_node *node = cgraph_get_node (root->context); 2549*e4b17023SJohn Marino 2550*e4b17023SJohn Marino /* For nested functions update the cgraph to reflect unnesting. 2551*e4b17023SJohn Marino We also delay finalizing of these functions up to this point. */ 2552*e4b17023SJohn Marino if (node->origin) 2553*e4b17023SJohn Marino { 2554*e4b17023SJohn Marino cgraph_unnest_node (node); 2555*e4b17023SJohn Marino cgraph_finalize_function (root->context, true); 2556*e4b17023SJohn Marino } 2557*e4b17023SJohn Marino } 2558*e4b17023SJohn Marino 2559*e4b17023SJohn Marino static void 2560*e4b17023SJohn Marino unnest_nesting_tree (struct nesting_info *root) 2561*e4b17023SJohn Marino { 2562*e4b17023SJohn Marino struct nesting_info *n; 2563*e4b17023SJohn Marino FOR_EACH_NEST_INFO (n, root) 2564*e4b17023SJohn Marino unnest_nesting_tree_1 (n); 2565*e4b17023SJohn Marino } 2566*e4b17023SJohn Marino 2567*e4b17023SJohn Marino /* Free the data structures allocated during this pass. */ 2568*e4b17023SJohn Marino 2569*e4b17023SJohn Marino static void 2570*e4b17023SJohn Marino free_nesting_tree (struct nesting_info *root) 2571*e4b17023SJohn Marino { 2572*e4b17023SJohn Marino struct nesting_info *node, *next; 2573*e4b17023SJohn Marino 2574*e4b17023SJohn Marino node = iter_nestinfo_start (root); 2575*e4b17023SJohn Marino do 2576*e4b17023SJohn Marino { 2577*e4b17023SJohn Marino next = iter_nestinfo_next (node); 2578*e4b17023SJohn Marino pointer_map_destroy (node->var_map); 2579*e4b17023SJohn Marino pointer_map_destroy (node->field_map); 2580*e4b17023SJohn Marino pointer_set_destroy (node->mem_refs); 2581*e4b17023SJohn Marino free (node); 2582*e4b17023SJohn Marino node = next; 2583*e4b17023SJohn Marino } 2584*e4b17023SJohn Marino while (node); 2585*e4b17023SJohn Marino } 2586*e4b17023SJohn Marino 2587*e4b17023SJohn Marino /* Gimplify a function and all its nested functions. */ 2588*e4b17023SJohn Marino static void 2589*e4b17023SJohn Marino gimplify_all_functions (struct cgraph_node *root) 2590*e4b17023SJohn Marino { 2591*e4b17023SJohn Marino struct cgraph_node *iter; 2592*e4b17023SJohn Marino if (!gimple_body (root->decl)) 2593*e4b17023SJohn Marino gimplify_function_tree (root->decl); 2594*e4b17023SJohn Marino for (iter = root->nested; iter; iter = iter->next_nested) 2595*e4b17023SJohn Marino gimplify_all_functions (iter); 2596*e4b17023SJohn Marino } 2597*e4b17023SJohn Marino 2598*e4b17023SJohn Marino /* Main entry point for this pass. Process FNDECL and all of its nested 2599*e4b17023SJohn Marino subroutines and turn them into something less tightly bound. */ 2600*e4b17023SJohn Marino 2601*e4b17023SJohn Marino void 2602*e4b17023SJohn Marino lower_nested_functions (tree fndecl) 2603*e4b17023SJohn Marino { 2604*e4b17023SJohn Marino struct cgraph_node *cgn; 2605*e4b17023SJohn Marino struct nesting_info *root; 2606*e4b17023SJohn Marino 2607*e4b17023SJohn Marino /* If there are no nested functions, there's nothing to do. */ 2608*e4b17023SJohn Marino cgn = cgraph_get_node (fndecl); 2609*e4b17023SJohn Marino if (!cgn->nested) 2610*e4b17023SJohn Marino return; 2611*e4b17023SJohn Marino 2612*e4b17023SJohn Marino gimplify_all_functions (cgn); 2613*e4b17023SJohn Marino 2614*e4b17023SJohn Marino dump_file = dump_begin (TDI_nested, &dump_flags); 2615*e4b17023SJohn Marino if (dump_file) 2616*e4b17023SJohn Marino fprintf (dump_file, "\n;; Function %s\n\n", 2617*e4b17023SJohn Marino lang_hooks.decl_printable_name (fndecl, 2)); 2618*e4b17023SJohn Marino 2619*e4b17023SJohn Marino bitmap_obstack_initialize (&nesting_info_bitmap_obstack); 2620*e4b17023SJohn Marino root = create_nesting_tree (cgn); 2621*e4b17023SJohn Marino 2622*e4b17023SJohn Marino walk_all_functions (convert_nonlocal_reference_stmt, 2623*e4b17023SJohn Marino convert_nonlocal_reference_op, 2624*e4b17023SJohn Marino root); 2625*e4b17023SJohn Marino walk_all_functions (convert_local_reference_stmt, 2626*e4b17023SJohn Marino convert_local_reference_op, 2627*e4b17023SJohn Marino root); 2628*e4b17023SJohn Marino walk_all_functions (convert_nl_goto_reference, NULL, root); 2629*e4b17023SJohn Marino walk_all_functions (convert_nl_goto_receiver, NULL, root); 2630*e4b17023SJohn Marino 2631*e4b17023SJohn Marino convert_all_function_calls (root); 2632*e4b17023SJohn Marino finalize_nesting_tree (root); 2633*e4b17023SJohn Marino unnest_nesting_tree (root); 2634*e4b17023SJohn Marino 2635*e4b17023SJohn Marino free_nesting_tree (root); 2636*e4b17023SJohn Marino bitmap_obstack_release (&nesting_info_bitmap_obstack); 2637*e4b17023SJohn Marino 2638*e4b17023SJohn Marino if (dump_file) 2639*e4b17023SJohn Marino { 2640*e4b17023SJohn Marino dump_end (TDI_nested, dump_file); 2641*e4b17023SJohn Marino dump_file = NULL; 2642*e4b17023SJohn Marino } 2643*e4b17023SJohn Marino } 2644*e4b17023SJohn Marino 2645*e4b17023SJohn Marino #include "gt-tree-nested.h" 2646