* Make-lang.in (cp/decl.o, cp/tree.o): Depend on tree-inline.h.
authoraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 5 Oct 2001 02:48:47 +0000 (02:48 +0000)
committeraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 5 Oct 2001 02:48:47 +0000 (02:48 +0000)
(cp/pt.o, cp/semantics.o, cp/optimize.o): Likewise.
* cp-tree.h (lang_decl): Moved inlined_fns to tree_decl.
(TREE_READONLY_DECL_P, DECL_INLINED_FNS): Moved to ../tree.h.
(flag_inline_trees): Moved declaration to ../tree-inline.h.
(walk_tree): Moved declaration to ../tree-inline.h.
(walk_tree_without_duplicates, copy_tree_r): Likewise.
(remap_save_expr): Likewise.
* decl.c: Include tree-inline.h.
(lang_mark_tree): Don't mark inlined_fns.
* decl2.c (flag_inline_trees): Moved defn to ../tree-inline.c.
* optimize.c: Include tree-inline.h.
(optimize_inline_calls): Move declaration to ../tree.h, as
non-static.
(remap_decl): Use language-independent constructs and hooks.
(remap_block, copy_body_r, declare_return_variable): Likewise.
(inlinable_function_p): Likewise.  Don't test for
DECL_LANG_SPECIFIC before DECL_INLINED_FNS as inlined_fns is
no longer language-specific.
(optimize_inline_calls): Likewise.  Make it non-static.  Moved
call of dump_function to...
(optimize_function): Here...
(clone_body): New function, extracted from...
(maybe_clone_body): ... here.  Build decl_map locally and pass
it on to clone_body.
* pt.c, semantics.c: Include tree-inline.h.
* tree.c: Likewise.
(cp_walk_subtrees): New language-specific hook for tree inlining.
(cp_cannot_inline_tree_fn, cp_add_pending_fn_decls,
cp_is_overload_p, cp_auto_var_in_fn_p,
cp_copy_res_decl_for_inlining): Likewise.
(walk_tree): Move language-specific constructs into...
(cp_walk_subtrees): this new function.
(copy_tree_r): Use language-independent constructs and hooks.
(init_tree): Initialize tree inlining hooks.
(remap_save_expr): Adjust prototype so that the declaration
does not require the definition of splay_tree.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@46020 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/optimize.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/tree.c

index c23768e..2926e12 100644 (file)
@@ -1,3 +1,43 @@
+2001-10-04  Alexandre Oliva  <aoliva@redhat.com>
+
+       * Make-lang.in (cp/decl.o, cp/tree.o): Depend on tree-inline.h.
+       (cp/pt.o, cp/semantics.o, cp/optimize.o): Likewise.
+       * cp-tree.h (lang_decl): Moved inlined_fns to tree_decl.
+       (TREE_READONLY_DECL_P, DECL_INLINED_FNS): Moved to ../tree.h.
+       (flag_inline_trees): Moved declaration to ../tree-inline.h.
+       (walk_tree): Moved declaration to ../tree-inline.h.
+       (walk_tree_without_duplicates, copy_tree_r): Likewise.
+       (remap_save_expr): Likewise.
+       * decl.c: Include tree-inline.h.
+       (lang_mark_tree): Don't mark inlined_fns.
+       * decl2.c (flag_inline_trees): Moved defn to ../tree-inline.c.
+       * optimize.c: Include tree-inline.h.
+       (optimize_inline_calls): Move declaration to ../tree.h, as
+       non-static.
+       (remap_decl): Use language-independent constructs and hooks.
+       (remap_block, copy_body_r, declare_return_variable): Likewise.
+       (inlinable_function_p): Likewise.  Don't test for
+       DECL_LANG_SPECIFIC before DECL_INLINED_FNS as inlined_fns is
+       no longer language-specific.
+       (optimize_inline_calls): Likewise.  Make it non-static.  Moved
+       call of dump_function to...
+       (optimize_function): Here...
+       (clone_body): New function, extracted from...
+       (maybe_clone_body): ... here.  Build decl_map locally and pass
+       it on to clone_body.
+       * pt.c, semantics.c: Include tree-inline.h.
+       * tree.c: Likewise.
+       (cp_walk_subtrees): New language-specific hook for tree inlining.
+       (cp_cannot_inline_tree_fn, cp_add_pending_fn_decls,
+       cp_is_overload_p, cp_auto_var_in_fn_p,
+       cp_copy_res_decl_for_inlining): Likewise.
+       (walk_tree): Move language-specific constructs into...
+       (cp_walk_subtrees): this new function.
+       (copy_tree_r): Use language-independent constructs and hooks.
+       (init_tree): Initialize tree inlining hooks.
+       (remap_save_expr): Adjust prototype so that the declaration
+       does not require the definition of splay_tree.
+
 2001-10-03  John David Anglin  <dave@hiauly1.hia.nrc.ca>
 
        * rtti.c (get_tinfo_decl): Call typeinfo_in_lib_p with the type used
index 4fe7e87..65a1606 100644 (file)
@@ -243,7 +243,7 @@ cp/lex.o: cp/lex.c $(CXX_TREE_H) cp/parse.h flags.h cp/lex.h c-pragma.h \
   $(TM_P_H)
 cp/decl.o: cp/decl.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h stack.h \
   output.h $(EXPR_H) except.h toplev.h hash.h $(GGC_H) $(RTL_H) \
-  cp/operators.def $(TM_P_H)
+  cp/operators.def $(TM_P_H) tree-inline.h
 cp/decl2.o: cp/decl2.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \
   output.h except.h toplev.h $(GGC_H) $(RTL_H)
 cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) flags.h toplev.h output.h $(TM_P_H) \
