aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Maddox <maddox@google.com>2008-06-10 02:00:29 +0000
committerBill Maddox <maddox@google.com>2008-06-10 02:00:29 +0000
commitbeafeb7bd974fd8abd842a50d1f8c4cdc1b2a2b3 (patch)
tree08ecfa456655608ce088f374b50b5cc140b331d1
parent288131c6f02a62d0accc753401931affa3fc33ce (diff)
* lto-tags.h: Add new tags LTO_local_type_ref
and LTO_global_type_ref. Split LTO_type_decl and LTO_field_decl into LTO_type_decl0, LTO_type_decl1, LTO_field_decl0, and LTO_field_decl1. * lto-tree-tags.h: Set names and tree code mappings for the new tags. * lto-function-out.c: Tidy comments and formatting. (output_record_start): Add forward declaration. (type_function_context): New function. (field_decl_is_local, type_decl_is_local): New functions. (output_type_ref_1): Write "local" (e.g., variably-modified) types to local_decls stream. (output_type_ref): Use "type_ref" as debug token to avoid confusing clash with use of "type" elsewhere. (output_local_decl_ref): Update comment. (output_expr_operand): Cases for FIELD_DECL and TYPE_DECL now write "local" declarations to local_decls stream. (output_local_var): Rename to output_local_var_decl. (output_local_var_decl): Remove code to set slot in local_decls_index, now handled by output_local_decl. (output_local_tree): New function. (output_local_field_decl, output_local_type_decl, output_local_type): New functions. (output_local_decl): New function. (output_field_decl): Use new tag LTO_field_decl1, to distinguish from "local" fields. (output_type_decl): Use new tag LTO_type_decl1, to distinguish from "local" fields. * lto-function-in.c: Tidy comments and formatting. (input_local_tree, input_local_var_decl, input_local_field_decl, input_local_type_decl, input_local_type): Add forward declarations. (input_type_ref_1): Distinguish references to global or local declaration streams. (input_type_ref): Use "type_ref" as debug token to avoid confusing clash with use of "type" elsewhere. (input_expr_operand): Cases for FIELD_DECL and TYPE_DECL now read "local" declarations from local_decls stream. (input_local_tree): New function. (input_local_var): Rename to input_local_var_decl. (input_local_var_decl): Input record tag is now an argument. (input_local_field_decl, input_local_type_decl, input_local_type): New functions. (input_local_decl): New function. (input_local_vars): Call input_local_decl instead of input_local_var. (lto_static_init_local): Don't call add_referenced_var on non-vars. * lto-section-out.c (lto_hash_decl_slot_node, lto_eq_decl_slot_node): Use object pointer, not UID, as hash key. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/lto-streamer@136611 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog.lto52
-rw-r--r--gcc/lto-function-in.c533
-rw-r--r--gcc/lto-function-out.c431
-rw-r--r--gcc/lto-section-out.c11
-rw-r--r--gcc/lto-tags.h9
-rw-r--r--gcc/lto-tree-tags.def15
6 files changed, 941 insertions, 110 deletions
diff --git a/gcc/ChangeLog.lto b/gcc/ChangeLog.lto
index 134d844768d..67010a49aab 100644
--- a/gcc/ChangeLog.lto
+++ b/gcc/ChangeLog.lto
@@ -1,4 +1,54 @@
-2008-06-09 Rafael Espindola <espindola@google.com>
+2008-06-09 Bill Maddox <maddox@google.com>
+
+ * lto-tags.h: Add new tags LTO_local_type_ref
+ and LTO_global_type_ref. Split LTO_type_decl
+ and LTO_field_decl into LTO_type_decl0, LTO_type_decl1,
+ LTO_field_decl0, and LTO_field_decl1.
+ * lto-tree-tags.h: Set names and tree code mappings for
+ the new tags.
+ * lto-function-out.c: Tidy comments and formatting.
+ (output_record_start): Add forward declaration.
+ (type_function_context): New function.
+ (field_decl_is_local, type_decl_is_local): New functions.
+ (output_type_ref_1): Write "local" (e.g., variably-modified)
+ types to local_decls stream.
+ (output_type_ref): Use "type_ref" as debug token to avoid
+ confusing clash with use of "type" elsewhere.
+ (output_local_decl_ref): Update comment.
+ (output_expr_operand): Cases for FIELD_DECL and TYPE_DECL
+ now write "local" declarations to local_decls stream.
+ (output_local_var): Rename to output_local_var_decl.
+ (output_local_var_decl): Remove code to set slot in
+ local_decls_index, now handled by output_local_decl.
+ (output_local_tree): New function.
+ (output_local_field_decl, output_local_type_decl,
+ output_local_type): New functions.
+ (output_local_decl): New function.
+ (output_field_decl): Use new tag LTO_field_decl1, to
+ distinguish from "local" fields.
+ (output_type_decl): Use new tag LTO_type_decl1, to
+ distinguish from "local" fields.
+ * lto-function-in.c: Tidy comments and formatting.
+ (input_local_tree, input_local_var_decl, input_local_field_decl,
+ input_local_type_decl, input_local_type): Add forward declarations.
+ (input_type_ref_1): Distinguish references to global or local
+ declaration streams.
+ (input_type_ref): Use "type_ref" as debug token to avoid
+ confusing clash with use of "type" elsewhere.
+ (input_expr_operand): Cases for FIELD_DECL and TYPE_DECL
+ now read "local" declarations from local_decls stream.
+ (input_local_tree): New function.
+ (input_local_var): Rename to input_local_var_decl.
+ (input_local_var_decl): Input record tag is now an argument.
+ (input_local_field_decl, input_local_type_decl,
+ input_local_type): New functions.
+ (input_local_decl): New function.
+ (input_local_vars): Call input_local_decl instead of input_local_var.
+ (lto_static_init_local): Don't call add_referenced_var on non-vars.
+ * lto-section-out.c (lto_hash_decl_slot_node, lto_eq_decl_slot_node):
+ Use object pointer, not UID, as hash key.
+
+2008-06-09 Rafael Espindola <espindola@google.com>http://www.google.com/
based on http://gcc.gnu.org/ml/gcc-patches/2008-03/msg00349.html
* langhooks-def.h (LANG_HOOKS_RESET_LANG_SPECIFICS): New.
diff --git a/gcc/lto-function-in.c b/gcc/lto-function-in.c
index d750f2fffa3..821f2a26625 100644
--- a/gcc/lto-function-in.c
+++ b/gcc/lto-function-in.c
@@ -96,10 +96,33 @@ eq_string_slot_node (const void *p1, const void *p2)
static htab_t file_name_hash_table;
static tree
-input_expr_operand (struct lto_input_block *, struct data_in *, struct function *,
- enum LTO_tags);
+input_expr_operand (struct lto_input_block *, struct data_in *,
+ struct function *, enum LTO_tags);
+
+static tree
+input_local_tree (struct lto_input_block *, struct data_in *,
+ struct function *);
+
+static tree
+input_local_var_decl (struct lto_input_block *, struct data_in *,
+ struct function *, unsigned int, enum LTO_tags);
+
+static tree
+input_local_field_decl (struct lto_input_block *, struct data_in *,
+ struct function *, unsigned int);
+
static tree
-input_local_var (struct lto_input_block *, struct data_in *, struct function *, unsigned int i);
+input_local_type_decl (struct lto_input_block *, struct data_in *,
+ struct function *, unsigned int);
+
+static tree
+input_local_type (struct lto_input_block *, struct data_in *,
+ struct function *, unsigned int, enum tree_code code);
+
+
+static tree
+input_local_decl (struct lto_input_block *, struct data_in *,
+ struct function *, unsigned int);
/* Return the next character of input from IB. Abort if you
@@ -199,8 +222,60 @@ input_type_ref_1 (struct data_in *data_in, struct lto_input_block *ib)
{
int index;
- index = lto_input_uleb128 (ib);
- return data_in->file_data->types[index];
+ tree result;
+ enum LTO_tags tag = input_record_start (ib);
+
+ if (tag == LTO_global_type_ref)
+ {
+ index = lto_input_uleb128 (ib);
+ result = data_in->file_data->types[index];
+ }
+ else if (tag == LTO_local_type_ref)
+ {
+ int lv_index = lto_input_uleb128 (ib);
+ result = data_in->local_decls [lv_index];
+ if (result == NULL)
+ {
+ /* Create a context to read the local variable so that
+ it does not disturb the position of the code that is
+ calling for the local variable. This allows locals
+ to refer to other locals. */
+ struct lto_input_block lib;
+
+#ifdef LTO_STREAM_DEBUGGING
+ struct lto_input_block *current = lto_debug_context.current_data;
+ struct lto_input_block debug;
+ int current_indent = lto_debug_context.indent;
+
+ debug.data = current->data;
+ debug.len = current->len;
+ debug.p = data_in->local_decls_index_d[lv_index];
+
+ lto_debug_context.indent = 0;
+ lto_debug_context.current_data = &debug;
+ lto_debug_context.tag_names = LTO_tree_tag_names;
+#endif
+ lib.data = ib->data;
+ lib.len = ib->len;
+ lib.p = data_in->local_decls_index[lv_index];
+
+ /* The TYPE_DECL case doesn't care about the FN argument. */
+ result = input_local_decl (&lib, data_in, NULL, lv_index);
+ gcc_assert (TYPE_P (result));
+ data_in->local_decls [lv_index] = result;
+
+#ifdef LTO_STREAM_DEBUGGING
+ lto_debug_context.indent = current_indent;
+ lto_debug_context.current_data = current;
+ lto_debug_context.tag_names = LTO_tree_tag_names;
+#endif
+ }
+ }
+ else
+ gcc_unreachable();
+
+ LTO_DEBUG_UNDENT();
+ return result;
}
@@ -210,7 +285,7 @@ input_type_ref_1 (struct data_in *data_in, struct lto_input_block *ib)
static tree
input_type_ref (struct data_in *data_in, struct lto_input_block *ib)
{
- LTO_DEBUG_TOKEN ("type");
+ LTO_DEBUG_TOKEN ("type_ref");
return input_type_ref_1 (data_in, ib);
}
@@ -565,7 +640,53 @@ input_expr_operand (struct lto_input_block *ib, struct data_in *data_in,
break;
case FIELD_DECL:
- result = data_in->file_data->field_decls [lto_input_uleb128 (ib)];
+ if (tag == LTO_field_decl1)
+ {
+ result = data_in->file_data->field_decls [lto_input_uleb128 (ib)];
+ gcc_assert (result);
+ }
+ else if (tag == LTO_field_decl0)
+ {
+ int lv_index = lto_input_uleb128 (ib);
+ result = data_in->local_decls [lv_index];
+ if (result == NULL)
+ {
+ /* Create a context to read the local variable so that
+ it does not disturb the position of the code that is
+ calling for the local variable. This allows locals
+ to refer to other locals. */
+ struct lto_input_block lib;
+
+#ifdef LTO_STREAM_DEBUGGING
+ struct lto_input_block *current = lto_debug_context.current_data;
+ struct lto_input_block debug;
+ int current_indent = lto_debug_context.indent;
+
+ debug.data = current->data;
+ debug.len = current->len;
+ debug.p = data_in->local_decls_index_d[lv_index];
+
+ lto_debug_context.indent = 0;
+ lto_debug_context.current_data = &debug;
+ lto_debug_context.tag_names = LTO_tree_tag_names;
+#endif
+ lib.data = ib->data;
+ lib.len = ib->len;
+ lib.p = data_in->local_decls_index[lv_index];
+
+ result = input_local_decl (&lib, data_in, fn, lv_index);
+ gcc_assert (TREE_CODE (result) == FIELD_DECL);
+ data_in->local_decls [lv_index] = result;
+
+#ifdef LTO_STREAM_DEBUGGING
+ lto_debug_context.indent = current_indent;
+ lto_debug_context.current_data = current;
+ lto_debug_context.tag_names = LTO_tree_tag_names;
+#endif
+ }
+ }
+ else
+ gcc_unreachable ();
break;
case FUNCTION_DECL:
@@ -574,8 +695,53 @@ input_expr_operand (struct lto_input_block *ib, struct data_in *data_in,
break;
case TYPE_DECL:
- result = data_in->file_data->type_decls [lto_input_uleb128 (ib)];
- gcc_assert (result);
+ if (tag == LTO_type_decl1)
+ {
+ result = data_in->file_data->type_decls [lto_input_uleb128 (ib)];
+ gcc_assert (result);
+ }
+ else if (tag == LTO_type_decl0)
+ {
+ int lv_index = lto_input_uleb128 (ib);
+ result = data_in->local_decls [lv_index];
+ if (result == NULL)
+ {
+ /* Create a context to read the local variable so that
+ it does not disturb the position of the code that is
+ calling for the local variable. This allows locals
+ to refer to other locals. */
+ struct lto_input_block lib;
+
+#ifdef LTO_STREAM_DEBUGGING
+ struct lto_input_block *current = lto_debug_context.current_data;
+ struct lto_input_block debug;
+ int current_indent = lto_debug_context.indent;
+
+ debug.data = current->data;
+ debug.len = current->len;
+ debug.p = data_in->local_decls_index_d[lv_index];
+
+ lto_debug_context.indent = 0;
+ lto_debug_context.current_data = &debug;
+ lto_debug_context.tag_names = LTO_tree_tag_names;
+#endif
+ lib.data = ib->data;
+ lib.len = ib->len;
+ lib.p = data_in->local_decls_index[lv_index];
+
+ result = input_local_decl (&lib, data_in, fn, lv_index);
+ gcc_assert (TREE_CODE (result) == TYPE_DECL);
+ data_in->local_decls [lv_index] = result;
+
+#ifdef LTO_STREAM_DEBUGGING
+ lto_debug_context.indent = current_indent;
+ lto_debug_context.current_data = current;
+ lto_debug_context.tag_names = LTO_tree_tag_names;
+#endif
+ }
+ }
+ else
+ gcc_unreachable ();
break;
case NAMESPACE_DECL:
@@ -621,7 +787,9 @@ input_expr_operand (struct lto_input_block *ib, struct data_in *data_in,
lib.len = ib->len;
lib.p = data_in->local_decls_index[lv_index];
- result = input_local_var (&lib, data_in, fn, lv_index);
+ result = input_local_decl (&lib, data_in, fn, lv_index);
+ gcc_assert (TREE_CODE (result) == VAR_DECL
+ || TREE_CODE (result) == PARM_DECL);
data_in->local_decls [lv_index] = result;
#ifdef LTO_STREAM_DEBUGGING
@@ -1037,7 +1205,7 @@ input_labels (struct lto_input_block *ib, struct data_in *data_in,
/* Input the local var index table. */
-
+/* FIXME: We are really reading index for all local decls, not just vars. */
static void
input_local_vars_index (struct lto_input_block *ib, struct data_in *data_in,
@@ -1059,13 +1227,81 @@ input_local_vars_index (struct lto_input_block *ib, struct data_in *data_in,
}
+static tree
+input_local_tree (struct lto_input_block *ib, struct data_in *data_in,
+ struct function *fn)
+{
+ int index;
+ tree result;
+ enum LTO_tags tag;
+
+ tag = input_record_start (ib);
+
+ if (tag == 0)
+ return NULL_TREE;
+ else if (tag == LTO_global_type_ref)
+ {
+ index = lto_input_uleb128 (ib);
+ result = data_in->file_data->types[index];
+ }
+ else if (tag == LTO_local_type_ref)
+ {
+ /* FIXME: Refactor to avoid all the cut/paste of
+ code cribbed from the VAR_DECL handler, here
+ and elsewhere. */
+ int lv_index = lto_input_uleb128 (ib);
+ result = data_in->local_decls [lv_index];
+ if (result == NULL)
+ {
+ /* Create a context to read the local variable so that
+ it does not disturb the position of the code that is
+ calling for the local variable. This allows locals
+ to refer to other locals. */
+ struct lto_input_block lib;
+
+#ifdef LTO_STREAM_DEBUGGING
+ struct lto_input_block *current = lto_debug_context.current_data;
+ struct lto_input_block debug;
+ int current_indent = lto_debug_context.indent;
+
+ debug.data = current->data;
+ debug.len = current->len;
+ debug.p = data_in->local_decls_index_d[lv_index];
+
+ lto_debug_context.indent = 0;
+ lto_debug_context.current_data = &debug;
+ lto_debug_context.tag_names = LTO_tree_tag_names;
+#endif
+ lib.data = ib->data;
+ lib.len = ib->len;
+ lib.p = data_in->local_decls_index[lv_index];
+
+ /* The TYPE_DECL case doesn't care about the FN argument. */
+ result = input_local_decl (&lib, data_in, NULL, lv_index);
+ gcc_assert (TYPE_P (result));
+ data_in->local_decls [lv_index] = result;
+
+#ifdef LTO_STREAM_DEBUGGING
+ lto_debug_context.indent = current_indent;
+ lto_debug_context.current_data = current;
+ lto_debug_context.tag_names = LTO_tree_tag_names;
+#endif
+ }
+ }
+ else
+ /* Not a type_ref. */
+ return input_expr_operand (ib, data_in, fn, tag);
+
+ LTO_DEBUG_UNDENT();
+ return result;
+}
+
/* Input local var I for FN from IB. */
static tree
-input_local_var (struct lto_input_block *ib, struct data_in *data_in,
- struct function *fn, unsigned int i)
+input_local_var_decl (struct lto_input_block *ib, struct data_in *data_in,
+ struct function *fn, unsigned int i, enum LTO_tags tag)
{
- enum LTO_tags tag;
unsigned int variant;
bool is_var;
unsigned int name_index;
@@ -1075,11 +1311,13 @@ input_local_var (struct lto_input_block *ib, struct data_in *data_in,
tree result;
tree context;
+#if 0
/* The line number info needs to be reset for each local var since
they are read in random order. */
clear_line_info (data_in);
tag = input_record_start (ib);
+#endif
variant = tag & 0xF;
is_var = ((tag & 0xFFF0) == LTO_local_var_decl_body0);
@@ -1129,7 +1367,6 @@ input_local_var (struct lto_input_block *ib, struct data_in *data_in,
}
flags = input_tree_flags (ib, 0, true);
- /* ### */
/* Bug fix for handling debug info previously omitted.
See comment in output_tree_flags, which failed to emit
the flags debug info in some cases. */
@@ -1173,8 +1410,230 @@ input_local_var (struct lto_input_block *ib, struct data_in *data_in,
}
+static tree
+input_local_field_decl (struct lto_input_block *ib, struct data_in *data_in,
+ struct function *fn, unsigned int i)
+{
+ lto_flags_type flags;
+ tree decl;
+
+ decl = make_node (FIELD_DECL);
+
+ flags = input_tree_flags (ib, FIELD_DECL, true);
+ if (input_line_info (ib, data_in, flags))
+ set_line_info (data_in, decl);
+ process_tree_flags (decl, flags);
+
+ data_in->local_decls[i] = decl;
+
+ /* omit locus, uid */
+ decl->decl_minimal.name = input_local_tree (ib, data_in, fn);
+ decl->decl_minimal.context = input_local_tree (ib, data_in, fn);
+
+ decl->common.type = input_local_tree (ib, data_in, fn);
+
+ decl->decl_common.attributes = input_local_tree (ib, data_in, fn);
+ decl->decl_common.abstract_origin = input_local_tree (ib, data_in, fn);
+
+ decl->decl_common.mode = lto_input_uleb128 (ib);
+ decl->decl_common.align = lto_input_uleb128 (ib);
+ decl->decl_common.off_align = lto_input_uleb128 (ib);
+
+ decl->decl_common.size = input_local_tree (ib, data_in, fn);
+ decl->decl_common.size_unit = input_local_tree (ib, data_in, fn);
+
+ decl->field_decl.offset = input_local_tree (ib, data_in, fn);
+ decl->field_decl.bit_field_type = input_local_tree (ib, data_in, fn);
+ decl->field_decl.qualifier = input_local_tree (ib, data_in, fn);
+ decl->field_decl.bit_offset = input_local_tree (ib, data_in, fn);
+ decl->field_decl.fcontext = input_local_tree (ib, data_in, fn);
+
+ decl->decl_common.initial = input_local_tree (ib, data_in, fn);
+
+ /* lang_specific */
+
+ decl->common.chain = input_local_tree (ib, data_in, fn);
+
+ return decl;
+}
+
+
+static tree
+input_local_type_decl (struct lto_input_block *ib, struct data_in *data_in,
+ struct function *fn, unsigned int i)
+{
+ lto_flags_type flags;
+ tree decl;
+
+ decl = make_node (TYPE_DECL);
+
+ flags = input_tree_flags (ib, TYPE_DECL, true);
+ if (input_line_info (ib, data_in, flags))
+ set_line_info (data_in, decl);
+ process_tree_flags (decl, flags);
+
+ data_in->local_decls[i] = decl;
+
+ /* omit locus, uid */
+ /* Must output name before type. */
+ decl->decl_minimal.name = input_local_tree (ib, data_in, fn);
+ decl->decl_minimal.context = input_local_tree (ib, data_in, fn);
+
+ decl->decl_with_vis.assembler_name = input_local_tree (ib, data_in, fn);
+ decl->decl_with_vis.section_name = input_local_tree (ib, data_in, fn);
+
+ decl->common.type = input_local_tree (ib, data_in, fn);
+
+ decl->decl_common.attributes = input_local_tree (ib, data_in, fn);
+ decl->decl_common.abstract_origin = input_local_tree (ib, data_in, fn);
+
+ decl->decl_common.mode = lto_input_uleb128 (ib);
+ decl->decl_common.align = lto_input_uleb128 (ib);
+
+ decl->decl_common.size = input_local_tree (ib, data_in, fn);
+ decl->decl_common.size_unit = input_local_tree (ib, data_in, fn);
+
+ /* lang_specific */
+ /* omit rtl */
+
+ decl->decl_common.initial = input_local_tree (ib, data_in, fn);
+
+ decl->decl_non_common.saved_tree = input_local_tree (ib, data_in, fn);
+ decl->decl_non_common.arguments = input_local_tree (ib, data_in, fn);
+ decl->decl_non_common.result = input_local_tree (ib, data_in, fn);
+ decl->decl_non_common.vindex = input_local_tree (ib, data_in, fn);
+
+ LTO_DEBUG_UNDENT();
+
+ return decl;
+}
+
+
+static tree
+input_local_type (struct lto_input_block *ib, struct data_in *data_in,
+ struct function *fn, unsigned int i, enum tree_code code)
+{
+ tree type;
+
+ type = make_node (code);
+ gcc_assert (TYPE_P (type));
+
+ process_tree_flags (type, input_tree_flags (ib, code, true));
+ /* Clear this flag, since we didn't stream the values cache. */
+ TYPE_CACHED_VALUES_P (type) = 0;
+
+ data_in->local_decls[i] = type;
+
+ LTO_DEBUG_TOKEN ("type");
+ type->common.type = input_local_tree (ib, data_in, fn);
+
+ LTO_DEBUG_TOKEN ("size");
+ type->type.size = input_local_tree (ib, data_in, fn);
+ LTO_DEBUG_TOKEN ("size_unit");
+ type->type.size_unit = input_local_tree (ib, data_in, fn);
+ LTO_DEBUG_TOKEN ("attributes");
+ type->type.attributes = input_local_tree (ib, data_in, fn);
+ LTO_DEBUG_TOKEN ("uid");
+ type->type.uid = lto_input_uleb128 (ib);
+ LTO_DEBUG_TOKEN ("precision");
+ type->type.precision = lto_input_uleb128 (ib);
+ LTO_DEBUG_TOKEN ("mode");
+ type->type.mode = lto_input_uleb128 (ib);
+ LTO_DEBUG_TOKEN ("align");
+ type->type.align = lto_input_uleb128 (ib);
+ LTO_DEBUG_TOKEN ("pointer_to");
+ /* FIXME: I think this is a cache that should not be streamed. */
+ type->type.pointer_to = input_local_tree (ib, data_in, fn);
+ LTO_DEBUG_TOKEN ("reference_to");
+ type->type.reference_to = input_local_tree (ib, data_in, fn);
+ /* FXIME: Read symtab here, if required. */
+ LTO_DEBUG_TOKEN ("name");
+ type->type.name = input_local_tree (ib, data_in, fn);
+ LTO_DEBUG_TOKEN ("minval");
+ type->type.minval = input_local_tree (ib, data_in, fn);
+ LTO_DEBUG_TOKEN ("maxval");
+ type->type.maxval = input_local_tree (ib, data_in, fn);
+ LTO_DEBUG_TOKEN ("next_variant");
+ type->type.next_variant = input_local_tree (ib, data_in, fn);
+ LTO_DEBUG_TOKEN ("main_variant");
+ type->type.main_variant = input_local_tree (ib, data_in, fn);
+ /* FIXME: Handle BINFO. */
+ /*
+ LTO_DEBUG_TOKEN ("binfo");
+ type->type.binfo = input_local_tree (ib, data_in, fn);
+ */
+ LTO_DEBUG_TOKEN ("context");
+ type->type.context = input_local_tree (ib, data_in, fn);
+ LTO_DEBUG_TOKEN ("canonical");
+ type->type.canonical = input_local_tree (ib, data_in, fn);
+
+ /* Do components last */
+ LTO_DEBUG_TOKEN ("values");
+ {
+ tree values = input_local_tree (ib, data_in, fn);
+ /* If using values cache, creation of integer
+ literals above may have allocated a new cache.
+ In this case, don't clobber it. */
+ if (!type->type.values)
+ type->type.values = values;
+ }
+
+ LTO_DEBUG_TOKEN ("chain");
+ type->common.chain = input_local_tree (ib, data_in, fn); /* TYPE_STUB_DECL */
+
+ LTO_DEBUG_UNDENT();
+
+ return type;
+}
+
+
+static tree
+input_local_decl (struct lto_input_block *ib, struct data_in *data_in,
+ struct function *fn, unsigned int i)
+{
+ enum LTO_tags tag;
+ tree result;
+
+ /* The line number info needs to be reset for each local decl since
+ they are read in random order. */
+ clear_line_info (data_in);
+
+ tag = input_record_start (ib);
+
+ /* FIXME: Use LTO_*_body nomenclature for fields and types?
+ Since we are reading from a separate local_decls stream,
+ re-use of the tags for a different purpose doesn't break
+ anything, but is perhaps ugly. */
+ if ((tag & 0xFFF0) == LTO_parm_decl_body0
+ || (tag & 0xFFF0) == LTO_local_var_decl_body0)
+ result = input_local_var_decl (ib, data_in, fn, i, tag);
+ else if (tag == LTO_type_decl0)
+ result = input_local_type_decl (ib, data_in, fn, i);
+ else if (tag == LTO_field_decl0)
+ result = input_local_field_decl (ib, data_in, fn, i);
+ else
+ {
+ enum tree_code code = tag_to_expr[tag];
+
+ gcc_assert (code);
+ gcc_assert (TREE_CODE_CLASS (code) == tcc_type);
+
+ result = input_local_type (ib, data_in, fn, i, code);
+ }
+
+ /* DEBUG */
+ /*
+ fprintf (stderr, "LOCAL: ");
+ print_generic_expr (stderr, result, 0);
+ fprintf (stderr, "\n");
+ */
+
+ return result;
+}
+
/* Load COUNT local var_decls and parm_decls from a DATA segment SIZE
bytes long using DATA_IN. */
+/* FIXME: We are really reading all local decls, not just vars. */
static void
input_local_vars (struct lto_input_block *ib, struct data_in *data_in,
@@ -1225,7 +1684,7 @@ input_local_vars (struct lto_input_block *ib, struct data_in *data_in,
= data_in->local_decls_index_d[i];
#endif
ib->p = data_in->local_decls_index[i];
- input_local_var (ib, data_in, fn, i);
+ input_local_decl (ib, data_in, fn, i);
}
/* Add the regular locals in the proper order. */
@@ -1416,7 +1875,6 @@ input_ssa_names (struct lto_input_block *ib, struct data_in *data_in, struct fun
ssa_name = make_ssa_name_fn (fn, name, build_empty_stmt ());
flags = input_tree_flags (ib, 0, true);
- /* ### */
/* Bug fix for handling debug info previously omitted.
See comment in output_tree_flags, which failed to emit
the flags debug info in some cases. */
@@ -1588,7 +2046,7 @@ static bool initialized_local = false;
/* Static initialization for the lto reader. */
-/* ### Declared in lto-section-in.h. Should probably be moved elsewhere. */
+/* FIXME: Declared in lto-section-in.h. Should probably be moved elsewhere. */
void
lto_static_init_local (void)
@@ -1844,7 +2302,12 @@ lto_read_body (struct lto_file_decl_data* file_data,
for (i = 0; i < file_data->num_var_decls; i++)
add_referenced_var (file_data->var_decls[i]);
for (j = 0; j < header->num_local_decls; j++)
- add_referenced_var (data_in.local_decls[j]);
+ {
+ tree decl = data_in.local_decls[j];
+ if (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == PARM_DECL)
+ add_referenced_var (decl);
+ }
}
#ifdef LTO_STREAM_DEBUGGING
@@ -1899,7 +2362,7 @@ lto_input_constructors_and_inits (struct lto_file_decl_data* file_data,
lto_read_body (file_data, NULL, data, LTO_section_static_initializer);
}
-/* ### Read types and globals. */
+/* Read types and globals. */
tree input_tree (struct lto_input_block *, struct data_in *);
tree input_type_tree (struct data_in *, struct lto_input_block *);
@@ -1917,7 +2380,7 @@ global_vector_enter (struct data_in *data_in, tree node)
{
unsigned index = VEC_length (tree, data_in->globals_index);
- /* ### DEBUG */
+ /* DEBUG */
/* fprintf (stderr, "ENTER %06u -> %p\n", index, node); */
VEC_safe_push (tree, heap, data_in->globals_index, node);
@@ -1928,7 +2391,7 @@ global_vector_enter (struct data_in *data_in, tree node)
static void
global_vector_fixup (struct data_in *data_in, unsigned index, tree node)
{
- /* ### DEBUG */
+ /* DEBUG */
/* fprintf (stderr, "FIXUP %06u -> %p\n", index, node); */
VEC_replace (tree, data_in->globals_index, index, node);
@@ -2020,7 +2483,7 @@ input_function_decl (struct lto_input_block *ib, struct data_in *data_in)
/* struct function is filled in when body is read */
- /* ### Adapted from DWARF reader. */
+ /* FIXME: Adapted from DWARF reader. Probably needs more thought. */
if (!TREE_PUBLIC (decl))
/* Need to ensure static entities between different files
don't clash unexpectedly. */
@@ -2093,7 +2556,7 @@ input_var_decl (struct lto_input_block *ib, struct data_in *data_in)
SET_DECL_DEBUG_EXPR (decl, debug_expr);
}
- /* ### Adapted from DWARF reader. */
+ /* FIXME: Adapted from DWARF reader. Probably needs more thought. */
if (!(decl->decl_minimal.context
&& TREE_CODE (decl->decl_minimal.context) == FUNCTION_DECL))
{
@@ -2222,7 +2685,7 @@ input_type_decl (struct lto_input_block *ib, struct data_in *data_in)
global_vector_enter (data_in, decl);
/* omit locus, uid */
- /* ### Must go before type */
+ /* Must output name before type. */
decl->decl_minimal.name = input_tree (ib, data_in);
decl->decl_minimal.context = input_tree (ib, data_in);
@@ -2433,11 +2896,11 @@ input_type (struct lto_input_block *ib, struct data_in *data_in, enum tree_code
LTO_DEBUG_TOKEN ("align");
type->type.align = lto_input_uleb128 (ib);
LTO_DEBUG_TOKEN ("pointer_to");
- /* ### I think this is a cache that should not be streamed. */
+ /* FIXME: I think this is a cache that should not be streamed. */
type->type.pointer_to = input_tree (ib, data_in);
LTO_DEBUG_TOKEN ("reference_to");
type->type.reference_to = input_tree (ib, data_in);
- /* ### Read symtab here, if required. */
+ /* FIXME: Read symtab here, if required. */
LTO_DEBUG_TOKEN ("name");
type->type.name = input_tree (ib, data_in);
LTO_DEBUG_TOKEN ("minval");
@@ -2521,7 +2984,7 @@ input_tree_operand (struct lto_input_block *ib, struct data_in *data_in,
flags = 0;
- /* ### Handlers for declarations currently handle line info themselves. */
+ /* Handlers for declarations currently handle line info themselves. */
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
|| IS_GIMPLE_STMT_CODE_CLASS(TREE_CODE_CLASS (code)))
needs_line_set = input_line_info (ib, data_in, flags);
@@ -2605,7 +3068,7 @@ input_tree_operand (struct lto_input_block *ib, struct data_in *data_in,
break;
case CASE_LABEL_EXPR:
- /* ### We shouldn't see these here. */
+ /* FIXME: We shouldn't see these here. Replace with assert? */
{
int variant = tag - LTO_case_label_expr0;
tree op0 = NULL_TREE;
@@ -2655,7 +3118,6 @@ input_tree_operand (struct lto_input_block *ib, struct data_in *data_in,
break;
case SSA_NAME:
- /* ### */
/* I'm not sure these are meaningful at file scope.
In any case, we cannot handle them in the same
manner as within a function body. */
@@ -2722,8 +3184,9 @@ input_tree_operand (struct lto_input_block *ib, struct data_in *data_in,
input_record_start (ib));
gcc_assert (label && TREE_CODE (label) == LABEL_DECL);
result = build1 (code, void_type_node, label);
- /* ###
- if (!DECL_CONTEXT (LABEL_EXPR_LABEL (result)))
+ /* FIXME: We may need this. */
+ /*
+ if (!DECL_CONTEXT (LABEL_EXPR_LABEL (result)))
DECL_CONTEXT (LABEL_EXPR_LABEL (result)) = fn->decl;
*/
gcc_assert (DECL_CONTEXT (LABEL_EXPR_LABEL (result)));
@@ -2863,7 +3326,7 @@ input_tree_operand (struct lto_input_block *ib, struct data_in *data_in,
break;
case RETURN_EXPR:
- /* ### We shouldn't see these here. */
+ /* We shouldn't see these here. */
gcc_unreachable ();
case RANGE_EXPR:
@@ -2888,7 +3351,7 @@ input_tree_operand (struct lto_input_block *ib, struct data_in *data_in,
break;
case SWITCH_EXPR:
- /* ### We shouldn't see these here. */
+ /* FIXME: We shouldn't see these here. Replace with assert? */
{
unsigned int len = lto_input_uleb128 (ib);
unsigned int i;
@@ -3111,7 +3574,7 @@ input_tree (struct lto_input_block *ib, struct data_in *data_in)
return NULL_TREE;
}
-/* ### Note reversed argument order. */
+/* FIXME: Note reversed argument order. */
tree
input_type_tree ( struct data_in *data_in, struct lto_input_block *ib)
{
diff --git a/gcc/lto-function-out.c b/gcc/lto-function-out.c
index beba935a09b..c61757c9b23 100644
--- a/gcc/lto-function-out.c
+++ b/gcc/lto-function-out.c
@@ -145,7 +145,7 @@ clear_line_info (struct output_block *ob)
/* Create the output block and return it. SECTION_TYPE is LTO_section_function_body or
lto_static_initializer. */
-/* ### Now declared in lto-section-out.h. Move definition to lto-section-out.c ? */
+/* FIXME: Now declared in lto-section-out.h. Move definition to lto-section-out.c ? */
struct output_block *
create_output_block (enum lto_section_type section_type)
@@ -191,7 +191,7 @@ create_output_block (enum lto_section_type section_type)
/* Destroy the output block OB. */
-/* ### Now declared in lto-section-out.h. Move definition to lto-section-out.c ? */
+/* FIXME: Now declared in lto-section-out.h. Move definition to lto-section-out.c ? */
void
destroy_output_block (struct output_block * ob)
@@ -497,7 +497,6 @@ output_tree_flags (struct output_block *ob, enum tree_code code, tree expr,
LTO_DEBUG_TOKEN ("flags");
output_widest_uint_uleb128 (ob, flags);
- /* ### */
/* Note that when we force flags with code == 0,
we cause the debugging info to be omitted.
I tried to fix this like so:
@@ -527,22 +526,90 @@ output_tree_flags (struct output_block *ob, enum tree_code code, tree expr,
}
}
+static void output_record_start (struct output_block *, tree, tree, unsigned int);
+static unsigned int output_local_decl_ref (struct output_block *, tree, bool);
+
+/* Return innermost enclosing FUNCTION_DECL for a type,
+ or NULL_TREE if there is none. */
+/* FIXME: Move this to tree.c alongside DECL_FUNCTION_CONTEXT. */
+/* FIXME: Can type be ERROR_MARK? See DECL_FUNCTION_CONTEXT. */
+
+static tree
+type_function_context (const_tree type)
+{
+ tree context = TYPE_CONTEXT (type);
+
+ while (context && TREE_CODE (context) != FUNCTION_DECL)
+ {
+ if (TREE_CODE (context) == BLOCK)
+ context = BLOCK_SUPERCONTEXT (context);
+ else
+ context = get_containing_scope (context);
+ }
+
+ return context;
+}
+
+/* Return true if a FIELD_DECL depends on a function context,
+ i.e., makes reference to a function body and should be serialized
+ with the function body, not the file scope. */
+
+static bool
+field_decl_is_local (tree decl)
+{
+#ifdef STREAM_LOCAL_TYPES
+ return (decl_function_context (decl)
+ || variably_modified_type_p (TREE_TYPE(decl), NULL)
+ || type_function_context (TREE_TYPE (decl)));
+#else
+ return false;
+#endif
+}
+
+/* Return true if a TYPE__DECL depends on a function context,
+ i.e., makes reference to a function body and should be serialized
+ with the function body, not the file scope. */
+
+static bool
+type_decl_is_local (tree decl)
+{
+#ifdef STREAM_LOCAL_TYPES
+ return (decl_function_context (decl)
+ || variably_modified_type_p (TREE_TYPE(decl), NULL));
+#else
+ return false;
+#endif
+}
/* Like output_type_ref, but no debug information is written. */
static void
output_type_ref_1 (struct output_block *ob, tree node)
{
- bool new;
- unsigned int index;
+#ifdef STREAM_LOCAL_TYPES
+ if (variably_modified_type_p (node, NULL) || type_function_context (node))
+ {
+ output_record_start (ob, NULL, NULL, LTO_local_type_ref);
+ output_local_decl_ref (ob, node, true);
+ }
+ else
+#endif
+ {
+ bool new;
+ unsigned int index;
- new = lto_output_decl_index (ob->main_stream,
- ob->decl_state->type_hash_table,
- &ob->decl_state->next_type_index,
- node, &index);
+ output_record_start (ob, NULL, NULL, LTO_global_type_ref);
- if (new)
- VEC_safe_push (tree, heap, ob->decl_state->types, node);
+ new = lto_output_decl_index (ob->main_stream,
+ ob->decl_state->type_hash_table,
+ &ob->decl_state->next_type_index,
+ node, &index);
+
+ if (new)
+ VEC_safe_push (tree, heap, ob->decl_state->types, node);
+ }
+
+ LTO_DEBUG_UNDENT();
}
@@ -552,7 +619,7 @@ output_type_ref_1 (struct output_block *ob, tree node)
static void
output_type_ref (struct output_block *ob, tree node)
{
- LTO_DEBUG_TOKEN ("type");
+ LTO_DEBUG_TOKEN ("type_ref");
output_type_ref_1 (ob, node);
}
@@ -570,8 +637,7 @@ output_local_decl_ref (struct output_block *ob, tree name, bool write)
ob->local_decl_hash_table,
&ob->next_local_decl_index,
name, &index);
- /* Push the new local var or param onto a vector for later
- processing. */
+ /* Push the new local decl onto a vector for later processing. */
if (new)
{
VEC_safe_push (tree, heap, ob->local_decls, name);
@@ -965,21 +1031,30 @@ output_expr_operand (struct output_block *ob, tree expr)
break;
case FIELD_DECL:
- {
- unsigned int index;
- bool new;
- output_record_start (ob, NULL, NULL, tag);
-
- new = lto_output_decl_index (ob->main_stream,
- ob->decl_state->field_decl_hash_table,
- &ob->decl_state->next_field_decl_index,
- expr, &index);
- if (new)
- VEC_safe_push (tree, heap, ob->decl_state->field_decls, expr);
- }
+ if (!field_decl_is_local (expr))
+ {
+ unsigned int index;
+ bool new;
+ output_record_start (ob, NULL, NULL, LTO_field_decl1);
+
+ new = lto_output_decl_index (ob->main_stream,
+ ob->decl_state->field_decl_hash_table,
+ &ob->decl_state->next_field_decl_index,
+ expr, &index);
+ if (new)
+ VEC_safe_push (tree, heap, ob->decl_state->field_decls, expr);
+ }
+ else
+ {
+ /* Local FIELD_DECLs. */
+ output_record_start (ob, NULL, NULL, LTO_field_decl0);
+ output_local_decl_ref (ob, expr, true);
+ }
break;
case FUNCTION_DECL:
+ /* FIXME: Local FUNCTION_DECLS are possible, i.e.,
+ nested functions. */
{
unsigned int index;
bool new;
@@ -1018,18 +1093,25 @@ output_expr_operand (struct output_block *ob, tree expr)
break;
case TYPE_DECL:
- {
- unsigned int index;
- bool new;
- output_record_start (ob, NULL, NULL, tag);
+ if (!type_decl_is_local (expr))
+ {
+ unsigned int index;
+ bool new;
+ output_record_start (ob, NULL, NULL, LTO_type_decl1);
- new = lto_output_decl_index (ob->main_stream,
- ob->decl_state->type_decl_hash_table,
- &ob->decl_state->next_type_decl_index,
- expr, &index);
- if (new)
- VEC_safe_push (tree, heap, ob->decl_state->type_decls, expr);
- }
+ new = lto_output_decl_index (ob->main_stream,
+ ob->decl_state->type_decl_hash_table,
+ &ob->decl_state->next_type_decl_index,
+ expr, &index);
+ if (new)
+ VEC_safe_push (tree, heap, ob->decl_state->type_decls, expr);
+ }
+ else
+ {
+ /* Local TYPE_DECLs. */
+ output_record_start (ob, NULL, NULL, LTO_type_decl0);
+ output_local_decl_ref (ob, expr, true);
+ }
break;
case NAMESPACE_DECL:
@@ -1317,10 +1399,11 @@ output_expr_operand (struct output_block *ob, tree expr)
LTO_DEBUG_UNDENT ();
}
-/* Output the local var INDEX to OB. */
+
+/* Output the local var at INDEX to OB. */
static void
-output_local_var (struct output_block *ob, int index)
+output_local_var_decl (struct output_block *ob, int index)
{
tree decl = VEC_index (tree, ob->local_decls, index);
unsigned int variant = 0;
@@ -1341,13 +1424,9 @@ output_local_var (struct output_block *ob, int index)
? LTO_local_var_decl_body0
: LTO_parm_decl_body0)
+ variant;
-
- VEC_replace (int, ob->local_decls_index, index, ob->main_stream->total_size);
-#ifdef LTO_STREAM_DEBUGGING
- VEC_replace (int, ob->local_decls_index_d, index, ob->debug_decl_stream->total_size);
-#endif
+
output_record_start (ob, NULL, NULL, tag);
-
+
/* Put out the name if there is one. */
if (DECL_NAME (decl))
{
@@ -1414,7 +1493,229 @@ output_local_var (struct output_block *ob, int index)
}
-/* Output the local var_decls and parm_decls to OB. */
+/* Emit tree node EXPR to output block OB. */
+
+static void
+output_local_tree (struct output_block *ob, tree expr)
+{
+ if (expr == NULL_TREE)
+ output_zero (ob);
+ else if (TYPE_P (expr))
+ output_type_ref_1 (ob, expr);
+ else
+ output_expr_operand (ob, expr);
+}
+
+
+/* Output the local field declaration DECL to OB.
+ A "local" field declaration is one that that has a
+ dependency on a function context, and should always
+ have been declared within a function. */
+
+static void
+output_local_field_decl (struct output_block *ob, tree decl)
+{
+ /* tag and flags */
+ output_record_start (ob, NULL, NULL, LTO_field_decl0);
+ output_tree_flags (ob, 0, decl, true);
+
+ /* uid and locus are handled specially */
+ output_local_tree (ob, decl->decl_minimal.name);
+ output_local_tree (ob, decl->decl_minimal.context);
+
+ output_local_tree (ob, decl->common.type);
+
+ output_local_tree (ob, decl->decl_common.attributes);
+ output_local_tree (ob, decl->decl_common.abstract_origin);
+
+ output_uleb128 (ob, decl->decl_common.mode);
+ output_uleb128 (ob, decl->decl_common.align);
+ output_uleb128 (ob, decl->decl_common.off_align);
+
+ output_local_tree (ob, decl->decl_common.size);
+ output_local_tree (ob, decl->decl_common.size_unit);
+
+ output_local_tree (ob, decl->field_decl.offset);
+ output_local_tree (ob, decl->field_decl.bit_field_type);
+ output_local_tree (ob, decl->field_decl.qualifier);
+ output_local_tree (ob, decl->field_decl.bit_offset);
+ output_local_tree (ob, decl->field_decl.fcontext);
+
+ /* lang_specific */
+ output_local_tree (ob, decl->decl_common.initial);
+
+ /* Write out current field before its siblings,
+ so follow the chain last. */
+ output_local_tree (ob, decl->common.chain);
+
+ LTO_DEBUG_UNDENT();
+}
+
+
+/* Output the local type declaration DECL to OB.
+ A "local" type declaration is one that that has a
+ dependency on a function context, and should always
+ have been declared within a function. */
+
+static void
+output_local_type_decl (struct output_block *ob, tree decl)
+{
+ /* tag and flags */
+ output_record_start (ob, NULL, NULL, LTO_type_decl0);
+ output_tree_flags (ob, 0, decl, true);
+
+ /* uid and locus are handled specially */
+ /* Must output name before type. */
+ output_local_tree (ob, decl->decl_minimal.name);
+ output_local_tree (ob, decl->decl_minimal.context);
+
+ output_local_tree (ob, decl->decl_with_vis.assembler_name);
+ output_local_tree (ob, decl->decl_with_vis.section_name);
+
+ output_local_tree (ob, decl->common.type);
+
+ output_local_tree (ob, decl->decl_common.attributes);
+ output_local_tree (ob, decl->decl_common.abstract_origin);
+
+ output_uleb128 (ob, decl->decl_common.mode);
+ output_uleb128 (ob, decl->decl_common.align);
+
+ output_local_tree (ob, decl->decl_common.size); /* ??? */
+ output_local_tree (ob, decl->decl_common.size_unit); /* ??? */
+
+ /* lang_specific */
+
+ gcc_assert (decl->decl_with_rtl.rtl == NULL);
+
+ output_local_tree (ob, decl->decl_common.initial); /* ??? */
+
+ output_local_tree (ob, decl->decl_non_common.saved_tree); /* ??? */
+ output_local_tree (ob, decl->decl_non_common.arguments); /* ??? */
+ output_local_tree (ob, decl->decl_non_common.result);
+ output_local_tree (ob, decl->decl_non_common.vindex); /* ??? */
+
+ LTO_DEBUG_UNDENT();
+}
+
+
+/* Output the local type TYPE to OB.
+ A "local" type is one that that has a dependency on a
+ function context, as the type of local var decl or
+ type decl, or a type that is variably-modified with a
+ dependency on a local variable or parameter. */
+
+static void
+output_local_type (struct output_block *ob, tree type, enum LTO_tags tag)
+{
+ /* tag and flags */
+ output_record_start (ob, NULL, NULL, tag);
+ output_tree_flags (ob, 0, type, false);
+
+ LTO_DEBUG_TOKEN ("type");
+ output_local_tree (ob, type->common.type);
+ LTO_DEBUG_TOKEN ("size");
+ output_local_tree (ob, type->type.size);
+ LTO_DEBUG_TOKEN ("size_unit");
+ output_local_tree (ob, type->type.size_unit);
+ LTO_DEBUG_TOKEN ("attributes");
+ output_local_tree (ob, type->type.attributes);
+ LTO_DEBUG_TOKEN ("uid");
+ output_uleb128 (ob, type->type.uid);
+ LTO_DEBUG_TOKEN ("precision");
+ output_uleb128 (ob, type->type.precision);
+ LTO_DEBUG_TOKEN ("mode");
+ output_uleb128 (ob, type->type.mode);
+ LTO_DEBUG_TOKEN ("align");
+ output_uleb128 (ob, type->type.align);
+ LTO_DEBUG_TOKEN ("pointer_to");
+ output_local_tree (ob, type->type.pointer_to);
+ LTO_DEBUG_TOKEN ("reference_to");
+ output_local_tree (ob, type->type.reference_to);
+ /* FIXME: Output symtab here. Do we need it? */
+ LTO_DEBUG_TOKEN ("name");
+ output_local_tree (ob, type->type.name); /* may be a TYPE_DECL */
+ LTO_DEBUG_TOKEN ("minval");
+ output_local_tree (ob, type->type.minval);
+ LTO_DEBUG_TOKEN ("maxval");
+ output_local_tree (ob, type->type.maxval);
+ LTO_DEBUG_TOKEN ("next_variant");
+ output_local_tree (ob, type->type.next_variant);
+ LTO_DEBUG_TOKEN ("main_variant");
+ output_local_tree (ob, type->type.main_variant);
+ /* FIXME: Handle BINFO. */
+ /*
+ LTO_DEBUG_TOKEN ("binfo");
+ output_local_tree (ob, type->type.binfo);
+ */
+ LTO_DEBUG_TOKEN ("context");
+ /* FIXME: We don't emit BLOCKs, so context must be a
+ function or toplevel. We probably break debugging. */
+ /*output_tree (ob, type->type.context);*/
+ output_local_tree (ob, type_function_context (type));
+ LTO_DEBUG_TOKEN ("canonical");
+ output_local_tree (ob, type->type.canonical);
+
+ /* Slot 'values' may be the structures fields, so do them last,
+ after other slots of the structure type have been filled in. */
+ LTO_DEBUG_TOKEN ("values");
+ if (TYPE_CACHED_VALUES_P (type))
+ {
+ gcc_assert (tag != RECORD_TYPE
+ && tag != UNION_TYPE
+ && tag != ARRAY_TYPE);
+ /* Don't stream the values cache. We must clear flag
+ TYPE_CACHED_VALUES_P on input. We don't do it here
+ because we don't want to clobber the tree as we write
+ it, and there is no infrastructure for modifying
+ flags as we serialize them. */
+ output_zero (ob);
+ }
+ else
+ output_local_tree (ob, type->type.values); /* should be a TREE_VEC */
+
+ LTO_DEBUG_TOKEN ("chain");
+ output_local_tree (ob, type->common.chain); /* overloaded as TYPE_STUB_DECL */
+
+ LTO_DEBUG_UNDENT();
+}
+
+
+/* Output the local declaration or type at INDEX to OB. */
+
+static void
+output_local_decl (struct output_block *ob, int index)
+{
+ tree decl = VEC_index (tree, ob->local_decls, index);
+
+ /* DEBUG */
+ /*
+ fprintf (stderr, "LOCAL: ");
+ print_generic_expr (stderr, decl, 0);
+ fprintf (stderr, "\n");
+ */
+
+ VEC_replace (int, ob->local_decls_index, index, ob->main_stream->total_size);
+#ifdef LTO_STREAM_DEBUGGING
+ VEC_replace (int, ob->local_decls_index_d, index, ob->debug_decl_stream->total_size);
+#endif
+
+ if (TREE_CODE (decl) == FIELD_DECL)
+ output_local_field_decl (ob, decl);
+ else if (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == PARM_DECL)
+ output_local_var_decl (ob, index);
+ else if (TREE_CODE (decl) == TYPE_DECL)
+ output_local_type_decl (ob, decl);
+ else
+ {
+ gcc_assert (TYPE_P (decl));
+
+ output_local_type (ob, decl, expr_to_tag [TREE_CODE (decl)]);
+ }
+}
+
+
+/* Output the local declarations and types to OB. */
static void
output_local_vars (struct output_block *ob, struct function *fn)
@@ -1480,7 +1781,7 @@ output_local_vars (struct output_block *ob, struct function *fn)
them. */
LTO_DEBUG_TOKEN ("local vars");
while (index < VEC_length (tree, ob->local_decls))
- output_local_var (ob, index++);
+ output_local_decl (ob, index++);
ob->main_stream = tmp_stream;
}
@@ -1822,7 +2123,6 @@ lto_static_init (void)
lto_types_needed_for = sbitmap_alloc (NUM_TREE_CODES);
- /* ### */
/* Global declarations and types will handle the
type field by other means, so lto_types_needed_for
should not be set for them. */
@@ -1848,7 +2148,7 @@ lto_static_init (void)
RESET_BIT (lto_types_needed_for, TYPE_DECL);
RESET_BIT (lto_types_needed_for, NAMESPACE_DECL);
RESET_BIT (lto_types_needed_for, TRANSLATION_UNIT_DECL);
- /* ### types -- should move into alphabetical order */
+ /* These forms *are* the types. */
RESET_BIT (lto_types_needed_for, VOID_TYPE);
RESET_BIT (lto_types_needed_for, INTEGER_TYPE);
RESET_BIT (lto_types_needed_for, REAL_TYPE);
@@ -2184,15 +2484,14 @@ lto_debug_tree_flags (struct lto_debug_context *context,
#endif
-/* ### Serialization of global types and declarations. */
+/* Serialization of global types and declarations. */
void output_tree (struct output_block *, tree);
void output_type_tree (struct output_block *, tree);
/* Output the start of a record with TAG and possibly flags for EXPR,
- and the TYPE for VALUE to OB. */
-
-/* ### Use output_type_tree instead of output_type_ref. */
+ and the TYPE for VALUE to OB. Unlike output_record_start, use
+ output_type_tree instead of output_type_ref. */
static void
output_global_record_start (struct output_block *ob, tree expr,
@@ -2215,7 +2514,7 @@ static void
output_field_decl (struct output_block *ob, tree decl)
{
/* tag and flags */
- output_global_record_start (ob, NULL, NULL, LTO_field_decl);
+ output_global_record_start (ob, NULL, NULL, LTO_field_decl1);
output_tree_flags (ob, 0, decl, true);
/* uid and locus are handled specially */
@@ -2358,7 +2657,7 @@ output_parm_decl (struct output_block *ob, tree decl)
output_tree (ob, decl->decl_common.size);
output_tree (ob, decl->decl_common.size_unit);
- output_tree (ob, decl->decl_common.initial); /* ### redundant? */
+ output_tree (ob, decl->decl_common.initial);
/* lang_specific */
/* omit rtl, incoming_rtl */
@@ -2392,7 +2691,8 @@ output_result_decl (struct output_block *ob, tree decl)
/* lang_specific */
/* omit rtl */
- output_tree (ob, decl->decl_common.initial); /* ### make sense for result? */
+ /* FIXME: Does this make sense for result? */
+ output_tree (ob, decl->decl_common.initial);
gcc_assert (!decl->common.chain);
}
@@ -2401,11 +2701,11 @@ static void
output_type_decl (struct output_block *ob, tree decl)
{
/* tag and flags */
- output_global_record_start (ob, NULL, NULL, LTO_type_decl);
+ output_global_record_start (ob, NULL, NULL, LTO_type_decl1);
output_tree_flags (ob, 0, decl, true);
/* uid and locus are handled specially */
- /* ### Must go before type. */
+ /* Must output name before type. */
output_tree (ob, decl->decl_minimal.name);
output_tree (ob, decl->decl_minimal.context);
@@ -2527,7 +2827,9 @@ output_translation_unit_decl (struct output_block *ob, tree decl)
gcc_assert (decl->decl_common.size == NULL_TREE);
gcc_assert (decl->decl_common.size_unit == NULL_TREE);
- /* ### omit initial for now -- I think it is covered elsewhere */
+ /* FIXME: Verify this. */
+ /* Omit initial value. I believe this is covered when
+ we read constructors and inits. */
gcc_assert (decl->decl_with_rtl.rtl == NULL);
@@ -2596,7 +2898,7 @@ output_type (struct output_block *ob, tree type, enum LTO_tags tag)
output_tree (ob, type->type.pointer_to);
LTO_DEBUG_TOKEN ("reference_to");
output_tree (ob, type->type.reference_to);
- /* ### Output symtab here. Do we need it? */
+ /* FIXME: Output symtab here. Do we need it? */
LTO_DEBUG_TOKEN ("name");
output_tree (ob, type->type.name); /* may be a TYPE_DECL */
LTO_DEBUG_TOKEN ("minval");
@@ -2636,7 +2938,7 @@ output_type (struct output_block *ob, tree type, enum LTO_tags tag)
output_tree (ob, type->common.chain); /* overloaded as TYPE_STUB_DECL */
}
-/* ### Use output_tree_operand */
+
/* Output constructor CTOR to OB. */
static void
@@ -2830,7 +3132,7 @@ output_tree (struct output_block *ob, tree expr)
break;
case CASE_LABEL_EXPR:
- /* ### We should not be seeing case labels here. */
+ /* FIXME: We should see case labels here. Assert? */
{
int variant = 0;
if (CASE_LOW (expr) != NULL_TREE)
@@ -2853,7 +3155,7 @@ output_tree (struct output_block *ob, tree expr)
break;
case SSA_NAME:
- /* ### I'm not sure SSA_NAME nodes make sense here. */
+ /* FIXME: I don't think SSA_NAME nodes make sense here. */
gcc_unreachable ();
/*
output_global_record_start (ob, expr, expr, LTO_ssa_name);
@@ -2984,7 +3286,6 @@ output_tree (struct output_block *ob, tree expr)
case ARRAY_RANGE_REF:
/* Ignore operands 2 and 3 for ARRAY_REF and ARRAY_RANGE REF
because they can be recomputed. */
- array_ref_low_bound (expr); /* ### DEBUG -- test for well-formedness */
output_global_record_start (ob, expr, expr, tag);
output_tree (ob, TREE_OPERAND (expr, 0));
output_tree (ob, TREE_OPERAND (expr, 1));
@@ -3073,7 +3374,7 @@ output_tree (struct output_block *ob, tree expr)
break;
case SWITCH_EXPR:
- /* ### We shouldn't see these here. */
+ /* FIXME: We should see these here. Assert? */
{
tree label_vec = TREE_OPERAND (expr, 2);
size_t len = TREE_VEC_LENGTH (label_vec);
diff --git a/gcc/lto-section-out.c b/gcc/lto-section-out.c
index d68c76169fe..d6ddcadb48a 100644
--- a/gcc/lto-section-out.c
+++ b/gcc/lto-section-out.c
@@ -59,7 +59,12 @@ hashval_t
lto_hash_decl_slot_node (const void *p)
{
const struct lto_decl_slot *ds = (const struct lto_decl_slot *) p;
- return (hashval_t) DECL_UID (ds->t);
+
+ /* ### */
+ /*
+ return (hashval_t) DECL_UID (ds->t);
+ */
+ return (hashval_t) TREE_HASH (ds->t);
}
@@ -73,7 +78,11 @@ lto_eq_decl_slot_node (const void *p1, const void *p2)
const struct lto_decl_slot *ds2 =
(const struct lto_decl_slot *) p2;
+ /* ### */
+ /*
return DECL_UID (ds1->t) == DECL_UID (ds2->t);
+ */
+ return ds1->t == ds2->t;
}
diff --git a/gcc/lto-tags.h b/gcc/lto-tags.h
index e4809819464..3141853d63e 100644
--- a/gcc/lto-tags.h
+++ b/gcc/lto-tags.h
@@ -325,7 +325,8 @@ enum LTO_tags {
LTO_eq_expr,
LTO_exact_div_expr,
LTO_exc_ptr_expr,
- LTO_field_decl,
+ LTO_field_decl0,
+ LTO_field_decl1,
LTO_filter_expr,
LTO_fixed_convert_expr,
LTO_fixed_cst,
@@ -406,7 +407,8 @@ enum LTO_tags {
LTO_truth_not_expr,
LTO_truth_or_expr,
LTO_truth_xor_expr,
- LTO_type_decl,
+ LTO_type_decl0,
+ LTO_type_decl1,
LTO_namespace_decl,
LTO_translation_unit_decl,
LTO_uneq_expr,
@@ -492,6 +494,9 @@ enum LTO_tags {
/* Special for global streamer. Reference to previously-streamed node. */
LTO_tree_pickle_reference,
+ LTO_local_type_ref,
+ LTO_global_type_ref,
+
/* There are 16 variants of the following decl bodies depending on the
subtrees that may or may not be there in the decl_common part of
the tree.
diff --git a/gcc/lto-tree-tags.def b/gcc/lto-tree-tags.def
index e66179b1831..06bda13352d 100644
--- a/gcc/lto-tree-tags.def
+++ b/gcc/lto-tree-tags.def
@@ -57,7 +57,9 @@
MAP_EXPR_TAGS(CASE_LABEL_EXPR, LTO_case_label_expr0, 4)
MAP_EXPR_TAGS(COND_EXPR, LTO_cond_expr0, 2)
MAP_EXPR_TAGS(COMPLEX_CST, LTO_complex_cst0, 2)
+ MAP_EXPR_TAGS(FIELD_DECL, LTO_field_decl0, 2)
MAP_EXPR_TAGS(RETURN_EXPR, LTO_return_expr0, 3)
+ MAP_EXPR_TAGS(TYPE_DECL, LTO_type_decl0, 2)
MAP_EXPR_TAGS(VAR_DECL, LTO_var_decl0, 2)
MAP_EXPR_TAGS(VECTOR_CST, LTO_vector_cst0, 2)
#endif
@@ -69,7 +71,6 @@
MAP_EXPR_TAG(COMPONENT_REF, LTO_component_ref)
MAP_EXPR_TAG(CONST_DECL, LTO_const_decl)
MAP_EXPR_TAG(CONSTRUCTOR, LTO_constructor)
- MAP_EXPR_TAG(FIELD_DECL, LTO_field_decl)
MAP_EXPR_TAG(FIXED_CST, LTO_fixed_cst)
MAP_EXPR_TAG(FUNCTION_DECL, LTO_function_decl)
MAP_EXPR_TAG(GIMPLE_MODIFY_STMT, LTO_gimple_modify_stmt)
@@ -91,7 +92,6 @@
MAP_EXPR_TAG(TREE_BINFO, LTO_tree_binfo)
MAP_EXPR_TAG(TREE_LIST, LTO_tree_list)
MAP_EXPR_TAG(TREE_VEC, LTO_tree_vec)
- MAP_EXPR_TAG(TYPE_DECL, LTO_type_decl)
/* ### types -- should move into alphabetical order */
MAP_EXPR_TAG(VOID_TYPE, LTO_void_type)
MAP_EXPR_TAG(INTEGER_TYPE, LTO_integer_type)
@@ -236,7 +236,8 @@
SET_NAME (LTO_eq_expr, "eq_expr")
SET_NAME (LTO_exact_div_expr, "exact_div_expr")
SET_NAME (LTO_exc_ptr_expr, "exc_ptr_expr")
- SET_NAME (LTO_field_decl, "field_decl")
+ SET_NAME (LTO_field_decl0, "field_decl0")
+ SET_NAME (LTO_field_decl1, "field_decl1")
SET_NAME (LTO_filter_expr, "filter_expr")
SET_NAME (LTO_fix_trunc_expr, "fix_trunc_expr")
SET_NAME (LTO_fixed_cst, "fixed_cst")
@@ -308,7 +309,8 @@
SET_NAME (LTO_truth_not_expr, "truth_not_expr")
SET_NAME (LTO_truth_or_expr, "truth_or_expr")
SET_NAME (LTO_truth_xor_expr, "truth_xor_expr")
- SET_NAME (LTO_type_decl, "type_decl")
+ SET_NAME (LTO_type_decl0, "type_decl0")
+ SET_NAME (LTO_type_decl1, "type_decl1")
SET_NAME (LTO_namespace_decl, "namespace_decl")
SET_NAME (LTO_uneq_expr, "uneq_expr")
SET_NAME (LTO_unge_expr, "unge_expr")
@@ -376,11 +378,12 @@
SET_NAME (LTO_eh_table_must_not_throw2, "eh_table_must_not_throw2")
SET_NAME (LTO_eh_table_must_not_throw3, "eh_table_must_not_throw3")
- /* ### */
/* Special for the global streamer. */
SET_NAME (LTO_tree_pickle_reference, "tree_pickle_reference")
-
/* ### */
+ SET_NAME (LTO_local_type_ref, "global_type_ref")
+ SET_NAME (LTO_global_type_ref, "global_type_ref")
+
/* The globals and types streamer uses the same tags used by
the local streamer to represent references to represent the
actual declarations instead. This was consistent with reusing