This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Avoid duplicate decls in inlined and versioned funtions


Hi,
Currently inliner merge callee's local_decls into callers duplicating all
global vars.  This can be easilly abused to construct memory bomb using early
inliner.

Patch adds referenced_var_check_and_insert check into local_decls copying
code. Now we need to reorder copying before body duplication because we
add into referenced vars all the variables while copying the VAR_DECLs.

Similar problem exists in function versioning code where declaration of removed
parameter is added twice: once by copy_arguments_for_versioning, second time by
setup_one_parameter.  We need to reorder copying and argument setup and watch
for existing decls during copying, otherwise we would miss completely
elliminated declarations.  Those remain in debug info and confuse GDB
not expecting multiple decls of same name in same scope.

Bootstrapped/regtested i686-linux, OK?

	* tree-inline.c (expand_call_inline): Avoid
Index: tree-inline.c
===================================================================
*** tree-inline.c	(revision 144474)
--- tree-inline.c	(working copy)
*************** expand_call_inline (basic_block bb, gimp
*** 3305,3330 ****
        DECL_NO_TBAA_P (retvar) = 1;
      }
  
-   /* This is it.  Duplicate the callee body.  Assume callee is
-      pre-gimplified.  Note that we must not alter the caller
-      function in any way before this point, as this CALL_EXPR may be
-      a self-referential call; if we're calling ourselves, we need to
-      duplicate our body before altering anything.  */
-   copy_body (id, bb->count, bb->frequency, bb, return_block);
- 
    /* Add local vars in this inlined callee to caller.  */
    t_step = id->src_cfun->local_decls;
    for (; t_step; t_step = TREE_CHAIN (t_step))
      {
        var = TREE_VALUE (t_step);
        if (TREE_STATIC (var) && !TREE_ASM_WRITTEN (var))
! 	cfun->local_decls = tree_cons (NULL_TREE, var,
! 					       cfun->local_decls);
        else
! 	cfun->local_decls = tree_cons (NULL_TREE, remap_decl (var, id),
! 					       cfun->local_decls);
      }
  
    /* Clean up.  */
    pointer_map_destroy (id->decl_map);
    id->decl_map = st;
--- 3362,3392 ----
        DECL_NO_TBAA_P (retvar) = 1;
      }
  
    /* Add local vars in this inlined callee to caller.  */
    t_step = id->src_cfun->local_decls;
    for (; t_step; t_step = TREE_CHAIN (t_step))
      {
        var = TREE_VALUE (t_step);
        if (TREE_STATIC (var) && !TREE_ASM_WRITTEN (var))
! 	{
! 	  if (referenced_var_check_and_insert (var))
! 	    cfun->local_decls = tree_cons (NULL_TREE, var,
! 					   cfun->local_decls);
! 	}
        else
!         {
! 	  cfun->local_decls = tree_cons (NULL_TREE, remap_decl (var, id),
! 					          cfun->local_decls);
! 	}
      }
  
+   /* This is it.  Duplicate the callee body.  Assume callee is
+      pre-gimplified.  Note that we must not alter the caller
+      function in any way before this point, as this CALL_EXPR may be
+      a self-referential call; if we're calling ourselves, we need to
+      duplicate our body before altering anything.  */
+   copy_body (id, bb->count, bb->frequency, bb, return_block);
+ 
    /* Clean up.  */
    pointer_map_destroy (id->decl_map);
    id->decl_map = st;
*************** copy_arguments_for_versioning (tree orig
*** 4140,4146 ****
          *parg = new_tree;
  	parg = &TREE_CHAIN (new_tree);
        }
!     else
        {
  	/* Make an equivalent VAR_DECL.  If the argument was used
  	   as temporary variable later in function, the uses will be
--- 4214,4220 ----
          *parg = new_tree;
  	parg = &TREE_CHAIN (new_tree);
        }
!     else if (!pointer_map_contains (id->decl_map, arg))
        {
  	/* Make an equivalent VAR_DECL.  If the argument was used
  	   as temporary variable later in function, the uses will be
*************** tree_function_versioning (tree old_decl,
*** 4263,4278 ****
      DECL_STRUCT_FUNCTION (new_decl)->static_chain_decl =
        copy_static_chain (DECL_STRUCT_FUNCTION (old_decl)->static_chain_decl,
  			 &id);
-   /* Copy the function's arguments.  */
-   if (DECL_ARGUMENTS (old_decl) != NULL_TREE)
-     DECL_ARGUMENTS (new_decl) =
-       copy_arguments_for_versioning (DECL_ARGUMENTS (old_decl), &id,
-       				     args_to_skip, &vars);
-   
-   DECL_INITIAL (new_decl) = remap_blocks (DECL_INITIAL (id.src_fn), &id);
-   
-   /* Renumber the lexical scoping (non-code) blocks consecutively.  */
-   number_blocks (id.dst_fn);
    
    /* If there's a tree_map, prepare for substitution.  */
    if (tree_map)
--- 4343,4348 ----
*************** tree_function_versioning (tree old_decl,
*** 4307,4312 ****
--- 4377,4392 ----
  	      VEC_safe_push (gimple, heap, init_stmts, init);
  	  }
        }
+   /* Copy the function's arguments.  */
+   if (DECL_ARGUMENTS (old_decl) != NULL_TREE)
+     DECL_ARGUMENTS (new_decl) =
+       copy_arguments_for_versioning (DECL_ARGUMENTS (old_decl), &id,
+       				     args_to_skip, &vars);
+   
+   DECL_INITIAL (new_decl) = remap_blocks (DECL_INITIAL (id.src_fn), &id);
+   
+   /* Renumber the lexical scoping (non-code) blocks consecutively.  */
+   number_blocks (id.dst_fn);
    
    declare_inline_vars (DECL_INITIAL (new_decl), vars);
    if (DECL_STRUCT_FUNCTION (old_decl)->local_decls != NULL_TREE)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]