@@ -261,7 +261,7 @@ cp/method.o: cp/method.c $(CXX_TREE_H) toplev.h $(GGC_H) $(RTL_H) $(EXPR_H) \
 cp/cvt.o: cp/cvt.c $(CXX_TREE_H) cp/decl.h flags.h toplev.h convert.h
 cp/search.o: cp/search.c $(CXX_TREE_H) stack.h flags.h toplev.h $(RTL_H)
 cp/tree.o: cp/tree.c $(CXX_TREE_H) flags.h toplev.h $(GGC_H) $(RTL_H) \
-  insn-config.h integrate.h
+  insn-config.h integrate.h tree-inline.h
 cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(SYSTEM_H)
 cp/rtti.o: cp/rtti.c $(CXX_TREE_H) flags.h toplev.h
 cp/except.o: cp/except.c $(CXX_TREE_H) flags.h $(RTL_H) except.h toplev.h \
@@ -270,14 +270,15 @@ cp/expr.o: cp/expr.c $(CXX_TREE_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \
   except.h $(TM_P_H)
 cp/xref.o: cp/xref.c $(CXX_TREE_H) input.h toplev.h
 cp/pt.o: cp/pt.c $(CXX_TREE_H) cp/decl.h cp/parse.h cp/lex.h toplev.h \
-  $(GGC_H) $(RTL_H) except.h
+  $(GGC_H) $(RTL_H) except.h tree-inline.h
 cp/error.o: cp/error.c $(CXX_TREE_H) toplev.h diagnostic.h flags.h real.h
 cp/repo.o: cp/repo.c $(CXX_TREE_H) toplev.h $(GGC_H) diagnostic.h
 cp/semantics.o: cp/semantics.c $(CXX_TREE_H) cp/lex.h except.h toplev.h \
-  flags.h $(GGC_H) debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H)
+  flags.h $(GGC_H) debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \
+  tree-inline.h
 cp/dump.o: cp/dump.c $(CXX_TREE_H) c-dump.h
 cp/optimize.o: cp/optimize.c $(CXX_TREE_H) rtl.h integrate.h insn-config.h \
-  input.h $(PARAMS_H) debug.h
+  input.h $(PARAMS_H) debug.h tree-inline.h
 cp/mangle.o: cp/mangle.c $(CXX_TREE_H) toplev.h
 
 cp/parse.o: cp/parse.c $(CXX_TREE_H) flags.h cp/lex.h except.h output.h \
index b4fc016..98e747d 100644 (file)
@@ -1758,10 +1758,6 @@ struct lang_decl
   /* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION.  */
   tree cloned_function;
 
-  /* In a FUNCTION_DECL, these are function data which is to be kept
-     as long as FUNCTION_DECL is kept.  */
-  tree inlined_fns;
-
   union
   {
     tree sorted_fields;
@@ -1778,10 +1774,6 @@ struct lang_decl
 
 #define DEFARG_POINTER(NODE) (DEFAULT_ARG_CHECK(NODE)->identifier.id.str)
 
-/* Non-zero if NODE is a _DECL with TREE_READONLY set.  */
-#define TREE_READONLY_DECL_P(NODE) \
-  (TREE_READONLY (NODE) && DECL_P (NODE))
-
 /* DECL_NEEDED_P holds of a declaration when we need to emit its
    definition.  This is true when the back-end tells us that
    the symbol has been referenced in the generated code.  If, however,
@@ -1888,10 +1880,6 @@ struct lang_decl
 #define DECL_CLONED_FUNCTION(NODE) \
   (DECL_LANG_SPECIFIC (NODE)->cloned_function)
 
-/* List of FUNCION_DECLs inlined into this function's body.  */
-#define DECL_INLINED_FNS(NODE) \
-  (DECL_LANG_SPECIFIC (NODE)->inlined_fns)
-
 /* Nonzero if NODE has DECL_DISCRIMINATOR and not DECL_ACCESS.  */
 #define DECL_DISCRIMINATOR_P(NODE)     \
   (TREE_CODE (NODE) == VAR_DECL                \
@@ -3262,13 +3250,6 @@ extern int flag_implicit_templates;
 
 extern int flag_weak;
 
-/* 0 if we should not perform inlining.
-   1 if we should expand functions calls inline at the tree level.  
-   2 if we should consider *all* functions to be inline 
-   candidates.  */
-
-extern int flag_inline_trees;
-
 /* Nonzero if we're done parsing and into end-of-file activities.  */
 
 extern int at_eof;
@@ -4197,18 +4178,9 @@ extern void debug_binfo                          PARAMS ((tree));
 extern tree build_dummy_object                 PARAMS ((tree));
 extern tree maybe_dummy_object                 PARAMS ((tree, tree *));
 extern int is_dummy_object                     PARAMS ((tree));
-extern tree walk_tree                           PARAMS ((tree *,
-                                                        walk_tree_fn,
-                                                        void *,
-                                                        htab_t));
-extern tree walk_tree_without_duplicates        PARAMS ((tree *,
-                                                        walk_tree_fn,
-                                                        void *));
-extern tree copy_tree_r                         PARAMS ((tree *, int *, void *));
 extern const struct attribute_spec cp_attribute_table[];
 extern tree make_ptrmem_cst                     PARAMS ((tree, tree));
 extern tree cp_build_qualified_type_real        PARAMS ((tree, int, int));
-extern void remap_save_expr                     PARAMS ((tree *, splay_tree, tree, int *));
 #define cp_build_qualified_type(TYPE, QUALS) \
   cp_build_qualified_type_real ((TYPE), (QUALS), /*complain=*/1)
 extern tree build_shared_int_cst                PARAMS ((int));
index 905784e..0dfd8d6 100644 (file)
@@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA.  */
 #include "expr.h"
 #include "flags.h"
 #include "cp-tree.h"
+#include "tree-inline.h"
 #include "decl.h"
 #include "lex.h"
 #include "output.h"
@@ -14479,7 +14480,6 @@ lang_mark_tree (t)
              ggc_mark_tree (ld->befriending_classes);
              ggc_mark_tree (ld->context);
              ggc_mark_tree (ld->cloned_function);
-             ggc_mark_tree (ld->inlined_fns);
              if (TREE_CODE (t) == TYPE_DECL)
                ggc_mark_tree (ld->u.sorted_fields);
              else if (TREE_CODE (t) == FUNCTION_DECL
index ee8f379..0ab9299 100644 (file)
@@ -378,13 +378,6 @@ int flag_weak = 1;
 
 int flag_use_cxa_atexit;
 
-/* 0 if we should not perform inlining.
-   1 if we should expand functions calls inline at the tree level.  
-   2 if we should consider *all* functions to be inline 
-   candidates.  */
-
-int flag_inline_trees = 0;
-
 /* Maximum template instantiation depth.  This limit is rather
    arbitrary, but it exists to limit the time it takes to notice
    infinite template instantiations.  */
index 95d02b7..bbc555b 100644 (file)
@@ -33,6 +33,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "params.h"
 #include "hashtab.h"
 #include "debug.h"
+#include "tree-inline.h"
 
 /* To Do:
 
@@ -99,7 +100,6 @@ static int inlinable_function_p PARAMS ((tree, inline_data *));
 static tree remap_decl PARAMS ((tree, inline_data *));
 static void remap_block PARAMS ((tree, tree, inline_data *));
 static void copy_scope_stmt PARAMS ((tree *, int *, inline_data *));
-static void optimize_inline_calls PARAMS ((tree));
 static tree calls_setjmp_r PARAMS ((tree *, int *, void *));
 static void update_cloned_parm PARAMS ((tree, tree));
 static void dump_function PARAMS ((enum tree_dump_index, tree));
@@ -121,7 +121,7 @@ remap_decl (decl, id)
 
   /* We only remap local variables in the current function.  */
   fn = VARRAY_TOP_TREE (id->fns);
-  if (!nonstatic_local_decl_p (decl) || DECL_CONTEXT (decl) != fn)
+  if (! LANG_AUTO_VAR_IN_FN_P (decl, fn))
     return NULL_TREE;
 
   /* See if we have remapped this declaration.  */
@@ -151,8 +151,8 @@ remap_decl (decl, id)
                     copy_body_r, id, NULL);
        }
 
-      if (!DECL_NAME (t) && TREE_TYPE (t)
-         && ANON_AGGR_TYPE_P (TREE_TYPE ((t))))
+      if (! DECL_NAME (t) && TREE_TYPE (t)
+         && LANG_ANON_AGGR_TYPE_P (TREE_TYPE (t)))
        {
          /* For a VAR_DECL of anonymous type, we must also copy the
             member VAR_DECLS here and rechain the
@@ -165,7 +165,8 @@ remap_decl (decl, id)
            {
              tree member = remap_decl (TREE_VALUE (src), id);
 
-             my_friendly_assert (!TREE_PURPOSE (src), 20010529);
+             if (TREE_PURPOSE (src))
+               abort ();
              members = tree_cons (NULL, member, members);
            }
          DECL_ANON_UNION_ELEMS (t) = nreverse (members);
@@ -277,7 +278,8 @@ remap_block (scope_stmt, decls, id)
       /* Find this block in the table of remapped things.  */
       n = splay_tree_lookup (id->decl_map,
                             (splay_tree_key) SCOPE_STMT_BLOCK (scope_stmt));
-      my_friendly_assert (n != NULL, 19991203);
+      if (! n)
+       abort ();
       SCOPE_STMT_BLOCK (scope_stmt) = (tree) n->value;
     }
 }
@@ -322,12 +324,14 @@ copy_body_r (tp, walk_subtrees, data)
   id = (inline_data *) data;
   fn = VARRAY_TOP_TREE (id->fns);
 
+#if 0
   /* All automatic variables should have a DECL_CONTEXT indicating
      what function they come from.  */
   if ((TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == LABEL_DECL)
       && DECL_NAMESPACE_SCOPE_P (*tp))
-    my_friendly_assert (DECL_EXTERNAL (*tp) || TREE_STATIC (*tp),
-                       19991113);
+    if (! DECL_EXTERNAL (*tp) && ! TREE_STATIC (*tp))
+      abort ();
+#endif
 
   /* If this is a RETURN_STMT, change it into an EXPR_STMT and a
      GOTO_STMT with the RET_LABEL as its target.  */
@@ -359,26 +363,29 @@ copy_body_r (tp, walk_subtrees, data)
      variables.  We don't want to copy static variables; there's only
      one of those, no matter how many times we inline the containing
      function.  */
-  else if (nonstatic_local_decl_p (*tp) && DECL_CONTEXT (*tp) == fn)
+  else if (LANG_AUTO_VAR_IN_FN_P (*tp, fn))
     {
       tree new_decl;
 
       /* Remap the declaration.  */
       new_decl = remap_decl (*tp, id);
-      my_friendly_assert (new_decl != NULL_TREE, 19991203);
+      if (! new_decl)
+       abort ();
       /* Replace this variable with the copy.  */
       STRIP_TYPE_NOPS (new_decl);
       *tp = new_decl;
     }
+#if 0
   else if (nonstatic_local_decl_p (*tp)
           && DECL_CONTEXT (*tp) != VARRAY_TREE (id->fns, 0))
-    my_friendly_abort (0);
+    abort ();
+#endif
   else if (TREE_CODE (*tp) == SAVE_EXPR)
     remap_save_expr (tp, id->decl_map, VARRAY_TREE (id->fns, 0),
                     walk_subtrees);
   else if (TREE_CODE (*tp) == UNSAVE_EXPR)
     /* UNSAVE_EXPRs should not be generated until expansion time.  */
-    my_friendly_abort (19991113);
+    abort ();
   /* For a SCOPE_STMT, we must copy the associated block so that we
      can write out debugging information for the inlined variables.  */
   else if (TREE_CODE (*tp) == SCOPE_STMT && !id->in_target_cleanup_p)
