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