1*38fd1498Szrj /* Perform optimizations on tree structure. 2*38fd1498Szrj Copyright (C) 1998-2018 Free Software Foundation, Inc. 3*38fd1498Szrj Written by Mark Michell (mark@codesourcery.com). 4*38fd1498Szrj 5*38fd1498Szrj This file is part of GCC. 6*38fd1498Szrj 7*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it 8*38fd1498Szrj under the terms of the GNU General Public License as published by 9*38fd1498Szrj the Free Software Foundation; either version 3, or (at your option) 10*38fd1498Szrj any later version. 11*38fd1498Szrj 12*38fd1498Szrj GCC is distributed in the hope that it will be useful, but 13*38fd1498Szrj WITHOUT ANY WARRANTY; without even the implied warranty of 14*38fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15*38fd1498Szrj General Public License for more details. 16*38fd1498Szrj 17*38fd1498Szrj You should have received a copy of the GNU General Public License 18*38fd1498Szrj along with GCC; see the file COPYING3. If not see 19*38fd1498Szrj <http://www.gnu.org/licenses/>. */ 20*38fd1498Szrj 21*38fd1498Szrj #include "config.h" 22*38fd1498Szrj #include "system.h" 23*38fd1498Szrj #include "coretypes.h" 24*38fd1498Szrj #include "target.h" 25*38fd1498Szrj #include "cp-tree.h" 26*38fd1498Szrj #include "stringpool.h" 27*38fd1498Szrj #include "cgraph.h" 28*38fd1498Szrj #include "debug.h" 29*38fd1498Szrj #include "tree-inline.h" 30*38fd1498Szrj #include "tree-iterator.h" 31*38fd1498Szrj 32*38fd1498Szrj /* Prototypes. */ 33*38fd1498Szrj 34*38fd1498Szrj static void update_cloned_parm (tree, tree, bool); 35*38fd1498Szrj 36*38fd1498Szrj /* CLONED_PARM is a copy of CLONE, generated for a cloned constructor 37*38fd1498Szrj or destructor. Update it to ensure that the source-position for 38*38fd1498Szrj the cloned parameter matches that for the original, and that the 39*38fd1498Szrj debugging generation code will be able to find the original PARM. */ 40*38fd1498Szrj 41*38fd1498Szrj static void 42*38fd1498Szrj update_cloned_parm (tree parm, tree cloned_parm, bool first) 43*38fd1498Szrj { 44*38fd1498Szrj DECL_ABSTRACT_ORIGIN (cloned_parm) = parm; 45*38fd1498Szrj 46*38fd1498Szrj /* We may have taken its address. */ 47*38fd1498Szrj TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm); 48*38fd1498Szrj 49*38fd1498Szrj /* The definition might have different constness. */ 50*38fd1498Szrj TREE_READONLY (cloned_parm) = TREE_READONLY (parm); 51*38fd1498Szrj 52*38fd1498Szrj TREE_USED (cloned_parm) = !first || TREE_USED (parm); 53*38fd1498Szrj 54*38fd1498Szrj /* The name may have changed from the declaration. */ 55*38fd1498Szrj DECL_NAME (cloned_parm) = DECL_NAME (parm); 56*38fd1498Szrj DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm); 57*38fd1498Szrj TREE_TYPE (cloned_parm) = TREE_TYPE (parm); 58*38fd1498Szrj 59*38fd1498Szrj DECL_GIMPLE_REG_P (cloned_parm) = DECL_GIMPLE_REG_P (parm); 60*38fd1498Szrj } 61*38fd1498Szrj 62*38fd1498Szrj 63*38fd1498Szrj /* FN is a function in High GIMPLE form that has a complete body and no 64*38fd1498Szrj CFG. CLONE is a function whose body is to be set to a copy of FN, 65*38fd1498Szrj mapping argument declarations according to the ARG_MAP splay_tree. */ 66*38fd1498Szrj 67*38fd1498Szrj static void 68*38fd1498Szrj clone_body (tree clone, tree fn, void *arg_map) 69*38fd1498Szrj { 70*38fd1498Szrj copy_body_data id; 71*38fd1498Szrj tree stmts; 72*38fd1498Szrj 73*38fd1498Szrj /* Clone the body, as if we were making an inline call. But, remap 74*38fd1498Szrj the parameters in the callee to the parameters of caller. */ 75*38fd1498Szrj memset (&id, 0, sizeof (id)); 76*38fd1498Szrj id.src_fn = fn; 77*38fd1498Szrj id.dst_fn = clone; 78*38fd1498Szrj id.src_cfun = DECL_STRUCT_FUNCTION (fn); 79*38fd1498Szrj id.decl_map = static_cast<hash_map<tree, tree> *> (arg_map); 80*38fd1498Szrj 81*38fd1498Szrj id.copy_decl = copy_decl_no_change; 82*38fd1498Szrj id.transform_call_graph_edges = CB_CGE_DUPLICATE; 83*38fd1498Szrj id.transform_new_cfg = true; 84*38fd1498Szrj id.transform_return_to_modify = false; 85*38fd1498Szrj id.transform_lang_insert_block = NULL; 86*38fd1498Szrj 87*38fd1498Szrj /* We're not inside any EH region. */ 88*38fd1498Szrj id.eh_lp_nr = 0; 89*38fd1498Szrj 90*38fd1498Szrj stmts = DECL_SAVED_TREE (fn); 91*38fd1498Szrj walk_tree (&stmts, copy_tree_body_r, &id, NULL); 92*38fd1498Szrj 93*38fd1498Szrj /* Also remap the initializer of any static variables so that they (in 94*38fd1498Szrj particular, any label addresses) correspond to the base variant rather 95*38fd1498Szrj than the abstract one. */ 96*38fd1498Szrj if (DECL_NAME (clone) == base_dtor_identifier 97*38fd1498Szrj || DECL_NAME (clone) == base_ctor_identifier) 98*38fd1498Szrj { 99*38fd1498Szrj unsigned ix; 100*38fd1498Szrj tree decl; 101*38fd1498Szrj 102*38fd1498Szrj FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (fn), ix, decl) 103*38fd1498Szrj walk_tree (&DECL_INITIAL (decl), copy_tree_body_r, &id, NULL); 104*38fd1498Szrj } 105*38fd1498Szrj 106*38fd1498Szrj append_to_statement_list_force (stmts, &DECL_SAVED_TREE (clone)); 107*38fd1498Szrj } 108*38fd1498Szrj 109*38fd1498Szrj /* DELETE_DTOR is a delete destructor whose body will be built. 110*38fd1498Szrj COMPLETE_DTOR is the corresponding complete destructor. */ 111*38fd1498Szrj 112*38fd1498Szrj static void 113*38fd1498Szrj build_delete_destructor_body (tree delete_dtor, tree complete_dtor) 114*38fd1498Szrj { 115*38fd1498Szrj tree parm = DECL_ARGUMENTS (delete_dtor); 116*38fd1498Szrj tree virtual_size = cxx_sizeof (current_class_type); 117*38fd1498Szrj 118*38fd1498Szrj /* Call the corresponding complete destructor. */ 119*38fd1498Szrj gcc_assert (complete_dtor); 120*38fd1498Szrj tree call_dtor = build_cxx_call (complete_dtor, 1, &parm, 121*38fd1498Szrj tf_warning_or_error); 122*38fd1498Szrj 123*38fd1498Szrj /* Call the delete function. */ 124*38fd1498Szrj tree call_delete = build_op_delete_call (DELETE_EXPR, current_class_ptr, 125*38fd1498Szrj virtual_size, 126*38fd1498Szrj /*global_p=*/false, 127*38fd1498Szrj /*placement=*/NULL_TREE, 128*38fd1498Szrj /*alloc_fn=*/NULL_TREE, 129*38fd1498Szrj tf_warning_or_error); 130*38fd1498Szrj 131*38fd1498Szrj /* Operator delete must be called, whether or not the dtor throws. */ 132*38fd1498Szrj add_stmt (build2 (TRY_FINALLY_EXPR, void_type_node, call_dtor, call_delete)); 133*38fd1498Szrj 134*38fd1498Szrj /* Return the address of the object. */ 135*38fd1498Szrj if (targetm.cxx.cdtor_returns_this ()) 136*38fd1498Szrj { 137*38fd1498Szrj tree val = DECL_ARGUMENTS (delete_dtor); 138*38fd1498Szrj val = build2 (MODIFY_EXPR, TREE_TYPE (val), 139*38fd1498Szrj DECL_RESULT (delete_dtor), val); 140*38fd1498Szrj add_stmt (build_stmt (0, RETURN_EXPR, val)); 141*38fd1498Szrj } 142*38fd1498Szrj } 143*38fd1498Szrj 144*38fd1498Szrj /* Return name of comdat group for complete and base ctor (or dtor) 145*38fd1498Szrj that have the same body. If dtor is virtual, deleting dtor goes 146*38fd1498Szrj into this comdat group as well. */ 147*38fd1498Szrj 148*38fd1498Szrj static tree 149*38fd1498Szrj cdtor_comdat_group (tree complete, tree base) 150*38fd1498Szrj { 151*38fd1498Szrj tree complete_name = DECL_ASSEMBLER_NAME (complete); 152*38fd1498Szrj tree base_name = DECL_ASSEMBLER_NAME (base); 153*38fd1498Szrj char *grp_name; 154*38fd1498Szrj const char *p, *q; 155*38fd1498Szrj bool diff_seen = false; 156*38fd1498Szrj size_t idx; 157*38fd1498Szrj gcc_assert (IDENTIFIER_LENGTH (complete_name) 158*38fd1498Szrj == IDENTIFIER_LENGTH (base_name)); 159*38fd1498Szrj grp_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name) + 1); 160*38fd1498Szrj p = IDENTIFIER_POINTER (complete_name); 161*38fd1498Szrj q = IDENTIFIER_POINTER (base_name); 162*38fd1498Szrj for (idx = 0; idx < IDENTIFIER_LENGTH (complete_name); idx++) 163*38fd1498Szrj if (p[idx] == q[idx]) 164*38fd1498Szrj grp_name[idx] = p[idx]; 165*38fd1498Szrj else 166*38fd1498Szrj { 167*38fd1498Szrj gcc_assert (!diff_seen 168*38fd1498Szrj && idx > 0 169*38fd1498Szrj && (p[idx - 1] == 'C' || p[idx - 1] == 'D' 170*38fd1498Szrj || p[idx - 1] == 'I') 171*38fd1498Szrj && p[idx] == '1' 172*38fd1498Szrj && q[idx] == '2'); 173*38fd1498Szrj grp_name[idx] = '5'; 174*38fd1498Szrj diff_seen = true; 175*38fd1498Szrj } 176*38fd1498Szrj grp_name[idx] = '\0'; 177*38fd1498Szrj gcc_assert (diff_seen); 178*38fd1498Szrj return get_identifier (grp_name); 179*38fd1498Szrj } 180*38fd1498Szrj 181*38fd1498Szrj /* Returns true iff we can make the base and complete [cd]tor aliases of 182*38fd1498Szrj the same symbol rather than separate functions. */ 183*38fd1498Szrj 184*38fd1498Szrj static bool 185*38fd1498Szrj can_alias_cdtor (tree fn) 186*38fd1498Szrj { 187*38fd1498Szrj /* If aliases aren't supported by the assembler, fail. */ 188*38fd1498Szrj if (!TARGET_SUPPORTS_ALIASES) 189*38fd1498Szrj return false; 190*38fd1498Szrj 191*38fd1498Szrj /* We can't use an alias if there are virtual bases. */ 192*38fd1498Szrj if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn))) 193*38fd1498Szrj return false; 194*38fd1498Szrj /* ??? Why not use aliases with -frepo? */ 195*38fd1498Szrj if (flag_use_repository) 196*38fd1498Szrj return false; 197*38fd1498Szrj gcc_assert (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn) 198*38fd1498Szrj || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)); 199*38fd1498Szrj /* Don't use aliases for weak/linkonce definitions unless we can put both 200*38fd1498Szrj symbols in the same COMDAT group. */ 201*38fd1498Szrj return (DECL_INTERFACE_KNOWN (fn) 202*38fd1498Szrj && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fn)) 203*38fd1498Szrj && (!DECL_ONE_ONLY (fn) 204*38fd1498Szrj || (HAVE_COMDAT_GROUP && DECL_WEAK (fn)))); 205*38fd1498Szrj } 206*38fd1498Szrj 207*38fd1498Szrj /* FN is a [cd]tor, fns is a pointer to an array of length 3. Fill fns 208*38fd1498Szrj with pointers to the base, complete, and deleting variants. */ 209*38fd1498Szrj 210*38fd1498Szrj static void 211*38fd1498Szrj populate_clone_array (tree fn, tree *fns) 212*38fd1498Szrj { 213*38fd1498Szrj tree clone; 214*38fd1498Szrj 215*38fd1498Szrj fns[0] = NULL_TREE; 216*38fd1498Szrj fns[1] = NULL_TREE; 217*38fd1498Szrj fns[2] = NULL_TREE; 218*38fd1498Szrj 219*38fd1498Szrj /* Look for the complete destructor which may be used to build the 220*38fd1498Szrj delete destructor. */ 221*38fd1498Szrj FOR_EACH_CLONE (clone, fn) 222*38fd1498Szrj if (DECL_NAME (clone) == complete_dtor_identifier 223*38fd1498Szrj || DECL_NAME (clone) == complete_ctor_identifier) 224*38fd1498Szrj fns[1] = clone; 225*38fd1498Szrj else if (DECL_NAME (clone) == base_dtor_identifier 226*38fd1498Szrj || DECL_NAME (clone) == base_ctor_identifier) 227*38fd1498Szrj fns[0] = clone; 228*38fd1498Szrj else if (DECL_NAME (clone) == deleting_dtor_identifier) 229*38fd1498Szrj fns[2] = clone; 230*38fd1498Szrj else 231*38fd1498Szrj gcc_unreachable (); 232*38fd1498Szrj } 233*38fd1498Szrj 234*38fd1498Szrj /* FN is a constructor or destructor, and there are FUNCTION_DECLs 235*38fd1498Szrj cloned from it nearby. Instead of cloning this body, leave it 236*38fd1498Szrj alone and create tiny one-call bodies for the cloned 237*38fd1498Szrj FUNCTION_DECLs. These clones are sibcall candidates, and their 238*38fd1498Szrj resulting code will be very thunk-esque. */ 239*38fd1498Szrj 240*38fd1498Szrj static bool 241*38fd1498Szrj maybe_thunk_body (tree fn, bool force) 242*38fd1498Szrj { 243*38fd1498Szrj tree bind, block, call, clone, clone_result, fn_parm, fn_parm_typelist; 244*38fd1498Szrj tree last_arg, modify, *args; 245*38fd1498Szrj int parmno, vtt_parmno, max_parms; 246*38fd1498Szrj tree fns[3]; 247*38fd1498Szrj 248*38fd1498Szrj if (!force && !flag_declone_ctor_dtor) 249*38fd1498Szrj return 0; 250*38fd1498Szrj 251*38fd1498Szrj /* If function accepts variable arguments, give up. */ 252*38fd1498Szrj last_arg = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fn))); 253*38fd1498Szrj if (last_arg != void_list_node) 254*38fd1498Szrj return 0; 255*38fd1498Szrj 256*38fd1498Szrj /* If we got this far, we've decided to turn the clones into thunks. */ 257*38fd1498Szrj 258*38fd1498Szrj /* We're going to generate code for fn, so it is no longer "abstract." 259*38fd1498Szrj Also make the unified ctor/dtor private to either the translation unit 260*38fd1498Szrj (for non-vague linkage ctors) or the COMDAT group (otherwise). */ 261*38fd1498Szrj 262*38fd1498Szrj populate_clone_array (fn, fns); 263*38fd1498Szrj 264*38fd1498Szrj /* Can happen during error recovery (c++/71464). */ 265*38fd1498Szrj if (!fns[0] || !fns[1]) 266*38fd1498Szrj return 0; 267*38fd1498Szrj 268*38fd1498Szrj /* Don't use thunks if the base clone omits inherited parameters. */ 269*38fd1498Szrj if (ctor_omit_inherited_parms (fns[0])) 270*38fd1498Szrj return 0; 271*38fd1498Szrj 272*38fd1498Szrj DECL_ABSTRACT_P (fn) = false; 273*38fd1498Szrj if (!DECL_WEAK (fn)) 274*38fd1498Szrj { 275*38fd1498Szrj TREE_PUBLIC (fn) = false; 276*38fd1498Szrj DECL_EXTERNAL (fn) = false; 277*38fd1498Szrj DECL_INTERFACE_KNOWN (fn) = true; 278*38fd1498Szrj } 279*38fd1498Szrj else if (HAVE_COMDAT_GROUP) 280*38fd1498Szrj { 281*38fd1498Szrj /* At eof, defer creation of mangling aliases temporarily. */ 282*38fd1498Szrj bool save_defer_mangling_aliases = defer_mangling_aliases; 283*38fd1498Szrj defer_mangling_aliases = true; 284*38fd1498Szrj tree comdat_group = cdtor_comdat_group (fns[1], fns[0]); 285*38fd1498Szrj defer_mangling_aliases = save_defer_mangling_aliases; 286*38fd1498Szrj cgraph_node::get_create (fns[0])->set_comdat_group (comdat_group); 287*38fd1498Szrj cgraph_node::get_create (fns[1])->add_to_same_comdat_group 288*38fd1498Szrj (cgraph_node::get_create (fns[0])); 289*38fd1498Szrj symtab_node::get (fn)->add_to_same_comdat_group 290*38fd1498Szrj (symtab_node::get (fns[0])); 291*38fd1498Szrj if (fns[2]) 292*38fd1498Szrj /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is 293*38fd1498Szrj virtual, it goes into the same comdat group as well. */ 294*38fd1498Szrj cgraph_node::get_create (fns[2])->add_to_same_comdat_group 295*38fd1498Szrj (symtab_node::get (fns[0])); 296*38fd1498Szrj /* Emit them now that the thunks are same comdat group aliases. */ 297*38fd1498Szrj if (!save_defer_mangling_aliases) 298*38fd1498Szrj generate_mangling_aliases (); 299*38fd1498Szrj TREE_PUBLIC (fn) = false; 300*38fd1498Szrj DECL_EXTERNAL (fn) = false; 301*38fd1498Szrj DECL_INTERFACE_KNOWN (fn) = true; 302*38fd1498Szrj /* function_and_variable_visibility doesn't want !PUBLIC decls to 303*38fd1498Szrj have these flags set. */ 304*38fd1498Szrj DECL_WEAK (fn) = false; 305*38fd1498Szrj DECL_COMDAT (fn) = false; 306*38fd1498Szrj } 307*38fd1498Szrj 308*38fd1498Szrj /* Find the vtt_parm, if present. */ 309*38fd1498Szrj for (vtt_parmno = -1, parmno = 0, fn_parm = DECL_ARGUMENTS (fn); 310*38fd1498Szrj fn_parm; 311*38fd1498Szrj ++parmno, fn_parm = TREE_CHAIN (fn_parm)) 312*38fd1498Szrj { 313*38fd1498Szrj if (DECL_ARTIFICIAL (fn_parm) 314*38fd1498Szrj && DECL_NAME (fn_parm) == vtt_parm_identifier) 315*38fd1498Szrj { 316*38fd1498Szrj /* Compensate for removed in_charge parameter. */ 317*38fd1498Szrj vtt_parmno = parmno; 318*38fd1498Szrj break; 319*38fd1498Szrj } 320*38fd1498Szrj } 321*38fd1498Szrj 322*38fd1498Szrj /* Allocate an argument buffer for build_cxx_call(). 323*38fd1498Szrj Make sure it is large enough for any of the clones. */ 324*38fd1498Szrj max_parms = 0; 325*38fd1498Szrj FOR_EACH_CLONE (clone, fn) 326*38fd1498Szrj { 327*38fd1498Szrj int length = list_length (DECL_ARGUMENTS (fn)); 328*38fd1498Szrj if (length > max_parms) 329*38fd1498Szrj max_parms = length; 330*38fd1498Szrj } 331*38fd1498Szrj args = XALLOCAVEC (tree, max_parms); 332*38fd1498Szrj 333*38fd1498Szrj /* We know that any clones immediately follow FN in TYPE_FIELDS. */ 334*38fd1498Szrj FOR_EACH_CLONE (clone, fn) 335*38fd1498Szrj { 336*38fd1498Szrj tree clone_parm; 337*38fd1498Szrj 338*38fd1498Szrj /* If we've already generated a body for this clone, avoid 339*38fd1498Szrj duplicating it. (Is it possible for a clone-list to grow after we 340*38fd1498Szrj first see it?) */ 341*38fd1498Szrj if (DECL_SAVED_TREE (clone) || TREE_ASM_WRITTEN (clone)) 342*38fd1498Szrj continue; 343*38fd1498Szrj 344*38fd1498Szrj /* Start processing the function. */ 345*38fd1498Szrj start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED); 346*38fd1498Szrj 347*38fd1498Szrj if (clone == fns[2]) 348*38fd1498Szrj { 349*38fd1498Szrj for (clone_parm = DECL_ARGUMENTS (clone); clone_parm; 350*38fd1498Szrj clone_parm = TREE_CHAIN (clone_parm)) 351*38fd1498Szrj DECL_ABSTRACT_ORIGIN (clone_parm) = NULL_TREE; 352*38fd1498Szrj /* Build the delete destructor by calling complete destructor and 353*38fd1498Szrj delete function. */ 354*38fd1498Szrj build_delete_destructor_body (clone, fns[1]); 355*38fd1498Szrj } 356*38fd1498Szrj else 357*38fd1498Szrj { 358*38fd1498Szrj /* Walk parameter lists together, creating parameter list for 359*38fd1498Szrj call to original function. */ 360*38fd1498Szrj for (parmno = 0, 361*38fd1498Szrj fn_parm = DECL_ARGUMENTS (fn), 362*38fd1498Szrj fn_parm_typelist = TYPE_ARG_TYPES (TREE_TYPE (fn)), 363*38fd1498Szrj clone_parm = DECL_ARGUMENTS (clone); 364*38fd1498Szrj fn_parm; 365*38fd1498Szrj ++parmno, 366*38fd1498Szrj fn_parm = TREE_CHAIN (fn_parm)) 367*38fd1498Szrj { 368*38fd1498Szrj if (parmno == vtt_parmno && ! DECL_HAS_VTT_PARM_P (clone)) 369*38fd1498Szrj { 370*38fd1498Szrj gcc_assert (fn_parm_typelist); 371*38fd1498Szrj /* Clobber argument with formal parameter type. */ 372*38fd1498Szrj args[parmno] 373*38fd1498Szrj = convert (TREE_VALUE (fn_parm_typelist), 374*38fd1498Szrj null_pointer_node); 375*38fd1498Szrj } 376*38fd1498Szrj else if (parmno == 1 && DECL_HAS_IN_CHARGE_PARM_P (fn)) 377*38fd1498Szrj { 378*38fd1498Szrj tree in_charge 379*38fd1498Szrj = copy_node (in_charge_arg_for_name (DECL_NAME (clone))); 380*38fd1498Szrj args[parmno] = in_charge; 381*38fd1498Szrj } 382*38fd1498Szrj /* Map other parameters to their equivalents in the cloned 383*38fd1498Szrj function. */ 384*38fd1498Szrj else 385*38fd1498Szrj { 386*38fd1498Szrj gcc_assert (clone_parm); 387*38fd1498Szrj DECL_ABSTRACT_ORIGIN (clone_parm) = NULL; 388*38fd1498Szrj args[parmno] = clone_parm; 389*38fd1498Szrj clone_parm = TREE_CHAIN (clone_parm); 390*38fd1498Szrj } 391*38fd1498Szrj if (fn_parm_typelist) 392*38fd1498Szrj fn_parm_typelist = TREE_CHAIN (fn_parm_typelist); 393*38fd1498Szrj } 394*38fd1498Szrj 395*38fd1498Szrj /* We built this list backwards; fix now. */ 396*38fd1498Szrj mark_used (fn); 397*38fd1498Szrj call = build_cxx_call (fn, parmno, args, tf_warning_or_error); 398*38fd1498Szrj /* Arguments passed to the thunk by invisible reference should 399*38fd1498Szrj be transmitted to the callee unchanged. Do not create a 400*38fd1498Szrj temporary and invoke the copy constructor. The thunking 401*38fd1498Szrj transformation must not introduce any constructor calls. */ 402*38fd1498Szrj CALL_FROM_THUNK_P (call) = 1; 403*38fd1498Szrj block = make_node (BLOCK); 404*38fd1498Szrj if (targetm.cxx.cdtor_returns_this ()) 405*38fd1498Szrj { 406*38fd1498Szrj clone_result = DECL_RESULT (clone); 407*38fd1498Szrj modify = build2 (MODIFY_EXPR, TREE_TYPE (clone_result), 408*38fd1498Szrj clone_result, call); 409*38fd1498Szrj modify = build1 (RETURN_EXPR, void_type_node, modify); 410*38fd1498Szrj add_stmt (modify); 411*38fd1498Szrj } 412*38fd1498Szrj else 413*38fd1498Szrj { 414*38fd1498Szrj add_stmt (call); 415*38fd1498Szrj } 416*38fd1498Szrj bind = c_build_bind_expr (DECL_SOURCE_LOCATION (clone), 417*38fd1498Szrj block, cur_stmt_list); 418*38fd1498Szrj DECL_SAVED_TREE (clone) = push_stmt_list (); 419*38fd1498Szrj add_stmt (bind); 420*38fd1498Szrj } 421*38fd1498Szrj 422*38fd1498Szrj DECL_ABSTRACT_ORIGIN (clone) = NULL; 423*38fd1498Szrj expand_or_defer_fn (finish_function (/*inline_p=*/false)); 424*38fd1498Szrj } 425*38fd1498Szrj return 1; 426*38fd1498Szrj } 427*38fd1498Szrj 428*38fd1498Szrj /* FN is a function that has a complete body. Clone the body as 429*38fd1498Szrj necessary. Returns nonzero if there's no longer any need to 430*38fd1498Szrj process the main body. */ 431*38fd1498Szrj 432*38fd1498Szrj bool 433*38fd1498Szrj maybe_clone_body (tree fn) 434*38fd1498Szrj { 435*38fd1498Szrj tree comdat_group = NULL_TREE; 436*38fd1498Szrj tree clone; 437*38fd1498Szrj tree fns[3]; 438*38fd1498Szrj bool first = true; 439*38fd1498Szrj int idx; 440*38fd1498Szrj bool need_alias = false; 441*38fd1498Szrj 442*38fd1498Szrj /* We only clone constructors and destructors. */ 443*38fd1498Szrj if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn) 444*38fd1498Szrj && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)) 445*38fd1498Szrj return 0; 446*38fd1498Szrj 447*38fd1498Szrj populate_clone_array (fn, fns); 448*38fd1498Szrj 449*38fd1498Szrj /* Remember if we can't have multiple clones for some reason. We need to 450*38fd1498Szrj check this before we remap local static initializers in clone_body. */ 451*38fd1498Szrj if (!tree_versionable_function_p (fn)) 452*38fd1498Szrj need_alias = true; 453*38fd1498Szrj 454*38fd1498Szrj /* We know that any clones immediately follow FN in the TYPE_FIELDS 455*38fd1498Szrj list. */ 456*38fd1498Szrj push_to_top_level (); 457*38fd1498Szrj for (idx = 0; idx < 3; idx++) 458*38fd1498Szrj { 459*38fd1498Szrj tree parm; 460*38fd1498Szrj tree clone_parm; 461*38fd1498Szrj 462*38fd1498Szrj clone = fns[idx]; 463*38fd1498Szrj if (!clone) 464*38fd1498Szrj continue; 465*38fd1498Szrj 466*38fd1498Szrj /* Update CLONE's source position information to match FN's. */ 467*38fd1498Szrj DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn); 468*38fd1498Szrj DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn); 469*38fd1498Szrj DECL_DECLARED_CONSTEXPR_P (clone) = DECL_DECLARED_CONSTEXPR_P (fn); 470*38fd1498Szrj DECL_COMDAT (clone) = DECL_COMDAT (fn); 471*38fd1498Szrj DECL_WEAK (clone) = DECL_WEAK (fn); 472*38fd1498Szrj 473*38fd1498Szrj /* We don't copy the comdat group from fn to clone because the assembler 474*38fd1498Szrj name of fn was corrupted by write_mangled_name by adding *INTERNAL* 475*38fd1498Szrj to it. By doing so, it also corrupted the comdat group. */ 476*38fd1498Szrj if (DECL_ONE_ONLY (fn)) 477*38fd1498Szrj cgraph_node::get_create (clone)->set_comdat_group (cxx_comdat_group (clone)); 478*38fd1498Szrj DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn); 479*38fd1498Szrj DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn); 480*38fd1498Szrj DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn); 481*38fd1498Szrj DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn); 482*38fd1498Szrj TREE_PUBLIC (clone) = TREE_PUBLIC (fn); 483*38fd1498Szrj DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn); 484*38fd1498Szrj DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn); 485*38fd1498Szrj DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn); 486*38fd1498Szrj DECL_ATTRIBUTES (clone) = copy_list (DECL_ATTRIBUTES (fn)); 487*38fd1498Szrj DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn); 488*38fd1498Szrj set_decl_section_name (clone, DECL_SECTION_NAME (fn)); 489*38fd1498Szrj 490*38fd1498Szrj /* Adjust the parameter names and locations. */ 491*38fd1498Szrj parm = DECL_ARGUMENTS (fn); 492*38fd1498Szrj clone_parm = DECL_ARGUMENTS (clone); 493*38fd1498Szrj /* Update the `this' parameter, which is always first. */ 494*38fd1498Szrj update_cloned_parm (parm, clone_parm, first); 495*38fd1498Szrj parm = DECL_CHAIN (parm); 496*38fd1498Szrj clone_parm = DECL_CHAIN (clone_parm); 497*38fd1498Szrj if (DECL_HAS_IN_CHARGE_PARM_P (fn)) 498*38fd1498Szrj parm = DECL_CHAIN (parm); 499*38fd1498Szrj if (DECL_HAS_VTT_PARM_P (fn)) 500*38fd1498Szrj parm = DECL_CHAIN (parm); 501*38fd1498Szrj if (DECL_HAS_VTT_PARM_P (clone)) 502*38fd1498Szrj clone_parm = DECL_CHAIN (clone_parm); 503*38fd1498Szrj for (; parm && clone_parm; 504*38fd1498Szrj parm = DECL_CHAIN (parm), clone_parm = DECL_CHAIN (clone_parm)) 505*38fd1498Szrj /* Update this parameter. */ 506*38fd1498Szrj update_cloned_parm (parm, clone_parm, first); 507*38fd1498Szrj } 508*38fd1498Szrj 509*38fd1498Szrj bool can_alias = can_alias_cdtor (fn); 510*38fd1498Szrj 511*38fd1498Szrj /* If we decide to turn clones into thunks, they will branch to fn. 512*38fd1498Szrj Must have original function available to call. */ 513*38fd1498Szrj if (!can_alias && maybe_thunk_body (fn, need_alias)) 514*38fd1498Szrj { 515*38fd1498Szrj pop_from_top_level (); 516*38fd1498Szrj /* We still need to emit the original function. */ 517*38fd1498Szrj return 0; 518*38fd1498Szrj } 519*38fd1498Szrj 520*38fd1498Szrj /* Emit the DWARF1 abstract instance. */ 521*38fd1498Szrj (*debug_hooks->deferred_inline_function) (fn); 522*38fd1498Szrj 523*38fd1498Szrj /* We know that any clones immediately follow FN in the TYPE_FIELDS. */ 524*38fd1498Szrj for (idx = 0; idx < 3; idx++) 525*38fd1498Szrj { 526*38fd1498Szrj tree parm; 527*38fd1498Szrj tree clone_parm; 528*38fd1498Szrj int parmno; 529*38fd1498Szrj hash_map<tree, tree> *decl_map; 530*38fd1498Szrj bool alias = false; 531*38fd1498Szrj 532*38fd1498Szrj clone = fns[idx]; 533*38fd1498Szrj if (!clone) 534*38fd1498Szrj continue; 535*38fd1498Szrj 536*38fd1498Szrj /* Start processing the function. */ 537*38fd1498Szrj start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED); 538*38fd1498Szrj 539*38fd1498Szrj /* Tell cgraph if both ctors or both dtors are known to have 540*38fd1498Szrj the same body. */ 541*38fd1498Szrj if (can_alias 542*38fd1498Szrj && fns[0] 543*38fd1498Szrj && idx == 1 544*38fd1498Szrj && cgraph_node::get_create (fns[0])->create_same_body_alias 545*38fd1498Szrj (clone, fns[0])) 546*38fd1498Szrj { 547*38fd1498Szrj alias = true; 548*38fd1498Szrj if (DECL_ONE_ONLY (fns[0])) 549*38fd1498Szrj { 550*38fd1498Szrj /* For comdat base and complete cdtors put them 551*38fd1498Szrj into the same, *[CD]5* comdat group instead of 552*38fd1498Szrj *[CD][12]*. */ 553*38fd1498Szrj comdat_group = cdtor_comdat_group (fns[1], fns[0]); 554*38fd1498Szrj cgraph_node::get_create (fns[0])->set_comdat_group (comdat_group); 555*38fd1498Szrj if (symtab_node::get (clone)->same_comdat_group) 556*38fd1498Szrj symtab_node::get (clone)->remove_from_same_comdat_group (); 557*38fd1498Szrj symtab_node::get (clone)->add_to_same_comdat_group 558*38fd1498Szrj (symtab_node::get (fns[0])); 559*38fd1498Szrj } 560*38fd1498Szrj } 561*38fd1498Szrj 562*38fd1498Szrj /* Build the delete destructor by calling complete destructor 563*38fd1498Szrj and delete function. */ 564*38fd1498Szrj if (idx == 2) 565*38fd1498Szrj { 566*38fd1498Szrj build_delete_destructor_body (clone, fns[1]); 567*38fd1498Szrj /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is 568*38fd1498Szrj virtual, it goes into the same comdat group as well. */ 569*38fd1498Szrj if (comdat_group) 570*38fd1498Szrj cgraph_node::get_create (clone)->add_to_same_comdat_group 571*38fd1498Szrj (symtab_node::get (fns[0])); 572*38fd1498Szrj } 573*38fd1498Szrj else if (alias) 574*38fd1498Szrj /* No need to populate body. */ ; 575*38fd1498Szrj else 576*38fd1498Szrj { 577*38fd1498Szrj /* If we can't have multiple copies of FN (say, because there's a 578*38fd1498Szrj static local initialized with the address of a label), we need 579*38fd1498Szrj to use an alias for the complete variant. */ 580*38fd1498Szrj if (idx == 1 && need_alias) 581*38fd1498Szrj { 582*38fd1498Szrj if (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_set) 583*38fd1498Szrj sorry (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_reason, fn); 584*38fd1498Szrj else 585*38fd1498Szrj sorry ("making multiple clones of %qD", fn); 586*38fd1498Szrj } 587*38fd1498Szrj 588*38fd1498Szrj /* Remap the parameters. */ 589*38fd1498Szrj decl_map = new hash_map<tree, tree>; 590*38fd1498Szrj for (parmno = 0, 591*38fd1498Szrj parm = DECL_ARGUMENTS (fn), 592*38fd1498Szrj clone_parm = DECL_ARGUMENTS (clone); 593*38fd1498Szrj parm; 594*38fd1498Szrj ++parmno, 595*38fd1498Szrj parm = DECL_CHAIN (parm)) 596*38fd1498Szrj { 597*38fd1498Szrj /* Map the in-charge parameter to an appropriate constant. */ 598*38fd1498Szrj if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1) 599*38fd1498Szrj { 600*38fd1498Szrj tree in_charge; 601*38fd1498Szrj in_charge = in_charge_arg_for_name (DECL_NAME (clone)); 602*38fd1498Szrj decl_map->put (parm, in_charge); 603*38fd1498Szrj } 604*38fd1498Szrj else if (DECL_ARTIFICIAL (parm) 605*38fd1498Szrj && DECL_NAME (parm) == vtt_parm_identifier) 606*38fd1498Szrj { 607*38fd1498Szrj /* For a subobject constructor or destructor, the next 608*38fd1498Szrj argument is the VTT parameter. Remap the VTT_PARM 609*38fd1498Szrj from the CLONE to this parameter. */ 610*38fd1498Szrj if (DECL_HAS_VTT_PARM_P (clone)) 611*38fd1498Szrj { 612*38fd1498Szrj DECL_ABSTRACT_ORIGIN (clone_parm) = parm; 613*38fd1498Szrj decl_map->put (parm, clone_parm); 614*38fd1498Szrj clone_parm = DECL_CHAIN (clone_parm); 615*38fd1498Szrj } 616*38fd1498Szrj /* Otherwise, map the VTT parameter to `NULL'. */ 617*38fd1498Szrj else 618*38fd1498Szrj { 619*38fd1498Szrj tree t 620*38fd1498Szrj = fold_convert (TREE_TYPE (parm), null_pointer_node); 621*38fd1498Szrj decl_map->put (parm, t); 622*38fd1498Szrj } 623*38fd1498Szrj } 624*38fd1498Szrj /* Map other parameters to their equivalents in the cloned 625*38fd1498Szrj function. */ 626*38fd1498Szrj else 627*38fd1498Szrj { 628*38fd1498Szrj tree replacement; 629*38fd1498Szrj if (clone_parm) 630*38fd1498Szrj { 631*38fd1498Szrj replacement = clone_parm; 632*38fd1498Szrj clone_parm = DECL_CHAIN (clone_parm); 633*38fd1498Szrj } 634*38fd1498Szrj else 635*38fd1498Szrj { 636*38fd1498Szrj /* Inheriting ctors can omit parameters from the base 637*38fd1498Szrj clone. Replace them with null lvalues. */ 638*38fd1498Szrj tree reftype = build_reference_type (TREE_TYPE (parm)); 639*38fd1498Szrj replacement = fold_convert (reftype, null_pointer_node); 640*38fd1498Szrj replacement = convert_from_reference (replacement); 641*38fd1498Szrj } 642*38fd1498Szrj decl_map->put (parm, replacement); 643*38fd1498Szrj } 644*38fd1498Szrj } 645*38fd1498Szrj 646*38fd1498Szrj if (targetm.cxx.cdtor_returns_this ()) 647*38fd1498Szrj { 648*38fd1498Szrj parm = DECL_RESULT (fn); 649*38fd1498Szrj clone_parm = DECL_RESULT (clone); 650*38fd1498Szrj decl_map->put (parm, clone_parm); 651*38fd1498Szrj } 652*38fd1498Szrj 653*38fd1498Szrj /* Clone the body. */ 654*38fd1498Szrj clone_body (clone, fn, decl_map); 655*38fd1498Szrj 656*38fd1498Szrj /* Clean up. */ 657*38fd1498Szrj delete decl_map; 658*38fd1498Szrj } 659*38fd1498Szrj 660*38fd1498Szrj /* The clone can throw iff the original function can throw. */ 661*38fd1498Szrj cp_function_chain->can_throw = !TREE_NOTHROW (fn); 662*38fd1498Szrj 663*38fd1498Szrj /* Now, expand this function into RTL, if appropriate. */ 664*38fd1498Szrj finish_function (/*inline_p=*/false); 665*38fd1498Szrj BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn); 666*38fd1498Szrj if (alias) 667*38fd1498Szrj { 668*38fd1498Szrj if (expand_or_defer_fn_1 (clone)) 669*38fd1498Szrj emit_associated_thunks (clone); 670*38fd1498Szrj /* We didn't generate a body, so remove the empty one. */ 671*38fd1498Szrj DECL_SAVED_TREE (clone) = NULL_TREE; 672*38fd1498Szrj } 673*38fd1498Szrj else 674*38fd1498Szrj expand_or_defer_fn (clone); 675*38fd1498Szrj first = false; 676*38fd1498Szrj } 677*38fd1498Szrj pop_from_top_level (); 678*38fd1498Szrj 679*38fd1498Szrj /* We don't need to process the original function any further. */ 680*38fd1498Szrj return 1; 681*38fd1498Szrj } 682