@@ -398,8 +405,7 @@ copy_body_r (tp, walk_subtrees, data)
        }
       else if (TREE_CODE (*tp) == MODIFY_EXPR
               && TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1)
-              && nonstatic_local_decl_p (TREE_OPERAND (*tp, 0))
-              && DECL_CONTEXT (TREE_OPERAND (*tp, 0)) == fn)
+              && LANG_AUTO_VAR_IN_FN_P (TREE_OPERAND (*tp, 0), fn))
        {
          /* Some assignments VAR = VAR; don't generate any rtl code
             and thus don't count as variable modification.  Avoid
@@ -561,7 +567,7 @@ declare_return_variable (id, use_stmt)
   tree fn = VARRAY_TOP_TREE (id->fns);
   tree result = DECL_RESULT (fn);
   tree var;
-  int aggregate_return_p;
+  int need_return_decl = 1;
 
   /* We don't need to do anything for functions that don't return
      anything.  */
@@ -571,29 +577,9 @@ declare_return_variable (id, use_stmt)
       return NULL_TREE;
     }
 
-  /* Figure out whether or not FN returns an aggregate.  */
-  aggregate_return_p = IS_AGGR_TYPE (TREE_TYPE (result));
-
-  /* If FN returns an aggregate then the caller will always create the
-     temporary (using a TARGET_EXPR) and the call will be the
-     initializing expression for the TARGET_EXPR.  If we were just to
-     create a new VAR_DECL here, then the result of this function
-     would be copied (bitwise) into the variable initialized by the
-     TARGET_EXPR.  That's incorrect, so we must transform any
-     references to the RESULT into references to the target.  */
-  if (aggregate_return_p)
-    {
-      my_friendly_assert (VARRAY_ACTIVE_SIZE (id->target_exprs) != 0,
-                         20000430);
-      var = TREE_OPERAND (VARRAY_TOP_TREE (id->target_exprs), 0);
-      my_friendly_assert
-       (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var),
-                                                   TREE_TYPE (result)),
-        20000430);
-    }
-  /* Otherwise, make an appropriate copy.  */
-  else
-    var = copy_decl_for_inlining (result, fn, VARRAY_TREE (id->fns, 0));
+  var = LANG_COPY_RES_DECL_FOR_INLINING (result, fn, VARRAY_TREE (id->fns, 0),
+                                        id->decl_map, &need_return_decl,
+                                        &id->target_exprs);
 
   /* Register the VAR_DECL as the equivalent for the RESULT_DECL; that
      way, when the RESULT_DECL is encountered, it will be
@@ -602,29 +588,12 @@ declare_return_variable (id, use_stmt)
                     (splay_tree_key) result,
                     (splay_tree_value) var);
 
-  if (DECL_SAVED_FUNCTION_DATA (fn))
-    {
-      tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
-      if (nrv)
-       {
-         /* We have a named return value; copy the name and source
-            position so we can get reasonable debugging information, and
-            register the return variable as its equivalent.  */
-         DECL_NAME (var) = DECL_NAME (nrv);
-         DECL_SOURCE_FILE (var) = DECL_SOURCE_FILE (nrv);
-         DECL_SOURCE_LINE (var) = DECL_SOURCE_LINE (nrv);
-         splay_tree_insert (id->decl_map,
-                            (splay_tree_key) nrv,
-                            (splay_tree_value) var);
-       }
-    }
-
   /* Build the USE_STMT.  */
   *use_stmt = build_stmt (EXPR_STMT, var);
 
   /* Build the declaration statement if FN does not return an
      aggregate.  */
-  if (!aggregate_return_p)
+  if (need_return_decl)
     return build_stmt (DECL_STMT, var);
   /* If FN does return an aggregate, there's no need to declare the
      return variable; we're using a variable in our caller's frame.  */
@@ -656,12 +625,11 @@ inlinable_function_p (fn, id)
      it.  */
   else if (!DECL_INLINE (fn))
     ;
-  /* We can't inline varargs functions.  */
-  else if (varargs_function_p (fn))
-    ;
-  /* We can't inline functions that are too big.
-   * Only allow a single function to eat up half of our budget. */
-  else if (DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 2)
+  /* We can't inline functions that are too big.  Only allow a single
+     function to eat up half of our budget.  Make special allowance
+     for extern inline functions, though.  */
+  else if (! LANG_DISREGARD_INLINE_LIMITS (fn)
+          && DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 2)
     ;
   /* All is well.  We can inline this function.  Traditionally, GCC
      has refused to inline functions using alloca, or functions whose
@@ -675,27 +643,26 @@ inlinable_function_p (fn, id)
 
   /* Even if this function is not itself too big to inline, it might
      be that we've done so much inlining already that we don't want to
-     risk too much inlining any more and thus halve the acceptable size. */
-  if ((DECL_NUM_STMTS (fn) + id->inlined_stmts) * INSNS_PER_STMT
-      > MAX_INLINE_INSNS
+     risk too much inlining any more and thus halve the acceptable
+     size.  */
+  if (! LANG_DISREGARD_INLINE_LIMITS (fn)
+      && ((DECL_NUM_STMTS (fn) + id->inlined_stmts) * INSNS_PER_STMT
+         > MAX_INLINE_INSNS)
       && DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 4)
     inlinable = 0;
 
-  /* We can inline a template instantiation only if it's fully
-     instantiated.  */
-  if (inlinable
-      && DECL_TEMPLATE_INFO (fn)
-      && TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
-    {
-      fn = instantiate_decl (fn, /*defer_ok=*/0);
-      inlinable = !TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn));
-    }
-
+  if (inlinable && LANG_CANNOT_INLINE_TREE_FN (&fn))
+    inlinable = 0;
+  
   /* If we don't have the function body available, we can't inline
      it.  */
   if (!DECL_SAVED_TREE (fn))
     inlinable = 0;
 
