parent
b7926cf905
commit
f0efc7aa77
219
gcc/ChangeLog
219
gcc/ChangeLog
|
@ -1,3 +1,222 @@
|
|||
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) \
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,207 @@
|
|||
/* 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);
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,355 @@
|
|||
/* Generic streaming support for various 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/>. */
|
||||
|
||||
#ifndef GCC_DATA_STREAMER_H
|
||||
#define GCC_DATA_STREAMER_H
|
||||
|
||||
#include "vec.h"
|
||||
#include "lto-streamer.h"
|
||||
|
||||
/* Data structures used to pack values and bitflags into a vector of
|
||||
words. Used to stream values of a fixed number of bits in a space
|
||||
efficient way. */
|
||||
static unsigned const BITS_PER_BITPACK_WORD = HOST_BITS_PER_WIDE_INT;
|
||||
|
||||
typedef unsigned HOST_WIDE_INT bitpack_word_t;
|
||||
DEF_VEC_I(bitpack_word_t);
|
||||
DEF_VEC_ALLOC_I(bitpack_word_t, heap);
|
||||
|
||||
struct bitpack_d
|
||||
{
|
||||
/* The position of the first unused or unconsumed bit in the word. */
|
||||
unsigned pos;
|
||||
|
||||
/* The current word we are (un)packing. */
|
||||
bitpack_word_t word;
|
||||
|
||||
/* The lto_output_stream or the lto_input_block we are streaming to/from. */
|
||||
void *stream;
|
||||
};
|
||||
|
||||
|
||||
/* String hashing. */
|
||||
struct string_slot
|
||||
{
|
||||
const char *s;
|
||||
int len;
|
||||
unsigned int slot_num;
|
||||
};
|
||||
|
||||
|
||||
/* Returns a hash code for P. Adapted from libiberty's htab_hash_string
|
||||
to support strings that may not end in '\0'. */
|
||||
|
||||
static inline hashval_t
|
||||
hash_string_slot_node (const void *p)
|
||||
{
|
||||
const struct string_slot *ds = (const struct string_slot *) p;
|
||||
hashval_t r = ds->len;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ds->len; i++)
|
||||
r = r * 67 + (unsigned)ds->s[i] - 113;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Returns nonzero if P1 and P2 are equal. */
|
||||
|
||||
static inline int
|
||||
eq_string_slot_node (const void *p1, const void *p2)
|
||||
{
|
||||
const struct string_slot *ds1 = (const struct string_slot *) p1;
|
||||
const struct string_slot *ds2 = (const struct string_slot *) p2;
|
||||
|
||||
if (ds1->len == ds2->len)
|
||||
return memcmp (ds1->s, ds2->s, ds1->len) == 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns a new bit-packing context for bit-packing into S. */
|
||||
static inline struct bitpack_d
|
||||
bitpack_create (struct lto_output_stream *s)
|
||||
{
|
||||
struct bitpack_d bp;
|
||||
bp.pos = 0;
|
||||
bp.word = 0;
|
||||
bp.stream = (void *)s;
|
||||
return bp;
|
||||
}
|
||||
|
||||
/* Pack the NBITS bit sized value VAL into the bit-packing context BP. */
|
||||
static inline void
|
||||
bp_pack_value (struct bitpack_d *bp, bitpack_word_t val, unsigned nbits)
|
||||
{
|
||||
bitpack_word_t word = bp->word;
|
||||
int pos = bp->pos;
|
||||
|
||||
/* Verify that VAL fits in the NBITS. */
|
||||
gcc_checking_assert (nbits == BITS_PER_BITPACK_WORD
|
||||
|| !(val & ~(((bitpack_word_t)1<<nbits)-1)));
|
||||
|
||||
/* If val does not fit into the current bitpack word switch to the
|
||||
next one. */
|
||||
if (pos + nbits > BITS_PER_BITPACK_WORD)
|
||||
{
|
||||
lto_output_uleb128_stream ((struct lto_output_stream *) bp->stream, word);
|
||||
word = val;
|
||||
pos = nbits;
|
||||
}
|
||||
else
|
||||
{
|
||||
word |= val << pos;
|
||||
pos += nbits;
|
||||
}
|
||||
bp->word = word;
|
||||
bp->pos = pos;
|
||||
}
|
||||
|
||||
/* Finishes bit-packing of BP. */
|
||||
static inline void
|
||||
lto_output_bitpack (struct bitpack_d *bp)
|
||||
{
|
||||
lto_output_uleb128_stream ((struct lto_output_stream *) bp->stream,
|
||||
bp->word);
|
||||
bp->word = 0;
|
||||
bp->pos = 0;
|
||||
}
|
||||
|
||||
/* Returns a new bit-packing context for bit-unpacking from IB. */
|
||||
static inline struct bitpack_d
|
||||
lto_input_bitpack (struct lto_input_block *ib)
|
||||
{
|
||||
struct bitpack_d bp;
|
||||
bp.word = lto_input_uleb128 (ib);
|
||||
bp.pos = 0;
|
||||
bp.stream = (void *)ib;
|
||||
return bp;
|
||||
}
|
||||
|
||||
/* Unpacks NBITS bits from the bit-packing context BP and returns them. */
|
||||
static inline bitpack_word_t
|
||||
bp_unpack_value (struct bitpack_d *bp, unsigned nbits)
|
||||
{
|
||||
bitpack_word_t mask, val;
|
||||
int pos = bp->pos;
|
||||
|
||||
mask = (nbits == BITS_PER_BITPACK_WORD
|
||||
? (bitpack_word_t) -1
|
||||
: ((bitpack_word_t) 1 << nbits) - 1);
|
||||
|
||||
/* If there are not continuous nbits in the current bitpack word
|
||||
switch to the next one. */
|
||||
if (pos + nbits > BITS_PER_BITPACK_WORD)
|
||||
{
|
||||
bp->word = val = lto_input_uleb128 ((struct lto_input_block *)bp->stream);
|
||||
bp->pos = nbits;
|
||||
return val & mask;
|
||||
}
|
||||
val = bp->word;
|
||||
val >>= pos;
|
||||
bp->pos = pos + nbits;
|
||||
|
||||
return val & mask;
|
||||
}
|
||||
|
||||
|
||||
/* Write a character to the output block. */
|
||||
|
||||
static inline void
|
||||
lto_output_1_stream (struct lto_output_stream *obs, char c)
|
||||
{
|
||||
/* No space left. */
|
||||
if (obs->left_in_block == 0)
|
||||
lto_append_block (obs);
|
||||
|
||||
/* Write the actual character. */
|
||||
*obs->current_pointer = c;
|
||||
obs->current_pointer++;
|
||||
obs->total_size++;
|
||||
obs->left_in_block--;
|
||||
}
|
||||
|
||||
|
||||
/* Read byte from the input block. */
|
||||
|
||||
static inline unsigned char
|
||||
lto_input_1_unsigned (struct lto_input_block *ib)
|
||||
{
|
||||
if (ib->p >= ib->len)
|
||||
lto_section_overrun (ib);
|
||||
return (ib->data[ib->p++]);
|
||||
}
|
||||
|
||||
/* Output VAL into OBS and verify it is in range MIN...MAX that is supposed
|
||||
to be compile time constant.
|
||||
Be host independent, limit range to 31bits. */
|
||||
|
||||
static inline void
|
||||
lto_output_int_in_range (struct lto_output_stream *obs,
|
||||
HOST_WIDE_INT min,
|
||||
HOST_WIDE_INT max,
|
||||
HOST_WIDE_INT val)
|
||||
{
|
||||
HOST_WIDE_INT range = max - min;
|
||||
|
||||
gcc_checking_assert (val >= min && val <= max && range > 0
|
||||
&& range < 0x7fffffff);
|
||||
|
||||
val -= min;
|
||||
lto_output_1_stream (obs, val & 255);
|
||||
if (range >= 0xff)
|
||||
lto_output_1_stream (obs, (val >> 8) & 255);
|
||||
if (range >= 0xffff)
|
||||
lto_output_1_stream (obs, (val >> 16) & 255);
|
||||
if (range >= 0xffffff)
|
||||
lto_output_1_stream (obs, (val >> 24) & 255);
|
||||
}
|
||||
|
||||
/* Input VAL into OBS and verify it is in range MIN...MAX that is supposed
|
||||
to be compile time constant. PURPOSE is used for error reporting. */
|
||||
|
||||
static inline HOST_WIDE_INT
|
||||
lto_input_int_in_range (struct lto_input_block *ib,
|
||||
const char *purpose,
|
||||
HOST_WIDE_INT min,
|
||||
HOST_WIDE_INT max)
|
||||
{
|
||||
HOST_WIDE_INT range = max - min;
|
||||
HOST_WIDE_INT val = lto_input_1_unsigned (ib);
|
||||
|
||||
gcc_checking_assert (range > 0 && range < 0x7fffffff);
|
||||
|
||||
if (range >= 0xff)
|
||||
val |= ((HOST_WIDE_INT)lto_input_1_unsigned (ib)) << 8;
|
||||
if (range >= 0xffff)
|
||||
val |= ((HOST_WIDE_INT)lto_input_1_unsigned (ib)) << 16;
|
||||
if (range >= 0xffffff)
|
||||
val |= ((HOST_WIDE_INT)lto_input_1_unsigned (ib)) << 24;
|
||||
val += min;
|
||||
if (val < min || val > max)
|
||||
lto_value_range_error (purpose, val, min, max);
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Output VAL into BP and verify it is in range MIN...MAX that is supposed
|
||||
to be compile time constant.
|
||||
Be host independent, limit range to 31bits. */
|
||||
|
||||
static inline void
|
||||
bp_pack_int_in_range (struct bitpack_d *bp,
|
||||
HOST_WIDE_INT min,
|
||||
HOST_WIDE_INT max,
|
||||
HOST_WIDE_INT val)
|
||||
{
|
||||
HOST_WIDE_INT range = max - min;
|
||||
int nbits = floor_log2 (range) + 1;
|
||||
|
||||
gcc_checking_assert (val >= min && val <= max && range > 0
|
||||
&& range < 0x7fffffff);
|
||||
|
||||
val -= min;
|
||||
bp_pack_value (bp, val, nbits);
|
||||
}
|
||||
|
||||
/* Input VAL into BP and verify it is in range MIN...MAX that is supposed
|
||||
to be compile time constant. PURPOSE is used for error reporting. */
|
||||
|
||||
static inline HOST_WIDE_INT
|
||||
bp_unpack_int_in_range (struct bitpack_d *bp,
|
||||
const char *purpose,
|
||||
HOST_WIDE_INT min,
|
||||
HOST_WIDE_INT max)
|
||||
{
|
||||
HOST_WIDE_INT range = max - min;
|
||||
int nbits = floor_log2 (range) + 1;
|
||||
HOST_WIDE_INT val = bp_unpack_value (bp, nbits);
|
||||
|
||||
gcc_checking_assert (range > 0 && range < 0x7fffffff);
|
||||
|
||||
if (val < min || val > max)
|
||||
lto_value_range_error (purpose, val, min, max);
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Output VAL of type "enum enum_name" into OBS.
|
||||
Assume range 0...ENUM_LAST - 1. */
|
||||
#define lto_output_enum(obs,enum_name,enum_last,val) \
|
||||
lto_output_int_in_range ((obs), 0, (int)(enum_last) - 1, (int)(val))
|
||||
|
||||
/* Input enum of type "enum enum_name" from IB.
|
||||
Assume range 0...ENUM_LAST - 1. */
|
||||
#define lto_input_enum(ib,enum_name,enum_last) \
|
||||
(enum enum_name)lto_input_int_in_range ((ib), #enum_name, 0, \
|
||||
(int)(enum_last) - 1)
|
||||
|
||||
/* Output VAL of type "enum enum_name" into BP.
|
||||
Assume range 0...ENUM_LAST - 1. */
|
||||
#define bp_pack_enum(bp,enum_name,enum_last,val) \
|
||||
bp_pack_int_in_range ((bp), 0, (int)(enum_last) - 1, (int)(val))
|
||||
|
||||
/* Input enum of type "enum enum_name" from BP.
|
||||
Assume range 0...ENUM_LAST - 1. */
|
||||
#define bp_unpack_enum(bp,enum_name,enum_last) \
|
||||
(enum enum_name)bp_unpack_int_in_range ((bp), #enum_name, 0, \
|
||||
(int)(enum_last) - 1)
|
||||
|
||||
/* Output the start of a record with TAG to output block OB. */
|
||||
|
||||
static inline void
|
||||
output_record_start (struct output_block *ob, enum LTO_tags tag)
|
||||
{
|
||||
lto_output_enum (ob->main_stream, LTO_tags, LTO_NUM_TAGS, tag);
|
||||
}
|
||||
|
||||
/* Return the next tag in the input block IB. */
|
||||
|
||||
static inline enum LTO_tags
|
||||
input_record_start (struct lto_input_block *ib)
|
||||
{
|
||||
return lto_input_enum (ib, LTO_tags, LTO_NUM_TAGS);
|
||||
}
|
||||
|
||||
/* In data-streamer.c */
|
||||
void bp_pack_var_len_unsigned (struct bitpack_d *, unsigned HOST_WIDE_INT);
|
||||
void bp_pack_var_len_int (struct bitpack_d *, HOST_WIDE_INT);
|
||||
unsigned HOST_WIDE_INT bp_unpack_var_len_unsigned (struct bitpack_d *);
|
||||
HOST_WIDE_INT bp_unpack_var_len_int (struct bitpack_d *);
|
||||
|
||||
/* In data-streamer-out.c */
|
||||
void output_zero (struct output_block *);
|
||||
void output_uleb128 (struct output_block *, unsigned HOST_WIDE_INT);
|
||||
void output_sleb128 (struct output_block *, HOST_WIDE_INT);
|
||||
void lto_output_string (struct output_block *, struct lto_output_stream *,
|
||||
const char *, bool);
|
||||
unsigned lto_string_index (struct output_block *, const char *, unsigned int,
|
||||
bool);
|
||||
void lto_output_string_with_length (struct output_block *,
|
||||
struct lto_output_stream *,
|
||||
const char *, unsigned int, bool);
|
||||
const char *input_string_internal (struct data_in *, struct lto_input_block *,
|
||||
unsigned int *);
|
||||
|
||||
/* In data-streamer-in.c */
|
||||
const char *string_for_index (struct data_in *, unsigned int, unsigned int *);
|
||||
const char *lto_input_string (struct data_in *, struct lto_input_block *);
|
||||
|
||||
#endif /* GCC_DATA_STREAMER_H */
|
|
@ -0,0 +1,333 @@
|
|||
/* 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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,213 @@
|
|||
/* 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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/* 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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -32,12 +32,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "vecprim.h"
|
||||
#include "alloc-pool.h"
|
||||
#include "gcov-io.h"
|
||||
|
||||
/* Forward declarations to avoid including unnecessary headers. */
|
||||
struct output_block;
|
||||
struct lto_input_block;
|
||||
struct data_in;
|
||||
struct bitpack_d;
|
||||
#include "diagnostic.h"
|
||||
|
||||
/* Define when debugging the LTO streamer. This causes the writer
|
||||
to output the numeric value for the memory address of the tree node
|
||||
|
@ -152,27 +147,6 @@ struct bitpack_d;
|
|||
typedef unsigned char lto_decl_flags_t;
|
||||
|
||||
|
||||
/* Data structures used to pack values and bitflags into a vector of
|
||||
words. Used to stream values of a fixed number of bits in a space
|
||||
efficient way. */
|
||||
static unsigned const BITS_PER_BITPACK_WORD = HOST_BITS_PER_WIDE_INT;
|
||||
|
||||
typedef unsigned HOST_WIDE_INT bitpack_word_t;
|
||||
DEF_VEC_I(bitpack_word_t);
|
||||
DEF_VEC_ALLOC_I(bitpack_word_t, heap);
|
||||
|
||||
struct bitpack_d
|
||||
{
|
||||
/* The position of the first unused or unconsumed bit in the word. */
|
||||
unsigned pos;
|
||||
|
||||
/* The current word we are (un)packing. */
|
||||
bitpack_word_t word;
|
||||
|
||||
/* The lto_output_stream or the lto_input_block we are streaming to/from. */
|
||||
void *stream;
|
||||
};
|
||||
|
||||
/* Tags representing the various IL objects written to the bytecode file
|
||||
(GIMPLE statements, basic blocks, EH regions, tree nodes, etc).
|
||||
|
||||
|
@ -332,33 +306,6 @@ typedef void (lto_free_section_data_f) (struct lto_file_decl_data *,
|
|||
const char *,
|
||||
size_t);
|
||||
|
||||
/* 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;
|
||||
};
|
||||
|
||||
|
||||
/* Structure used as buffer for reading an LTO file. */
|
||||
struct lto_input_block
|
||||
{
|
||||
|
@ -747,86 +694,6 @@ struct data_in
|
|||
};
|
||||
|
||||
|
||||
/* 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 lto-section-in.c */
|
||||
extern struct lto_input_block * lto_create_simple_input_block (
|
||||
struct lto_file_decl_data *,
|
||||
|
@ -864,10 +731,6 @@ extern void lto_section_overrun (struct lto_input_block *) ATTRIBUTE_NORETURN;
|
|||
extern void lto_value_range_error (const char *,
|
||||
HOST_WIDE_INT, HOST_WIDE_INT,
|
||||
HOST_WIDE_INT) ATTRIBUTE_NORETURN;
|
||||
extern void bp_pack_var_len_unsigned (struct bitpack_d *, unsigned HOST_WIDE_INT);
|
||||
extern void bp_pack_var_len_int (struct bitpack_d *, HOST_WIDE_INT);
|
||||
extern unsigned HOST_WIDE_INT bp_unpack_var_len_unsigned (struct bitpack_d *);
|
||||
extern HOST_WIDE_INT bp_unpack_var_len_int (struct bitpack_d *);
|
||||
|
||||
/* In lto-section-out.c */
|
||||
extern hashval_t lto_hash_decl_slot_node (const void *);
|
||||
|
@ -919,16 +782,6 @@ extern bitmap lto_bitmap_alloc (void);
|
|||
extern void lto_bitmap_free (bitmap);
|
||||
extern char *lto_get_section_name (int, const char *, struct lto_file_decl_data *);
|
||||
extern void print_lto_report (void);
|
||||
extern bool lto_streamer_cache_insert (struct lto_streamer_cache_d *, tree,
|
||||
unsigned *);
|
||||
extern bool lto_streamer_cache_insert_at (struct lto_streamer_cache_d *, tree,
|
||||
unsigned);
|
||||
extern void lto_streamer_cache_append (struct lto_streamer_cache_d *, tree);
|
||||
extern bool lto_streamer_cache_lookup (struct lto_streamer_cache_d *, tree,
|
||||
unsigned *);
|
||||
extern tree lto_streamer_cache_get (struct lto_streamer_cache_d *, unsigned);
|
||||
extern struct lto_streamer_cache_d *lto_streamer_cache_create (void);
|
||||
extern void lto_streamer_cache_delete (struct lto_streamer_cache_d *);
|
||||
extern void lto_streamer_init (void);
|
||||
extern bool gate_lto_out (void);
|
||||
#ifdef LTO_STREAMER_DEBUG
|
||||
|
@ -938,15 +791,10 @@ extern void lto_orig_address_remove (tree);
|
|||
#endif
|
||||
extern void lto_check_version (int, int);
|
||||
extern void lto_streamer_hooks_init (void);
|
||||
extern void lto_streamer_write_tree (struct output_block *, tree, bool);
|
||||
extern void lto_streamer_read_tree (struct lto_input_block *,
|
||||
struct data_in *, tree);
|
||||
extern void streamer_hooks_init (void);
|
||||
|
||||
/* In lto-streamer-in.c */
|
||||
extern void lto_input_cgraph (struct lto_file_decl_data *, const char *);
|
||||
extern void lto_reader_init (void);
|
||||
extern tree lto_input_tree (struct lto_input_block *, struct data_in *);
|
||||
extern void lto_input_function_body (struct lto_file_decl_data *, tree,
|
||||
const char *);
|
||||
extern void lto_input_constructors_and_inits (struct lto_file_decl_data *,
|
||||
|
@ -955,9 +803,12 @@ extern struct data_in *lto_data_in_create (struct lto_file_decl_data *,
|
|||
const char *, unsigned,
|
||||
VEC(ld_plugin_symbol_resolution_t,heap) *);
|
||||
extern void lto_data_in_delete (struct data_in *);
|
||||
extern const char *lto_input_string (struct data_in *,
|
||||
struct lto_input_block *);
|
||||
extern void lto_input_data_block (struct lto_input_block *, void *, size_t);
|
||||
location_t lto_input_location (struct lto_input_block *, struct data_in *);
|
||||
tree lto_input_tree_ref (struct lto_input_block *, struct data_in *,
|
||||
struct function *, enum LTO_tags);
|
||||
void lto_tag_check_set (enum LTO_tags, int, ...);
|
||||
void lto_init_eh (void);
|
||||
|
||||
|
||||
/* In lto-streamer-out.c */
|
||||
|
@ -971,6 +822,8 @@ void lto_output_decl_state_streams (struct output_block *,
|
|||
void lto_output_decl_state_refs (struct output_block *,
|
||||
struct lto_output_stream *,
|
||||
struct lto_out_decl_state *);
|
||||
void lto_output_tree_ref (struct output_block *, tree);
|
||||
void lto_output_location (struct output_block *, location_t);
|
||||
|
||||
|
||||
/* In lto-cgraph.c */
|
||||
|
@ -1096,6 +949,28 @@ lto_tag_to_tree_code (enum LTO_tags tag)
|
|||
return (enum tree_code) ((unsigned) tag - 1);
|
||||
}
|
||||
|
||||
/* Check that tag ACTUAL == EXPECTED. */
|
||||
static inline void
|
||||
lto_tag_check (enum LTO_tags actual, enum LTO_tags expected)
|
||||
{
|
||||
if (actual != expected)
|
||||
internal_error ("bytecode stream: expected tag %s instead of %s",
|
||||
lto_tag_name (expected), lto_tag_name (actual));
|
||||
}
|
||||
|
||||
/* Check that tag ACTUAL is in the range [TAG1, TAG2]. */
|
||||
static inline void
|
||||
lto_tag_check_range (enum LTO_tags actual, enum LTO_tags tag1,
|
||||
enum LTO_tags tag2)
|
||||
{
|
||||
if (actual < tag1 || actual > tag2)
|
||||
internal_error ("bytecode stream: tag %s is not in the expected range "
|
||||
"[%s, %s]",
|
||||
lto_tag_name (actual),
|
||||
lto_tag_name (tag1),
|
||||
lto_tag_name (tag2));
|
||||
}
|
||||
|
||||
/* Initialize an lto_out_decl_buffer ENCODER. */
|
||||
static inline void
|
||||
lto_init_tree_ref_encoder (struct lto_tree_ref_encoder *encoder,
|
||||
|
@ -1160,232 +1035,4 @@ DEFINE_DECL_STREAM_FUNCS (TYPE_DECL, type_decl)
|
|||
DEFINE_DECL_STREAM_FUNCS (NAMESPACE_DECL, namespace_decl)
|
||||
DEFINE_DECL_STREAM_FUNCS (LABEL_DECL, label_decl)
|
||||
|
||||
/* Returns a new bit-packing context for bit-packing into S. */
|
||||
static inline struct bitpack_d
|
||||
bitpack_create (struct lto_output_stream *s)
|
||||
{
|
||||
struct bitpack_d bp;
|
||||
bp.pos = 0;
|
||||
bp.word = 0;
|
||||
bp.stream = (void *)s;
|
||||
return bp;
|
||||
}
|
||||
|
||||
/* Pack the NBITS bit sized value VAL into the bit-packing context BP. */
|
||||
static inline void
|
||||
bp_pack_value (struct bitpack_d *bp, bitpack_word_t val, unsigned nbits)
|
||||
{
|
||||
bitpack_word_t word = bp->word;
|
||||
int pos = bp->pos;
|
||||
|
||||
/* Verify that VAL fits in the NBITS. */
|
||||
gcc_checking_assert (nbits == BITS_PER_BITPACK_WORD
|
||||
|| !(val & ~(((bitpack_word_t)1<<nbits)-1)));
|
||||
|
||||
/* If val does not fit into the current bitpack word switch to the
|
||||
next one. */
|
||||
if (pos + nbits > BITS_PER_BITPACK_WORD)
|
||||
{
|
||||
lto_output_uleb128_stream ((struct lto_output_stream *) bp->stream, word);
|
||||
word = val;
|
||||
pos = nbits;
|
||||
}
|
||||
else
|
||||
{
|
||||
word |= val << pos;
|
||||
pos += nbits;
|
||||
}
|
||||
bp->word = word;
|
||||
bp->pos = pos;
|
||||
}
|
||||
|
||||
/* Finishes bit-packing of BP. */
|
||||
static inline void
|
||||
lto_output_bitpack (struct bitpack_d *bp)
|
||||
{
|
||||
lto_output_uleb128_stream ((struct lto_output_stream *) bp->stream,
|
||||
bp->word);
|
||||
bp->word = 0;
|
||||
bp->pos = 0;
|
||||
}
|
||||
|
||||
/* Returns a new bit-packing context for bit-unpacking from IB. */
|
||||
static inline struct bitpack_d
|
||||
lto_input_bitpack (struct lto_input_block *ib)
|
||||
{
|
||||
struct bitpack_d bp;
|
||||
bp.word = lto_input_uleb128 (ib);
|
||||
bp.pos = 0;
|
||||
bp.stream = (void *)ib;
|
||||
return bp;
|
||||
}
|
||||
|
||||
/* Unpacks NBITS bits from the bit-packing context BP and returns them. */
|
||||
static inline bitpack_word_t
|
||||
bp_unpack_value (struct bitpack_d *bp, unsigned nbits)
|
||||
{
|
||||
bitpack_word_t mask, val;
|
||||
int pos = bp->pos;
|
||||
|
||||
mask = (nbits == BITS_PER_BITPACK_WORD
|
||||
? (bitpack_word_t) -1
|
||||
: ((bitpack_word_t) 1 << nbits) - 1);
|
||||
|
||||
/* If there are not continuous nbits in the current bitpack word
|
||||
switch to the next one. */
|
||||
if (pos + nbits > BITS_PER_BITPACK_WORD)
|
||||
{
|
||||
bp->word = val = lto_input_uleb128 ((struct lto_input_block *)bp->stream);
|
||||
bp->pos = nbits;
|
||||
return val & mask;
|
||||
}
|
||||
val = bp->word;
|
||||
val >>= pos;
|
||||
bp->pos = pos + nbits;
|
||||
|
||||
return val & mask;
|
||||
}
|
||||
|
||||
|
||||
/* Write a character to the output block. */
|
||||
|
||||
static inline void
|
||||
lto_output_1_stream (struct lto_output_stream *obs, char c)
|
||||
{
|
||||
/* No space left. */
|
||||
if (obs->left_in_block == 0)
|
||||
lto_append_block (obs);
|
||||
|
||||
/* Write the actual character. */
|
||||
*obs->current_pointer = c;
|
||||
obs->current_pointer++;
|
||||
obs->total_size++;
|
||||
obs->left_in_block--;
|
||||
}
|
||||
|
||||
|
||||
/* Read byte from the input block. */
|
||||
|
||||
static inline unsigned char
|
||||
lto_input_1_unsigned (struct lto_input_block *ib)
|
||||
{
|
||||
if (ib->p >= ib->len)
|
||||
lto_section_overrun (ib);
|
||||
return (ib->data[ib->p++]);
|
||||
}
|
||||
|
||||
/* Output VAL into OBS and verify it is in range MIN...MAX that is supposed
|
||||
to be compile time constant.
|
||||
Be host independent, limit range to 31bits. */
|
||||
|
||||
static inline void
|
||||
lto_output_int_in_range (struct lto_output_stream *obs,
|
||||
HOST_WIDE_INT min,
|
||||
HOST_WIDE_INT max,
|
||||
HOST_WIDE_INT val)
|
||||
{
|
||||
HOST_WIDE_INT range = max - min;
|
||||
|
||||
gcc_checking_assert (val >= min && val <= max && range > 0
|
||||
&& range < 0x7fffffff);
|
||||
|
||||
val -= min;
|
||||
lto_output_1_stream (obs, val & 255);
|
||||
if (range >= 0xff)
|
||||
lto_output_1_stream (obs, (val >> 8) & 255);
|
||||
if (range >= 0xffff)
|
||||
lto_output_1_stream (obs, (val >> 16) & 255);
|
||||
if (range >= 0xffffff)
|
||||
lto_output_1_stream (obs, (val >> 24) & 255);
|
||||
}
|
||||
|
||||
/* Input VAL into OBS and verify it is in range MIN...MAX that is supposed
|
||||
to be compile time constant. PURPOSE is used for error reporting. */
|
||||
|
||||
static inline HOST_WIDE_INT
|
||||
lto_input_int_in_range (struct lto_input_block *ib,
|
||||
const char *purpose,
|
||||
HOST_WIDE_INT min,
|
||||
HOST_WIDE_INT max)
|
||||
{
|
||||
HOST_WIDE_INT range = max - min;
|
||||
HOST_WIDE_INT val = lto_input_1_unsigned (ib);
|
||||
|
||||
gcc_checking_assert (range > 0 && range < 0x7fffffff);
|
||||
|
||||
if (range >= 0xff)
|
||||
val |= ((HOST_WIDE_INT)lto_input_1_unsigned (ib)) << 8;
|
||||
if (range >= 0xffff)
|
||||
val |= ((HOST_WIDE_INT)lto_input_1_unsigned (ib)) << 16;
|
||||
if (range >= 0xffffff)
|
||||
val |= ((HOST_WIDE_INT)lto_input_1_unsigned (ib)) << 24;
|
||||
val += min;
|
||||
if (val < min || val > max)
|
||||
lto_value_range_error (purpose, val, min, max);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/* Output VAL into BP and verify it is in range MIN...MAX that is supposed
|
||||
to be compile time constant.
|
||||
Be host independent, limit range to 31bits. */
|
||||
|
||||
static inline void
|
||||
bp_pack_int_in_range (struct bitpack_d *bp,
|
||||
HOST_WIDE_INT min,
|
||||
HOST_WIDE_INT max,
|
||||
HOST_WIDE_INT val)
|
||||
{
|
||||
HOST_WIDE_INT range = max - min;
|
||||
int nbits = floor_log2 (range) + 1;
|
||||
|
||||
gcc_checking_assert (val >= min && val <= max && range > 0
|
||||
&& range < 0x7fffffff);
|
||||
|
||||
val -= min;
|
||||
bp_pack_value (bp, val, nbits);
|
||||
}
|
||||
|
||||
/* Input VAL into BP and verify it is in range MIN...MAX that is supposed
|
||||
to be compile time constant. PURPOSE is used for error reporting. */
|
||||
|
||||
static inline HOST_WIDE_INT
|
||||
bp_unpack_int_in_range (struct bitpack_d *bp,
|
||||
const char *purpose,
|
||||
HOST_WIDE_INT min,
|
||||
HOST_WIDE_INT max)
|
||||
{
|
||||
HOST_WIDE_INT range = max - min;
|
||||
int nbits = floor_log2 (range) + 1;
|
||||
HOST_WIDE_INT val = bp_unpack_value (bp, nbits);
|
||||
|
||||
gcc_checking_assert (range > 0 && range < 0x7fffffff);
|
||||
|
||||
if (val < min || val > max)
|
||||
lto_value_range_error (purpose, val, min, max);
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Output VAL of type "enum enum_name" into OBS.
|
||||
Assume range 0...ENUM_LAST - 1. */
|
||||
#define lto_output_enum(obs,enum_name,enum_last,val) \
|
||||
lto_output_int_in_range ((obs), 0, (int)(enum_last) - 1, (int)(val))
|
||||
|
||||
/* Input enum of type "enum enum_name" from IB.
|
||||
Assume range 0...ENUM_LAST - 1. */
|
||||
#define lto_input_enum(ib,enum_name,enum_last) \
|
||||
(enum enum_name)lto_input_int_in_range ((ib), #enum_name, 0, \
|
||||
(int)(enum_last) - 1)
|
||||
|
||||
/* Output VAL of type "enum enum_name" into BP.
|
||||
Assume range 0...ENUM_LAST - 1. */
|
||||
#define bp_pack_enum(bp,enum_name,enum_last,val) \
|
||||
bp_pack_int_in_range ((bp), 0, (int)(enum_last) - 1, (int)(val))
|
||||
|
||||
/* Input enum of type "enum enum_name" from BP.
|
||||
Assume range 0...ENUM_LAST - 1. */
|
||||
#define bp_unpack_enum(bp,enum_name,enum_last) \
|
||||
(enum enum_name)bp_unpack_int_in_range ((bp), #enum_name, 0, \
|
||||
(int)(enum_last) - 1)
|
||||
|
||||
#endif /* GCC_LTO_STREAMER_H */
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
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"
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/* 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));
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
/* 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 */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,279 @@
|
|||
/* 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);
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/* 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 */
|
Loading…
Reference in New Issue