diff options
author | Bill Maddox <maddox@google.com> | 2008-06-10 02:00:29 +0000 |
---|---|---|
committer | Bill Maddox <maddox@google.com> | 2008-06-10 02:00:29 +0000 |
commit | beafeb7bd974fd8abd842a50d1f8c4cdc1b2a2b3 (patch) | |
tree | 08ecfa456655608ce088f374b50b5cc140b331d1 | |
parent | 288131c6f02a62d0accc753401931affa3fc33ce (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.lto | 52 | ||||
-rw-r--r-- | gcc/lto-function-in.c | 533 | ||||
-rw-r--r-- | gcc/lto-function-out.c | 431 | ||||
-rw-r--r-- | gcc/lto-section-out.c | 11 | ||||
-rw-r--r-- | gcc/lto-tags.h | 9 | ||||
-rw-r--r-- | gcc/lto-tree-tags.def | 15 |
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 |