+  /* Check again, language hooks may have modified it.  */
+  if (! inlinable || DECL_UNINLINABLE (fn))
+    return 0;
+
   /* Don't do recursive inlining, either.  We don't record this in
      DECL_UNINLINABLE; we may be able to inline this function later.  */
   if (inlinable)
@@ -706,7 +673,7 @@ inlinable_function_p (fn, id)
        if (VARRAY_TREE (id->fns, i) == fn)
          return 0;
 
-      if (inlinable && DECL_LANG_SPECIFIC (fn) && DECL_INLINED_FNS (fn))
+      if (inlinable && DECL_INLINED_FNS (fn))
        {
          int j;
          tree inlined_fns = DECL_INLINED_FNS (fn);
@@ -808,7 +775,7 @@ expand_call_inline (tp, walk_subtrees, data)
      for the return statements within the function to jump to.  The
      type of the statement expression is the return type of the
      function call.  */
-  expr = build_min (STMT_EXPR, TREE_TYPE (TREE_TYPE (fn)), NULL_TREE);
+  expr = build1 (STMT_EXPR, TREE_TYPE (TREE_TYPE (fn)), NULL_TREE);
 
   /* Local declarations will be replaced by their equivalents in this
      map.  */
@@ -832,7 +799,7 @@ expand_call_inline (tp, walk_subtrees, data)
 
   /* Record the function we are about to inline if optimize_function
      has not been called on it yet and we don't have it in the list.  */
-  if (DECL_LANG_SPECIFIC (fn) && !DECL_INLINED_FNS (fn))
+  if (DECL_INLINED_FNS (fn))
     {
       int i;
 
@@ -878,9 +845,9 @@ expand_call_inline (tp, walk_subtrees, data)
   /* Close the block for the parameters.  */
   scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn));
   SCOPE_NO_CLEANUPS_P (scope_stmt) = 1;
-  my_friendly_assert (DECL_INITIAL (fn)
-                     && TREE_CODE (DECL_INITIAL (fn)) == BLOCK,
-                     19991203);
+  if (! DECL_INITIAL (fn)
+      || TREE_CODE (DECL_INITIAL (fn)) != BLOCK)
+    abort ();
   remap_block (scope_stmt, NULL_TREE, id);
   STMT_EXPR_STMT (expr)
     = chainon (STMT_EXPR_STMT (expr), scope_stmt);
@@ -957,13 +924,12 @@ expand_calls_inline (tp, id)
 
 /* Expand calls to inline functions in the body of FN.  */
 
-static void
+void
 optimize_inline_calls (fn)
      tree fn;
 {
   inline_data id;
   tree prev_fn;
-  struct saved_scope *s;
   
   /* Clear out ID.  */
   memset (&id, 0, sizeof (id));
@@ -978,12 +944,8 @@ optimize_inline_calls (fn)
       VARRAY_PUSH_TREE (id.fns, current_function_decl);
       prev_fn = current_function_decl;
     }
-  for (s = scope_chain; s; s = s->prev)
-    if (s->function_decl && s->function_decl != prev_fn)
-      {
-       VARRAY_PUSH_TREE (id.fns, s->function_decl);
-       prev_fn = s->function_decl;
-      }
+
+  prev_fn = LANG_ADD_PENDING_FN_DECLS (&id.fns, prev_fn);
   
   /* Create the stack of TARGET_EXPRs.  */
   VARRAY_TREE_INIT (id.target_exprs, 32, "target_exprs");
@@ -1014,8 +976,6 @@ optimize_inline_calls (fn)
       DECL_INLINED_FNS (fn) = ifn;
     }
   VARRAY_FREE (id.inlined_fns);
-  
-  dump_function (TDI_inlined, fn);
 }
 
 /* Optimize the body of FN. */
@@ -1043,7 +1003,11 @@ optimize_function (fn)
          optimization, (c) virtual functions are rarely inlineable,
          and (d) ASM_OUTPUT_MI_THUNK is there to DTRT anyway.  */
       && !DECL_THUNK_P (fn))
-    optimize_inline_calls (fn);
+    {
+      optimize_inline_calls (fn);
+
+      dump_function (TDI_inlined, fn);
+    }
   
   /* Undo the call to ggc_push_context above.  */
   --function_depth;
@@ -1106,6 +1070,38 @@ update_cloned_parm (parm, cloned_parm)
   DECL_SOURCE_LINE (cloned_parm) = DECL_SOURCE_LINE (parm);
 }
 
+/* FN is a function that has a complete body, and CLONE is a function
+   whose body is to be set to a copy of FN, mapping argument
+   declarations according to the ARG_MAP splay_tree.  */
+
+void
+clone_body (clone, fn, arg_map)
+     tree clone, fn;
+     void *arg_map;
+{
+  inline_data id;
+
+  /* Clone the body, as if we were making an inline call.  But, remap
+     the parameters in the callee to the parameters of caller.  If
+     there's an in-charge parameter, map it to an appropriate
+     constant.  */
+  memset (&id, 0, sizeof (id));
+  VARRAY_TREE_INIT (id.fns, 2, "fns");
+  VARRAY_PUSH_TREE (id.fns, clone);
+  VARRAY_PUSH_TREE (id.fns, fn);
+  id.decl_map = (splay_tree)arg_map;
+
+  /* Cloning is treated slightly differently from inlining.  Set
+     CLONING_P so that it's clear which operation we're performing.  */
+  id.cloning_p = true;
+
+  /* Actually copy the body.  */
+  TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id);
+
+  /* Clean up.  */
+  VARRAY_FREE (id.fns);
+}
+
 /* FN is a function that has a complete body.  Clone the body as
    necessary.  Returns non-zero if there's no longer any need to
    process the main body.  */
