optimize.c revision 256281
1/* Perform optimizations on tree structure. 2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 3 Free Software Foundation, Inc. 4 Written by Mark Michell (mark@codesourcery.com). 5 6This file is part of GCC. 7 8GCC is free software; you can redistribute it and/or modify it 9under the terms of the GNU General Public License as published by 10the Free Software Foundation; either version 2, or (at your option) 11any later version. 12 13GCC is distributed in the hope that it will be useful, but 14WITHOUT ANY WARRANTY; without even the implied warranty of 15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16General Public License for more details. 17 18You should have received a copy of the GNU General Public License 19along with GCC; see the file COPYING. If not, write to the Free 20Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 2102110-1301, USA. */ 22 23#include "config.h" 24#include "system.h" 25#include "coretypes.h" 26#include "tm.h" 27#include "tree.h" 28#include "cp-tree.h" 29#include "rtl.h" 30#include "insn-config.h" 31#include "input.h" 32#include "integrate.h" 33#include "toplev.h" 34#include "varray.h" 35#include "params.h" 36#include "hashtab.h" 37#include "target.h" 38#include "debug.h" 39#include "tree-inline.h" 40#include "flags.h" 41#include "langhooks.h" 42#include "diagnostic.h" 43#include "tree-dump.h" 44#include "tree-gimple.h" 45 46/* Prototypes. */ 47 48static void update_cloned_parm (tree, tree, bool); 49 50/* CLONED_PARM is a copy of CLONE, generated for a cloned constructor 51 or destructor. Update it to ensure that the source-position for 52 the cloned parameter matches that for the original, and that the 53 debugging generation code will be able to find the original PARM. */ 54 55static void 56update_cloned_parm (tree parm, tree cloned_parm, bool first) 57{ 58 DECL_ABSTRACT_ORIGIN (cloned_parm) = parm; 59 60 /* We may have taken its address. */ 61 TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm); 62 63 /* The definition might have different constness. */ 64 TREE_READONLY (cloned_parm) = TREE_READONLY (parm); 65 66 TREE_USED (cloned_parm) = !first || TREE_USED (parm); 67 68 /* The name may have changed from the declaration. */ 69 DECL_NAME (cloned_parm) = DECL_NAME (parm); 70 DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm); 71 TREE_TYPE (cloned_parm) = TREE_TYPE (parm); 72 73 DECL_COMPLEX_GIMPLE_REG_P (cloned_parm) = DECL_COMPLEX_GIMPLE_REG_P (parm); 74} 75 76/* FN is a function that has a complete body. Clone the body as 77 necessary. Returns nonzero if there's no longer any need to 78 process the main body. */ 79 80bool 81maybe_clone_body (tree fn) 82{ 83 tree clone; 84 bool first = true; 85 86 /* We only clone constructors and destructors. */ 87 if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn) 88 && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)) 89 return 0; 90 91 /* Emit the DWARF1 abstract instance. */ 92 (*debug_hooks->deferred_inline_function) (fn); 93 94 /* We know that any clones immediately follow FN in the TYPE_METHODS 95 list. */ 96 push_to_top_level (); 97 FOR_EACH_CLONE (clone, fn) 98 { 99 tree parm; 100 tree clone_parm; 101 int parmno; 102 splay_tree decl_map; 103 104 /* Update CLONE's source position information to match FN's. */ 105 DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn); 106 DECL_INLINE (clone) = DECL_INLINE (fn); 107 DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn); 108 DECL_COMDAT (clone) = DECL_COMDAT (fn); 109 DECL_WEAK (clone) = DECL_WEAK (fn); 110 DECL_ONE_ONLY (clone) = DECL_ONE_ONLY (fn); 111 DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn); 112 DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn); 113 DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn); 114 DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn); 115 DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn); 116 TREE_PUBLIC (clone) = TREE_PUBLIC (fn); 117 DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn); 118 DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn); 119 120 /* Adjust the parameter names and locations. */ 121 parm = DECL_ARGUMENTS (fn); 122 clone_parm = DECL_ARGUMENTS (clone); 123 /* Update the `this' parameter, which is always first. */ 124 update_cloned_parm (parm, clone_parm, first); 125 parm = TREE_CHAIN (parm); 126 clone_parm = TREE_CHAIN (clone_parm); 127 if (DECL_HAS_IN_CHARGE_PARM_P (fn)) 128 parm = TREE_CHAIN (parm); 129 if (DECL_HAS_VTT_PARM_P (fn)) 130 parm = TREE_CHAIN (parm); 131 if (DECL_HAS_VTT_PARM_P (clone)) 132 clone_parm = TREE_CHAIN (clone_parm); 133 for (; parm; 134 parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm)) 135 /* Update this parameter. */ 136 update_cloned_parm (parm, clone_parm, first); 137 138 /* Start processing the function. */ 139 start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED); 140 141 /* Remap the parameters. */ 142 decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL); 143 for (parmno = 0, 144 parm = DECL_ARGUMENTS (fn), 145 clone_parm = DECL_ARGUMENTS (clone); 146 parm; 147 ++parmno, 148 parm = TREE_CHAIN (parm)) 149 { 150 /* Map the in-charge parameter to an appropriate constant. */ 151 if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1) 152 { 153 tree in_charge; 154 in_charge = in_charge_arg_for_name (DECL_NAME (clone)); 155 splay_tree_insert (decl_map, 156 (splay_tree_key) parm, 157 (splay_tree_value) in_charge); 158 } 159 else if (DECL_ARTIFICIAL (parm) 160 && DECL_NAME (parm) == vtt_parm_identifier) 161 { 162 /* For a subobject constructor or destructor, the next 163 argument is the VTT parameter. Remap the VTT_PARM 164 from the CLONE to this parameter. */ 165 if (DECL_HAS_VTT_PARM_P (clone)) 166 { 167 DECL_ABSTRACT_ORIGIN (clone_parm) = parm; 168 splay_tree_insert (decl_map, 169 (splay_tree_key) parm, 170 (splay_tree_value) clone_parm); 171 clone_parm = TREE_CHAIN (clone_parm); 172 } 173 /* Otherwise, map the VTT parameter to `NULL'. */ 174 else 175 { 176 splay_tree_insert (decl_map, 177 (splay_tree_key) parm, 178 (splay_tree_value) null_pointer_node); 179 } 180 } 181 /* Map other parameters to their equivalents in the cloned 182 function. */ 183 else 184 { 185 splay_tree_insert (decl_map, 186 (splay_tree_key) parm, 187 (splay_tree_value) clone_parm); 188 clone_parm = TREE_CHAIN (clone_parm); 189 } 190 } 191 192 if (targetm.cxx.cdtor_returns_this ()) 193 { 194 parm = DECL_RESULT (fn); 195 clone_parm = DECL_RESULT (clone); 196 splay_tree_insert (decl_map, (splay_tree_key) parm, 197 (splay_tree_value) clone_parm); 198 } 199 /* Clone the body. */ 200 clone_body (clone, fn, decl_map); 201 202 /* Clean up. */ 203 splay_tree_delete (decl_map); 204 205 /* The clone can throw iff the original function can throw. */ 206 cp_function_chain->can_throw = !TREE_NOTHROW (fn); 207 208 /* Now, expand this function into RTL, if appropriate. */ 209 finish_function (0); 210 BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn); 211 expand_or_defer_fn (clone); 212 first = false; 213 } 214 pop_from_top_level (); 215 216 /* We don't need to process the original function any further. */ 217 return 1; 218} 219