190075Sobrien/* Perform optimizations on tree structure. 2169689Skan Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 3132718Skan Free Software Foundation, Inc. 490075Sobrien Written by Mark Michell (mark@codesourcery.com). 590075Sobrien 6132718SkanThis file is part of GCC. 790075Sobrien 8132718SkanGCC is free software; you can redistribute it and/or modify it 990075Sobrienunder the terms of the GNU General Public License as published by 1090075Sobrienthe Free Software Foundation; either version 2, or (at your option) 1190075Sobrienany later version. 1290075Sobrien 13132718SkanGCC is distributed in the hope that it will be useful, but 1490075SobrienWITHOUT ANY WARRANTY; without even the implied warranty of 1590075SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1690075SobrienGeneral Public License for more details. 1790075Sobrien 1890075SobrienYou should have received a copy of the GNU General Public License 19132718Skanalong with GCC; see the file COPYING. If not, write to the Free 20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21169689Skan02110-1301, USA. */ 2290075Sobrien 2390075Sobrien#include "config.h" 2490075Sobrien#include "system.h" 25132718Skan#include "coretypes.h" 26132718Skan#include "tm.h" 2790075Sobrien#include "tree.h" 2890075Sobrien#include "cp-tree.h" 2990075Sobrien#include "rtl.h" 3090075Sobrien#include "insn-config.h" 3190075Sobrien#include "input.h" 3290075Sobrien#include "integrate.h" 3390075Sobrien#include "toplev.h" 3490075Sobrien#include "varray.h" 3590075Sobrien#include "params.h" 3690075Sobrien#include "hashtab.h" 37169689Skan#include "target.h" 3890075Sobrien#include "debug.h" 3990075Sobrien#include "tree-inline.h" 40169689Skan#include "flags.h" 41169689Skan#include "langhooks.h" 42169689Skan#include "diagnostic.h" 43169689Skan#include "tree-dump.h" 44169689Skan#include "tree-gimple.h" 4590075Sobrien 4690075Sobrien/* Prototypes. */ 4790075Sobrien 48169689Skanstatic void update_cloned_parm (tree, tree, bool); 4990075Sobrien 5090075Sobrien/* CLONED_PARM is a copy of CLONE, generated for a cloned constructor 5190075Sobrien or destructor. Update it to ensure that the source-position for 5290075Sobrien the cloned parameter matches that for the original, and that the 5390075Sobrien debugging generation code will be able to find the original PARM. */ 5490075Sobrien 5590075Sobrienstatic void 56169689Skanupdate_cloned_parm (tree parm, tree cloned_parm, bool first) 5790075Sobrien{ 5890075Sobrien DECL_ABSTRACT_ORIGIN (cloned_parm) = parm; 5990075Sobrien 60117395Skan /* We may have taken its address. */ 6190075Sobrien TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm); 6290075Sobrien 63117395Skan /* The definition might have different constness. */ 6490075Sobrien TREE_READONLY (cloned_parm) = TREE_READONLY (parm); 65169689Skan 66169689Skan TREE_USED (cloned_parm) = !first || TREE_USED (parm); 67169689Skan 68117395Skan /* The name may have changed from the declaration. */ 6990075Sobrien DECL_NAME (cloned_parm) = DECL_NAME (parm); 70117395Skan DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm); 71169689Skan TREE_TYPE (cloned_parm) = TREE_TYPE (parm); 72169689Skan 73169689Skan DECL_COMPLEX_GIMPLE_REG_P (cloned_parm) = DECL_COMPLEX_GIMPLE_REG_P (parm); 7490075Sobrien} 7590075Sobrien 7690075Sobrien/* FN is a function that has a complete body. Clone the body as 77117395Skan necessary. Returns nonzero if there's no longer any need to 7890075Sobrien process the main body. */ 7990075Sobrien 80132718Skanbool 81132718Skanmaybe_clone_body (tree fn) 8290075Sobrien{ 8390075Sobrien tree clone; 84169689Skan bool first = true; 8590075Sobrien 8690075Sobrien /* We only clone constructors and destructors. */ 8790075Sobrien if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn) 8890075Sobrien && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)) 8990075Sobrien return 0; 9090075Sobrien 9190075Sobrien /* Emit the DWARF1 abstract instance. */ 9290075Sobrien (*debug_hooks->deferred_inline_function) (fn); 9390075Sobrien 9490075Sobrien /* We know that any clones immediately follow FN in the TYPE_METHODS 9590075Sobrien list. */ 96169689Skan push_to_top_level (); 97169689Skan FOR_EACH_CLONE (clone, fn) 9890075Sobrien { 9990075Sobrien tree parm; 10090075Sobrien tree clone_parm; 10190075Sobrien int parmno; 10290075Sobrien splay_tree decl_map; 10390075Sobrien 10490075Sobrien /* Update CLONE's source position information to match FN's. */ 105117395Skan DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn); 10690075Sobrien DECL_INLINE (clone) = DECL_INLINE (fn); 10790075Sobrien DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn); 10890075Sobrien DECL_COMDAT (clone) = DECL_COMDAT (fn); 10990075Sobrien DECL_WEAK (clone) = DECL_WEAK (fn); 11090075Sobrien DECL_ONE_ONLY (clone) = DECL_ONE_ONLY (fn); 11190075Sobrien DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn); 11290075Sobrien DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn); 11390075Sobrien DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn); 11490075Sobrien DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn); 11590075Sobrien DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn); 11690075Sobrien TREE_PUBLIC (clone) = TREE_PUBLIC (fn); 117132718Skan DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn); 118169689Skan DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn); 11990075Sobrien 120117395Skan /* Adjust the parameter names and locations. */ 12190075Sobrien parm = DECL_ARGUMENTS (fn); 12290075Sobrien clone_parm = DECL_ARGUMENTS (clone); 12390075Sobrien /* Update the `this' parameter, which is always first. */ 124169689Skan update_cloned_parm (parm, clone_parm, first); 12590075Sobrien parm = TREE_CHAIN (parm); 12690075Sobrien clone_parm = TREE_CHAIN (clone_parm); 12790075Sobrien if (DECL_HAS_IN_CHARGE_PARM_P (fn)) 12890075Sobrien parm = TREE_CHAIN (parm); 12990075Sobrien if (DECL_HAS_VTT_PARM_P (fn)) 13090075Sobrien parm = TREE_CHAIN (parm); 13190075Sobrien if (DECL_HAS_VTT_PARM_P (clone)) 13290075Sobrien clone_parm = TREE_CHAIN (clone_parm); 13390075Sobrien for (; parm; 13490075Sobrien parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm)) 135132718Skan /* Update this parameter. */ 136169689Skan update_cloned_parm (parm, clone_parm, first); 13790075Sobrien 13890075Sobrien /* Start processing the function. */ 139169689Skan start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED); 14090075Sobrien 14190075Sobrien /* Remap the parameters. */ 14290075Sobrien decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL); 14390075Sobrien for (parmno = 0, 14490075Sobrien parm = DECL_ARGUMENTS (fn), 14590075Sobrien clone_parm = DECL_ARGUMENTS (clone); 14690075Sobrien parm; 14790075Sobrien ++parmno, 14890075Sobrien parm = TREE_CHAIN (parm)) 14990075Sobrien { 15090075Sobrien /* Map the in-charge parameter to an appropriate constant. */ 15190075Sobrien if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1) 15290075Sobrien { 15390075Sobrien tree in_charge; 15490075Sobrien in_charge = in_charge_arg_for_name (DECL_NAME (clone)); 15590075Sobrien splay_tree_insert (decl_map, 15690075Sobrien (splay_tree_key) parm, 15790075Sobrien (splay_tree_value) in_charge); 15890075Sobrien } 15990075Sobrien else if (DECL_ARTIFICIAL (parm) 16090075Sobrien && DECL_NAME (parm) == vtt_parm_identifier) 16190075Sobrien { 16290075Sobrien /* For a subobject constructor or destructor, the next 16390075Sobrien argument is the VTT parameter. Remap the VTT_PARM 16490075Sobrien from the CLONE to this parameter. */ 16590075Sobrien if (DECL_HAS_VTT_PARM_P (clone)) 16690075Sobrien { 16790075Sobrien DECL_ABSTRACT_ORIGIN (clone_parm) = parm; 16890075Sobrien splay_tree_insert (decl_map, 16990075Sobrien (splay_tree_key) parm, 17090075Sobrien (splay_tree_value) clone_parm); 17190075Sobrien clone_parm = TREE_CHAIN (clone_parm); 17290075Sobrien } 17390075Sobrien /* Otherwise, map the VTT parameter to `NULL'. */ 17490075Sobrien else 17590075Sobrien { 17690075Sobrien splay_tree_insert (decl_map, 17790075Sobrien (splay_tree_key) parm, 17890075Sobrien (splay_tree_value) null_pointer_node); 17990075Sobrien } 18090075Sobrien } 18190075Sobrien /* Map other parameters to their equivalents in the cloned 18290075Sobrien function. */ 18390075Sobrien else 18490075Sobrien { 18590075Sobrien splay_tree_insert (decl_map, 18690075Sobrien (splay_tree_key) parm, 18790075Sobrien (splay_tree_value) clone_parm); 18890075Sobrien clone_parm = TREE_CHAIN (clone_parm); 18990075Sobrien } 19090075Sobrien } 19190075Sobrien 192169689Skan if (targetm.cxx.cdtor_returns_this ()) 193169689Skan { 194169689Skan parm = DECL_RESULT (fn); 195169689Skan clone_parm = DECL_RESULT (clone); 196169689Skan splay_tree_insert (decl_map, (splay_tree_key) parm, 197169689Skan (splay_tree_value) clone_parm); 198169689Skan } 19990075Sobrien /* Clone the body. */ 20090075Sobrien clone_body (clone, fn, decl_map); 20190075Sobrien 20290075Sobrien /* Clean up. */ 20390075Sobrien splay_tree_delete (decl_map); 20490075Sobrien 205117395Skan /* The clone can throw iff the original function can throw. */ 206117395Skan cp_function_chain->can_throw = !TREE_NOTHROW (fn); 207117395Skan 20890075Sobrien /* Now, expand this function into RTL, if appropriate. */ 20990075Sobrien finish_function (0); 21090075Sobrien BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn); 211132718Skan expand_or_defer_fn (clone); 212169689Skan first = false; 21390075Sobrien } 214169689Skan pop_from_top_level (); 21590075Sobrien 21690075Sobrien /* We don't need to process the original function any further. */ 21790075Sobrien return 1; 21890075Sobrien} 219