@@ -1114,7 +1110,6 @@ int
 maybe_clone_body (fn)
      tree fn;
 {
-  inline_data id;
   tree clone;
   int first = 1;
 
@@ -1135,6 +1130,7 @@ maybe_clone_body (fn)
       tree parm;
       tree clone_parm;
       int parmno;
+      splay_tree decl_map;
 
       /* Update CLONE's source position information to match FN's.  */
       DECL_SOURCE_FILE (clone) = DECL_SOURCE_FILE (fn);
@@ -1178,22 +1174,8 @@ maybe_clone_body (fn)
       push_to_top_level ();
       start_function (NULL_TREE, clone, NULL_TREE, SF_PRE_PARSED);
 
-      /* Just clone the body, as if we were making an inline call.
-        But, remap the parameters in the callee to the parameters of
-        caller.  If there's an in-charge parameter, map it to an
-        appropriate constant.  */
-      memset (&id, 0, sizeof (id));
-      VARRAY_TREE_INIT (id.fns, 2, "fns");
-      VARRAY_PUSH_TREE (id.fns, clone);
-      VARRAY_PUSH_TREE (id.fns, fn);
-
-      /* Cloning is treated slightly differently from inlining.  Set
-        CLONING_P so that its clear which operation we're performing.  */
-      id.cloning_p = true;
-
       /* Remap the parameters.  */
-      id.decl_map = splay_tree_new (splay_tree_compare_pointers,
-                                   NULL, NULL);
+      decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
       for (parmno = 0,
             parm = DECL_ARGUMENTS (fn),
             clone_parm = DECL_ARGUMENTS (clone);
@@ -1206,7 +1188,7 @@ maybe_clone_body (fn)
            {
              tree in_charge;
              in_charge = in_charge_arg_for_name (DECL_NAME (clone));
-             splay_tree_insert (id.decl_map,
+             splay_tree_insert (decl_map,
                                 (splay_tree_key) parm,
                                 (splay_tree_value) in_charge);
            }
@@ -1219,7 +1201,7 @@ maybe_clone_body (fn)
              if (DECL_HAS_VTT_PARM_P (clone))
                {
                  DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
-                 splay_tree_insert (id.decl_map,
+                 splay_tree_insert (decl_map,
                                     (splay_tree_key) parm,
                                     (splay_tree_value) clone_parm);
                  clone_parm = TREE_CHAIN (clone_parm);
@@ -1227,7 +1209,7 @@ maybe_clone_body (fn)
              /* Otherwise, map the VTT parameter to `NULL'.  */
              else
                {
-                 splay_tree_insert (id.decl_map,
+                 splay_tree_insert (decl_map,
                                     (splay_tree_key) parm,
                                     (splay_tree_value) null_pointer_node);
                }
@@ -1236,23 +1218,22 @@ maybe_clone_body (fn)
             function.  */
          else
            {
-             splay_tree_insert (id.decl_map,
+             splay_tree_insert (decl_map,
                                 (splay_tree_key) parm,
                                 (splay_tree_value) clone_parm);
              clone_parm = TREE_CHAIN (clone_parm);
            }
        }
 
-      /* Actually copy the body.  */
-      TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id);
+      /* Clone the body.  */
+      clone_body (clone, fn, decl_map);
 
       /* There are as many statements in the clone as in the
         original.  */
       DECL_NUM_STMTS (clone) = DECL_NUM_STMTS (fn);
 
       /* Clean up.  */
-      splay_tree_delete (id.decl_map);
-      VARRAY_FREE (id.fns);
+      splay_tree_delete (decl_map);
 
       /* Now, expand this function into RTL, if appropriate.  */
       finish_function (0);
index 292513f..e29a738 100644 (file)
@@ -29,10 +29,10 @@ Boston, MA 02111-1307, USA.  */
 #include "config.h"
 #include "system.h"
 #include "obstack.h"
-
 #include "tree.h"
 #include "flags.h"
 #include "cp-tree.h"
+#include "tree-inline.h"
 #include "decl.h"
 #include "parse.h"
 #include "lex.h"
index 6564f8e..ec7b968 100644 (file)
@@ -28,6 +28,7 @@
 #include "system.h"
 #include "tree.h"
 #include "cp-tree.h"
+#include "tree-inline.h"
 #include "except.h"
 #include "lex.h"
 #include "toplev.h"
index 32783ad..ec51eaa 100644 (file)
@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA.  */
 #include "ggc.h"
 #include "insn-config.h"
 #include "integrate.h"
+#include "tree-inline.h"
 
 static tree bot_manip PARAMS ((tree *, int *, void *));
 static tree bot_replace PARAMS ((tree *, int *, void *));
@@ -49,6 +50,12 @@ static tree count_trees_r PARAMS ((tree *, int *, void *));
 static tree verify_stmt_tree_r PARAMS ((tree *, int *, void *));
 static tree find_tree_r PARAMS ((tree *, int *, void *));
 extern int cp_statement_code_p PARAMS ((enum tree_code));
+static treeopt_walk_subtrees_type cp_walk_subtrees;
+static treeopt_cannot_inline_tree_fn_type cp_cannot_inline_tree_fn;
+static treeopt_add_pending_fn_decls_type cp_add_pending_fn_decls;
+static treeopt_tree_chain_matters_p_type cp_is_overload_p;
+static treeopt_auto_var_in_fn_p_type cp_auto_var_in_fn_p;
+static treeopt_copy_res_decl_for_inlining_type cp_copy_res_decl_for_inlining;
 
 static tree handle_java_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
 static tree handle_com_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
@@ -1154,12 +1161,13 @@ bind_template_template_parm (t, newargs)
    once.  */
 
 tree 
-walk_tree (tp, func, data, htab)
+walk_tree (tp, func, data, htab_)
      tree *tp;
      walk_tree_fn func;
      void *data;
-     htab_t htab;
+     void *htab_;
 {
+  htab_t htab = (htab_t) htab_;
   enum tree_code code;
   int walk_subtrees;
   tree result;
@@ -1204,7 +1212,8 @@ walk_tree (tp, func, data, htab)
      interesting below this point in the tree.  */
   if (!walk_subtrees)
     {
-      if (statement_code_p (code) || code == TREE_LIST || code == OVERLOAD)
+      if (statement_code_p (code) || code == TREE_LIST
+         || LANG_TREE_CHAIN_MATTERS_P (*tp))
        /* But we still need to check our siblings.  */
        return walk_tree (&TREE_CHAIN (*tp), func, data, htab);
       else
@@ -1268,6 +1277,10 @@ walk_tree (tp, func, data, htab)
       return NULL_TREE;
     }
 
+  result = LANG_WALK_SUBTREES (tp, &walk_subtrees, func, data, htab);
+  if (result || ! walk_subtrees)
+    return result;
+
   /* Not one of the easy cases.  We must explicitly go through the
      children.  */
   switch (code)
@@ -1277,47 +1290,29 @@ walk_tree (tp, func, data, htab)
     case INTEGER_CST:
     case REAL_CST:
     case STRING_CST:
-    case DEFAULT_ARG:
-    case TEMPLATE_TEMPLATE_PARM:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
-    case TEMPLATE_PARM_INDEX:
-    case TEMPLATE_TYPE_PARM:
     case REAL_TYPE:
     case COMPLEX_TYPE:
     case VECTOR_TYPE:
     case VOID_TYPE:
     case BOOLEAN_TYPE:
-    case TYPENAME_TYPE:
     case UNION_TYPE:
     case ENUMERAL_TYPE:
-    case TYPEOF_TYPE:
     case BLOCK:
+    case RECORD_TYPE:
       /* None of thse have subtrees other than those already walked
          above.  */
       break;
 
-    case PTRMEM_CST:
-      WALK_SUBTREE (TREE_TYPE (*tp));
-      break;
-
     case POINTER_TYPE:
     case REFERENCE_TYPE:
       WALK_SUBTREE (TREE_TYPE (*tp));
       break;
 
     case TREE_LIST:
-      /* A BASELINK_P's TREE_PURPOSE is a BINFO, and hence circular.  */
-      if (!BASELINK_P (*tp))
-        WALK_SUBTREE (TREE_PURPOSE (*tp));
       WALK_SUBTREE (TREE_VALUE (*tp));
       WALK_SUBTREE (TREE_CHAIN (*tp));
       break;
 
-    case OVERLOAD:
-      WALK_SUBTREE (OVL_FUNCTION (*tp));
-      WALK_SUBTREE (OVL_CHAIN (*tp));
-      break;
-
     case TREE_VEC:
       {
        int len = TREE_VEC_LENGTH (*tp);
@@ -1365,13 +1360,8 @@ walk_tree (tp, func, data, htab)
       WALK_SUBTREE (TYPE_OFFSET_BASETYPE (*tp));
       break;
 
-    case RECORD_TYPE:
-      if (TYPE_PTRMEMFUNC_P (*tp))
-       WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE (*tp));
-      break;
-
     default:
-      my_friendly_abort (19990803);
+      abort ();
     }
 
   /* We didn't find what we were looking for.  */
@@ -1539,7 +1529,7 @@ copy_tree_r (tp, walk_subtrees, data)
       || TREE_CODE_CLASS (code) == 's'
       || code == TREE_LIST
       || code == TREE_VEC
-      || code == OVERLOAD)
+      || LANG_TREE_CHAIN_MATTERS_P (*tp))
     {
       /* Because the chain gets clobbered when we make a copy, we save it
         here.  */
@@ -1550,7 +1540,8 @@ copy_tree_r (tp, walk_subtrees, data)
 
       /* Now, restore the chain, if appropriate.  That will cause
         walk_tree to walk into the chain as well.  */
-      if (code == PARM_DECL || code == TREE_LIST || code == OVERLOAD
+      if (code == PARM_DECL || code == TREE_LIST
+         || LANG_TREE_CHAIN_MATTERS_P (*tp)
          || statement_code_p (code))
        TREE_CHAIN (*tp) = chain;
 
@@ -2344,12 +2335,227 @@ make_ptrmem_cst (type, member)
   return ptrmem_cst;
 }
 
+/* Apply FUNC to all language-specific sub-trees of TP in a pre-order
+   traversal.  Called from walk_tree().  */
+
+static tree 
+cp_walk_subtrees (tp, walk_subtrees_p, func, data, htab)
+     tree *tp;
+     int *walk_subtrees_p;
+     walk_tree_fn func;
+     void *data;
+     void *htab;
+{
+  enum tree_code code = TREE_CODE (*tp);
+  tree result;
+  
+#define WALK_SUBTREE(NODE)                             \
+  do                                                   \
+    {                                                  \
+      result = walk_tree (&(NODE), func, data, htab);  \
+      if (result)                                      \
+       return result;                                  \
+    }                                                  \
+  while (0)
+
+  /* Not one of the easy cases.  We must explicitly go through the
+     children.  */
+  switch (code)
+    {
+    case DEFAULT_ARG:
+    case TEMPLATE_TEMPLATE_PARM:
+    case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_PARM_INDEX:
+    case TEMPLATE_TYPE_PARM:
+    case TYPENAME_TYPE:
+    case TYPEOF_TYPE:
+      /* None of thse have subtrees other than those already walked
+         above.  */
+      *walk_subtrees_p = 0;
+      break;
+
+    case PTRMEM_CST:
+      WALK_SUBTREE (TREE_TYPE (*tp));
+      *walk_subtrees_p = 0;
+      break;
+
+    case TREE_LIST:
+      /* A BASELINK_P's TREE_PURPOSE is a BINFO, and hence circular.  */
+      if (!BASELINK_P (*tp))
+        WALK_SUBTREE (TREE_PURPOSE (*tp));
+      break;
+
+    case OVERLOAD:
+      WALK_SUBTREE (OVL_FUNCTION (*tp));
+      WALK_SUBTREE (OVL_CHAIN (*tp));
+      *walk_subtrees_p = 0;
+      break;
+
+    case RECORD_TYPE:
+      if (TYPE_PTRMEMFUNC_P (*tp))
+       WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE (*tp));
+      break;
+
+    default:
+      break;
+    }
+
+  /* We didn't find what we were looking for.  */
+  return NULL_TREE;
+
+#undef WALK_SUBTREE
+}
+
+/* Decide whether there are language-specific reasons to not inline a
+   function as a tree.  */
+
+static int
+cp_cannot_inline_tree_fn (fnp)
+     tree *fnp;
+{
+  tree fn = *fnp;
+
+  /* We can inline a template instantiation only if it's fully
+     instantiated.  */
+  if (DECL_TEMPLATE_INFO (fn)
+      && TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
+    {
+      fn = *fnp = instantiate_decl (fn, /*defer_ok=*/0);
+      return TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn));
+    }
+
+  if (varargs_function_p (fn))
+    {
+      DECL_UNINLINABLE (fn) = 1;
+      return 1;
+    }
+
+  if (! function_attribute_inlinable_p (fn))
+    {
+      DECL_UNINLINABLE (fn) = 1;
+      return 1;
+    }
+
+  return 0;
+}
+
+/* Add any pending functions other than the current function (already
+   handled by the caller), that thus cannot be inlined, to FNS_P, then
+   return the latest function added to the array, PREV_FN.  */
+
+static tree
+cp_add_pending_fn_decls (fns_p, prev_fn)
+     void *fns_p;
+     tree prev_fn;
+{
+  varray_type *fnsp = (varray_type *)fns_p;
+  struct saved_scope *s;
+
+  for (s = scope_chain; s; s = s->prev)
+    if (s->function_decl && s->function_decl != prev_fn)
+      {
+       VARRAY_PUSH_TREE (*fnsp, s->function_decl);
+       prev_fn = s->function_decl;
+      }
+
+  return prev_fn;
+}
+
+/* Determine whether a tree node is an OVERLOAD node.  Used to decide
+   whether to copy a node or to preserve its chain when inlining a
+   function.  */
+
+static int
+cp_is_overload_p (t)
+     tree t;
+{
+  return TREE_CODE (t) == OVERLOAD;
+}
+
+/* Determine whether VAR is a declaration of an automatic variable in
+   function FN.  */
+
+static int
+cp_auto_var_in_fn_p (var, fn)
+     tree var, fn;
+{
+  return (DECL_P (var) && DECL_CONTEXT (var) == fn
+         && nonstatic_local_decl_p (var));
+}
+
+/* Tell whether a declaration is needed for the RESULT of a function
+   FN being inlined into CALLER or if the top node of target_exprs is
+   to be used.  */
+
+static tree
+cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
+                              need_decl, target_exprs)
+     tree result, fn, caller;
+     void *decl_map_;
+     int *need_decl;
+     void *target_exprs;
+{
+  splay_tree decl_map = (splay_tree)decl_map_;
+  varray_type *texps = (varray_type *)target_exprs;
+  tree var;
+  int aggregate_return_p;
+
+  /* Figure out whether or not FN returns an aggregate.  */
+  aggregate_return_p = IS_AGGR_TYPE (TREE_TYPE (result));
+  *need_decl = ! aggregate_return_p;
+
+  /* If FN returns an aggregate then the caller will always create the
+     temporary (using a TARGET_EXPR) and the call will be the
+     initializing expression for the TARGET_EXPR.  If we were just to
+     create a new VAR_DECL here, then the result of this function
+     would be copied (bitwise) into the variable initialized by the
+     TARGET_EXPR.  That's incorrect, so we must transform any
+     references to the RESULT into references to the target.  */
+  if (aggregate_return_p)
+    {
+      if (VARRAY_ACTIVE_SIZE (*texps) == 0)
+       abort ();
+      var = TREE_OPERAND (VARRAY_TOP_TREE (*texps), 0);
+      if (! same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var),
+                                                      TREE_TYPE (result)))
+       abort ();
+    }
+  /* Otherwise, make an appropriate copy.  */
+  else
+    var = copy_decl_for_inlining (result, fn, caller);
+
+  if (DECL_SAVED_FUNCTION_DATA (fn))
+    {
+      tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
+      if (nrv)
+       {
+         /* We have a named return value; copy the name and source
+            position so we can get reasonable debugging information, and
+            register the return variable as its equivalent.  */
+         DECL_NAME (var) = DECL_NAME (nrv);
+         DECL_SOURCE_FILE (var) = DECL_SOURCE_FILE (nrv);
+         DECL_SOURCE_LINE (var) = DECL_SOURCE_LINE (nrv);
+         splay_tree_insert (decl_map,
+                            (splay_tree_key) nrv,
+                            (splay_tree_value) var);
+       }
+    }
+
+  return var;
+}
+
 /* Initialize tree.c.  */
 
 void
 init_tree ()
 {
   make_lang_type_fn = cp_make_lang_type;
+  lang_walk_subtrees = cp_walk_subtrees;
+  lang_cannot_inline_tree_fn = cp_cannot_inline_tree_fn;
+  lang_add_pending_fn_decls = cp_add_pending_fn_decls;
+  lang_tree_chain_matters_p = cp_is_overload_p;
+  lang_auto_var_in_fn_p = cp_auto_var_in_fn_p;
+  lang_copy_res_decl_for_inlining = cp_copy_res_decl_for_inlining;
   lang_unsave = cp_unsave;
   lang_statement_code_p = cp_statement_code_p;
   lang_set_decl_assembler_name = mangle_decl;
@@ -2365,12 +2571,13 @@ init_tree ()
    ST.  FN is the function into which the copy will be placed.  */
 
 void
-remap_save_expr (tp, st, fn, walk_subtrees)
+remap_save_expr (tp, st_, fn, walk_subtrees)
      tree *tp;
-     splay_tree st;
+     void *st_;
      tree fn;
      int *walk_subtrees;
 {
+  splay_tree st = (splay_tree) st_;
   splay_tree_node n;
 
   /* See if we already encountered this SAVE_EXPR.  */