Save the DECL_STRUCT_FUNCTION(...) field of FUNCTION_DECL.  This change
factors common functionality with the LTO streamer.


Index: gcc/testsuite/ChangeLog.pph

2011-06-14  Lawrence Crowl <cr...@google.com>

        * g++.dg/pph/x1tmplfunc.cc: Replace ICE xfail with an assembly diff
        xfail.

Index: gcc/cp/ChangeLog.pph

2011-06-14  Lawrence Crowl <cr...@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.

Index: gcc/ChangeLog.pph

2011-06-14  Lawrence Crowl  <cr...@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.


Index: gcc/testsuite/g++.dg/pph/x1tmplfunc.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x1tmplfunc.cc      (revision 175056)
+++ gcc/testsuite/g++.dg/pph/x1tmplfunc.cc      (working copy)
@@ -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"
 
Index: gcc/cp/pph-streamer-in.c
===================================================================
--- gcc/cp/pph-streamer-in.c    (revision 175056)
+++ gcc/cp/pph-streamer-in.c    (working copy)
@@ -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:
Index: gcc/cp/pph-streamer-out.c
===================================================================
--- gcc/cp/pph-streamer-out.c   (revision 175056)
+++ gcc/cp/pph-streamer-out.c   (working copy)
@@ -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:
Index: gcc/lto-streamer-out.c
===================================================================
--- gcc/lto-streamer-out.c      (revision 175056)
+++ gcc/lto-streamer-out.c      (working copy)
@@ -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));
Index: gcc/lto-streamer-in.c
===================================================================
--- gcc/lto-streamer-in.c       (revision 175056)
+++ gcc/lto-streamer-in.c       (working copy)
@@ -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.  */
Index: gcc/lto-streamer.h
===================================================================
--- gcc/lto-streamer.h  (revision 175056)
+++ gcc/lto-streamer.h  (working copy)
@@ -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 *);

--
This patch is available for review at http://codereview.appspot.com/4620043

Reply via email to