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]

[lto] Fix 700 failures in testsuite


This patch fixes 700 out of the 1200 failures in the testsuite.
There are three main issues addressed by the patch:

1- Nested functions were missing the static chain and the
   nonlocal goto receiver.  The streamer now writes and reads
   these.

2- DECL_NONLOCAL labels were not being emitted properly.  Instead
   of having the same label shared between two functions, the
   streamer was creating two different copies.  Non-local labels
   are now streamed as global symbols.

3- Fields with non-constant offsets were confusing the streamer.
   These non-constant offsets are now cleared by free_lang_data.

Some of the tests changed from compile failures to runtime
failures, but I prefer to commit the patch as-is now so it
doesn't grow too much more.

Tested on x86_64.


Diego.


2009-05-11  Diego Novillo  <dnovillo@google.com>

	* tree.c (free_lang_data_in_decl): If a FIELD_DECL has a
	non-constant offset, set it to NULL.
	* lto-function-out.c (eq_label_slot_node): Use pointer
	equality.
	(hash_label_slot_node): Use pointer hashing.
	(output_label_ref): Handle DECL_NONLOCAL labels.
	(output_expr_operand) <CASE_LABEL_EXPR>: Assert that the
	label is local.
	<VAR_DECL>: Call decl_function_context to determine if
	the symbol is local or global.
	<LABEL_DECL>: Use LTO_label_decl1 for DECL_NONLOCAL
	labels and LTO_label_decl0 for local labels.
	(output_function): Write FN->STATIC_CHAIN_DECL and
	FN->NONLOCAL_GOTO_SAVE_AREA.
	(output_label_decl): Use LTO_label_decl1 for
	DECL_NONLOCAL labels and LTO_label_decl0 for local
	labels.
	Emit the label context.
	* lto-function-in.c (get_label_decl): Make sure that the
	index read falls inside the label array.
	Assert that the label is local.
	(input_expr_operand) <TYPE_DECL>: Call
	lto_file_decl_data_get_type_decl instead of
	lto_file_decl_data_get_field_decl.
	<LABEL_DECL>: Call lto_file_decl_data_get_label_decl for
	LTO_label_decl1.
	(input_labels): Set DATA_IN->NUM_NAMED_LABELS and
	DATA_IN->NUM_UNNAMED_LABELS.
	Set DECL_CONTEXT for every label built.
	(input_eh_region): Add new LABEL_TAG local.  Use it as
	argument to input_expr_operand when building the tree
	label for the region.
	(input_gimple_stmt): For GIMPLE_LABELs, assert that the
	label is either DECL_NONLOCAL or its context is the
	function being read.
	(input_bb): Assert that after the statement there should
	be an EH region or a null delimiter.
	(input_function): Read FN->STATIC_CHAIN_DECL and
	FN->NONLOCAL_GOTO_SAVE_AREA.
	(lto_read_body): Do not set DATA_IN.NUM_NAMED_LABELS.
	(input_label_decl): Read DECL_CONTEXT.
	* lto-header.h (lto_decl_stream_e_t): Add LTO_DECL_STREAM_LABEL_DECL.
	/* FIXME lto tuple streamer.  */
	* lto-tree-in.h (struct data_in): Add field 'num_unnamed_labels'.
	* lto-tree-tags.def: Call MAP_EXPR_TAGS for
	LTO_label_decl0 and LTO_label_decl1.
	Remove call to MAP_EXPR_TAG for LTO_label_decl.
	Call SET_NAME for LTO_label_decl0 and LTO_label_decl1.
	* lto-section-in.h: Call DEFINE_DECL_STREAM_FUNCS for
	label_decl.
	* lto-tags.h (enum LTO_tags): Add LTO_label_decl0 and
	LTO_label_decl1.

Index: tree.c
===================================================================
--- tree.c	(revision 147246)
+++ tree.c	(working copy)
@@ -4009,6 +4009,11 @@ free_lang_data_in_decl (tree decl)
 	  DECL_SIZE_UNIT (decl) = NULL_TREE;
 	  DECL_SIZE (decl) = NULL_TREE;
 	}
