Commit f0efc7aa by Diego Novillo Committed by Diego Novillo

rebase

From-SVN: r177571
parent b7926cf9
2011-08-08 Diego Novillo <dnovillo@google.com>
* Makefile.in (LTO_STREAMER_H): Add DIAGNOSTIC_H.
(DATA_STREAMER_H): New.
(GIMPLE_STREAMER_H): New.
(TREE_STREAMER_H): New.
(STREAMER_HOOKS_H): New.
(OBJS): Add data-streamer.o, data-streamer-in.o, data-streamer-out.o,
gimple-streamer-in.o, gimple-streamer-out.o, streamer-hooks.o,
tree-streamer.o, tree-streamer-in.o and tree-streamer-out.o.
(data-streamer.o): New.
(data-streamer-in.o): New.
(data-streamer-out.o): New.
(gimple-streamer-in.o): New.
(gimple-streamer-out.o): New.
(streamer-hooks.o): New.
(tree-streamer.o): New.
(tree-streamer-in.o): New.
(tree-streamer-out.o): New.
(lto-cgraph.o): Add dependency on DATA_STREAMER_H and
TREE_STREAMER_H.
(lto-streamer-in.o): Add dependency on DATA_STREAMER_H,
GIMPLE_STREAMER_H and TREE_STREAMER_H.
(lto-streamer-out.o): Add dependency on DATA_STREAMER_H,
GIMPLE_STREAMER_H and TREE_STREAMER_H.
(lto-streamer.o): Add dependency on STREAMER_HOOKS_H.
(ipa-prop.o): Add dependency on DATA_STREAMER_H and
TREE_STREAMER_H.
(ipa-inline-analysis.o): Likewise.
(ipa-pure-const.o): Likewise.
* data-streamer-in.c: New.
* data-streamer-out.c: New.
* data-streamer.c: New.
* data-streamer.h: New.
* gimple-streamer-in.c: New.
* gimple-streamer-out.c: New.
* gimple-streamer.h: New.
* ipa-inline-analysis.c: Include data-streamer.h.
* ipa-prop.c: Include data-streamer.h.
* ipa-pure-const.c: Include data-streamer.h.
* lto-cgraph.c: Include data-streamer.h.
* lto-section-in.c (lto_input_uleb128): Move to data-streamer-in.c.
(lto_input_widest_uint_uleb128): Likewise.
(lto_input_sleb128): Likewise.
(bp_unpack_var_len_unsigned): Likewise.
(bp_unpack_var_len_int): Likewise.
* lto-section-out.c (lto_output_uleb128_stream): Move to
data-streamer-out.c.
(lto_output_widest_uint_uleb128_stream): Likewise.
(lto_output_sleb128_stream): Likewise.
(bp_pack_var_len_unsigned): Likewise.
(bp_pack_var_len_int): Likewise.
* lto-streamer-in.c: Include data-streamer.h and
gimple-streamer.h.
(struct string_slot): Remove. Update all users.
(lto_tag_check_set): Make extern.
(lto_tag_check_range): Move to lto-streamer.h.
(lto_tag_check): Likewise.
(hash_string_slot_node): Remove. Update all users.
(eq_string_slot_node): Remove. Update all users.
(string_for_index): Move to data-streamer-in.c
(input_string_internal): Likewise.
(input_string_cst): Move to tree-streamer-in.c.
(input_identifier): Likewise.
(lto_input_string): Move to data-streamer-in.c
(input_record_start): Move to data-streamer.h
(canon_file_name): Use new definition of struct string_slot
from data-streamer.h.
Set S_SLOT.LEN.
(lto_input_location): Make extern.
(lto_input_chain): Move to tree-streamer-in.c.
(lto_init_eh): Make extern.
(input_phi): Move to gimple-streamer-in.c.
(input_gimple_stmt): Likewise.
(input_bb): Likewise.
(unpack_ts_base_value_fields): Move to tree-streamer-in.c.
(unpack_ts_real_cst_value_fields): Likewise.
(unpack_ts_fixed_cst_value_fields): Likewise.
(unpack_ts_decl_common_value_fields): Likewise.
(unpack_ts_decl_wrtl_value_fields): Likewise.
(unpack_ts_decl_with_vis_value_fields): Likewise.
(unpack_ts_function_decl_value_fields): Likewise.
(unpack_ts_type_common_value_fields): Likewise.
(unpack_ts_block_value_fields): Likewise.
(unpack_ts_translation_unit_decl_value_fields): Likewise.
(unpack_value_fields): Likewise.
(lto_materialize_tree): Likewise.
(lto_input_ts_common_tree_pointers): Likewise.
(lto_input_ts_vector_tree_pointers): Likewise.
(lto_input_ts_complex_tree_pointers): Likewise.
(lto_input_ts_decl_minimal_tree_pointers): Likewise.
(lto_input_ts_decl_common_tree_pointers): Likewise.
(lto_input_ts_decl_non_common_tree_pointers): Likewise.
(lto_input_ts_decl_with_vis_tree_pointers): Likewise.
(lto_input_ts_field_decl_tree_pointers): Likewise.
(lto_input_ts_function_decl_tree_pointers): Likewise.
(lto_input_ts_type_common_tree_pointers): Likewise.
(lto_input_ts_type_non_common_tree_pointers): Likewise.
(lto_input_ts_list_tree_pointers): Likewise.
(lto_input_ts_vec_tree_pointers): Likewise.
(lto_input_ts_exp_tree_pointers): Likewise.
(lto_input_ts_block_tree_pointers): Likewise.
(lto_input_ts_binfo_tree_pointers): Likewise.
(lto_input_ts_constructor_tree_pointers): Likewise.
(lto_input_ts_target_option): Likewise.
(lto_input_ts_translation_unit_decl_tree_pointers): Likewise.
(lto_input_tree_pointers): Likewise.
(lto_get_pickled_tree): Likewise.
(lto_get_builtin_tree): Likewise.
(lto_read_tree): Likewise.
(lto_input_integer_cst): Likewise.
(lto_input_tree): Likewise.
* lto-streamer-out.c: Include data-streamer.h,
gimple-streamer.h and streamer-hooks.h.
(struct string_slot): Move to data-streamer.h.
(hash_string_slot_node): Likewise.
(eq_string_slot_node): Likewise.
(lto_string_index): Move to data-streamer-out.c.
(lto_output_string_with_length): Likewise.
(lto_output_string): Likewise.
(output_string_cst): Move to tree-streamer-out.c.
(output_identifier): Likewise.
(output_zero): Move to data-streamer-out.c
(output_uleb128): Likewise.
(output_sleb128): Likewise.
(output_record_start): Move to data-streamer.h
(pack_ts_base_value_fields): Move to tree-streamer-out.c.
(pack_ts_real_cst_value_fields): Likewise.
(pack_ts_fixed_cst_value_fields): Likewise.
(pack_ts_decl_common_value_fields): Likewise.
(pack_ts_decl_wrtl_value_fields): Likewise.
(pack_ts_decl_with_vis_value_fields): Likewise.
(pack_ts_function_decl_value_fields): Likewise.
(pack_ts_type_common_value_fields): Likewise.
(pack_ts_block_value_fields): Likewise.
(pack_ts_translation_unit_decl_value_fields): Likewise.
(pack_value_fields): Likewise.
(lto_output_chain): Likewise.
(lto_output_ts_common_tree_pointers): Likewise.
(lto_output_ts_vector_tree_pointers): Likewise.
(lto_output_ts_complex_tree_pointers): Likewise.
(lto_output_ts_decl_minimal_tree_pointers): Likewise.
(lto_output_ts_decl_common_tree_pointers): Likewise.
(lto_output_ts_decl_non_common_tree_pointers): Likewise.
(lto_output_ts_decl_with_vis_tree_pointers): Likewise.
(lto_output_ts_field_decl_tree_pointers): Likewise.
(lto_output_ts_function_decl_tree_pointers): Likewise.
(lto_output_ts_type_common_tree_pointers): Likewise.
(lto_output_ts_type_non_common_tree_pointers): Likewise.
(lto_output_ts_list_tree_pointers): Likewise.
(lto_output_ts_vec_tree_pointers): Likewise.
(lto_output_ts_exp_tree_pointers): Likewise.
(lto_output_ts_block_tree_pointers): Likewise.
(lto_output_ts_binfo_tree_pointers): Likewise.
(lto_output_ts_constructor_tree_pointers): Likewise.
(lto_output_ts_target_option): Likewise.
(lto_output_ts_translation_unit_decl_tree_pointers): Likewise.
(lto_output_tree_pointers): Likewise.
(lto_output_tree_header): Likewise.
(lto_output_builtin_tree): Likewise.
(lto_write_tree): Likewise.
(lto_output_integer_cst): Likewise.
(lto_output_tree): Likewise.
(output_phi): Move to gimple-streamer-out.c.
(output_gimple_stmt): Likewise.
(output_bb): Likewise.
* lto-streamer.c: Include tree-streamer.h and streamer-hooks.h.
(streamer_hooks): Move to streamer-hooks.c.
(check_handled_ts_structures): Move to tree-streamer.c
(lto_streamer_cache_add_to_node_array): Likewise.
(lto_streamer_cache_insert_1): Likewise.
(lto_streamer_cache_insert): Likewise.
(lto_streamer_cache_insert_at): Likewise.
(lto_streamer_cache_append): Likewise.
(lto_streamer_cache_lookup): Likewise.
(lto_streamer_cache_get): Likewise.
(lto_record_common_node): Likewise.
(lto_preload_common_nodes): Likewise.
(lto_streamer_cache_create): Likewise.
(lto_streamer_cache_delete): Likewise.
(streamer_hooks_init): Move to streamer-hooks.c.
* lto-streamer.h: Include diagnostic.h
(struct output_block, struct lto_input_block,
struct data_in, struct bitpack_d): Remove forward
declarations.
(struct bitpack_d): Move to data-streamer.h.
(struct lto_streamer_cache_d): Move to tree-streamer.h.
(struct streamer_hooks): Move to streamer-hooks.h.
(bp_pack_var_len_unsigned): Move to data-streamer.h.
(bp_pack_var_len_int): Likewise.
(bp_unpack_var_len_unsigned): Likewise.
(bp_unpack_var_len_int): Likewise.
(lto_input_location): Declare.
(lto_tag_check_set): Declare.
(lto_init_eh): Declare.
(lto_output_tree_ref): Declare.
(lto_output_location): Declare.
(bitpack_create): Move to data-streamer.h.
(bp_pack_value): Likewise.
(lto_output_bitpack): Likewise.
(lto_input_bitpack): Likewise.
(bp_unpack_value): Likewise.
(lto_output_1_stream): Likewise.
(lto_input_1_unsigned): Likewise.
(lto_output_int_in_range): Likewise.
(lto_input_int_in_range): Likewise.
(bp_pack_int_in_range): Likewise.
(bp_unpack_int_in_range): Likewise.
(lto_output_enum): Likewise.
(lto_input_enum): Likewise.
(bp_pack_enum): Likewise.
(bp_unpack_enum): Likewise.
* streamer-hooks.c: New.
* streamer-hooks.h: New.
* tree-streamer-in.c: New.
* tree-streamer-out.c: New.
* tree-streamer.c: New.
* tree-streamer.h: New.
2011-08-08 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* gthr-posix95.h: Remove.
......
......@@ -995,7 +995,12 @@ DBGCNT_H = dbgcnt.h dbgcnt.def
EBITMAP_H = ebitmap.h sbitmap.h
LTO_STREAMER_H = lto-streamer.h $(LINKER_PLUGIN_API_H) $(TARGET_H) \
$(CGRAPH_H) $(VEC_H) vecprim.h $(TREE_H) $(GIMPLE_H) \
$(GCOV_IO_H)
$(GCOV_IO_H) $(DIAGNOSTIC_H)
DATA_STREAMER_H = data-streamer.h $(VEC_H) $(LTO_STREAMER_H)
GIMPLE_STREAMER_H = gimple-streamer.h $(LTO_STREAMER_H) $(BASIC_BLOCK_H) \
$(FUNCTION_H)
TREE_STREAMER_H = tree-streamer.h $(TREE_H) $(LTO_STREAMER_H)
STREAMER_HOOKS_H = streamer-hooks.h $(TREE_H)
TREE_VECTORIZER_H = tree-vectorizer.h $(TREE_DATA_REF_H)
IPA_PROP_H = ipa-prop.h $(TREE_H) $(VEC_H) $(CGRAPH_H) $(GIMPLE_H) alloc-pool.h
GSTAB_H = gstab.h stab.def
......@@ -1239,6 +1244,9 @@ OBJS = \
cprop.o \
cse.o \
cselib.o \
data-streamer.o \
data-streamer-in.o \
data-streamer-out.o \
dbxout.o \
dbgcnt.o \
dce.o \
......@@ -1275,6 +1283,8 @@ OBJS = \
gimple-fold.o \
gimple-low.o \
gimple-pretty-print.o \
gimple-streamer-in.o \
gimple-streamer-out.o \
gimplify.o \
godump.o \
graph.o \
......@@ -1330,13 +1340,13 @@ OBJS = \
loop-unswitch.o \
lower-subreg.o \
lto-cgraph.o \
lto-streamer.o \
lto-streamer-in.o \
lto-streamer-out.o \
lto-section-in.o \
lto-section-out.o \
lto-symtab.o \
lto-opts.o \
lto-streamer.o \
lto-compress.o \
matrix-reorg.o \
mcf.o \
......@@ -1391,6 +1401,7 @@ OBJS = \
stmt.o \
stor-layout.o \
store-motion.o \
streamer-hooks.o \
stringpool.o \
target-globals.o \
targhooks.o \
......@@ -1467,6 +1478,9 @@ OBJS = \
tree-ssa.o \
tree-ssanames.o \
tree-stdarg.o \
tree-streamer.o \
tree-streamer-in.o \
tree-streamer-out.o \
tree-tailcall.o \
tree-vect-generic.o \
tree-vect-patterns.o \
......@@ -2281,22 +2295,47 @@ lto-compress.o: lto-compress.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TREE_H) langhooks.h $(LTO_STREAMER_H) $(LTO_SECTION_H) \
lto-compress.h $(DIAGNOSTIC_CORE_H) $(DIAGNOSTIC_CORE_H)
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(ZLIBINC) $< $(OUTPUT_OPTION)
data-streamer-in.o: data-streamer-in.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(DATA_STREAMER_H) $(DIAGNOSTIC_H)
data-streamer-out.o: data-streamer-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(DATA_STREAMER_H)
data-streamer.o: data-streamer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(DATA_STREAMER_H)
gimple-streamer-in.o: gimple-streamer-in.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(GIMPLE_STREAMER_H) $(TREE_FLOW_H) $(DATA_STREAMER_H) \
$(TREE_STREAMER_H) $(DIAGNOSTIC_H)
gimple-streamer-out.o: gimple-streamer-out.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(GIMPLE_STREAMER_H) $(DATA_STREAMER_H) $(TREE_FLOW_H) \
$(LTO_STREAMER_H)
tree-streamer.o: tree-streamer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TREE_STREAMER_H) $(STREAMER_HOOKS_H)
tree-streamer-in.o: tree-streamer-in.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(DIAGNOSTIC_H) $(TREE_H) $(TREE_FLOW_H) $(TREE_STREAMER_H) \
$(DATA_STREAMER_H) $(STREAMER_HOOKS_H) $(LTO_STREAMER_H)
tree-streamer-out.o: tree-streamer-out.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(DIAGNOSTIC_H) $(TREE_STREAMER_H) $(DATA_STREAMER_H) \
$(STREAMER_HOOKS_H)
streamer-hooks.o: streamer-hooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(STREAMER_HOOKS_H)
lto-cgraph.o: lto-cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(DIAGNOSTIC_CORE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \
$(HASHTAB_H) langhooks.h $(BASIC_BLOCK_H) \
$(TREE_FLOW_H) $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_CORE_H) \
$(EXCEPT_H) $(TIMEVAR_H) output.h pointer-set.h $(LTO_STREAMER_H) $(GCOV_IO_H)
$(EXCEPT_H) $(TIMEVAR_H) output.h pointer-set.h $(LTO_STREAMER_H) \
$(GCOV_IO_H) $(DATA_STREAMER_H) $(TREE_STREAMER_H)
lto-streamer-in.o: lto-streamer-in.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) toplev.h $(DIAGNOSTIC_CORE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \
$(HASHTAB_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TREE_PASS_H) $(CGRAPH_H) \
$(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) $(LIBFUNCS_H) $(EXCEPT_H) debug.h \
$(TIMEVAR_H) output.h $(IPA_UTILS_H) $(LTO_STREAMER_H) toplev.h
$(TIMEVAR_H) output.h $(IPA_UTILS_H) $(LTO_STREAMER_H) toplev.h \
$(DATA_STREAMER_H) $(GIMPLE_STREAMER_H) $(TREE_STREAMER_H)
lto-streamer-out.o : lto-streamer-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(DIAGNOSTIC_CORE_H) $(TREE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \
$(HASHTAB_H) $(BASIC_BLOCK_H) tree-iterator.h \
$(TREE_FLOW_H) $(TREE_PASS_H) $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) \
$(DIAGNOSTIC_CORE_H) $(EXCEPT_H) $(LTO_STREAMER_H) $(DIAGNOSTIC_CORE_H)
$(DIAGNOSTIC_CORE_H) $(EXCEPT_H) $(LTO_STREAMER_H) $(DIAGNOSTIC_CORE_H) \
$(DATA_STREAMER_H) $(STREAMER_HOOKS_H) $(GIMPLE_STREAMER_H) \
$(TREE_STREAMER_H)
lto-section-in.o: lto-section-in.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(DIAGNOSTIC_CORE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \
$(HASHTAB_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(CGRAPH_H) $(FUNCTION_H) \
......@@ -2315,7 +2354,8 @@ lto-opts.o: lto-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
$(COMMON_TARGET_H) $(DIAGNOSTIC_H) $(LTO_STREAMER_H)
lto-streamer.o: lto-streamer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) $(GIMPLE_H) $(BITMAP_H) $(LTO_STREAMER_H) $(FLAGS_H) \
$(TREE_FLOW_H) $(DIAGNOSTIC_CORE_H) $(LTO_SYMTAB_H) toplev.h $(DIAGNOSTIC_CORE_H)
$(TREE_FLOW_H) $(DIAGNOSTIC_CORE_H) $(LTO_SYMTAB_H) toplev.h \
$(DIAGNOSTIC_CORE_H) $(STREAMER_HOOKS_H)
langhooks.o : langhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) toplev.h $(DIAGNOSTIC_CORE_H) $(TREE_INLINE_H) $(RTL_H) insn-config.h $(INTEGRATE_H) \
langhooks.h $(TARGET_H) $(LANGHOOKS_DEF_H) $(FLAGS_H) $(GGC_H) $(DIAGNOSTIC_H) \
......@@ -2995,7 +3035,8 @@ ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(DIAGNOSTIC_H) \
$(TREE_FLOW_H) $(TM_H) $(TREE_PASS_H) $(FLAGS_H) $(TREE_H) \
$(TREE_INLINE_H) $(GIMPLE_H) $(TIMEVAR_H) \
tree-pretty-print.h gimple-pretty-print.h $(LTO_STREAMER_H)
tree-pretty-print.h gimple-pretty-print.h $(LTO_STREAMER_H) \
$(DATA_STREAMER_H) $(TREE_STREAMER_H)
ipa-ref.o : ipa-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) $(TREE_H) $(TARGET_H) \
$(TREE_FLOW_H) $(TM_H) $(TREE_PASS_H) $(FLAGS_H) $(TREE_H) $(GGC_H)
......@@ -3023,7 +3064,8 @@ ipa-inline-analysis.o : ipa-inline-analysis.c $(CONFIG_H) $(SYSTEM_H) coretypes.
$(TREE_H) langhooks.h $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) intl.h \
$(DIAGNOSTIC_H) $(PARAMS_H) $(TIMEVAR_H) $(TREE_PASS_H) \
$(HASHTAB_H) $(COVERAGE_H) $(GGC_H) $(TREE_FLOW_H) $(IPA_PROP_H) \
gimple-pretty-print.h ipa-inline.h $(LTO_STREAMER_H)
gimple-pretty-print.h ipa-inline.h $(LTO_STREAMER_H) $(DATA_STREAMER_H) \
$(TREE_STREAMER_H)
ipa-inline-transform.o : ipa-inline-transform.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) intl.h \
$(DIAGNOSTIC_H) $(PARAMS_H) $(TIMEVAR_H) $(TREE_PASS_H) \
......@@ -3043,7 +3085,7 @@ ipa-pure-const.o : ipa-pure-const.c $(CONFIG_H) $(SYSTEM_H) \
pointer-set.h $(GGC_H) $(IPA_UTILS_H) $(TARGET_H) \
$(GIMPLE_H) $(CGRAPH_H) output.h $(FLAGS_H) $(TREE_PASS_H) $(TIMEVAR_H) \
$(DIAGNOSTIC_H) $(CFGLOOP_H) $(SCEV_H) $(LTO_STREAMER_H) \
gimple-pretty-print.h
gimple-pretty-print.h $(DATA_STREAMER_H) $(TREE_STREAMER_H)
coverage.o : coverage.c $(GCOV_IO_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) \
$(FUNCTION_H) $(BASIC_BLOCK_H) toplev.h $(DIAGNOSTIC_CORE_H) $(GGC_H) langhooks.h $(COVERAGE_H) \
......
/* Routines for restoring various data types from a file stream. This deals
with various data types like strings, integers, enums, etc.
Copyright 2011 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@google.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "diagnostic.h"
#include "data-streamer.h"
/* Read a string from the string table in DATA_IN using input block
IB. Write the length to RLEN. */
const char *
string_for_index (struct data_in *data_in, unsigned int loc, unsigned int *rlen)
{
struct lto_input_block str_tab;
unsigned int len;
const char *result;
if (!loc)
{
*rlen = 0;
return NULL;
}
/* Get the string stored at location LOC in DATA_IN->STRINGS. */
LTO_INIT_INPUT_BLOCK (str_tab, data_in->strings, loc - 1,
data_in->strings_len);
len = lto_input_uleb128 (&str_tab);
*rlen = len;
if (str_tab.p + len > data_in->strings_len)
internal_error ("bytecode stream: string too long for the string table");
result = (const char *)(data_in->strings + str_tab.p);
return result;
}
/* Read a string from the string table in DATA_IN using input block
IB. Write the length to RLEN. */
const char *
input_string_internal (struct data_in *data_in, struct lto_input_block *ib,
unsigned int *rlen)
{
return string_for_index (data_in, lto_input_uleb128 (ib), rlen);
}
/* Read a NULL terminated string from the string table in DATA_IN. */
const char *
lto_input_string (struct data_in *data_in, struct lto_input_block *ib)
{
unsigned int len;
const char *ptr;
ptr = input_string_internal (data_in, ib, &len);
if (!ptr)
return NULL;
if (ptr[len - 1] != '\0')
internal_error ("bytecode stream: found non-null terminated string");
return ptr;
}
/* Read an ULEB128 Number of IB. */
unsigned HOST_WIDE_INT
lto_input_uleb128 (struct lto_input_block *ib)
{
unsigned HOST_WIDE_INT result = 0;
int shift = 0;
unsigned HOST_WIDE_INT byte;
while (true)
{
byte = lto_input_1_unsigned (ib);
result |= (byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
return result;
}
}
/* HOST_WIDEST_INT version of lto_input_uleb128. IB is as in
lto_input_uleb128. */
unsigned HOST_WIDEST_INT
lto_input_widest_uint_uleb128 (struct lto_input_block *ib)
{
unsigned HOST_WIDEST_INT result = 0;
int shift = 0;
unsigned HOST_WIDEST_INT byte;
while (true)
{
byte = lto_input_1_unsigned (ib);
result |= (byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
return result;
}
}
/* Read an SLEB128 Number of IB. */
HOST_WIDE_INT
lto_input_sleb128 (struct lto_input_block *ib)
{
HOST_WIDE_INT result = 0;
int shift = 0;
unsigned HOST_WIDE_INT byte;
while (true)
{
byte = lto_input_1_unsigned (ib);
result |= (byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
{
if ((shift < HOST_BITS_PER_WIDE_INT) && (byte & 0x40))
result |= - ((HOST_WIDE_INT)1 << shift);
return result;
}
}
}
/* Routines for saving various data types to a file stream. This deals
with various data types like strings, integers, enums, etc.
Copyright 2011 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@google.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "data-streamer.h"
/* Return index used to reference STRING of LEN characters in the string table
in OB. The string might or might not include a trailing '\0'.
Then put the index onto the INDEX_STREAM.
When PERSISTENT is set, the string S is supposed to not change during
duration of the OB and thus OB can keep pointer into it. */
unsigned
lto_string_index (struct output_block *ob, const char *s, unsigned int len,
bool persistent)
{
struct string_slot **slot;
struct string_slot s_slot;
s_slot.s = s;
s_slot.len = len;
s_slot.slot_num = 0;
slot = (struct string_slot **) htab_find_slot (ob->string_hash_table,
&s_slot, INSERT);
if (*slot == NULL)
{
struct lto_output_stream *string_stream = ob->string_stream;
unsigned int start = string_stream->total_size;
struct string_slot *new_slot = XOBNEW (&ob->obstack, struct string_slot);
const char *string;
if (!persistent)
{
char *tmp;
string = tmp = XOBNEWVEC (&ob->obstack, char, len);
memcpy (tmp, s, len);
}
else
string = s;
new_slot->s = string;
new_slot->len = len;
new_slot->slot_num = start;
*slot = new_slot;
lto_output_uleb128_stream (string_stream, len);
lto_output_data_stream (string_stream, string, len);
return start + 1;
}
else
{
struct string_slot *old_slot = *slot;
return old_slot->slot_num + 1;
}
}
/* Output STRING of LEN characters to the string table in OB. The
string might or might not include a trailing '\0'. Then put the
index onto the INDEX_STREAM.
When PERSISTENT is set, the string S is supposed to not change during
duration of the OB and thus OB can keep pointer into it. */
void
lto_output_string_with_length (struct output_block *ob,
struct lto_output_stream *index_stream,
const char *s, unsigned int len, bool persistent)
{
if (s)
lto_output_uleb128_stream (index_stream,
lto_string_index (ob, s, len, persistent));
else
lto_output_1_stream (index_stream, 0);
}
/* Output the '\0' terminated STRING to the string
table in OB. Then put the index onto the INDEX_STREAM.
When PERSISTENT is set, the string S is supposed to not change during
duration of the OB and thus OB can keep pointer into it. */
void
lto_output_string (struct output_block *ob,
struct lto_output_stream *index_stream,
const char *string, bool persistent)
{
if (string)
lto_output_string_with_length (ob, index_stream, string,
strlen (string) + 1,
persistent);
else
lto_output_1_stream (index_stream, 0);
}
/* Write a zero to the output stream. */
void
output_zero (struct output_block *ob)
{
lto_output_1_stream (ob->main_stream, 0);
}
/* Output an unsigned LEB128 quantity to OB->main_stream. */
void
output_uleb128 (struct output_block *ob, unsigned HOST_WIDE_INT work)
{
lto_output_uleb128_stream (ob->main_stream, work);
}
/* Output a signed LEB128 quantity to OB->main_stream. */
void
output_sleb128 (struct output_block *ob, HOST_WIDE_INT work)
{
lto_output_sleb128_stream (ob->main_stream, work);
}
/* Output an unsigned LEB128 quantity to OBS. */
void
lto_output_uleb128_stream (struct lto_output_stream *obs,
unsigned HOST_WIDE_INT work)
{
do
{
unsigned int byte = (work & 0x7f);
work >>= 7;
if (work != 0)
/* More bytes to follow. */
byte |= 0x80;
lto_output_1_stream (obs, byte);
}
while (work != 0);
}
/* Identical to output_uleb128_stream above except using unsigned
HOST_WIDEST_INT type. For efficiency on host where unsigned HOST_WIDEST_INT
is not native, we only use this if we know that HOST_WIDE_INT is not wide
enough. */
void
lto_output_widest_uint_uleb128_stream (struct lto_output_stream *obs,
unsigned HOST_WIDEST_INT work)
{
do
{
unsigned int byte = (work & 0x7f);
work >>= 7;
if (work != 0)
/* More bytes to follow. */
byte |= 0x80;
lto_output_1_stream (obs, byte);
}
while (work != 0);
}
/* Output a signed LEB128 quantity. */
void
lto_output_sleb128_stream (struct lto_output_stream *obs, HOST_WIDE_INT work)
{
int more, byte;
do
{
byte = (work & 0x7f);
/* arithmetic shift */
work >>= 7;
more = !((work == 0 && (byte & 0x40) == 0)
|| (work == -1 && (byte & 0x40) != 0));
if (more)
byte |= 0x80;
lto_output_1_stream (obs, byte);
}
while (more);
}
/* Generic streaming support for basic data types.
Copyright 2011 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@google.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "data-streamer.h"
/* Pack WORK into BP in a variant of uleb format. */
void
bp_pack_var_len_unsigned (struct bitpack_d *bp, unsigned HOST_WIDE_INT work)
{
do
{
unsigned int half_byte = (work & 0x7);
work >>= 3;
if (work != 0)
/* More half_bytes to follow. */
half_byte |= 0x8;
bp_pack_value (bp, half_byte, 4);
}
while (work != 0);
}
/* Pack WORK into BP in a variant of sleb format. */
void
bp_pack_var_len_int (struct bitpack_d *bp, HOST_WIDE_INT work)
{
int more, half_byte;
do
{
half_byte = (work & 0x7);
/* arithmetic shift */
work >>= 3;
more = !((work == 0 && (half_byte & 0x4) == 0)
|| (work == -1 && (half_byte & 0x4) != 0));
if (more)
half_byte |= 0x8;
bp_pack_value (bp, half_byte, 4);
}
while (more);
}
/* Unpack VAL from BP in a variant of uleb format. */
unsigned HOST_WIDE_INT
bp_unpack_var_len_unsigned (struct bitpack_d *bp)
{
unsigned HOST_WIDE_INT result = 0;
int shift = 0;
unsigned HOST_WIDE_INT half_byte;
while (true)
{
half_byte = bp_unpack_value (bp, 4);
result |= (half_byte & 0x7) << shift;
shift += 3;
if ((half_byte & 0x8) == 0)
return result;
}
}
/* Unpack VAL from BP in a variant of sleb format. */
HOST_WIDE_INT
bp_unpack_var_len_int (struct bitpack_d *bp)
{
HOST_WIDE_INT result = 0;
int shift = 0;
unsigned HOST_WIDE_INT half_byte;
while (true)
{
half_byte = bp_unpack_value (bp, 4);
result |= (half_byte & 0x7) << shift;
shift += 3;
if ((half_byte & 0x8) == 0)
{
if ((shift < HOST_BITS_PER_WIDE_INT) && (half_byte & 0x4))
result |= - ((HOST_WIDE_INT)1 << shift);
return result;
}
}
}
/* Routines for reading GIMPLE from a file stream.
Copyright 2011 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@google.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "diagnostic.h"
#include "tree.h"
#include "tree-flow.h"
#include "data-streamer.h"
#include "tree-streamer.h"
#include "gimple-streamer.h"
/* Read a PHI function for basic block BB in function FN. DATA_IN is
the file being read. IB is the input block to use for reading. */
static gimple
input_phi (struct lto_input_block *ib, basic_block bb, struct data_in *data_in,
struct function *fn)
{
unsigned HOST_WIDE_INT ix;
tree phi_result;
int i, len;
gimple result;
ix = lto_input_uleb128 (ib);
phi_result = VEC_index (tree, SSANAMES (fn), ix);
len = EDGE_COUNT (bb->preds);
result = create_phi_node (phi_result, bb);
SSA_NAME_DEF_STMT (phi_result) = result;
/* We have to go through a lookup process here because the preds in the
reconstructed graph are generally in a different order than they
were in the original program. */
for (i = 0; i < len; i++)
{
tree def = lto_input_tree (ib, data_in);
int src_index = lto_input_uleb128 (ib);
location_t arg_loc = lto_input_location (ib, data_in);
basic_block sbb = BASIC_BLOCK_FOR_FUNCTION (fn, src_index);
edge e = NULL;
int j;
for (j = 0; j < len; j++)
if (EDGE_PRED (bb, j)->src == sbb)
{
e = EDGE_PRED (bb, j);
break;
}
add_phi_arg (result, def, e, arg_loc);
}
return result;
}
/* Read a statement with tag TAG in function FN from block IB using
descriptors in DATA_IN. */
static gimple
input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
struct function *fn, enum LTO_tags tag)
{
gimple stmt;
enum gimple_code code;
unsigned HOST_WIDE_INT num_ops;
size_t i;
struct bitpack_d bp;
code = lto_tag_to_gimple_code (tag);
/* Read the tuple header. */
bp = lto_input_bitpack (ib);
num_ops = bp_unpack_var_len_unsigned (&bp);
stmt = gimple_alloc (code, num_ops);
stmt->gsbase.no_warning = bp_unpack_value (&bp, 1);
if (is_gimple_assign (stmt))
stmt->gsbase.nontemporal_move = bp_unpack_value (&bp, 1);
stmt->gsbase.has_volatile_ops = bp_unpack_value (&bp, 1);
stmt->gsbase.subcode = bp_unpack_var_len_unsigned (&bp);
/* Read location information. */
gimple_set_location (stmt, lto_input_location (ib, data_in));
/* Read lexical block reference. */
gimple_set_block (stmt, lto_input_tree (ib, data_in));
/* Read in all the operands. */
switch (code)
{
case GIMPLE_RESX:
gimple_resx_set_region (stmt, lto_input_sleb128 (ib));
break;
case GIMPLE_EH_MUST_NOT_THROW:
gimple_eh_must_not_throw_set_fndecl (stmt, lto_input_tree (ib, data_in));
break;
case GIMPLE_EH_DISPATCH:
gimple_eh_dispatch_set_region (stmt, lto_input_sleb128 (ib));
break;
case GIMPLE_ASM:
{
/* FIXME lto. Move most of this into a new gimple_asm_set_string(). */
tree str;
stmt->gimple_asm.ni = lto_input_uleb128 (ib);
stmt->gimple_asm.no = lto_input_uleb128 (ib);
stmt->gimple_asm.nc = lto_input_uleb128 (ib);
stmt->gimple_asm.nl = lto_input_uleb128 (ib);
str = input_string_cst (data_in, ib);
stmt->gimple_asm.string = TREE_STRING_POINTER (str);
}
/* Fallthru */
case GIMPLE_ASSIGN:
case GIMPLE_CALL:
case GIMPLE_RETURN:
case GIMPLE_SWITCH:
case GIMPLE_LABEL:
case GIMPLE_COND:
case GIMPLE_GOTO:
case GIMPLE_DEBUG:
for (i = 0; i < num_ops; i++)
{
tree op = lto_input_tree (ib, data_in);
gimple_set_op (stmt, i, op);
if (!op)
continue;
/* Fixup FIELD_DECLs in COMPONENT_REFs, they are not handled
by decl merging. */
if (TREE_CODE (op) == ADDR_EXPR)
op = TREE_OPERAND (op, 0);
while (handled_component_p (op))
{
if (TREE_CODE (op) == COMPONENT_REF)
{
tree field, type, tem;
tree closest_match = NULL_TREE;
field = TREE_OPERAND (op, 1);
type = DECL_CONTEXT (field);
for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
{
if (tem == field)
break;
if (DECL_NONADDRESSABLE_P (tem)
== DECL_NONADDRESSABLE_P (field)
&& gimple_compare_field_offset (tem, field))
{
if (types_compatible_p (TREE_TYPE (tem),
TREE_TYPE (field)))
break;
else
closest_match = tem;
}
}
/* In case of type mismatches across units we can fail
to unify some types and thus not find a proper
field-decl here. */
if (tem == NULL_TREE)
{
/* Thus, emit a ODR violation warning. */
if (warning_at (gimple_location (stmt), 0,
"use of type %<%E%> with two mismatching "
"declarations at field %<%E%>",
type, TREE_OPERAND (op, 1)))
{
if (TYPE_FIELDS (type))
inform (DECL_SOURCE_LOCATION (TYPE_FIELDS (type)),
"original type declared here");
inform (DECL_SOURCE_LOCATION (TREE_OPERAND (op, 1)),
"field in mismatching type declared here");
if (TYPE_NAME (TREE_TYPE (field))
&& (TREE_CODE (TYPE_NAME (TREE_TYPE (field)))
== TYPE_DECL))
inform (DECL_SOURCE_LOCATION
(TYPE_NAME (TREE_TYPE (field))),
"type of field declared here");
if (closest_match
&& TYPE_NAME (TREE_TYPE (closest_match))
&& (TREE_CODE (TYPE_NAME
(TREE_TYPE (closest_match))) == TYPE_DECL))
inform (DECL_SOURCE_LOCATION
(TYPE_NAME (TREE_TYPE (closest_match))),
"type of mismatching field declared here");
}
/* And finally fixup the types. */
TREE_OPERAND (op, 0)
= build1 (VIEW_CONVERT_EXPR, type,
TREE_OPERAND (op, 0));
}
else
TREE_OPERAND (op, 1) = tem;
}
op = TREE_OPERAND (op, 0);
}
}
if (is_gimple_call (stmt))
{
if (gimple_call_internal_p (stmt))
gimple_call_set_internal_fn
(stmt, lto_input_enum (ib, internal_fn, IFN_LAST));
else
gimple_call_set_fntype (stmt, lto_input_tree (ib, data_in));
}
break;
case GIMPLE_NOP:
case GIMPLE_PREDICT:
break;
default:
internal_error ("bytecode stream: unknown GIMPLE statement tag %s",
lto_tag_name (tag));
}
/* Update the properties of symbols, SSA names and labels associated
with STMT. */
if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL)
{
tree lhs = gimple_get_lhs (stmt);
if (lhs && TREE_CODE (lhs) == SSA_NAME)
SSA_NAME_DEF_STMT (lhs) = stmt;
}
else if (code == GIMPLE_LABEL)
gcc_assert (emit_label_in_global_context_p (gimple_label_label (stmt))
|| DECL_CONTEXT (gimple_label_label (stmt)) == fn->decl);
else if (code == GIMPLE_ASM)
{
unsigned i;
for (i = 0; i < gimple_asm_noutputs (stmt); i++)
{
tree op = TREE_VALUE (gimple_asm_output_op (stmt, i));
if (TREE_CODE (op) == SSA_NAME)
SSA_NAME_DEF_STMT (op) = stmt;
}
}
/* Reset alias information. */
if (code == GIMPLE_CALL)
gimple_call_reset_alias_info (stmt);
/* Mark the statement modified so its operand vectors can be filled in. */
gimple_set_modified (stmt, true);
return stmt;
}
/* Read a basic block with tag TAG from DATA_IN using input block IB.
FN is the function being processed. */
void
input_bb (struct lto_input_block *ib, enum LTO_tags tag,
struct data_in *data_in, struct function *fn,
int count_materialization_scale)
{
unsigned int index;
basic_block bb;
gimple_stmt_iterator bsi;
/* This routine assumes that CFUN is set to FN, as it needs to call
basic GIMPLE routines that use CFUN. */
gcc_assert (cfun == fn);
index = lto_input_uleb128 (ib);
bb = BASIC_BLOCK_FOR_FUNCTION (fn, index);
bb->count = (lto_input_sleb128 (ib) * count_materialization_scale
+ REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
bb->loop_depth = lto_input_sleb128 (ib);
bb->frequency = lto_input_sleb128 (ib);
bb->flags = lto_input_sleb128 (ib);
/* LTO_bb1 has statements. LTO_bb0 does not. */
if (tag == LTO_bb0)
return;
bsi = gsi_start_bb (bb);
tag = input_record_start (ib);
while (tag)
{
gimple stmt = input_gimple_stmt (ib, data_in, fn, tag);
if (!is_gimple_debug (stmt))
find_referenced_vars_in (stmt);
gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
/* After the statement, expect a 0 delimiter or the EH region
that the previous statement belongs to. */
tag = input_record_start (ib);
lto_tag_check_set (tag, 2, LTO_eh_region, LTO_null);
if (tag == LTO_eh_region)
{
HOST_WIDE_INT region = lto_input_sleb128 (ib);
gcc_assert (region == (int) region);
add_stmt_to_eh_lp (stmt, region);
}
tag = input_record_start (ib);
}
tag = input_record_start (ib);
while (tag)
{
gimple phi = input_phi (ib, bb, data_in, fn);
find_referenced_vars_in (phi);
tag = input_record_start (ib);
}
}
/* Routines for emitting GIMPLE to a file stream.
Copyright 2011 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@google.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
#include "tree-flow.h"
#include "data-streamer.h"
#include "gimple-streamer.h"
#include "lto-streamer.h"
/* Output PHI function PHI to the main stream in OB. */
static void
output_phi (struct output_block *ob, gimple phi)
{
unsigned i, len = gimple_phi_num_args (phi);
output_record_start (ob, lto_gimple_code_to_tag (GIMPLE_PHI));
output_uleb128 (ob, SSA_NAME_VERSION (PHI_RESULT (phi)));
for (i = 0; i < len; i++)
{
lto_output_tree_ref (ob, gimple_phi_arg_def (phi, i));
output_uleb128 (ob, gimple_phi_arg_edge (phi, i)->src->index);
lto_output_location (ob, gimple_phi_arg_location (phi, i));
}
}
/* Emit statement STMT on the main stream of output block OB. */
static void
output_gimple_stmt (struct output_block *ob, gimple stmt)
{
unsigned i;
enum gimple_code code;
enum LTO_tags tag;
struct bitpack_d bp;
/* Emit identifying tag. */
code = gimple_code (stmt);
tag = lto_gimple_code_to_tag (code);
output_record_start (ob, tag);
/* Emit the tuple header. */
bp = bitpack_create (ob->main_stream);
bp_pack_var_len_unsigned (&bp, gimple_num_ops (stmt));
bp_pack_value (&bp, gimple_no_warning_p (stmt), 1);
if (is_gimple_assign (stmt))
bp_pack_value (&bp, gimple_assign_nontemporal_move_p (stmt), 1);
bp_pack_value (&bp, gimple_has_volatile_ops (stmt), 1);
bp_pack_var_len_unsigned (&bp, stmt->gsbase.subcode);
lto_output_bitpack (&bp);
/* Emit location information for the statement. */
lto_output_location (ob, gimple_location (stmt));
/* Emit the lexical block holding STMT. */
lto_output_tree (ob, gimple_block (stmt), true);
/* Emit the operands. */
switch (gimple_code (stmt))
{
case GIMPLE_RESX:
output_sleb128 (ob, gimple_resx_region (stmt));
break;
case GIMPLE_EH_MUST_NOT_THROW:
lto_output_tree_ref (ob, gimple_eh_must_not_throw_fndecl (stmt));
break;
case GIMPLE_EH_DISPATCH:
output_sleb128 (ob, gimple_eh_dispatch_region (stmt));
break;
case GIMPLE_ASM:
lto_output_uleb128_stream (ob->main_stream, gimple_asm_ninputs (stmt));
lto_output_uleb128_stream (ob->main_stream, gimple_asm_noutputs (stmt));
lto_output_uleb128_stream (ob->main_stream, gimple_asm_nclobbers (stmt));
lto_output_uleb128_stream (ob->main_stream, gimple_asm_nlabels (stmt));
lto_output_string (ob, ob->main_stream, gimple_asm_string (stmt), true);
/* Fallthru */
case GIMPLE_ASSIGN:
case GIMPLE_CALL:
case GIMPLE_RETURN:
case GIMPLE_SWITCH:
case GIMPLE_LABEL:
case GIMPLE_COND:
case GIMPLE_GOTO:
case GIMPLE_DEBUG:
for (i = 0; i < gimple_num_ops (stmt); i++)
{
tree op = gimple_op (stmt, i);
/* Wrap all uses of non-automatic variables inside MEM_REFs
so that we do not have to deal with type mismatches on
merged symbols during IL read in. The first operand
of GIMPLE_DEBUG must be a decl, not MEM_REF, though. */
if (op && (i || !is_gimple_debug (stmt)))
{
tree *basep = &op;
while (handled_component_p (*basep))
basep = &TREE_OPERAND (*basep, 0);
if (TREE_CODE (*basep) == VAR_DECL
&& !auto_var_in_fn_p (*basep, current_function_decl)
&& !DECL_REGISTER (*basep))
{
bool volatilep = TREE_THIS_VOLATILE (*basep);
*basep = build2 (MEM_REF, TREE_TYPE (*basep),
build_fold_addr_expr (*basep),
build_int_cst (build_pointer_type
(TREE_TYPE (*basep)), 0));
TREE_THIS_VOLATILE (*basep) = volatilep;
}
}
lto_output_tree_ref (ob, op);
}
if (is_gimple_call (stmt))
{
if (gimple_call_internal_p (stmt))
lto_output_enum (ob->main_stream, internal_fn,
IFN_LAST, gimple_call_internal_fn (stmt));
else
lto_output_tree_ref (ob, gimple_call_fntype (stmt));
}
break;
case GIMPLE_NOP:
case GIMPLE_PREDICT:
break;
default:
gcc_unreachable ();
}
}
/* Output a basic block BB to the main stream in OB for this FN. */
void
output_bb (struct output_block *ob, basic_block bb, struct function *fn)
{
gimple_stmt_iterator bsi = gsi_start_bb (bb);
output_record_start (ob,
(!gsi_end_p (bsi)) || phi_nodes (bb)
? LTO_bb1
: LTO_bb0);
output_uleb128 (ob, bb->index);
output_sleb128 (ob, bb->count);
output_sleb128 (ob, bb->loop_depth);
output_sleb128 (ob, bb->frequency);
output_sleb128 (ob, bb->flags);
if (!gsi_end_p (bsi) || phi_nodes (bb))
{
/* Output the statements. The list of statements is terminated
with a zero. */
for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
{
int region;
gimple stmt = gsi_stmt (bsi);
output_gimple_stmt (ob, stmt);
/* Emit the EH region holding STMT. */
region = lookup_stmt_eh_lp_fn (fn, stmt);
if (region != 0)
{
output_record_start (ob, LTO_eh_region);
output_sleb128 (ob, region);
}
else
output_record_start (ob, LTO_null);
}
output_record_start (ob, LTO_null);
for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi))
{
gimple phi = gsi_stmt (bsi);
/* Only emit PHIs for gimple registers. PHI nodes for .MEM
will be filled in on reading when the SSA form is
updated. */
if (is_gimple_reg (gimple_phi_result (phi)))
output_phi (ob, phi);
}
output_record_start (ob, LTO_null);
}
}
/* Data structures and functions for streaming GIMPLE.
Copyright 2011 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@google.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_GIMPLE_STREAMER_H
#define GCC_GIMPLE_STREAMER_H
#include "basic-block.h"
#include "function.h"
#include "lto-streamer.h"
/* In gimple-streamer-in.c */
void input_bb (struct lto_input_block *, enum LTO_tags, struct data_in *,
struct function *, int);
/* In gimple-streamer-out.c */
void output_bb (struct output_block *, basic_block, struct function *);
#endif /* GCC_GIMPLE_STREAMER_H */
......@@ -84,6 +84,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-flow.h"
#include "ipa-prop.h"
#include "lto-streamer.h"
#include "data-streamer.h"
#include "tree-streamer.h"
#include "ipa-inline.h"
#include "alloc-pool.h"
......
......@@ -38,6 +38,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pretty-print.h"
#include "gimple-pretty-print.h"
#include "lto-streamer.h"
#include "data-streamer.h"
#include "tree-streamer.h"
/* Intermediate information about a parameter that is only useful during the
......
......@@ -54,6 +54,8 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "target.h"
#include "lto-streamer.h"
#include "data-streamer.h"
#include "tree-streamer.h"
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
#include "intl.h"
......
......@@ -43,6 +43,8 @@ along with GCC; see the file COPYING3. If not see
#include "output.h"
#include "pointer-set.h"
#include "lto-streamer.h"
#include "data-streamer.h"
#include "tree-streamer.h"
#include "gcov-io.h"
static void output_varpool (cgraph_node_set, varpool_node_set);
......
......@@ -63,115 +63,6 @@ const char *lto_section_name[LTO_N_SECTION_TYPES] =
};
/* Read an ULEB128 Number of IB. */
unsigned HOST_WIDE_INT
lto_input_uleb128 (struct lto_input_block *ib)
{
unsigned HOST_WIDE_INT result = 0;
int shift = 0;
unsigned HOST_WIDE_INT byte;
while (true)
{
byte = lto_input_1_unsigned (ib);
result |= (byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
return result;
}
}
/* HOST_WIDEST_INT version of lto_input_uleb128. IB is as in
lto_input_uleb128. */
unsigned HOST_WIDEST_INT
lto_input_widest_uint_uleb128 (struct lto_input_block *ib)
{
unsigned HOST_WIDEST_INT result = 0;
int shift = 0;
unsigned HOST_WIDEST_INT byte;
while (true)
{
byte = lto_input_1_unsigned (ib);
result |= (byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
return result;
}
}
/* Read an SLEB128 Number of IB. */
HOST_WIDE_INT
lto_input_sleb128 (struct lto_input_block *ib)
{
HOST_WIDE_INT result = 0;
int shift = 0;
unsigned HOST_WIDE_INT byte;
while (true)
{
byte = lto_input_1_unsigned (ib);
result |= (byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
{
if ((shift < HOST_BITS_PER_WIDE_INT) && (byte & 0x40))
result |= - ((HOST_WIDE_INT)1 << shift);
return result;
}
}
}
/* Unpack VAL from BP in a variant of uleb format. */
unsigned HOST_WIDE_INT
bp_unpack_var_len_unsigned (struct bitpack_d *bp)
{
unsigned HOST_WIDE_INT result = 0;
int shift = 0;
unsigned HOST_WIDE_INT half_byte;
while (true)
{
half_byte = bp_unpack_value (bp, 4);
result |= (half_byte & 0x7) << shift;
shift += 3;
if ((half_byte & 0x8) == 0)
return result;
}
}
/* Unpack VAL from BP in a variant of sleb format. */
HOST_WIDE_INT
bp_unpack_var_len_int (struct bitpack_d *bp)
{
HOST_WIDE_INT result = 0;
int shift = 0;
unsigned HOST_WIDE_INT half_byte;
while (true)
{
half_byte = bp_unpack_value (bp, 4);
result |= (half_byte & 0x7) << shift;
shift += 3;
if ((half_byte & 0x8) == 0)
{
if ((shift < HOST_BITS_PER_WIDE_INT) && (half_byte & 0x4))
result |= - ((HOST_WIDE_INT)1 << shift);
return result;
}
}
}
/* Hooks so that the ipa passes can call into the lto front end to get
sections. */
......
......@@ -265,113 +265,6 @@ lto_output_data_stream (struct lto_output_stream *obs, const void *data,
}
/* Output an unsigned LEB128 quantity to OBS. */
void
lto_output_uleb128_stream (struct lto_output_stream *obs,
unsigned HOST_WIDE_INT work)
{
do
{
unsigned int byte = (work & 0x7f);
work >>= 7;
if (work != 0)
/* More bytes to follow. */
byte |= 0x80;
lto_output_1_stream (obs, byte);
}
while (work != 0);
}
/* Identical to output_uleb128_stream above except using unsigned
HOST_WIDEST_INT type. For efficiency on host where unsigned HOST_WIDEST_INT
is not native, we only use this if we know that HOST_WIDE_INT is not wide
enough. */
void
lto_output_widest_uint_uleb128_stream (struct lto_output_stream *obs,
unsigned HOST_WIDEST_INT work)
{
do
{
unsigned int byte = (work & 0x7f);
work >>= 7;
if (work != 0)
/* More bytes to follow. */
byte |= 0x80;
lto_output_1_stream (obs, byte);
}
while (work != 0);
}
/* Output a signed LEB128 quantity. */
void
lto_output_sleb128_stream (struct lto_output_stream *obs, HOST_WIDE_INT work)
{
int more, byte;
do
{
byte = (work & 0x7f);
/* arithmetic shift */
work >>= 7;
more = !((work == 0 && (byte & 0x40) == 0)
|| (work == -1 && (byte & 0x40) != 0));
if (more)
byte |= 0x80;
lto_output_1_stream (obs, byte);
}
while (more);
}
/* Pack WORK into BP in a variant of uleb format. */
void
bp_pack_var_len_unsigned (struct bitpack_d *bp, unsigned HOST_WIDE_INT work)
{
do
{
unsigned int half_byte = (work & 0x7);
work >>= 3;
if (work != 0)
/* More half_bytes to follow. */
half_byte |= 0x8;
bp_pack_value (bp, half_byte, 4);
}
while (work != 0);
}
/* Pack WORK into BP in a variant of sleb format. */
void
bp_pack_var_len_int (struct bitpack_d *bp, HOST_WIDE_INT work)
{
int more, half_byte;
do
{
half_byte = (work & 0x7);
/* arithmetic shift */
work >>= 3;
more = !((work == 0 && (half_byte & 0x4) == 0)
|| (work == -1 && (half_byte & 0x4) != 0));
if (more)
half_byte |= 0x8;
bp_pack_value (bp, half_byte, 4);
}
while (more);
}
/* Lookup NAME in ENCODER. If NAME is not found, create a new entry in
ENCODER for NAME with the next available index of ENCODER, then
print the index to OBS. True is returned if NAME was added to
......
......@@ -32,14 +32,13 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-core.h"
#include "bitmap.h"
#include "vec.h"
#include "tree-streamer.h"
#include "lto-streamer.h"
#include "streamer-hooks.h"
/* Statistics gathered during LTO, WPA and LTRANS. */
struct lto_stats_d lto_stats;
/* Streamer hooks. */
struct streamer_hooks streamer_hooks;
/* LTO uses bitmaps with different life-times. So use a seperate
obstack for all LTO bitmaps. */
static bitmap_obstack lto_obstack;
......@@ -258,226 +257,6 @@ print_lto_report (void)
}
/* Check that all the TS_* structures handled by the lto_output_* and
lto_input_* routines are exactly ALL the structures defined in
treestruct.def. */
static void
check_handled_ts_structures (void)
{
bool handled_p[LAST_TS_ENUM];
unsigned i;
memset (&handled_p, 0, sizeof (handled_p));
/* These are the TS_* structures that are either handled or
explicitly ignored by the streamer routines. */
handled_p[TS_BASE] = true;
handled_p[TS_TYPED] = true;
handled_p[TS_COMMON] = true;
handled_p[TS_INT_CST] = true;
handled_p[TS_REAL_CST] = true;
handled_p[TS_FIXED_CST] = true;
handled_p[TS_VECTOR] = true;
handled_p[TS_STRING] = true;
handled_p[TS_COMPLEX] = true;
handled_p[TS_IDENTIFIER] = true;
handled_p[TS_DECL_MINIMAL] = true;
handled_p[TS_DECL_COMMON] = true;
handled_p[TS_DECL_WRTL] = true;
handled_p[TS_DECL_NON_COMMON] = true;
handled_p[TS_DECL_WITH_VIS] = true;
handled_p[TS_FIELD_DECL] = true;
handled_p[TS_VAR_DECL] = true;
handled_p[TS_PARM_DECL] = true;
handled_p[TS_LABEL_DECL] = true;
handled_p[TS_RESULT_DECL] = true;
handled_p[TS_CONST_DECL] = true;
handled_p[TS_TYPE_DECL] = true;
handled_p[TS_FUNCTION_DECL] = true;
handled_p[TS_TYPE_COMMON] = true;
handled_p[TS_TYPE_WITH_LANG_SPECIFIC] = true;
handled_p[TS_TYPE_NON_COMMON] = true;
handled_p[TS_LIST] = true;
handled_p[TS_VEC] = true;
handled_p[TS_EXP] = true;
handled_p[TS_SSA_NAME] = true;
handled_p[TS_BLOCK] = true;
handled_p[TS_BINFO] = true;
handled_p[TS_STATEMENT_LIST] = true;
handled_p[TS_CONSTRUCTOR] = true;
handled_p[TS_OMP_CLAUSE] = true;
handled_p[TS_OPTIMIZATION] = true;
handled_p[TS_TARGET_OPTION] = true;
handled_p[TS_TRANSLATION_UNIT_DECL] = true;
/* Anything not marked above will trigger the following assertion.
If this assertion triggers, it means that there is a new TS_*
structure that should be handled by the streamer. */
for (i = 0; i < LAST_TS_ENUM; i++)
gcc_assert (handled_p[i]);
}
/* Helper for lto_streamer_cache_insert_1. Add T to CACHE->NODES at
slot IX. */
static void
lto_streamer_cache_add_to_node_array (struct lto_streamer_cache_d *cache,
unsigned ix, tree t)
{
/* Make sure we're either replacing an old element or
appending consecutively. */
gcc_assert (ix <= VEC_length (tree, cache->nodes));
if (ix == VEC_length (tree, cache->nodes))
VEC_safe_push (tree, heap, cache->nodes, t);
else
VEC_replace (tree, cache->nodes, ix, t);
}
/* Helper for lto_streamer_cache_insert and lto_streamer_cache_insert_at.
CACHE, T, and IX_P are as in lto_streamer_cache_insert.
If INSERT_AT_NEXT_SLOT_P is true, T is inserted at the next available
slot in the cache. Otherwise, T is inserted at the position indicated
in *IX_P.
If T already existed in CACHE, return true. Otherwise,
return false. */
static bool
lto_streamer_cache_insert_1 (struct lto_streamer_cache_d *cache,
tree t, unsigned *ix_p,
bool insert_at_next_slot_p)
{
void **slot;
unsigned ix;
bool existed_p;
gcc_assert (t);
slot = pointer_map_insert (cache->node_map, t);
if (!*slot)
{
/* Determine the next slot to use in the cache. */
if (insert_at_next_slot_p)
ix = VEC_length (tree, cache->nodes);
else
ix = *ix_p;
*slot = (void *)(size_t) (ix + 1);
lto_streamer_cache_add_to_node_array (cache, ix, t);
/* Indicate that the item was not present in the cache. */
existed_p = false;
}
else
{
ix = (size_t) *slot - 1;
if (!insert_at_next_slot_p && ix != *ix_p)
{
/* If the caller wants to insert T at a specific slot
location, and ENTRY->TO does not match *IX_P, add T to
the requested location slot. */
ix = *ix_p;
lto_streamer_cache_add_to_node_array (cache, ix, t);
}
/* Indicate that T was already in the cache. */
existed_p = true;
}
if (ix_p)
*ix_p = ix;
return existed_p;
}
/* Insert tree node T in CACHE. If T already existed in the cache
return true. Otherwise, return false.
If IX_P is non-null, update it with the index into the cache where
T has been stored. */
bool
lto_streamer_cache_insert (struct lto_streamer_cache_d *cache, tree t,
unsigned *ix_p)
{
return lto_streamer_cache_insert_1 (cache, t, ix_p, true);
}
/* Insert tree node T in CACHE at slot IX. If T already
existed in the cache return true. Otherwise, return false. */
bool
lto_streamer_cache_insert_at (struct lto_streamer_cache_d *cache,
tree t, unsigned ix)
{
return lto_streamer_cache_insert_1 (cache, t, &ix, false);
}
/* Appends tree node T to CACHE, even if T already existed in it. */
void
lto_streamer_cache_append (struct lto_streamer_cache_d *cache, tree t)
{
unsigned ix = VEC_length (tree, cache->nodes);
lto_streamer_cache_insert_1 (cache, t, &ix, false);
}
/* Return true if tree node T exists in CACHE, otherwise false. If IX_P is
not NULL, write to *IX_P the index into the cache where T is stored
((unsigned)-1 if T is not found). */
bool
lto_streamer_cache_lookup (struct lto_streamer_cache_d *cache, tree t,
unsigned *ix_p)
{
void **slot;
bool retval;
unsigned ix;
gcc_assert (t);
slot = pointer_map_contains (cache->node_map, t);
if (slot == NULL)
{
retval = false;
ix = -1;
}
else
{
retval = true;
ix = (size_t) *slot - 1;
}
if (ix_p)
*ix_p = ix;
return retval;
}
/* Return the tree node at slot IX in CACHE. */
tree
lto_streamer_cache_get (struct lto_streamer_cache_d *cache, unsigned ix)
{
gcc_assert (cache);
/* Make sure we're not requesting something we don't have. */
gcc_assert (ix < VEC_length (tree, cache->nodes));
return VEC_index (tree, cache->nodes, ix);
}
/* Record NODE in CACHE. */
static void
......@@ -557,39 +336,6 @@ lto_preload_common_nodes (struct lto_streamer_cache_d *cache)
lto_record_common_node (cache, global_trees[i]);
}
/* Create a cache of pickled nodes. */
struct lto_streamer_cache_d *
lto_streamer_cache_create (void)
{
struct lto_streamer_cache_d *cache;
cache = XCNEW (struct lto_streamer_cache_d);
cache->node_map = pointer_map_create ();
/* Load all the well-known tree nodes that are always created by
the compiler on startup. This prevents writing them out
unnecessarily. */
streamer_hooks.preload_common_nodes (cache);
return cache;
}
/* Delete the streamer cache C. */
void
lto_streamer_cache_delete (struct lto_streamer_cache_d *c)
{
if (c == NULL)
return;
pointer_map_destroy (c->node_map);
VEC_free (tree, heap, c->nodes);
free (c);
}
#ifdef LTO_STREAMER_DEBUG
static htab_t tree_htab;
......@@ -756,12 +502,3 @@ lto_streamer_hooks_init (void)
streamer_hooks.write_tree = lto_streamer_write_tree;
streamer_hooks.read_tree = lto_streamer_read_tree;
}
/* Initialize the current set of streamer hooks. */
void
streamer_hooks_init (void)
{
memset (&streamer_hooks, 0, sizeof (streamer_hooks));
}
2011-08-08 Diego Novillo <dnovillo@google.com>
* Make-lang.in (lto/lto.o): Add TREE_STREAMER_H.
* lto.c: Include tree-streamer.h.
2011-07-06 Richard Guenther <rguenther@suse.de>
* lto-lang.c (lto_init):
......
......@@ -86,7 +86,7 @@ lto/lto.o: lto/lto.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(OPTS_H) \
langhooks.h $(VEC_H) $(BITMAP_H) pointer-set.h $(IPA_PROP_H) \
$(COMMON_H) debug.h $(TIMEVAR_H) $(GIMPLE_H) $(LTO_H) $(LTO_TREE_H) \
$(LTO_TAGS_H) $(LTO_STREAMER_H) $(SPLAY_TREE_H) gt-lto-lto.h $(PARAMS_H) \
ipa-inline.h $(IPA_UTILS_H)
ipa-inline.h $(IPA_UTILS_H) $(TREE_STREAMER_H)
lto/lto-object.o: lto/lto-object.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(DIAGNOSTIC_CORE_H) $(LTO_H) $(TM_H) $(LTO_STREAMER_H) \
../include/simple-object.h
......
......@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "lto.h"
#include "lto-tree.h"
#include "lto-streamer.h"
#include "tree-streamer.h"
#include "splay-tree.h"
#include "params.h"
#include "ipa-inline.h"
......
/* Streamer hooks. Support for adding streamer-specific callbacks to
generic streaming routines.
Copyright 2011 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@google.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "streamer-hooks.h"
/* Streamer hooks. */
struct streamer_hooks streamer_hooks;
/* Initialize the current set of streamer hooks. */
void
streamer_hooks_init (void)
{
memset (&streamer_hooks, 0, sizeof (streamer_hooks));
}
/* Streamer hooks. Support for adding streamer-specific callbacks to
generic streaming routines.
Copyright 2011 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@google.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_STREAMER_HOOKS_H
#define GCC_STREAMER_HOOKS_H
#include "tree.h"
/* Forward declarations to avoid including unnecessary headers. */
struct output_block;
struct lto_input_block;
struct data_in;
struct bitpack_d;
struct lto_streamer_cache_d;
/* Streamer hooks. These functions do additional processing as
needed by the module. There are two types of callbacks, those that
replace the default behavior and those that supplement it.
Hooks marked [REQ] are required to be set. Those marked [OPT] may
be NULL, if the streamer does not need to implement them. */
struct streamer_hooks {
/* [REQ] A string identifying this streamer. */
const char *name;
/* [REQ] Called by lto_streamer_cache_create to instantiate a cache of
well-known nodes. These are tree nodes that are always
instantiated by the compiler on startup. Additionally, these
nodes need to be shared. This function should call
lto_streamer_cache_append on every tree node that it wishes to
preload in the streamer cache. This way, the writer will only
write out a reference to the tree and the reader will instantiate
the tree out of this pre-populated cache. */
void (*preload_common_nodes) (struct lto_streamer_cache_d *);
/* [REQ] Return true if the given tree is supported by this streamer. */
bool (*is_streamable) (tree);
/* [OPT] Called by lto_write_tree after writing all the common parts of
a tree. If defined, the callback is in charge of writing all
the fields that lto_write_tree did not write out. Arguments
are as in lto_write_tree.
The following tree fields are not handled by common code:
DECL_ABSTRACT_ORIGIN
DECL_INITIAL
DECL_SAVED_TREE
Callbacks may choose to ignore or handle them. If handled,
the reader should read them in the exact same sequence written
by the writer. */
void (*write_tree) (struct output_block *, tree, bool);
/* [OPT] Called by lto_read_tree after reading all the common parts of
a tree. If defined, the callback is in charge of reading all
the fields that lto_read_tree did not read in. Arguments
are as in lto_read_tree. */
void (*read_tree) (struct lto_input_block *, struct data_in *, tree);
/* [OPT] Called by lto_output_tree_ref to determine if the given tree node
should be emitted as a reference to the table of declarations
(the same table that holds global declarations). */
bool (*indexable_with_decls_p) (tree);
/* [OPT] Called by pack_value_fields to store any non-pointer fields
in the tree structure. The arguments are as in pack_value_fields. */
void (*pack_value_fields) (struct bitpack_d *, tree);
/* [OPT] Called by unpack_value_fields to retrieve any non-pointer fields
in the tree structure. The arguments are as in unpack_value_fields. */
void (*unpack_value_fields) (struct bitpack_d *, tree);
/* [OPT] Called by lto_materialize_tree for tree nodes that it does not
know how to allocate memory for. If defined, this hook should
return a new tree node of the given code. The data_in and
input_block arguments are passed in case the hook needs to
read more data from the stream to allocate the node.
If this hook returns NULL, then lto_materialize_tree will attempt
to allocate the tree by calling make_node directly. */
tree (*alloc_tree) (enum tree_code, struct lto_input_block *,
struct data_in *);
/* [OPT] Called by lto_output_tree_header to write any streamer-specific
information needed to allocate the tree. This hook may assume
that the basic header data (tree code, etc) has already been
written. It should only write any extra data needed to allocate
the node (e.g., in the case of CALL_EXPR, this hook would write
the number of arguments to the CALL_EXPR). */
void (*output_tree_header) (struct output_block *, tree);
};
/* Streamer hooks. */
extern struct streamer_hooks streamer_hooks;
/* In streamer-hooks.c. */
void streamer_hooks_init (void);
#endif /* GCC_STREAMER_HOOKS_H */
/* Miscellaneous utilities for tree streaming. Things that are used
in both input and output are here.
Copyright 2011 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@google.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "streamer-hooks.h"
#include "tree-streamer.h"
/* Check that all the TS_* structures handled by the lto_output_* and
lto_input_* routines are exactly ALL the structures defined in
treestruct.def. */
void
check_handled_ts_structures (void)
{
bool handled_p[LAST_TS_ENUM];
unsigned i;
memset (&handled_p, 0, sizeof (handled_p));
/* These are the TS_* structures that are either handled or
explicitly ignored by the streamer routines. */
handled_p[TS_BASE] = true;
handled_p[TS_TYPED] = true;
handled_p[TS_COMMON] = true;
handled_p[TS_INT_CST] = true;
handled_p[TS_REAL_CST] = true;
handled_p[TS_FIXED_CST] = true;
handled_p[TS_VECTOR] = true;
handled_p[TS_STRING] = true;
handled_p[TS_COMPLEX] = true;
handled_p[TS_IDENTIFIER] = true;
handled_p[TS_DECL_MINIMAL] = true;
handled_p[TS_DECL_COMMON] = true;
handled_p[TS_DECL_WRTL] = true;
handled_p[TS_DECL_NON_COMMON] = true;
handled_p[TS_DECL_WITH_VIS] = true;
handled_p[TS_FIELD_DECL] = true;
handled_p[TS_VAR_DECL] = true;
handled_p[TS_PARM_DECL] = true;
handled_p[TS_LABEL_DECL] = true;
handled_p[TS_RESULT_DECL] = true;
handled_p[TS_CONST_DECL] = true;
handled_p[TS_TYPE_DECL] = true;
handled_p[TS_FUNCTION_DECL] = true;
handled_p[TS_TYPE_COMMON] = true;
handled_p[TS_TYPE_WITH_LANG_SPECIFIC] = true;
handled_p[TS_TYPE_NON_COMMON] = true;
handled_p[TS_LIST] = true;
handled_p[TS_VEC] = true;
handled_p[TS_EXP] = true;
handled_p[TS_SSA_NAME] = true;
handled_p[TS_BLOCK] = true;
handled_p[TS_BINFO] = true;
handled_p[TS_STATEMENT_LIST] = true;
handled_p[TS_CONSTRUCTOR] = true;
handled_p[TS_OMP_CLAUSE] = true;
handled_p[TS_OPTIMIZATION] = true;
handled_p[TS_TARGET_OPTION] = true;
handled_p[TS_TRANSLATION_UNIT_DECL] = true;
/* Anything not marked above will trigger the following assertion.
If this assertion triggers, it means that there is a new TS_*
structure that should be handled by the streamer. */
for (i = 0; i < LAST_TS_ENUM; i++)
gcc_assert (handled_p[i]);
}
/* Helper for lto_streamer_cache_insert_1. Add T to CACHE->NODES at
slot IX. */
static void
lto_streamer_cache_add_to_node_array (struct lto_streamer_cache_d *cache,
unsigned ix, tree t)
{
/* Make sure we're either replacing an old element or
appending consecutively. */
gcc_assert (ix <= VEC_length (tree, cache->nodes));
if (ix == VEC_length (tree, cache->nodes))
VEC_safe_push (tree, heap, cache->nodes, t);
else
VEC_replace (tree, cache->nodes, ix, t);
}
/* Helper for lto_streamer_cache_insert and lto_streamer_cache_insert_at.
CACHE, T, and IX_P are as in lto_streamer_cache_insert.
If INSERT_AT_NEXT_SLOT_P is true, T is inserted at the next available
slot in the cache. Otherwise, T is inserted at the position indicated
in *IX_P.
If T already existed in CACHE, return true. Otherwise,
return false. */
static bool
lto_streamer_cache_insert_1 (struct lto_streamer_cache_d *cache,
tree t, unsigned *ix_p,
bool insert_at_next_slot_p)
{
void **slot;
unsigned ix;
bool existed_p;
gcc_assert (t);
slot = pointer_map_insert (cache->node_map, t);
if (!*slot)
{
/* Determine the next slot to use in the cache. */
if (insert_at_next_slot_p)
ix = VEC_length (tree, cache->nodes);
else
ix = *ix_p;
*slot = (void *)(size_t) (ix + 1);
lto_streamer_cache_add_to_node_array (cache, ix, t);
/* Indicate that the item was not present in the cache. */
existed_p = false;
}
else
{
ix = (size_t) *slot - 1;
if (!insert_at_next_slot_p && ix != *ix_p)
{
/* If the caller wants to insert T at a specific slot
location, and ENTRY->TO does not match *IX_P, add T to
the requested location slot. */
ix = *ix_p;
lto_streamer_cache_add_to_node_array (cache, ix, t);
}
/* Indicate that T was already in the cache. */
existed_p = true;
}
if (ix_p)
*ix_p = ix;
return existed_p;
}
/* Insert tree node T in CACHE. If T already existed in the cache
return true. Otherwise, return false.
If IX_P is non-null, update it with the index into the cache where
T has been stored. */
bool
lto_streamer_cache_insert (struct lto_streamer_cache_d *cache, tree t,
unsigned *ix_p)
{
return lto_streamer_cache_insert_1 (cache, t, ix_p, true);
}
/* Insert tree node T in CACHE at slot IX. If T already
existed in the cache return true. Otherwise, return false. */
bool
lto_streamer_cache_insert_at (struct lto_streamer_cache_d *cache,
tree t, unsigned ix)
{
return lto_streamer_cache_insert_1 (cache, t, &ix, false);
}
/* Appends tree node T to CACHE, even if T already existed in it. */
void
lto_streamer_cache_append (struct lto_streamer_cache_d *cache, tree t)
{
unsigned ix = VEC_length (tree, cache->nodes);
lto_streamer_cache_insert_1 (cache, t, &ix, false);
}
/* Return true if tree node T exists in CACHE, otherwise false. If IX_P is
not NULL, write to *IX_P the index into the cache where T is stored
((unsigned)-1 if T is not found). */
bool
lto_streamer_cache_lookup (struct lto_streamer_cache_d *cache, tree t,
unsigned *ix_p)
{
void **slot;
bool retval;
unsigned ix;
gcc_assert (t);
slot = pointer_map_contains (cache->node_map, t);
if (slot == NULL)
{
retval = false;
ix = -1;
}
else
{
retval = true;
ix = (size_t) *slot - 1;
}
if (ix_p)
*ix_p = ix;
return retval;
}
/* Return the tree node at slot IX in CACHE. */
tree
lto_streamer_cache_get (struct lto_streamer_cache_d *cache, unsigned ix)
{
gcc_assert (cache);
/* Make sure we're not requesting something we don't have. */
gcc_assert (ix < VEC_length (tree, cache->nodes));
return VEC_index (tree, cache->nodes, ix);
}
/* Create a cache of pickled nodes. */
struct lto_streamer_cache_d *
lto_streamer_cache_create (void)
{
struct lto_streamer_cache_d *cache;
cache = XCNEW (struct lto_streamer_cache_d);
cache->node_map = pointer_map_create ();
/* Load all the well-known tree nodes that are always created by
the compiler on startup. This prevents writing them out
unnecessarily. */
streamer_hooks.preload_common_nodes (cache);
return cache;
}
/* Delete the streamer cache C. */
void
lto_streamer_cache_delete (struct lto_streamer_cache_d *c)
{
if (c == NULL)
return;
pointer_map_destroy (c->node_map);
VEC_free (tree, heap, c->nodes);
free (c);
}
/* Data structures and functions for streaming trees.
Copyright 2011 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@google.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_TREE_STREAMER_H
#define GCC_TREE_STREAMER_H
#include "tree.h"
#include "lto-streamer.h"
/* Cache of pickled nodes. Used to avoid writing the same node more
than once. The first time a tree node is streamed out, it is
entered in this cache. Subsequent references to the same node are
resolved by looking it up in this cache.
This is used in two ways:
- On the writing side, the first time T is added to STREAMER_CACHE,
a new reference index is created for T and T is emitted on the
stream. If T needs to be emitted again to the stream, instead of
pickling it again, the reference index is emitted.
- On the reading side, the first time T is read from the stream, it
is reconstructed in memory and a new reference index created for
T. The reconstructed T is inserted in some array so that when
the reference index for T is found in the input stream, it can be
used to look up into the array to get the reconstructed T. */
struct lto_streamer_cache_d
{
/* The mapping between tree nodes and slots into the nodes array. */
struct pointer_map_t *node_map;
/* The nodes pickled so far. */
VEC(tree,heap) *nodes;
};
/* In tree-streamer-in.c. */
tree input_string_cst (struct data_in *, struct lto_input_block *);
tree lto_input_tree (struct lto_input_block *, struct data_in *);
void lto_streamer_read_tree (struct lto_input_block *,
struct data_in *, tree);
/* In tree-streamer-out.c. */
void lto_streamer_write_tree (struct output_block *, tree, bool);
/* In tree-streamer.c. */
void check_handled_ts_structures (void);
bool lto_streamer_cache_insert (struct lto_streamer_cache_d *, tree,
unsigned *);
bool lto_streamer_cache_insert_at (struct lto_streamer_cache_d *, tree,
unsigned);
void lto_streamer_cache_append (struct lto_streamer_cache_d *, tree);
bool lto_streamer_cache_lookup (struct lto_streamer_cache_d *, tree,
unsigned *);
tree lto_streamer_cache_get (struct lto_streamer_cache_d *, unsigned);
struct lto_streamer_cache_d *lto_streamer_cache_create (void);
void lto_streamer_cache_delete (struct lto_streamer_cache_d *);
#endif /* GCC_TREE_STREAMER_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment