[lto] Fix execution failures in nested functions

Diego Novillo dnovillo@google.com
Tue Jun 2 12:45:00 GMT 2009


The backend uses DECL_CONTEXT when computing offsets for prologue
and epilogue generation.  Since we were clearing DECL_CONTEXT for
all functions, this was causing execution failures on nested
functions.

This fixes 24 failures in the gcc testsuite.  Tested on x86_64.


Diego.


	* tree.c (free_lang_data_in_decl): Do not clear
	DECL_CONTEXT for FUNCTION_DECLs.
	* lto-function-out.c (output_function): Do not expect
	DECL_CONTEXT to be NULL.
	(output_function_decl): Emit DECL_CONTEXT.
	* lto-function-in.c (input_function): Do not clear
	DECL_CONTEXT.
	(input_function_decl): Read DECL_CONTEXT.
	* lto-cgraph.c (input_cgraph): Tolerate extra cgraph
	nodes created by cgraph_node while reading the call
	graph.


lto/ChangeLog

	* lto.c (lto_1_to_1_map): Ignore nodes that have not been
	read in.
	(materialize_cgraph): Only materialize nodes that have a
	representation on file.

Index: tree.c
===================================================================
--- tree.c	(revision 148004)
+++ tree.c	(working copy)
@@ -4017,20 +4017,15 @@ free_lang_data_in_decl (tree decl)
     }
   else if (TREE_CODE (decl) == FUNCTION_DECL)
     {
-      tree context = DECL_CONTEXT (decl);
       tree t;
 
       /* An weakref to an external function is DECL_EXTERNAL but not
 	 TREE_PUBLIC. FIXME lto: This is confusing, why does it need to be
 	 DECL_EXTERNAL? */
-
       if (DECL_EXTERNAL (decl)
 	  && !lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
 	TREE_PUBLIC (decl) = true;
 
-      if (context && TREE_CODE (context) == FUNCTION_DECL)
-	DECL_CONTEXT (decl) = NULL_TREE;
-
       /* If DECL has a gimple body, then the context for its arguments
 	 must be DECL.  Otherwise, it doesn't really matter, as we
 	 will not be emitting any code for DECL.  In general, there
Index: lto-function-out.c
===================================================================
--- lto-function-out.c	(revision 148038)
+++ lto-function-out.c	(working copy)
@@ -2191,8 +2191,6 @@ output_function (struct cgraph_node *nod
   else
     output_zero (ob);
 
-  gcc_assert (!DECL_CONTEXT (function));
-
   /* We will renumber the statements.  The code that does this uses
      the same ordering that we use for serializing them so we can use
      the same code on the other end and not have to write out the
@@ -2786,7 +2784,7 @@ output_function_decl (struct output_bloc
 
   /* uid and locus are handled specially */
   output_tree (ob, decl->decl_minimal.name);
-  gcc_assert (decl->decl_minimal.context == NULL_TREE);
+  output_tree (ob, decl->decl_minimal.context);
 
   output_tree (ob, decl->decl_with_vis.assembler_name);
   output_tree (ob, decl->decl_with_vis.section_name);
Index: lto-function-in.c
===================================================================
--- lto-function-in.c	(revision 148028)
+++ lto-function-in.c	(working copy)
@@ -2026,8 +2026,6 @@ input_function (tree fn_decl, struct dat
   if (tag)
     DECL_ARGUMENTS (fn_decl) = input_expr_operand (ib, data_in, fn, tag); 
 
-  DECL_CONTEXT (fn_decl) = NULL_TREE;
-
   /* Read all the basic blocks.  */
   tag = input_record_start (ib);
   while (tag)
@@ -2755,6 +2753,7 @@ input_function_decl (struct lto_input_bl
   index = global_vector_enter (data_in, decl);
 
   decl->decl_minimal.name = input_tree (ib, data_in);
+  decl->decl_minimal.context = input_tree (ib, data_in);
   decl->decl_with_vis.assembler_name = input_tree (ib, data_in);
   decl->decl_with_vis.section_name = input_tree (ib, data_in);
   decl->decl_with_vis.comdat_group = input_tree (ib, data_in);
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 148004)
+++ lto-cgraph.c	(working copy)
@@ -729,8 +729,13 @@ input_cgraph (void)
      tell which nodes should be overwritten.  */
   for (node = cgraph_nodes; node; node = node->next)
     {
-      gcc_assert (node->local.lto_file_data);
-      node->aux = NULL;
+      /* Some nodes may have been created by cgraph_node.  This
+	 happens when the callgraph contains nested functions.  If the
+	 node for the parent function was never emitted to the gimple
+	 file, cgraph_node will create a node for it when setting the
+	 context of the nested function.  */
+      if (node->local.lto_file_data)
+	node->aux = NULL;
     }
 }
 
Index: lto/lto.c
===================================================================
--- lto/lto.c	(revision 148004)
+++ lto/lto.c	(working copy)
@@ -545,9 +545,11 @@ lto_1_to_1_map (void)
 
   for (node = cgraph_nodes; node; node = node->next)
     {
-      /* We assume file_data are unique.  */
+      /* We only need to partition the nodes that we read from the
+	 gimple bytecode files.  */
       file_data = node->local.lto_file_data;
-      gcc_assert (file_data);
+      if (file_data == NULL)
+	continue;
 
       slot = pointer_map_contains (pmap, file_data);
       if (slot)
@@ -1720,14 +1722,21 @@ materialize_cgraph (void)
 
   for (node = cgraph_nodes; node; node = node->next)
     {
-      /* Builtin functions need not be materialized and may, in fact,
-	 cause confusion because there may be a regular function in
-	 the file whose assembler name matches that of the function
-	 (e.g., testsuite/gcc.c-torture/execute/20030125-1.c).  */
-      if (!DECL_IS_BUILTIN (node->decl))
-	lto_materialize_function (node);
-
-      lto_stats.num_input_cgraph_nodes++;
+      /* Some cgraph nodes get created on the fly, and they don't need
+	 to be materialized.  For instance, nodes for nested functions
+	 where the parent function was not streamed out or builtin
+	 functions.  Additionally, builtin functions should not be
+	 materialized and may, in fact, cause confusion because there
+	 may be a regular function in the file whose assembler name
+	 matches that of the function.
+	 See gcc.c-torture/execute/20030125-1.c and
+	 gcc.c-torture/execute/921215-1.c.  */
+      if (node->local.lto_file_data
+          && !DECL_IS_BUILTIN (node->decl))
+	{
+	  lto_materialize_function (node);
+	  lto_stats.num_input_cgraph_nodes++;
+	}
     }
 
   timevar_pop (TV_IPA_LTO_GIMPLE_IO);



More information about the Gcc-patches mailing list