2011-06-14 Lawrence Crowl <crowl@google.com>
* g++.dg/pph/x1tmplfunc.cc: Replace ICE xfail with an assembly diff
xfail.
2011-06-14 Lawrence Crowl <crowl@google.com>
* pph-streamer-out.c (pph_out_struct_function): New.
(pph_out_used_types_slot): New for pph_out_struct_function.
(struct pph_tree_info): New for pph_out_struct_function.
(pph_write_tree): Save DECL_STRUCT_FUNCTION of FUNCTION_DECL with
pph_out_struct_function.
* pph-streamer-in.c (pph_in_struct_function): New.
(pph_read_tree): Load DECL_STRUCT_FUNCTION of FUNCTION_DECL with
pph_in_struct_function.
2011-06-14 Lawrence Crowl <crowl@google.com>
* lto-streamer.h (extern output_struct_function_base): New.
(extern input_struct_function_base): New.
* lto-streamer-out.c (lto_output_ts_function_decl_tree_pointers):
Update comment.
(output_struct_function_base): New.
(output_function): Factor out code common with PPH into
output_struct_function_base.
* lto-streamer-in.c (input_struct_function_base): New.
(input_function): Factor out common code with PPH into
input_struct_function_base.
===================================================================
@@ -1,6 +1,4 @@
-// { dg-xfail-if "ICE" { "*-*-*" } { "-fpph-map=pph.map" } }
-// { dg-bogus "x1tmplfunc.h:8:16: internal compiler error: Segmentation fault" "" { xfail *-*-* } 0 }
-// { dg-prune-output "In file included from " }
+// pph asm xdiff
#include "x1tmplfunc.h"
===================================================================
@@ -608,6 +608,88 @@ pph_in_ld_fn (pph_stream *stream, struct
}
+/* Read applicable fields of struct function instance FN from STREAM. */
+
+static struct function *
+pph_in_struct_function (pph_stream *stream)
+{
+ size_t count, i;
+ unsigned ix;
+ enum pph_record_marker marker;
+ struct function *fn;
+
+ gcc_assert (stream->data_in != NULL);
+
+ marker = pph_start_record (stream, &ix);
+ if (marker == PPH_RECORD_END)
+ return NULL;
+
+ /* Since struct function is embedded in every decl, fn cannot be shared. */
+ gcc_assert (marker != PPH_RECORD_SHARED);
+
+ fn = ggc_alloc_cleared_function ();
+
+ input_struct_function_base (fn, stream->data_in, stream->ib);
+
+ /* struct eh_status *eh; -- zero init */
+ /* struct control_flow_graph *cfg; -- zero init */
+ /* struct gimple_seq_d *gimple_body; -- zero init */
+ /* struct gimple_df *gimple_df; -- zero init */
+ /* struct loops *x_current_loops; -- zero init */
+ /* struct stack_usage *su; -- zero init */
+ /* htab_t value_histograms; -- zero init */
+ /* tree decl; -- zero init */
+ /* tree static_chain_decl; -- in base */
+ /* tree nonlocal_goto_save_area; -- in base */
+ /* tree local_decls; -- in base */
+ /* struct machine_function * machine; -- zero init */
+
+ fn->language = pph_in_language_function (stream);
+
+ count = pph_in_uint (stream);
+ if ( count > 0 )
+ {
+ fn->used_types_hash = htab_create_ggc (37, htab_hash_pointer,
+ htab_eq_pointer, NULL);
+ for (i = 0; i < count; i++)
+ {
+ void **slot;
+ tree type = pph_in_tree (stream);
+ slot = htab_find_slot (fn->used_types_hash, type, INSERT);
+ if (*slot == NULL)
+ *slot = type;
+ }
+ }
+ /* else zero initialized */
+
+ /* int last_stmt_uid; -- zero init */
+ /* int funcdef_no; -- zero init */
+ /* location_t function_start_locus; -- in base */
+ /* location_t function_end_locus; -- in base */
+ /* unsigned int curr_properties; -- in base */
+ /* unsigned int last_verified; -- zero init */
+ /* const char *cannot_be_copied_reason; -- zero init */
+
+ /* unsigned int va_list_gpr_size : 8; -- in base */
+ /* unsigned int va_list_fpr_size : 8; -- in base */
+ /* unsigned int calls_setjmp : 1; -- in base */
+ /* unsigned int calls_alloca : 1; -- in base */
+ /* unsigned int has_nonlocal_label : 1; -- in base */
+ /* unsigned int cannot_be_copied_set : 1; -- zero init */
+ /* unsigned int stdarg : 1; -- in base */
+ /* unsigned int after_inlining : 1; -- in base */
+ /* unsigned int always_inline_functions_inlined : 1; -- in base */
+ /* unsigned int can_throw_non_call_exceptions : 1; -- in base */
+ /* unsigned int returns_struct : 1; -- in base */
+ /* unsigned int returns_pcc_struct : 1; -- in base */
+ /* unsigned int after_tree_profile : 1; -- in base */
+ /* unsigned int has_local_explicit_reg_vars : 1; -- in base */
+ /* unsigned int is_thunk : 1; -- in base */
+
+ return fn;
+}
+
+
/* Read all the fields of lang_decl_ns instance LDNS from STREAM. */
static void
@@ -932,6 +1014,7 @@ pph_read_tree (struct lto_input_block *i
DECL_INITIAL (expr) = pph_in_tree (stream);
pph_in_lang_specific (stream, expr);
DECL_SAVED_TREE (expr) = pph_in_tree (stream);
+ DECL_STRUCT_FUNCTION (expr) = pph_in_struct_function (stream);
break;
case TYPE_DECL:
===================================================================
@@ -599,6 +599,89 @@ pph_out_ld_fn (pph_stream *stream, struc
}
+/* A callback of htab_traverse. Just extracts a (type) tree from SLOT
+ and writes it out for PPH. */
+
+struct pph_tree_info {
+ pph_stream *stream;
+ bool ref_p;
+};
+
+static int
+pph_out_used_types_slot (void **slot, void *aux)
+{
+ struct pph_tree_info *pti = (struct pph_tree_info *)aux;
+ pph_out_tree_or_ref (pti->stream, (tree) *slot, pti->ref_p);
+ return 1;
+}
+
+
+/* Write applicable fields of struct function instance FN to STREAM.
+ If REF_P is true, all tree fields should be written as references. */
+
+static void
+pph_out_struct_function (pph_stream *stream, struct function *fn, bool ref_p)
+{
+ struct pph_tree_info pti;
+
+ if (!pph_start_record (stream, fn))
+ return;
+
+ output_struct_function_base (stream->ob, fn);
+
+ /* struct eh_status *eh; -- ignored */
+ gcc_assert (fn->cfg == NULL);
+ gcc_assert (fn->gimple_body == NULL);
+ gcc_assert (fn->gimple_df == NULL);
+ gcc_assert (fn->x_current_loops == NULL);
+ gcc_assert (fn->su == NULL);
+ /* htab_t value_histograms; -- ignored */
+ /* tree decl; -- ignored */
+ /* tree static_chain_decl; -- in base */
+ /* tree nonlocal_goto_save_area; -- in base */
+ /* VEC(tree,gc) *local_decls; -- in base */
+ /* struct machine_function *machine; -- ignored */
+ pph_out_language_function (stream, fn->language, ref_p);
+
+ /*FIXME pph: We would like to detect improper sharing here. */
+ if (fn->used_types_hash)
+ {
+ /*FIXME pph: This write may be unstable. */
+ pph_out_uint (stream, htab_elements (fn->used_types_hash));
+ pti.stream = stream;
+ pti.ref_p = ref_p;
+ htab_traverse_noresize (fn->used_types_hash,
+ pph_out_used_types_slot, &pti);
+ }
+ else
+ pph_out_uint (stream, 0);
+
+ gcc_assert (fn->last_stmt_uid == 0);
+ /* int funcdef_no; -- ignored */
+ /* location_t function_start_locus; -- in base */
+ /* location_t function_end_locus; -- in base */
+ /* unsigned int curr_properties; -- in base */
+ /* unsigned int last_verified; -- ignored */
+ /* const char *cannot_be_copied_reason; -- ignored */
+
+ /* unsigned int va_list_gpr_size : 8; -- in base */
+ /* unsigned int va_list_fpr_size : 8; -- in base */
+ /* unsigned int calls_setjmp : 1; -- in base */
+ /* unsigned int calls_alloca : 1; -- in base */
+ /* unsigned int has_nonlocal_label : 1; -- in base */
+ /* unsigned int cannot_be_copied_set : 1; -- ignored */
+ /* unsigned int stdarg : 1; -- in base */
+ /* unsigned int after_inlining : 1; -- in base */
+ /* unsigned int always_inline_functions_inlined : 1; -- in base */
+ /* unsigned int can_throw_non_call_exceptions : 1; -- in base */
+ /* unsigned int returns_struct : 1; -- in base */
+ /* unsigned int returns_pcc_struct : 1; -- in base */
+ /* unsigned int after_tree_profile : 1; -- in base */
+ /* unsigned int has_local_explicit_reg_vars : 1; -- in base */
+ /* unsigned int is_thunk : 1; -- in base */
+}
+
+
/* Write all the fields of lang_decl_ns instance LDNS to STREAM. If REF_P
is true, all tree fields should be written as references. */
@@ -883,6 +966,7 @@ pph_write_tree (struct output_block *ob,
pph_out_tree_or_ref_1 (stream, DECL_INITIAL (expr), ref_p, 3);
pph_out_lang_specific (stream, expr, ref_p);
pph_out_tree_or_ref_1 (stream, DECL_SAVED_TREE (expr), ref_p, 3);
+ pph_out_struct_function (stream, DECL_STRUCT_FUNCTION (expr), ref_p);
break;
case TYPE_DECL:
===================================================================
@@ -967,8 +967,8 @@ static void
lto_output_ts_function_decl_tree_pointers (struct output_block *ob, tree expr,
bool ref_p)
{
- /* DECL_STRUCT_FUNCTION is handled by lto_output_function. FIXME lto,
- maybe it should be handled here? */
+ /* DECL_STRUCT_FUNCTION is handled by lto_streamer-out.c:output_function
+ or by pph-specific code. */
lto_output_tree_or_ref (ob, DECL_FUNCTION_PERSONALITY (expr), ref_p);
lto_output_tree_or_ref (ob, DECL_FUNCTION_SPECIFIC_TARGET (expr), ref_p);
lto_output_tree_or_ref (ob, DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr),
@@ -1974,36 +1974,48 @@ produce_asm (struct output_block *ob, tr
}
-/* Output the body of function NODE->DECL. */
+/* Output the base body of struct function FN using output block OB. */
-static void
-output_function (struct cgraph_node *node)
+void
+output_struct_function_base (struct output_block *ob, struct function *fn)
{
struct bitpack_d bp;
- tree function;
- struct function *fn;
- basic_block bb;
- struct output_block *ob;
unsigned i;
tree t;
- function = node->decl;
- fn = DECL_STRUCT_FUNCTION (function);
- ob = create_output_block (LTO_section_function_body);
+ /* struct eh_status *eh; -- maybe elsewhere */
+ /* struct control_flow_graph *cfg; -- maybe elsewhere */
+ /* struct gimple_seq_d *gimple_body; -- maybe elsewhere */
+ /* struct gimple_df *gimple_df; -- maybe elsewhere */
+ /* struct loops *x_current_loops; -- maybe elsewhere */
+ /* struct stack_usage *su; -- maybe elsewhere */
+ /* htab_t value_histograms; -- ignored */
+ /* tree decl; -- ignored */
- clear_line_info (ob);
- ob->cgraph_node = node;
+ /* Output the static chain and non-local goto save area. */
+ lto_output_tree_ref (ob, fn->static_chain_decl);
+ lto_output_tree_ref (ob, fn->nonlocal_goto_save_area);
- gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
+ /* Output all the local variables in the function. */
+ output_sleb128 (ob, VEC_length (tree, fn->local_decls));
+ FOR_EACH_VEC_ELT (tree, fn->local_decls, i, t)
+ lto_output_tree_ref (ob, t);
- /* Set current_function_decl and cfun. */
- current_function_decl = function;
- push_cfun (fn);
+ /* struct machine_function * machine; -- ignored */
+ /* struct language_function * language; -- maybe elsewhere */
+ /* htab_t used_types_hash; -- maybe elsewhere */
+ /* int last_stmt_uid; -- maybe elsewhere */
+ /* int funcdef_no; -- maybe elsewhere */
- /* Make string 0 be a NULL string. */
- lto_output_1_stream (ob->string_stream, 0);
+ /* Output the function start and end loci. */
+ lto_output_location (ob, fn->function_start_locus);
+ lto_output_location (ob, fn->function_end_locus);
- output_record_start (ob, LTO_function);
+ /* Output current IL state of the function. */
+ output_uleb128 (ob, fn->curr_properties);
+
+ /* unsigned int last_verified; -- ignored */
+ /* const char *cannot_be_copied_reason; -- ignored */
/* Write all the attributes for FN. */
bp = bitpack_create (ob->main_stream);
@@ -2016,28 +2028,45 @@ output_function (struct cgraph_node *nod
bp_pack_value (&bp, fn->always_inline_functions_inlined, 1);
bp_pack_value (&bp, fn->after_inlining, 1);
bp_pack_value (&bp, fn->stdarg, 1);
+ /* unsigned int cannot_be_copied_set : 1; -- ignored */
bp_pack_value (&bp, fn->has_nonlocal_label, 1);
bp_pack_value (&bp, fn->calls_alloca, 1);
bp_pack_value (&bp, fn->calls_setjmp, 1);
bp_pack_value (&bp, fn->va_list_fpr_size, 8);
bp_pack_value (&bp, fn->va_list_gpr_size, 8);
lto_output_bitpack (&bp);
+}
- /* Output the function start and end loci. */
- lto_output_location (ob, fn->function_start_locus);
- lto_output_location (ob, fn->function_end_locus);
- /* Output current IL state of the function. */
- output_uleb128 (ob, fn->curr_properties);
+/* Output the body of function NODE->DECL. */
- /* Output the static chain and non-local goto save area. */
- lto_output_tree_ref (ob, fn->static_chain_decl);
- lto_output_tree_ref (ob, fn->nonlocal_goto_save_area);
+static void
+output_function (struct cgraph_node *node)
+{
+ tree function;
+ struct function *fn;
+ basic_block bb;
+ struct output_block *ob;
- /* Output all the local variables in the function. */
- output_sleb128 (ob, VEC_length (tree, fn->local_decls));
- FOR_EACH_VEC_ELT (tree, fn->local_decls, i, t)
- lto_output_tree_ref (ob, t);
+ function = node->decl;
+ fn = DECL_STRUCT_FUNCTION (function);
+ ob = create_output_block (LTO_section_function_body);
+
+ clear_line_info (ob);
+ ob->cgraph_node = node;
+
+ gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
+
+ /* Set current_function_decl and cfun. */
+ current_function_decl = function;
+ push_cfun (fn);
+
+ /* Make string 0 be a NULL string. */
+ lto_output_1_stream (ob->string_stream, 0);
+
+ output_record_start (ob, LTO_function);
+
+ output_struct_function_base (ob, fn);
/* Output the head of the arguments list. */
lto_output_tree_ref (ob, DECL_ARGUMENTS (function));
===================================================================
@@ -1242,27 +1242,55 @@ fixup_call_stmt_edges (struct cgraph_nod
}
}
-/* Read the body of function FN_DECL from DATA_IN using input block IB. */
-static void
-input_function (tree fn_decl, struct data_in *data_in,
- struct lto_input_block *ib)
+/* Input the base body of struct function FN from DATA_IN
+ using input block IB. */
+
+void
+input_struct_function_base (struct function *fn, struct data_in *data_in,
+ struct lto_input_block *ib)
{
- struct function *fn;
- enum LTO_tags tag;
- gimple *stmts;
- basic_block bb;
struct bitpack_d bp;
- struct cgraph_node *node;
- tree args, narg, oarg;
int len;
- fn = DECL_STRUCT_FUNCTION (fn_decl);
- tag = input_record_start (ib);
- clear_line_info (data_in);
+ /* struct eh_status *eh; -- maybe elsewhere */
+ /* struct control_flow_graph *cfg; -- maybe elsewhere */
+ /* struct gimple_seq_d *gimple_body; -- maybe elsewhere */
+ /* struct gimple_df *gimple_df; -- maybe elsewhere */
+ /* struct loops *x_current_loops; -- maybe elsewhere */
+ /* struct stack_usage *su; -- maybe elsewhere */
+ /* htab_t value_histograms; -- ignored */
+ /* tree decl; -- ignored */
- gimple_register_cfg_hooks ();
- lto_tag_check (tag, LTO_function);
+ /* Read the static chain and non-local goto save area. */
+ fn->static_chain_decl = lto_input_tree (ib, data_in);
+ fn->nonlocal_goto_save_area = lto_input_tree (ib, data_in);
+
+ /* Read all the local symbols. */
+ len = lto_input_sleb128 (ib);
+ if (len > 0)
+ {
+ int i;
+ VEC_safe_grow (tree, gc, fn->local_decls, len);
+ for (i = 0; i < len; i++)
+ {
+ tree t = lto_input_tree (ib, data_in);
+ VEC_replace (tree, fn->local_decls, i, t);
+ }
+ }
+
+ /* struct machine_function * machine; -- ignored */
+ /* struct language_function * language; -- maybe elsewhere */
+ /* htab_t used_types_hash; -- maybe elsewhere */
+ /* int last_stmt_uid; -- maybe elsewhere */
+ /* int funcdef_no; -- maybe elsewhere */
+
+ /* Input the function start and end loci. */
+ fn->function_start_locus = lto_input_location (ib, data_in);
+ fn->function_end_locus = lto_input_location (ib, data_in);
+
+ /* Input the current IL state of the function. */
+ fn->curr_properties = lto_input_uleb128 (ib);
/* Read all the attributes for FN. */
bp = lto_input_bitpack (ib);
@@ -1280,30 +1308,30 @@ input_function (tree fn_decl, struct dat
fn->calls_setjmp = bp_unpack_value (&bp, 1);
fn->va_list_fpr_size = bp_unpack_value (&bp, 8);
fn->va_list_gpr_size = bp_unpack_value (&bp, 8);
+}
- /* Input the function start and end loci. */
- fn->function_start_locus = lto_input_location (ib, data_in);
- fn->function_end_locus = lto_input_location (ib, data_in);
- /* Input the current IL state of the function. */
- fn->curr_properties = lto_input_uleb128 (ib);
+/* Read the body of function FN_DECL from DATA_IN using input block IB. */
- /* Read the static chain and non-local goto save area. */
- fn->static_chain_decl = lto_input_tree (ib, data_in);
- fn->nonlocal_goto_save_area = lto_input_tree (ib, data_in);
+static void
+input_function (tree fn_decl, struct data_in *data_in,
+ struct lto_input_block *ib)
+{
+ struct function *fn;
+ enum LTO_tags tag;
+ gimple *stmts;
+ basic_block bb;
+ struct cgraph_node *node;
+ tree args, narg, oarg;
- /* Read all the local symbols. */
- len = lto_input_sleb128 (ib);
- if (len > 0)
- {
- int i;
- VEC_safe_grow (tree, gc, fn->local_decls, len);
- for (i = 0; i < len; i++)
- {
- tree t = lto_input_tree (ib, data_in);
- VEC_replace (tree, fn->local_decls, i, t);
- }
- }
+ fn = DECL_STRUCT_FUNCTION (fn_decl);
+ tag = input_record_start (ib);
+ clear_line_info (data_in);
+
+ gimple_register_cfg_hooks ();
+ lto_tag_check (tag, LTO_function);
+
+ input_struct_function_base (fn, data_in, ib);
/* Read all function arguments. We need to re-map them here to the
arguments of the merged function declaration. */
===================================================================
@@ -963,6 +963,9 @@ extern void lto_input_cgraph (struct lto
extern void lto_reader_init (void);
extern tree lto_input_tree (struct lto_input_block *, struct data_in *);
extern tree lto_input_chain (struct lto_input_block *, struct data_in *);
+extern void input_struct_function_base (struct function *fn,
+ struct data_in *data_in,
+ struct lto_input_block *ib);
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 *,
@@ -985,6 +988,8 @@ extern void destroy_output_block (struct
extern void lto_output_tree (struct output_block *, tree, bool);
extern void lto_output_tree_or_ref (struct output_block *, tree, bool);
extern void lto_output_chain (struct output_block *, tree, bool);
+extern void output_struct_function_base (struct output_block *ob,
+ struct function *fn);
extern void produce_asm (struct output_block *ob, tree fn);
void lto_output_decl_state_streams (struct output_block *,
struct lto_out_decl_state *);