+
+      if (TREE_CODE (decl) == FIELD_DECL
+	  && DECL_FIELD_OFFSET (decl)
+	  && TREE_CODE (DECL_FIELD_OFFSET (decl)) != INTEGER_CST)
+	DECL_FIELD_OFFSET (decl) = NULL_TREE;
     }
   else if (TREE_CODE (decl) == FUNCTION_DECL)
     {
Index: lto-function-out.c
===================================================================
--- lto-function-out.c	(revision 147291)
+++ lto-function-out.c	(working copy)
@@ -1,7 +1,7 @@
 /* Write the gimple representation of a function and its local
    variables to a .o file.
 
-   Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright 2009 Free Software Foundation, Inc.
    Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
 
 This file is part of GCC.
@@ -80,7 +80,7 @@ eq_label_slot_node (const void *p1, cons
   const struct lto_decl_slot *ds2 =
     (const struct lto_decl_slot *) p2;
 
-  return LABEL_DECL_UID (ds1->t) == LABEL_DECL_UID (ds2->t);
+  return ds1->t == ds2->t;
 }
 
 /* Returns a hash code for P.  */
@@ -89,7 +89,7 @@ static hashval_t
 hash_label_slot_node (const void *p)
 {
   const struct lto_decl_slot *ds = (const struct lto_decl_slot *) p;
-  return (hashval_t) LABEL_DECL_UID (ds->t);
+  return htab_hash_pointer (ds->t);
 }
 
 
@@ -698,6 +698,22 @@ output_label_ref (struct output_block *o
   struct lto_decl_slot d_slot;
   d_slot.t = label;
 
+  /* If LABEL is DECL_NONLOCAL it will referenced from other
+     functions, so it needs to be streamed out in the global context.  */
+  if (DECL_NONLOCAL (label))
+    {
+      struct lto_out_decl_state *state;
+      struct lto_output_stream *obs;
+      struct lto_tree_ref_encoder *encoder;
+      unsigned index;
+
+      obs = ob->main_stream;
+      state = ob->decl_state;
+      encoder = &state->streams[LTO_DECL_STREAM_LABEL_DECL];
+      lto_output_decl_index (obs, encoder, label, &index);
+      return;
+    }
+
   slot = htab_find_slot (ob->label_hash_table, &d_slot, INSERT);
   if (*slot == NULL)
     {
@@ -720,6 +736,7 @@ output_label_ref (struct output_block *o
   else
     {
       struct lto_decl_slot *old_slot = (struct lto_decl_slot *)*slot;
+      gcc_assert (old_slot->t == label);
       output_sleb128 (ob, old_slot->slot_num);
     }
 }
@@ -1060,13 +1077,13 @@ output_expr_operand (struct output_block
 	  variant |= 0x1;
 	if (CASE_HIGH (expr) != NULL_TREE)
 	  variant |= 0x2;
-	output_record_start (ob, expr, NULL,
-			     LTO_case_label_expr0 + variant);
+	output_record_start (ob, expr, NULL, LTO_case_label_expr0 + variant);
 
 	if (CASE_LOW (expr) != NULL_TREE)
 	  output_expr_operand (ob, CASE_LOW (expr));
 	if (CASE_HIGH (expr) != NULL_TREE)
 	  output_expr_operand (ob, CASE_HIGH (expr));
+	gcc_assert (!DECL_NONLOCAL (CASE_LABEL (expr)));
 	output_label_ref (ob, CASE_LABEL (expr));
       }
       break;
@@ -1097,7 +1114,7 @@ output_expr_operand (struct output_block
       break;
 
     case VAR_DECL:
-      if (TREE_STATIC (expr) || DECL_EXTERNAL (expr))
+      if (decl_function_context (expr) == NULL)
 	{
 	  output_record_start (ob, NULL, NULL, LTO_var_decl1);
 	  lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
@@ -1126,7 +1143,9 @@ output_expr_operand (struct output_block
       break;
 
     case LABEL_DECL:
-      output_record_start (ob, expr, NULL, tag);
+      output_record_start (ob, expr, NULL_TREE,
+			   DECL_NONLOCAL (expr) ? LTO_label_decl1
+					        : LTO_label_decl0);
       output_label_ref (ob, expr);
       break;
 
@@ -1444,7 +1463,6 @@ output_local_vars (struct output_block *
 	}
     }
 
-
   /* End of statics.  */
   output_zero (ob);
   lto_bitmap_free (local_statics);
@@ -2010,6 +2028,17 @@ output_function (struct cgraph_node *nod
 
   gcc_assert (!DECL_CONTEXT (function));
 
+  /* Output the static chain and non-local goto save area.  */
+  if (fn->static_chain_decl)
+    output_expr_operand (ob, fn->static_chain_decl);
+  else
+    output_zero (ob);
+
+  if (fn->nonlocal_goto_save_area)
+    output_expr_operand (ob, fn->nonlocal_goto_save_area);
+  else
+    output_zero (ob);
+
   /* 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
@@ -2827,15 +2856,16 @@ output_type_decl (struct output_block *o
 static void
 output_label_decl (struct output_block *ob, tree decl)
 {
+  enum LTO_tags tag = DECL_NONLOCAL (decl) ? LTO_label_decl1 : LTO_label_decl0;
+
   /* tag and flags */
-  output_global_record_start (ob, NULL, NULL, LTO_label_decl);
-  output_tree_flags (ob, ERROR_MARK, decl, true);
+  output_global_record_start (ob, decl, NULL, tag);
 
   global_vector_debug (ob);
 
   /* uid and locus are handled specially */
   output_tree (ob, decl->decl_minimal.name);
-  /* We don't output the context here. It is output by output_named_labels. */
+  output_tree (ob, decl->decl_minimal.context);
 
   output_tree (ob, decl->common.type);
 
Index: lto-function-in.c
===================================================================
--- lto-function-in.c	(revision 147291)
+++ lto-function-in.c	(working copy)
@@ -254,14 +254,20 @@ input_record_start (struct lto_input_blo
 static tree 
 get_label_decl (struct data_in *data_in, struct lto_input_block *ib)
 {
-  int index = lto_input_sleb128 (ib);
+  int ix, nlabels;
+  tree label;
 
-  /* A negative INDEX indicates that the label is an unnamed label.
+  /* A negative IX indicates that the label is an unnamed label.
      These are stored at the back of DATA_IN->LABELS.  */
-  if (index >= 0)
-    return data_in->labels[index];
-  else
-    return data_in->labels[data_in->num_named_labels - index];
+  ix = lto_input_sleb128 (ib);
+  ix = (ix >= 0) ? ix : (int) data_in->num_named_labels - ix;
+  nlabels = (int) data_in->num_named_labels + data_in->num_unnamed_labels;
+  gcc_assert (ix >= 0 && ix < nlabels);
+
+  label = data_in->labels[ix];
+  gcc_assert (!DECL_NONLOCAL (label));
+
+  return label;
 }
 
 
@@ -694,7 +700,7 @@ input_expr_operand (struct lto_input_blo
 
     case TYPE_DECL:
       gcc_assert (tag == LTO_type_decl);
-      result = lto_file_decl_data_get_field_decl (data_in->file_data,
+      result = lto_file_decl_data_get_type_decl (data_in->file_data,
 						  lto_input_uleb128 (ib));
       gcc_assert (result);
       break;
@@ -763,7 +769,11 @@ input_expr_operand (struct lto_input_blo
       break;
 
     case LABEL_DECL:
-      result = get_label_decl (data_in, ib);
+      if (tag == LTO_label_decl1)
+	result = lto_file_decl_data_get_label_decl (data_in->file_data,
+						    lto_input_uleb128 (ib));
+      else
+	result = get_label_decl (data_in, ib);
       break;
 
     case COMPONENT_REF:
@@ -867,7 +877,7 @@ input_expr_operand (struct lto_input_blo
 	tree ops[7];
 	int len = TREE_CODE_LENGTH (code);
 	int i;
-	for (i = 0; i<len; i++)
+	for (i = 0; i < len; i++)
 	  ops[i] = input_expr_operand (ib, data_in, fn, 
 				       input_record_start (ib));
 	switch (len)
@@ -938,6 +948,7 @@ input_labels (struct lto_input_block *ib
 	      unsigned int named_count, unsigned int unnamed_count)
 {
   unsigned int i;
+  tree label;
 
   clear_line_info (data_in);
 
@@ -947,15 +958,23 @@ input_labels (struct lto_input_block *ib
      number of named labels.  */
   data_in->labels = (tree *) xcalloc (named_count + unnamed_count,
 				      sizeof (tree));
+  data_in->num_named_labels = named_count;
+  data_in->num_unnamed_labels = unnamed_count;
+
   for (i = 0; i < named_count; i++)
     {
       tree name = input_identifier (data_in, ib);
-      data_in->labels[i] = build_decl (LABEL_DECL, name, void_type_node);
+      label = build_decl (LABEL_DECL, name, void_type_node);
+      DECL_CONTEXT (label) = current_function_decl;
+      data_in->labels[i] = label;
     }
 
   for (i = 0; i < unnamed_count; i++)
-    data_in->labels[i + named_count] 
-      = build_decl (LABEL_DECL, NULL_TREE, void_type_node);
+    {
+      label = build_decl (LABEL_DECL, NULL_TREE, void_type_node);
+      DECL_CONTEXT (label) = current_function_decl;
+      data_in->labels[i + named_count] = label;
+    }
 }
 
 
@@ -1154,7 +1173,7 @@ input_local_vars (struct lto_input_block
     }
 
   LTO_DEBUG_TOKEN ("local vars");
-  for (i = 0; i < (int)count; i++)
+  for (i = 0; i < (int) count; i++)
     if (!data_in->local_decls[i])
       {
 	/* Some local decls may have already been read in if they are
@@ -1187,7 +1206,7 @@ static eh_region
 input_eh_region (struct lto_input_block *ib, struct data_in *data_in,
 		 struct function *fn, int region_number)
 {
-  enum LTO_tags tag;
+  enum LTO_tags tag, label_tag;
   eh_region r;
 
   /* Read the region header.  */
@@ -1212,8 +1231,9 @@ input_eh_region (struct lto_input_block 
   r->outer = (eh_region) (intptr_t) lto_input_uleb128 (ib);
   r->inner = (eh_region) (intptr_t) lto_input_uleb128 (ib);
   r->next_peer = (eh_region) (intptr_t) lto_input_uleb128 (ib);
-  if (input_record_start (ib))
-    r->tree_label = input_expr_operand (ib, data_in, fn, LTO_label_decl);
+  label_tag = input_record_start (ib);
+  if (label_tag)
+    r->tree_label = input_expr_operand (ib, data_in, fn, label_tag);
 
   if (tag == LTO_eh_table_cleanup1
       || tag == LTO_eh_table_try1
@@ -1711,7 +1731,8 @@ input_gimple_stmt (struct lto_input_bloc
 	SSA_NAME_DEF_STMT (lhs) = stmt;
     }
   else if (code == GIMPLE_LABEL)
-    DECL_CONTEXT (gimple_label_label (stmt)) = fn->decl;
+    gcc_assert (DECL_NONLOCAL (gimple_label_label (stmt))
+	        || DECL_CONTEXT (gimple_label_label (stmt)) == fn->decl);
   else if (code == GIMPLE_ASM)
     {
       unsigned i;
@@ -1788,7 +1809,11 @@ input_bb (struct lto_input_block *ib, en
       gimple_set_block (stmt, DECL_INITIAL (fn->decl));
       gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
 
+      /* After the statement, expect a 0 delimiter or the EH region
+	 that the previous statement belongs to.  */
       tag = input_record_start (ib);
+      gcc_assert (tag == LTO_set_eh1 || tag == LTO_set_eh0 || tag == LTO_null);
+
       if (tag == LTO_set_eh1 || tag == LTO_set_eh0)
 	{
 	  HOST_WIDE_INT region = 0;
@@ -1857,6 +1882,16 @@ input_function (tree fn_decl, struct dat
 
   DECL_CONTEXT (fn_decl) = NULL_TREE;
 
+  /* Read the static chain and non-local goto save area.  */
+  tag = input_record_start (ib);
+  if (tag)
+    fn->static_chain_decl = input_expr_operand (ib, data_in, fn, tag);
+
+  tag = input_record_start (ib);
+  if (tag)
+    fn->nonlocal_goto_save_area = input_expr_operand (ib, data_in, fn, tag);
+
+  /* Read all the basic blocks.  */
   tag = input_record_start (ib);
   while (tag)
     {
@@ -2184,7 +2219,6 @@ lto_read_body (struct lto_file_decl_data
 
       push_cfun (fn);
       init_tree_ssa (fn);
-      data_in.num_named_labels = header->num_named_labels;
 
       /* Use the function's decl state. */
       decl_state = lto_get_function_in_decl_state (file_data, fn_decl);
@@ -2841,7 +2875,7 @@ input_label_decl (struct lto_input_block
   global_vector_enter (data_in, decl);
 
   decl->decl_minimal.name = input_tree (ib, data_in);
-  decl->decl_minimal.context = NULL_TREE;
+  decl->decl_minimal.context = input_tree (ib, data_in);
   decl->common.type = input_tree (ib, data_in);
   decl->decl_common.attributes = input_tree (ib, data_in);
   decl->decl_common.abstract_origin = input_tree (ib, data_in);
Index: lto-header.h
===================================================================
--- lto-header.h	(revision 147098)
+++ lto-header.h	(working copy)
@@ -80,6 +80,7 @@ typedef enum {
   LTO_DECL_STREAM_VAR_DECL,
   LTO_DECL_STREAM_TYPE_DECL,
   LTO_DECL_STREAM_NAMESPACE_DECL,
+  LTO_DECL_STREAM_LABEL_DECL,
   LTO_N_DECL_STREAMS
 } lto_decl_stream_e_t;
 
Index: lto-tree-in.h
===================================================================
--- lto-tree-in.h	(revision 147291)
+++ lto-tree-in.h	(working copy)
@@ -56,9 +56,14 @@ struct data_in
 
   /* The length of the string table.  */
   unsigned int strings_len;
+
   /* Number of named labels.  Used to find the index of unnamed labels
      since they share space with the named labels.  */
   unsigned int num_named_labels;  
+
+  /* Number of unnamed labels.  */
+  unsigned int num_unnamed_labels;
+
   const char *current_file;
   int current_line;
   int current_col;
Index: lto-tree-tags.def
===================================================================
--- lto-tree-tags.def	(revision 147291)
+++ lto-tree-tags.def	(working copy)
@@ -56,6 +56,7 @@
   MAP_EXPR_TAGS(CASE_LABEL_EXPR, LTO_case_label_expr0, 4)
   MAP_EXPR_TAGS(COMPLEX_CST, LTO_complex_cst0, 2)
   MAP_EXPR_TAGS(VAR_DECL, LTO_var_decl0, 2)
+  MAP_EXPR_TAGS(LABEL_DECL, LTO_label_decl0, 2)
   MAP_EXPR_TAGS(VECTOR_CST, LTO_vector_cst0, 2)
 #endif
 
@@ -77,7 +78,6 @@
   MAP_EXPR_TAG(IDENTIFIER_NODE, LTO_identifier_node)
   MAP_EXPR_TAG(INTEGER_CST, LTO_integer_cst)
   MAP_EXPR_TAG(INTEGER_TYPE, LTO_integer_type)
-  MAP_EXPR_TAG(LABEL_DECL, LTO_label_decl)
   MAP_EXPR_TAG(METHOD_TYPE, LTO_method_type)
   MAP_EXPR_TAG(NAMESPACE_DECL, LTO_namespace_decl)
   MAP_EXPR_TAG(OFFSET_TYPE, LTO_offset_type)
@@ -254,7 +254,8 @@
   SET_NAME (LTO_identifier_node, "identifier_node")
   SET_NAME (LTO_indirect_ref, "indirect_ref")
   SET_NAME (LTO_integer_cst, "integer_cst")
-  SET_NAME (LTO_label_decl, "label_decl")
+  SET_NAME (LTO_label_decl0, "label_decl0")
+  SET_NAME (LTO_label_decl1, "label_decl1")
   SET_NAME (LTO_label_expr, "label_expr")
   SET_NAME (LTO_le_expr, "le_expr")
   SET_NAME (LTO_lrotate_expr, "lrotate_expr")
Index: lto-section-in.h
===================================================================
--- lto-section-in.h	(revision 147098)
+++ lto-section-in.h	(working copy)
@@ -125,6 +125,7 @@ DEFINE_DECL_STREAM_FUNCS (FN_DECL, fn_de
 DEFINE_DECL_STREAM_FUNCS (VAR_DECL, var_decl)
 DEFINE_DECL_STREAM_FUNCS (TYPE_DECL, type_decl)
 DEFINE_DECL_STREAM_FUNCS (NAMESPACE_DECL, namespace_decl)
+DEFINE_DECL_STREAM_FUNCS (LABEL_DECL, label_decl)
 
 /* Return a char pointer to the start of a data stream for an lto pass
    or function.  The first parameter is the file data that contains
Index: lto-tags.h
===================================================================
--- lto-tags.h	(revision 147291)
+++ lto-tags.h	(working copy)
@@ -363,7 +363,11 @@ enum LTO_tags 
   LTO_identifier_node,
   LTO_indirect_ref,
   LTO_integer_cst,
-  LTO_label_decl,
+
+  /* 1 for DECL_NONLOCAL labels, 0 for local labels.  */
+  LTO_label_decl0,
+  LTO_label_decl1,
+
   LTO_label_expr,
   LTO_le_expr,
   LTO_lrotate_expr,


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