This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[lto] Fix 700 failures in testsuite
- From: Diego Novillo <dnovillo at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 11 May 2009 22:51:05 -0400
- Subject: [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,