This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[LTO] Merge from trunk rev 151374


[ Jason, Mark, you are CC'd because I needed to restore a C++
  patch that had been rejected in trunk (item #7). ]

This merge was somewhat painful.  The main problems were due to
VTA (because in LTO we disable debug generation halfway through
the pipeline) and the changes I had made in free_lang_data in
trunk.

The changes are all over the place, but not very big:

1- I was getting many ICEs during optimization and RTL generation
   with VTA enabled.  I'm not quite sure what the problem is, but
   in all instances, VTA code was getting confused by something
   that was unexpectedly NULL.  I presume this is all the stuff
   we remove in free_lang_data.  For now I've disabled VTA if LTO
   is enabled, but this will need to be handled by the early
   debug generator.

2- Since free_lang_data now allows BINFO_VIRTUALS (for
   gimple_fold_obj_type_ref), we were getting confused during
   type merging because the streamer was trying to merge decls as
   it read them.  For BINFOs, it means that a decl may be
   pointing to a yet-unfinished type.  Richi fixed this by
   deferring decl merging until all the symbols have been read.

3- When we merge a complete and an incomplete type, the type
   comparison cache may end up with the old comparison result
   cached.  This needs to be cleared if the two types are merged
   together, otherwise the type comparison may unexpectedly fail
   later.

4- The size of a tree node does not need to be written out.

5- The debugging functions associated with LTO_STREAMER_DEBUG
   only need to be compiled-in when LTO_STREAMER_DEBUG is
   enabled.

6- Symbols reached from TYPE_BINFO need to be added to
   free_lang_data lists.

7- I needed to hack the C++ mangler to avoid ICEs when dealing
   with symbols that are mangled by free_lang_data.

   a- In decl_is_template_id, we call PRIMARY_TEMPLATE_P on the
      result of DECL_TI_TEMPLATE.  The problem here is that
      DECL_TI_TEMPLATE can return 3 kinds of nodes:
      FUNCTION_DECL, OVERLOAD or IDENTIFIER_NODE.  But
      PRIMARY_TEMPLATE_P can only handle FUNCTION_DECL.

      In very many cases, we are getting OVERLOAD and
      IDENTIFIER_NODEs, causing an ICE at the call.  This is the
      hunk that Jason and Mark had objected to in my
      free_lang_data merge.  I could avoid this in trunk because
      we don't enable free_lang_data if -g is on.  However, in
      the branch, this is always enabled.

      I do not know enough to figure out a real solution to this,
      so I will appreciate any hints on what to do here.  I
      realize that this means that we are mangling many more
      symbols that we should.  So, part of this will be try to
      make need_assembler_name_p smarter.  However, I think that
      we cannot escape this easily.  For LTO to be able to merge
      decls, we will need to mangle more than before (maybe I'm
      wrong about this).

   b- In write_template_arg, we implicitly assume that
      CONST_DECLs will hold a tcc_constant in their DECL_INITIAL.
      However, as is the case in
      testsuite/g++.dg/ext/tmplattr9.C, we can have another
      CONST_DECL which in turn may have no DECL_INITIAL at all:

	    template<int> struct B
	    {
		enum { a, b = a };
		void bar(B<b>) __attribute((weak));
	    };

      When mangling B::bar, we ICE trying to mangle 'b'.  I
      worked around the issue by mangling 'b' as a DECL, but
      that that produces an unmangleable string, so this is
      obviously wrong.  Any hints?

Bootstrapped and tested on x86_64.  The merge fixes several
testsuite failures, but exposes new problems in
g++.dg/lto/20090106.C and g++.dg/lto/20090311.C.


Thanks.  Diego.



2009-09-07  Diego Novillo  <dnovillo@google.com>

	* builtins.c (is_builtin_fn): New.
	(is_builtin_name): Add comment.
	* c-opts.c (c_common_post_options): Disable var tracking when
	LTO is enabled.
	* gimple.c (gimple_force_type_merge): Move below
	lookup_type_pair and call it.
	(gimple_decl_printable_name): Do not use DMGL_TYPES in call
	to cplus_demangle_v3.
	* lto-streamer-in.c (lto_materialize_tree): Do not read
	expected tree node size.
	(lto_input_ts_binfo_tree_pointers): Read BINFO_BASE_BINFOS as
	a zero-terminated list.
	* lto-streamer-out.c (lto_output_tree_ref): Do not expect
	DECL_CONTEXT for CONST_DECLs to be NULL.
	(lto_output_ts_binfo_tree_pointers): Output BINFO_BASE_BINFOS
	as a zero-terminated list.
	(lto_output_tree_header): Do not emit size of EXPR.
	(write_symbol_vec): Call is_builtin_fn.
	* lto-streamer.c (lto_orig_address_map, lto_orig_address_get,
	lto_orig_address_remove): Enable only with LTO_STREAMER_DEBUG.
	* lto-streamer.h (LTO_STREAMER_DEBUG): Add with comment and
	undefined by default.
	(lto_orig_address_map, lto_orig_address_get,
	lto_orig_address_remove): Declare only with LTO_STREAMER_DEBUG.
	* lto-symtab.c (lto_symtab_prevailing_decl): Call is_builtin_fn.
	(lto_symtab_get_resolution): Likewise.
	* tree-parloops.c (try_create_reduction_list): Fix for 32bit
	hosts.
	* tree.c (free_lang_data_in_binfo): Factor out of ...
	(free_lang_data_in_type): ... here.
	(need_assembler_name_p): Return false for non-public functions.
	(free_lang_data_in_decl): Do not remove DECL_CONTEXT from
	CONST_DECLs.
	(find_decls_types_r): Walk TYPE_BINFO for records and unions.
	* tree.h (RECORD_OR_UNION_TYPE_P): Declare.  Update all users
	of the predicate.
	(AGGREGATE_TYPE_P): Call it.
	(is_builtin_fn): Declare.
	

cp/ChangeLog.lto:

	* mangle.c (decl_is_template_id): Protect calls to
	PRIMARY_TEMPLATE_P from IDENTIFIER_NODE and OVERLOAD.
	(write_template_arg): Do not call write_template_arg_literal
	if NODE is a CONST_DECL without a tcc_constant initializer.

2009-09-07  Richard Guenther  <rguenther@google.com>

	* lto-streamer-in.c (lto_register_deferred_decls_in_symtab): New.
	(deferred_global_decls): New file local.
	(lto_register_var_decl_in_symtab): Remove arguments DATA_IN
	and IX.  Update all callers.
	If DECL is TREE_PUBLIC, add it to deferred_global_decls.
	(lto_register_function_decl_in_symtab): Remove argument IX.
	If DECL is TREE_PUBLIC, add it to deferred_global_decls.
	Update all callers.
	* lto-streamer.h (lto_register_deferred_decls_in_symtab): Declare.
	* lto.c (lto_read_decls): Call it after reading all decls.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 38d3ed2..9c4f7e2 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -244,6 +244,8 @@ static tree do_mpfr_bessel_n (tree, tree, tree,
 static tree do_mpfr_remquo (tree, tree, tree);
 static tree do_mpfr_lgamma_r (tree, tree, tree);
 
+/* Return true if NAME starts with __builtin_ or __sync_.  */
+
 bool
 is_builtin_name (const char *name)
 {
@@ -254,6 +256,16 @@ is_builtin_name (const char *name)
   return false;
 }
 
+
+/* Return true if DECL is a function symbol representing a built-in.  */
+
+bool
+is_builtin_fn (tree decl)
+{
+  return TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl);
+}
+
+
 /* Return true if NODE should be considered for inline expansion regardless
    of the optimization level.  This means whenever a function is invoked with
    its "internal" name, which normally contains the prefix "__builtin".  */
diff --git a/gcc/c-opts.c b/gcc/c-opts.c
index e46f794..7e5f963 100644
--- a/gcc/c-opts.c
+++ b/gcc/c-opts.c
@@ -1043,6 +1043,10 @@ c_common_post_options (const char **pfilename)
 	 Otherwise, symbols will be privatized too early, causing link
 	 errors later.  */
       flag_whole_program = 0;
+
+      /* FIXME lto.  Disable var-tracking until debug information
+	 is properly handled in free_lang_data.  */
+      flag_var_tracking = 0;
 #else
       error ("LTO support has not been enabled in this configuration");
 #endif
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index bb046d2..2de3d54 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -282,6 +282,15 @@ decl_is_template_id (const tree decl, tree* const template_info)
       /* Check if this is a primary template.  */
       if (DECL_LANG_SPECIFIC (decl) != NULL
 	  && DECL_USE_TEMPLATE (decl)
+	  /* FIXME lto.  DECL_TI_TEMPLATE can return an OVERLOAD or
+	     an IDENTIFIER_NODE, but PRIMARY_TEMPLATE_P can only
+	     handle DECLs.  This was initially rejected by the C++
+	     maintainers, so it needs to be handled some other way
+	     (http://gcc.gnu.org/ml/gcc-patches/2009-09/msg00126.html).
+	     Undoing this will produce many failures in check-g++ that
+	     are easy to spot.  */
+	  && TREE_CODE (DECL_TI_TEMPLATE (decl)) != OVERLOAD
+	  && TREE_CODE (DECL_TI_TEMPLATE (decl)) != IDENTIFIER_NODE
 	  && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))
 	  && TREE_CODE (decl) != TEMPLATE_DECL)
 	{
@@ -2550,7 +2559,14 @@ write_template_arg (tree node)
     /* A template appearing as a template arg is a template template arg.  */
     write_template_template_arg (node);
   else if ((TREE_CODE_CLASS (code) == tcc_constant && code != PTRMEM_CST)
-	   || (abi_version_at_least (2) && code == CONST_DECL))
+	   || (abi_version_at_least (2)
+	       && code == CONST_DECL
+	       /* FIXME lto.  The initial value of a CONST_DECL may be another
+		  CONST_DECL or NULL but write_template_arg_literal assumes
+		  that it can extract a tcc_constant.  It's unclear whether
+		  this is the right thing to do here.  */
+	       && TREE_CODE_CLASS (TREE_CODE (DECL_INITIAL (node)))
+	          == tcc_constant))
     write_template_arg_literal (node);
   else if (DECL_P (node))
     {
diff --git a/gcc/gimple.c b/gcc/gimple.c
index e0d80d2..d06221b 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -3115,28 +3115,6 @@ gimple_call_copy_skip_args (gimple stmt, bitmap args_to_skip)
 
 static hashval_t gimple_type_hash (const void *);
 
-/* Force merging the type T2 into the type T1.  */
-
-void
-gimple_force_type_merge (tree t1, tree t2)
-{
-  void **slot;
-
-  /* There's no other way than copying t2 to t1 in this case.
-     Yuck.  We'll just call this "completing" t1.  */
-  memcpy (t1, t2, tree_size (t1));
-
-  /* Adjust the hash value of T1 if it was computed already.  Otherwise
-     we would be forced to not hash fields of structs to match the
-     hash value of an incomplete struct.  */
-  if (type_hash_cache
-      && (slot = pointer_map_contains (type_hash_cache, t1)) != NULL)
-    {
-      gimple_type_hash (t2);
-      *slot = *pointer_map_contains (type_hash_cache, t2);
-    }
-}
-
 /* Structure used to maintain a cache of some type pairs compared by
    gimple_types_compatible_p when comparing aggregate types.  There are
    four possible values for SAME_P:
@@ -3210,6 +3188,39 @@ lookup_type_pair (tree t1, tree t2, htab_t *visited_p)
 }
 
 
+/* Force merging the type T2 into the type T1.  */
+
+void
+gimple_force_type_merge (tree t1, tree t2)
+{
+  void **slot;
+  type_pair_t p;
+
+  /* There's no other way than copying t2 to t1 in this case.
+     Yuck.  We'll just call this "completing" t1.  */
+  memcpy (t1, t2, tree_size (t1));
+
+  /* Adjust the hash value of T1 if it was computed already.  Otherwise
+     we would be forced to not hash fields of structs to match the
+     hash value of an incomplete struct.  */
+  if (type_hash_cache
+      && (slot = pointer_map_contains (type_hash_cache, t1)) != NULL)
+    {
+      gimple_type_hash (t2);
+      *slot = *pointer_map_contains (type_hash_cache, t2);
+    }
+
+  /* Adjust cached comparison results for T1 and T2 to make sure
+     they now compare compatible.  Update both directions to
+     preserve the symmetry of gimple_compare_types.  */
+  p = lookup_type_pair (t1, t2, &gtc_visited);
+  p->same_p = 1;
+
+  p = lookup_type_pair (t2, t1, &gtc_visited);
+  p->same_p = 1;
+}
+
+
 /* Return true if both types have the same name.  */
 
 static bool
@@ -4625,7 +4636,6 @@ gimple_decl_printable_name (tree decl, int verbosity)
       if (verbosity >= 2)
 	{
 	  dmgl_opts = DMGL_VERBOSE
-		      | DMGL_TYPES
 		      | DMGL_ANSI
 		      | DMGL_GNU_V3
 		      | DMGL_RET_POSTFIX;
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index 19c6d67..42bbc56 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -1714,7 +1714,6 @@ lto_materialize_tree (struct lto_input_block *ib, struct data_in *data_in,
   struct bitpack_d *bp;
   enum tree_code code;
   tree result;
-  unsigned HOST_WIDE_INT expected_size;
 #ifdef LTO_STREAMER_DEBUG
   HOST_WIDEST_INT orig_address_in_writer;
 #endif
@@ -1723,7 +1722,6 @@ lto_materialize_tree (struct lto_input_block *ib, struct data_in *data_in,
   result = NULL_TREE;
 
   /* Read the header of the node we are about to create.  */
-  expected_size = lto_input_uleb128 (ib);
   ix = lto_input_sleb128 (ib);
   gcc_assert ((int) ix == ix);
   *ix_p = (int) ix;
@@ -1773,12 +1771,6 @@ lto_materialize_tree (struct lto_input_block *ib, struct data_in *data_in,
   lto_orig_address_map (result, (intptr_t) orig_address_in_writer);
 #endif
 
-  /* Make sure that the size of the tree we just created matches
-     what we were expecting.  Skip this check for IDENTIFIER_NODEs,
-     since these are language-dependent.  */
-  if (code != IDENTIFIER_NODE)
-    gcc_assert (expected_size == tree_size (result));
-
   /* Read the bitpack of non-pointer values from IB.  */
   bp = lto_input_bitpack (ib);
 
@@ -2004,7 +1996,7 @@ lto_input_ts_type_tree_pointers (struct lto_input_block *ib,
   TYPE_MAIN_VARIANT (expr) = lto_input_tree (ib, data_in);
   /* Do not stream TYPE_NEXT_VARIANT, we reconstruct the variant lists
      during fixup.  */
-  if (TREE_CODE (expr) == RECORD_TYPE || TREE_CODE (expr) == UNION_TYPE)
+  if (RECORD_OR_UNION_TYPE_P (expr))
     TYPE_BINFO (expr) = lto_input_tree (ib, data_in);
   TYPE_CONTEXT (expr) = lto_input_tree (ib, data_in);
   TYPE_CANONICAL (expr) = lto_input_tree (ib, data_in);
@@ -2103,14 +2095,20 @@ lto_input_ts_binfo_tree_pointers (struct lto_input_block *ib,
 				  struct data_in *data_in, tree expr)
 {
   unsigned i, len;
+  tree t;
 
   /* Note that the number of slots in EXPR was read in
-     lto_materialize_tree when instantiating EXPR.  */
-  for (i = 0; i < VEC_length (tree, BINFO_BASE_BINFOS (expr)); i++)
+     lto_materialize_tree when instantiating EXPR.  However, the
+     vector is empty so we cannot rely on VEC_length to know how many
+     elements to read.  So, this list is emitted as a 0-terminated
+     list on the writer side.  */
+  do
     {
-      tree t = lto_input_tree (ib, data_in);
-      VEC_replace (tree, BINFO_BASE_BINFOS (expr), i, t);
+      t = lto_input_tree (ib, data_in);
+      if (t)
+	VEC_quick_push (tree, BINFO_BASE_BINFOS (expr), t);
     }
+  while (t);
 
   BINFO_OFFSET (expr) = lto_input_tree (ib, data_in);
   BINFO_VTABLE (expr) = lto_input_tree (ib, data_in);
@@ -2243,15 +2241,55 @@ lto_input_tree_pointers (struct lto_input_block *ib, struct data_in *data_in,
     }
 }
 
+static VEC(tree, heap) *deferred_global_decls;
+
+/* Register the queued global decls with the symtab.  DATA_IN contains
+   tables and descriptors for the file being read.*/
+
+void
+lto_register_deferred_decls_in_symtab (struct data_in *data_in)
+{
+  unsigned i;
+  tree decl;
+
+  for (i = 0; VEC_iterate (tree, deferred_global_decls, i, decl); ++i)
+    {
+      enum ld_plugin_symbol_resolution resolution;
+      int ix;
+
+      if (!lto_streamer_cache_lookup (data_in->reader_cache, decl, &ix))
+	gcc_unreachable ();
+
+      /* Register and adjust the decls type.  */
+      TREE_TYPE (decl) = gimple_register_type (TREE_TYPE (decl));
+
+      if (TREE_CODE (decl) == VAR_DECL)
+	{
+	  gcc_assert (TREE_PUBLIC (decl));
+	  resolution = get_resolution (data_in, ix);
+	  lto_symtab_merge_var (decl, resolution);
+	}
+      else if (TREE_CODE (decl) == FUNCTION_DECL)
+	{
+	  gcc_assert (TREE_PUBLIC (decl) && !DECL_ABSTRACT (decl));
+	  resolution = get_resolution (data_in, ix);
+	  lto_symtab_merge_fn (decl, resolution, data_in->file_data);
+	}
+      else
+	gcc_unreachable ();
+    }
+
+  VEC_free (tree, heap, deferred_global_decls);
+  deferred_global_decls = NULL;
+}
+
 
 /* Register DECL with the global symbol table and change its
    name if necessary to avoid name clashes for static globals across
-   different files.  DATA_IN is the file being read.  IX is the
-   index in DATA_IN arrays where DECL is stored.  */
+   different files.  */
 
 static void
-lto_register_var_decl_in_symtab (struct data_in *data_in, tree decl,
-				 unsigned ix)
+lto_register_var_decl_in_symtab (tree decl)
 {
   /* Register symbols with file or global scope to mark what input
      file has their definition.  */
@@ -2261,12 +2299,12 @@ lto_register_var_decl_in_symtab (struct data_in *data_in, tree decl,
 	 between different files don't clash unexpectedly.  */
       if (!TREE_PUBLIC (decl))
         {
-	  /* FIXME lto:  We normally pre-mangle names before we
-	     serialize them out.  Here, in lto1, we do not know the
-	     language, and thus cannot do the mangling again. Instead,
-	     we just append a suffix to the mangled name.  The
-	     resulting name, however, is not a properly-formed mangled
-	     name, and will confuse any attempt to unmangle it.  */
+	  /* ??? We normally pre-mangle names before we serialize them
+	     out.  Here, in lto1, we do not know the language, and
+	     thus cannot do the mangling again. Instead, we just
+	     append a suffix to the mangled name.  The resulting name,
+	     however, is not a properly-formed mangled name, and will
+	     confuse any attempt to unmangle it.  */
 	  const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
 	  char *label;
       
@@ -2276,26 +2314,21 @@ lto_register_var_decl_in_symtab (struct data_in *data_in, tree decl,
         }
     }
 
-  /* If this variable has already been declared, merge the
-     declarations.  */
+  /* If this variable has already been declared, queue the
+     declaration for merging.  */
   if (TREE_PUBLIC (decl))
-    {
-      enum ld_plugin_symbol_resolution resolution;
-      resolution = get_resolution (data_in, ix);
-      lto_symtab_merge_var (decl, resolution);
-    }
+    VEC_safe_push (tree, heap, deferred_global_decls, decl);
 }
 
 
 
 /* Register DECL with the global symbol table and change its
    name if necessary to avoid name clashes for static globals across
-   different files.  DATA_IN is the file being read.  IX is the
-   index in DATA_IN arrays where DECL is stored.  */
+   different files.  DATA_IN contains descriptors and tables for the
+   file being read.  */
 
 static void
-lto_register_function_decl_in_symtab (struct data_in *data_in, tree decl,
-				      unsigned ix)
+lto_register_function_decl_in_symtab (struct data_in *data_in, tree decl)
 {
   /* Need to ensure static entities between different files
      don't clash unexpectedly.  */
@@ -2342,14 +2375,10 @@ lto_register_function_decl_in_symtab (struct data_in *data_in, tree decl,
 	}				   
     }
 
-  /* If the function has already been declared, merge the
-     declarations.  */
+  /* If this variable has already been declared, queue the
+     declaration for merging.  */
   if (TREE_PUBLIC (decl) && !DECL_ABSTRACT (decl))
-    {
-      enum ld_plugin_symbol_resolution resolution;
-      resolution = get_resolution (data_in, ix);
-      lto_symtab_merge_fn (decl, resolution, data_in->file_data);
-    }
+    VEC_safe_push (tree, heap, deferred_global_decls, decl);
 }
 
 
@@ -2448,9 +2477,9 @@ lto_read_tree (struct lto_input_block *ib, struct data_in *data_in,
     gcc_assert (!lto_stream_as_builtin_p (result));
 
   if (TREE_CODE (result) == VAR_DECL)
-    lto_register_var_decl_in_symtab (data_in, result, (unsigned) ix);
-  else if (TREE_CODE (result) == FUNCTION_DECL)
-    lto_register_function_decl_in_symtab (data_in, result, (unsigned) ix);
+    lto_register_var_decl_in_symtab (result);
+  else if (TREE_CODE (result) == FUNCTION_DECL && !DECL_BUILT_IN (result))
+    lto_register_function_decl_in_symtab (data_in, result);
 
   end_marker = lto_input_1_unsigned (ib);
   gcc_assert (end_marker == 0);
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index ac49f75..7228f4a 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -808,7 +808,6 @@ lto_output_tree_ref (struct output_block *ob, tree expr)
       break;
 
     case CONST_DECL:
-      gcc_assert (decl_function_context (expr) == NULL);
       output_record_start (ob, LTO_const_decl_ref);
       lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
       break;
@@ -1162,9 +1161,11 @@ lto_output_ts_binfo_tree_pointers (struct output_block *ob, tree expr,
   tree t;
 
   /* Note that the number of BINFO slots has already been emitted in
-     EXPR's header (see lto_output_tree_header).  */
+     EXPR's header (see lto_output_tree_header) because this length
+     is needed to build the empty BINFO node on the reader side.  */
   for (i = 0; VEC_iterate (tree, BINFO_BASE_BINFOS (expr), i, t); i++)
     lto_output_tree_or_ref (ob, t, ref_p);
+  output_zero (ob);
 
   lto_output_tree_or_ref (ob, BINFO_OFFSET (expr), ref_p);
   lto_output_tree_or_ref (ob, BINFO_VTABLE (expr), ref_p);
@@ -1318,7 +1319,6 @@ lto_output_tree_header (struct output_block *ob, tree expr, int ix)
      variable sized nodes).  */
   tag = lto_tree_code_to_tag (code);
   output_record_start (ob, tag);
-  output_uleb128 (ob, tree_size (expr));
   output_sleb128 (ob, ix);
 
   /* The following will cause bootstrap miscomparisons.  Enable with care.  */
@@ -2398,7 +2398,7 @@ write_symbol_vec (struct lto_streamer_cache_d *cache,
       /* None of the following kinds of symbols are needed in the
 	 symbol table.  */
       if (!TREE_PUBLIC (t)
-	  || DECL_BUILT_IN (t)
+	  || is_builtin_fn (t)
 	  || DECL_ABSTRACT (t)
 	  || TREE_CODE (t) == RESULT_DECL)
 	continue;
diff --git a/gcc/lto-streamer.c b/gcc/lto-streamer.c
index b1f0d6d..9a62762 100644
--- a/gcc/lto-streamer.c
+++ b/gcc/lto-streamer.c
@@ -825,6 +825,7 @@ gate_lto_out (void)
 }
 
 
+#ifdef LTO_STREAMER_DEBUG
 /* Add a mapping between T and ORIG_T, which is the numeric value of
    the original address of T as it was seen by the LTO writer.  This
    mapping is useful when debugging streaming problems.  A debugging
@@ -862,3 +863,4 @@ lto_orig_address_remove (tree t)
 {
   t->base.ann = NULL;
 }
+#endif
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index 4e4affb..f713cc8 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -31,6 +31,14 @@ along with GCC; see the file COPYING3.  If not see
 #include "vec.h"
 #include "vecprim.h"
 
+/* Define when debugging the LTO streamer.  This causes the writer
+   to output the numeric value for the memory address of the tree node
+   being emitted.  When debugging a problem in the reader, check the
+   original address that the writer was emitting using lto_orig_address_get.
+   With this value, set a breakpoint in the writer (e.g., lto_output_tree)
+   to trace how the faulty node is being emitted.  */
+/* #define LTO_STREAMER_DEBUG	1  */
+
 /* The encoding for a function consists of the following sections:
 
    1)    The header.
@@ -805,9 +813,11 @@ 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
 extern void lto_orig_address_map (tree, intptr_t);
 extern intptr_t lto_orig_address_get (tree);
 extern void lto_orig_address_remove (tree);
+#endif
 
 
 /* In lto-streamer-in.c */
@@ -828,6 +838,7 @@ 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 void lto_register_deferred_decls_in_symtab (struct data_in *);
 
 
 /* In lto-streamer-out.c  */
diff --git a/gcc/lto-symtab.c b/gcc/lto-symtab.c
index ac31336..3890f47 100644
--- a/gcc/lto-symtab.c
+++ b/gcc/lto-symtab.c
@@ -698,10 +698,10 @@ lto_symtab_prevailing_decl (tree decl)
   gcc_assert (decl);
 
   /* Builtins and local symbols are their own prevailing decl.  */
-  if (!TREE_PUBLIC (decl) || DECL_IS_BUILTIN (decl))
+  if (!TREE_PUBLIC (decl) || is_builtin_fn (decl))
     return decl;
 
-  /* FIXME lto. There should be no DECL_ABSTRACT in the middle end. */
+  /* DECL_ABSTRACTs are their own prevailng decl.  */
   if (TREE_CODE (decl) == FUNCTION_DECL && DECL_ABSTRACT (decl))
     return decl;
 
@@ -752,7 +752,7 @@ lto_symtab_get_resolution (tree decl)
 {
   gcc_assert (decl);
 
-  if (!TREE_PUBLIC (decl))
+  if (!TREE_PUBLIC (decl) || is_builtin_fn (decl))
     return LDPR_PREVAILING_DEF_IRONLY;
 
   /* FIXME lto: There should be no DECL_ABSTRACT in the middle end. */
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index a8f5dea..4747925 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -227,6 +227,10 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
   /* Set the current decl state to be the global state. */
   decl_data->current_decl_state = decl_data->global_decl_state;
 
+  /* After each CU is read register and possibly merge global
+     symbols and their types.  */
+  lto_register_deferred_decls_in_symtab (data_in);
+
   lto_data_in_delete (data_in);
 }
 
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index 0053ad2..48e910a 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -1870,7 +1870,7 @@ try_create_reduction_list (loop_p loop, htab_t reduction_list)
 bool
 parallelize_loops (void)
 {
-  unsigned n_threads = flag_tree_parallelize_loops;
+  HOST_WIDE_INT n_threads = (HOST_WIDE_INT) flag_tree_parallelize_loops;
   bool changed = false;
   struct loop *loop;
   struct tree_niter_desc niter_desc;
@@ -1908,7 +1908,8 @@ parallelize_loops (void)
       /* FIXME: Bypass this check as graphite doesn't update the
       count and frequency correctly now.  */
       if (!flag_loop_parallelize_all
-	  && (estimated_loop_iterations_int (loop, false)<= n_threads * MIN_PER_THREAD
+	  && (estimated_loop_iterations_int (loop, false)
+	      <= n_threads * MIN_PER_THREAD
 	      /* Do not bother with loops in cold areas.  */
 	      || optimize_loop_nest_for_size_p (loop)))
 	continue;
diff --git a/gcc/tree.c b/gcc/tree.c
index 470d0ea..c9890f6 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4132,6 +4132,31 @@ build_type_attribute_variant (tree ttype, tree attribute)
 					    TYPE_QUALS (ttype));
 }
 
+
+/* Reset all the fields in a binfo node BINFO.  We only keep
+   BINFO_VIRTUALS, which is used by gimple_fold_obj_type_ref.  */
+
+static void
+free_lang_data_in_binfo (tree binfo)
+{
+  unsigned i;
+  tree t;
+
+  gcc_assert (TREE_CODE (binfo) == TREE_BINFO);
+
+  BINFO_OFFSET (binfo) = NULL_TREE;
+  BINFO_VTABLE (binfo) = NULL_TREE;
+  BINFO_VPTR_FIELD (binfo) = NULL_TREE;
+  BINFO_BASE_ACCESSES (binfo) = NULL;
+  BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
+  BINFO_SUBVTT_INDEX (binfo) = NULL_TREE;
+  BINFO_VPTR_FIELD (binfo) = NULL_TREE;
+
+  for (i = 0; VEC_iterate (tree, BINFO_BASE_BINFOS (binfo), i, t); i++)
+    free_lang_data_in_binfo (t);
+}
+
+
 /* Reset all language specific information still present in TYPE.  */
 
 static void
@@ -4181,9 +4206,7 @@ free_lang_data_in_type (tree type)
 	      
   /* Remove members that are not actually FIELD_DECLs from the field
      list of an aggregate.  These occur in C++.  */
-  if (TREE_CODE (type) == RECORD_TYPE
-      || TREE_CODE (type) == UNION_TYPE
-      || TREE_CODE (type) == QUAL_UNION_TYPE)
+  if (RECORD_OR_UNION_TYPE_P (type))
     {
       tree prev, member;
 
@@ -4217,30 +4240,7 @@ free_lang_data_in_type (tree type)
 
       TYPE_METHODS (type) = NULL_TREE;
       if (TYPE_BINFO (type))
-	{
-	  tree binfo = TYPE_BINFO (type);
-
-	  if (BINFO_VIRTUALS (binfo))
-	    {
-	      /* If the virtual function table for BINFO contains
-		 entries, these may be useful for folding OBJ_TYPE_REF
-		 expressions (see gimple_fold_obj_type_ref).  In that
-		 case, we only clear the unused fields in the BINFO
-		 structure.  */
-	      BINFO_OFFSET (binfo) = NULL_TREE;
-	      BINFO_VTABLE (binfo) = NULL_TREE;
-	      BINFO_VPTR_FIELD (binfo) = NULL_TREE;
-	      BINFO_BASE_ACCESSES (binfo) = NULL;
-	      BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
-	      BINFO_SUBVTT_INDEX (binfo) = NULL_TREE;
-	      BINFO_VPTR_FIELD (binfo) = NULL_TREE;
-	    }
-	  else
-	    {
-	      /* Otherwise, get rid of the whole binfo data.  */
-	      TYPE_BINFO (type) = NULL_TREE;
-	    }
-	}
+	free_lang_data_in_binfo (TYPE_BINFO (type));
     }
   else
     {
@@ -4299,7 +4299,8 @@ need_assembler_name_p (tree decl)
      represented in the callgraph need an assembler name.  */
   if (TREE_CODE (decl) == FUNCTION_DECL
       && cgraph_node_for_decl (decl) == NULL
-      && !TREE_USED (decl))
+      && !TREE_USED (decl)
+      && !TREE_PUBLIC (decl))
     return false;
 
   return true;
@@ -4352,9 +4353,6 @@ free_lang_data_in_decl (tree decl)
   if (DECL_NAME (decl))
     TREE_TYPE (DECL_NAME (decl)) = NULL_TREE;
 
-  if (TREE_CODE (decl) == CONST_DECL)
-    DECL_CONTEXT (decl) = NULL_TREE;
-
   /* Ignore any intervening types, because we are going to clear their
      TYPE_CONTEXT fields.  */
   if (TREE_CODE (decl) != FIELD_DECL)
@@ -4604,6 +4602,8 @@ find_decls_types_r (tree *tp, int *ws ATTRIBUTE_UNUSED, void *data)
       walk_tree (&TYPE_MAIN_VARIANT (t), find_decls_types_r, fld, fld->pset);
       walk_tree (&TYPE_CONTEXT (t), find_decls_types_r, fld, fld->pset);
       walk_tree (&TYPE_CANONICAL (t), find_decls_types_r, fld, fld->pset);
+      if (RECORD_OR_UNION_TYPE_P (t))
+	walk_tree (&TYPE_BINFO (t), find_decls_types_r, fld, fld->pset);
     }
 
   if (TREE_TYPE (t))
@@ -4882,6 +4882,13 @@ free_lang_data (void)
   diagnostic_finalizer (global_dc) = default_diagnostic_finalizer;
   diagnostic_format_decoder (global_dc) = default_tree_printer;
 
+  /* FIXME lto: We remove sufficient language data that the debug
+     info writer gets completely confused.  Disable debug information
+     for now.  */
+  debug_info_level = DINFO_LEVEL_NONE;
+  write_symbols = NO_DEBUG;
+  debug_hooks = &do_nothing_debug_hooks;
+
   return 0;
 }
 
@@ -10070,9 +10077,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
 	    return result;
 
 	  /* If this is a record type, also walk the fields.  */
-	  if (TREE_CODE (*type_p) == RECORD_TYPE
-	      || TREE_CODE (*type_p) == UNION_TYPE
-	      || TREE_CODE (*type_p) == QUAL_UNION_TYPE)
+	  if (RECORD_OR_UNION_TYPE_P (*type_p))
 	    {
 	      tree field;
 
diff --git a/gcc/tree.h b/gcc/tree.h
index 9c2d166..d912f70 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1065,12 +1065,17 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
   (SCALAR_FLOAT_TYPE_P (TYPE)			\
    && DECIMAL_FLOAT_MODE_P (TYPE_MODE (TYPE)))
 
+/* Nonzero if TYPE is a record or union type.  */
+#define RECORD_OR_UNION_TYPE_P(TYPE)		\
+   (TREE_CODE (TYPE) == RECORD_TYPE		\
+    || TREE_CODE (TYPE) == UNION_TYPE		\
+    || TREE_CODE (TYPE) == QUAL_UNION_TYPE)
+
 /* Nonzero if TYPE represents an aggregate (multi-component) type.
    Keep these checks in ascending code order.  */
 
 #define AGGREGATE_TYPE_P(TYPE) \
-  (TREE_CODE (TYPE) == ARRAY_TYPE || TREE_CODE (TYPE) == RECORD_TYPE \
-   || TREE_CODE (TYPE) == UNION_TYPE || TREE_CODE (TYPE) == QUAL_UNION_TYPE)
+  (TREE_CODE (TYPE) == ARRAY_TYPE || RECORD_OR_UNION_TYPE_P (TYPE))
 
 /* Nonzero if TYPE represents a pointer or reference type.
    (It should be renamed to INDIRECT_TYPE_P.)  Keep these checks in
@@ -4891,7 +4896,8 @@ extern bool validate_arglist (const_tree, ...);
 extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
 extern bool can_trust_pointer_alignment (void);
 extern int get_pointer_alignment (tree, unsigned int);
-extern bool is_builtin_name (const char*);
+extern bool is_builtin_name (const char *);
+extern bool is_builtin_fn (tree);
 extern int get_object_alignment (tree, unsigned int, unsigned int);
 extern tree fold_call_stmt (gimple, bool);
 extern tree gimple_fold_builtin_snprintf_chk (gimple, tree, enum built_in_function);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]