OSDN Git Service

./:
[pf3gnuchains/gcc-fork.git] / gcc / lto-streamer-in.c
index f31b319..d249033 100644 (file)
@@ -1,6 +1,6 @@
 /* Read the GIMPLE representation from a file stream.
 
-   Copyright 2009 Free Software Foundation, Inc.
+   Copyright 2009, 2010 Free Software Foundation, Inc.
    Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
    Re-implemented by Diego Novillo <dnovillo@google.com>
 
@@ -30,7 +30,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "params.h"
 #include "input.h"
-#include "varray.h"
 #include "hashtab.h"
 #include "basic-block.h"
 #include "tree-flow.h"
@@ -133,28 +132,45 @@ eq_string_slot_node (const void *p1, const void *p2)
    IB.  Write the length to RLEN.  */
 
 static const char *
-input_string_internal (struct data_in *data_in, struct lto_input_block *ib,
-                      unsigned int *rlen)
+string_for_index (struct data_in *data_in,
+                 unsigned int loc,
+                 unsigned int *rlen)
 {
   struct lto_input_block str_tab;
   unsigned int len;
-  unsigned int loc;
   const char *result;
-  
-  loc = lto_input_uleb128 (ib);
-  LTO_INIT_INPUT_BLOCK (str_tab, data_in->strings, loc, data_in->strings_len);
+
+  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.  */
+
+static 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 STRING_CST from the string table in DATA_IN using input
    block IB.  */
 
@@ -163,13 +179,10 @@ input_string_cst (struct data_in *data_in, struct lto_input_block *ib)
 {
   unsigned int len;
   const char * ptr;
-  unsigned int is_null;
-
-  is_null = lto_input_uleb128 (ib);
-  if (is_null)
-    return NULL;
 
   ptr = input_string_internal (data_in, ib, &len);
+  if (!ptr)
+    return NULL;
   return build_string (len, ptr);
 }
 
@@ -182,30 +195,38 @@ input_identifier (struct data_in *data_in, struct lto_input_block *ib)
 {
   unsigned int len;
   const char *ptr;
-  unsigned int is_null;
-
-  is_null = lto_input_uleb128 (ib);
-  if (is_null)
-    return NULL;
 
   ptr = input_string_internal (data_in, ib, &len);
+  if (!ptr)
+    return NULL;
   return get_identifier_with_length (ptr, len);
 }
 
+
+/* Read LENGTH bytes from STREAM to ADDR.  */
+
+void
+lto_input_data_block (struct lto_input_block *ib, void *addr, size_t length)
+{
+  size_t i;
+  unsigned char *const buffer = (unsigned char *const) addr;
+
+  for (i = 0; i < length; i++)
+    buffer[i] = lto_input_1_unsigned (ib);
+}
+
+
 /* Read a NULL terminated string from the string table in DATA_IN.  */
 
-static const char *
-input_string (struct data_in *data_in, struct lto_input_block *ib)
+const char *
+lto_input_string (struct data_in *data_in, struct lto_input_block *ib)
 {
   unsigned int len;
   const char *ptr;
-  unsigned int is_null;
-
-  is_null = lto_input_uleb128 (ib);
-  if (is_null)
-    return NULL;
 
   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");
 
@@ -215,12 +236,11 @@ input_string (struct data_in *data_in, struct lto_input_block *ib)
 
 /* Return the next tag in the input block IB.  */
 
-static enum LTO_tags
+static inline enum LTO_tags
 input_record_start (struct lto_input_block *ib)
 {
-  enum LTO_tags tag = (enum LTO_tags) lto_input_uleb128 (ib);
-  return tag;
-} 
+  return lto_input_enum (ib, LTO_tags, LTO_NUM_TAGS);
+}
 
 
 /* Lookup STRING in file_name_hash_table.  If found, return the existing
@@ -269,36 +289,57 @@ clear_line_info (struct data_in *data_in)
 }
 
 
-/* Read a location from input block IB.  */
+/* Read a location bitpack from input block IB.  */
 
 static location_t
-lto_input_location (struct lto_input_block *ib, struct data_in *data_in)
+lto_input_location_bitpack (struct data_in *data_in, struct bitpack_d *bp)
 {
-  expanded_location xloc;
+  bool file_change, line_change, column_change;
+  unsigned len;
+  bool prev_file = data_in->current_file != NULL;
 
-  xloc.file = input_string (data_in, ib);
-  if (xloc.file == NULL)
+  if (bp_unpack_value (bp, 1))
     return UNKNOWN_LOCATION;
 
-  xloc.file = canon_file_name (xloc.file);
-  xloc.line = lto_input_sleb128 (ib);
-  xloc.column = lto_input_sleb128 (ib);
+  file_change = bp_unpack_value (bp, 1);
+  if (file_change)
+    data_in->current_file = canon_file_name
+                             (string_for_index (data_in,
+                                                bp_unpack_var_len_unsigned (bp),
+                                                &len));
+
+  line_change = bp_unpack_value (bp, 1);
+  if (line_change)
+    data_in->current_line = bp_unpack_var_len_unsigned (bp);
+
+  column_change = bp_unpack_value (bp, 1);
+  if (column_change)
+    data_in->current_col = bp_unpack_var_len_unsigned (bp);
 
-  if (data_in->current_file != xloc.file)
+  if (file_change)
     {
-      if (data_in->current_file)
+      if (prev_file)
        linemap_add (line_table, LC_LEAVE, false, NULL, 0);
 
-      linemap_add (line_table, LC_ENTER, false, xloc.file, xloc.line);
+      linemap_add (line_table, LC_ENTER, false, data_in->current_file,
+                  data_in->current_line);
     }
-  else if (data_in->current_line != xloc.line)
-    linemap_line_start (line_table, xloc.line, xloc.column);
+  else if (line_change)
+    linemap_line_start (line_table, data_in->current_line, data_in->current_col);
 
-  data_in->current_file = xloc.file;
-  data_in->current_line = xloc.line;
-  data_in->current_col = xloc.column;
+  return linemap_position_for_column (line_table, data_in->current_col);
+}
+
+
+/* Read a location from input block IB.  */
 
-  return linemap_position_for_column (line_table, xloc.column);
+static location_t
+lto_input_location (struct lto_input_block *ib, struct data_in *data_in)
+{
+  struct bitpack_d bp;
+
+  bp = lto_input_bitpack (ib);
+  return lto_input_location_bitpack (data_in, &bp);
 }
 
 
@@ -310,7 +351,7 @@ lto_input_location (struct lto_input_block *ib, struct data_in *data_in)
    function scope for the read tree.  */
 
 static tree
-lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in, 
+lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in,
                    struct function *fn, enum LTO_tags tag)
 {
   unsigned HOST_WIDE_INT ix_u;
@@ -355,10 +396,9 @@ lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in,
     case LTO_const_decl_ref:
     case LTO_imported_decl_ref:
     case LTO_label_decl_ref:
+    case LTO_translation_unit_decl_ref:
       ix_u = lto_input_uleb128 (ib);
       result = lto_file_decl_data_get_var_decl (data_in->file_data, ix_u);
-      if (tag == LTO_global_decl_ref)
-       varpool_mark_needed_node (varpool_node (result));
       break;
 
     default:
@@ -371,6 +411,33 @@ lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in,
 }
 
 
+/* Read a chain of tree nodes from input block IB. DATA_IN contains
+   tables and descriptors for the file being read.  */
+
+static tree
+lto_input_chain (struct lto_input_block *ib, struct data_in *data_in)
+{
+  int i, count;
+  tree first, prev, curr;
+
+  first = prev = NULL_TREE;
+  count = lto_input_sleb128 (ib);
+  for (i = 0; i < count; i++)
+    {
+      curr = lto_input_tree (ib, data_in);
+      if (prev)
+       TREE_CHAIN (prev) = curr;
+      else
+       first = curr;
+
+      TREE_CHAIN (curr) = NULL_TREE;
+      prev = curr;
+    }
+
+  return first;
+}
+
+
 /* Read and return a double-linked list of catch handlers from input
    block IB, using descriptors in DATA_IN.  */
 
@@ -391,7 +458,7 @@ lto_input_eh_catch_list (struct lto_input_block *ib, struct data_in *data_in,
       lto_tag_check_range (tag, LTO_eh_catch, LTO_eh_catch);
 
       /* Read the catch node.  */
-      n = GGC_CNEW (struct eh_catch_d);
+      n = ggc_alloc_cleared_eh_catch_d ();
       n->type_list = lto_input_tree (ib, data_in);
       n->filter_list = lto_input_tree (ib, data_in);
       n->label = lto_input_tree (ib, data_in);
@@ -431,7 +498,7 @@ input_eh_region (struct lto_input_block *ib, struct data_in *data_in, int ix)
   if (tag == LTO_null)
     return NULL;
 
-  r = GGC_CNEW (struct eh_region_d);
+  r = ggc_alloc_cleared_eh_region_d ();
   r->index = lto_input_sleb128 (ib);
 
   gcc_assert (r->index == ix);
@@ -504,7 +571,7 @@ input_eh_lp (struct lto_input_block *ib, struct data_in *data_in, int ix)
 
   lto_tag_check_range (tag, LTO_eh_landing_pad, LTO_eh_landing_pad);
 
-  lp = GGC_CNEW (struct eh_landing_pad_d);
+  lp = ggc_alloc_cleared_eh_landing_pad_d ();
   lp->index = lto_input_sleb128 (ib);
   gcc_assert (lp->index == ix);
   lp->next_lp = (eh_landing_pad) (intptr_t) lto_input_sleb128 (ib);
@@ -541,7 +608,7 @@ fixup_eh_region_pointers (struct function *fn, HOST_WIDE_INT root_region)
 
   /* Convert all the index numbers stored in pointer fields into
      pointers to the corresponding slots in the EH region array.  */
-  for (i = 0; VEC_iterate (eh_region, eh_array, i, r); i++)
+  FOR_EACH_VEC_ELT (eh_region, eh_array, i, r)
     {
       /* The array may contain NULL regions.  */
       if (r == NULL)
@@ -556,7 +623,7 @@ fixup_eh_region_pointers (struct function *fn, HOST_WIDE_INT root_region)
 
   /* Convert all the index numbers stored in pointer fields into
      pointers to the corresponding slots in the EH landing pad array.  */
-  for (i = 0; VEC_iterate (eh_landing_pad, lp_array, i, lp); i++)
+  FOR_EACH_VEC_ELT (eh_landing_pad, lp_array, i, lp)
     {
       /* The array may contain NULL landing pads.  */
       if (lp == NULL)
@@ -577,6 +644,11 @@ fixup_eh_region_pointers (struct function *fn, HOST_WIDE_INT root_region)
 static void
 lto_init_eh (void)
 {
+  static bool eh_initialized_p = false;
+
+  if (eh_initialized_p)
+    return;
+
   /* Contrary to most other FEs, we only initialize EH support when at
      least one of the files in the set contains exception regions in
      it.  Since this happens much later than the call to init_eh in
@@ -585,13 +657,7 @@ lto_init_eh (void)
   flag_exceptions = 1;
   init_eh ();
 
-  /* Initialize dwarf2 tables.  Since dwarf2out_do_frame() returns
-     true only when exceptions are enabled, this initialization is
-     never done during lang_dependent_init.  */
-#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
-  if (dwarf2out_do_frame ())
-    dwarf2out_frame_init ();
-#endif
+  eh_initialized_p = true;
 }
 
 
@@ -604,8 +670,7 @@ input_eh_regions (struct lto_input_block *ib, struct data_in *data_in,
 {
   HOST_WIDE_INT i, root_region, len;
   enum LTO_tags tag;
-  static bool eh_initialized_p = false;
-  
+
   tag = input_record_start (ib);
   if (tag == LTO_null)
     return;
@@ -615,11 +680,7 @@ input_eh_regions (struct lto_input_block *ib, struct data_in *data_in,
   /* If the file contains EH regions, then it was compiled with
      -fexceptions.  In that case, initialize the backend EH
      machinery.  */
-  if (!eh_initialized_p)
-    {
-      lto_init_eh ();
-      eh_initialized_p = true;
-    }
+  lto_init_eh ();
 
   gcc_assert (fn->eh);
 
@@ -707,7 +768,7 @@ make_new_block (struct function *fn, unsigned int index)
   basic_block bb = alloc_block ();
   bb->index = index;
   SET_BASIC_BLOCK_FOR_FUNCTION (fn, index, bb);
-  bb->il.gimple = GGC_CNEW (struct gimple_bb_info);
+  bb->il.gimple = ggc_alloc_cleared_gimple_bb_info ();
   n_basic_blocks_for_function (fn)++;
   bb->flags = 0;
   set_bb_seq (bb, gimple_seq_alloc ());
@@ -717,8 +778,9 @@ make_new_block (struct function *fn, unsigned int index)
 
 /* Read the CFG for function FN from input block IB.  */
 
-static void 
-input_cfg (struct lto_input_block *ib, struct function *fn)
+static void
+input_cfg (struct lto_input_block *ib, struct function *fn,
+          int count_materialization_scale)
 {
   unsigned int bb_count;
   basic_block p_bb;
@@ -728,8 +790,7 @@ input_cfg (struct lto_input_block *ib, struct function *fn)
   init_empty_tree_cfg_for_function (fn);
   init_ssa_operands ();
 
-  profile_status_for_function (fn) = 
-    (enum profile_status_d) lto_input_uleb128 (ib);
+  profile_status_for_function (fn) = lto_input_enum (ib, profile_status_d, PROFILE_LAST);
 
   bb_count = lto_input_uleb128 (ib);
 
@@ -739,7 +800,7 @@ input_cfg (struct lto_input_block *ib, struct function *fn)
                           basic_block_info_for_function (fn), bb_count);
 
   if (bb_count > VEC_length (basic_block, label_to_block_map_for_function (fn)))
-    VEC_safe_grow_cleared (basic_block, gc, 
+    VEC_safe_grow_cleared (basic_block, gc,
                           label_to_block_map_for_function (fn), bb_count);
 
   index = lto_input_sleb128 (ib);
@@ -765,12 +826,13 @@ input_cfg (struct lto_input_block *ib, struct function *fn)
 
          dest_index = lto_input_uleb128 (ib);
          probability = (int) lto_input_sleb128 (ib);
-         count = (gcov_type) lto_input_sleb128 (ib);
+         count = ((gcov_type) lto_input_sleb128 (ib) * count_materialization_scale
+                  + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
          edge_flags = lto_input_uleb128 (ib);
 
          dest = BASIC_BLOCK_FOR_FUNCTION (fn, dest_index);
 
-         if (dest == NULL) 
+         if (dest == NULL)
            dest = make_new_block (fn, dest_index);
 
          e = make_edge (bb, dest, edge_flags);
@@ -821,10 +883,10 @@ input_phi (struct lto_input_block *ib, basic_block bb, struct data_in *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)
          {
@@ -832,7 +894,7 @@ input_phi (struct lto_input_block *ib, basic_block bb, struct data_in *data_in,
            break;
          }
 
-      add_phi_arg (result, def, e, arg_loc); 
+      add_phi_arg (result, def, e, arg_loc);
     }
 
   return result;
@@ -869,129 +931,6 @@ input_ssa_names (struct lto_input_block *ib, struct data_in *data_in,
        set_default_def (SSA_NAME_VAR (ssa_name), ssa_name);
 
       i = lto_input_uleb128 (ib);
-    } 
-}
-
-
-/* Fixup the reference tree OP for replaced VAR_DECLs with mismatched
-   types.  */
-
-static void
-maybe_fixup_handled_component (tree op)
-{
-  tree decl_type;
-  tree wanted_type;
-
-  while (handled_component_p (TREE_OPERAND (op, 0)))
-    op = TREE_OPERAND (op, 0);
-  if (TREE_CODE (TREE_OPERAND (op, 0)) != VAR_DECL)
-    return;
-
-  decl_type = TREE_TYPE (TREE_OPERAND (op, 0));
-
-  switch (TREE_CODE (op))
-    {
-    case COMPONENT_REF:
-      /* The DECL_CONTEXT of the field-decl is the record type we look for.  */
-      wanted_type = DECL_CONTEXT (TREE_OPERAND (op, 1));
-      break;
-
-    case ARRAY_REF:
-      if (TREE_CODE (decl_type) == ARRAY_TYPE
-         && (TREE_TYPE (decl_type) == TREE_TYPE (op)
-             || useless_type_conversion_p (TREE_TYPE (op),
-                                           TREE_TYPE (decl_type))))
-       return;
-      /* An unknown size array type should be ok.  But we do not
-         lower the lower bound in all cases - ugh.  */
-      wanted_type = build_array_type (TREE_TYPE (op), NULL_TREE);
-      break;
-
-    case ARRAY_RANGE_REF:
-      if (TREE_CODE (decl_type) == ARRAY_TYPE
-         && (TREE_TYPE (decl_type) == TREE_TYPE (TREE_TYPE (op))
-             || useless_type_conversion_p (TREE_TYPE (TREE_TYPE (op)),
-                                           TREE_TYPE (decl_type))))
-       return;
-      /* An unknown size array type should be ok.  But we do not
-         lower the lower bound in all cases - ugh.  */
-      wanted_type = build_array_type (TREE_TYPE (TREE_TYPE (op)), NULL_TREE);
-      break;
-
-    case BIT_FIELD_REF:
-    case VIEW_CONVERT_EXPR:
-      /* Very nice - nothing to do.  */
-      return;
-
-    case REALPART_EXPR:
-    case IMAGPART_EXPR:
-      if (TREE_CODE (decl_type) == COMPLEX_TYPE
-         && (TREE_TYPE (decl_type) == TREE_TYPE (op)
-             || useless_type_conversion_p (TREE_TYPE (op),
-                                           TREE_TYPE (decl_type))))
-       return;
-      wanted_type = build_complex_type (TREE_TYPE (op));
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-
-  if (!useless_type_conversion_p (wanted_type, decl_type))
-    TREE_OPERAND (op, 0) = build1 (VIEW_CONVERT_EXPR, wanted_type,
-                                  TREE_OPERAND (op, 0));
-}
-
-/* Fixup reference tree operands for substituted prevailing decls
-   with mismatched types in STMT.  */
-
-static void
-maybe_fixup_decls (gimple stmt)
-{
-  /* We have to fixup replaced decls here in case there were
-     inter-TU type mismatches.  Catch the most common cases
-     for now - this way we'll get testcases for the rest as
-     the type verifier will complain.  */
-  if (gimple_assign_single_p (stmt))
-    {
-      tree lhs = gimple_assign_lhs (stmt);
-      tree rhs = gimple_assign_rhs1 (stmt);
-
-      /* First catch loads and aggregate copies by adjusting the rhs.  */
-      if (TREE_CODE (rhs) == VAR_DECL)
-       {
-         if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
-           gimple_assign_set_rhs1 (stmt, build1 (VIEW_CONVERT_EXPR,
-                                                 TREE_TYPE (lhs), rhs));
-       }
-      else if (handled_component_p (rhs))
-       maybe_fixup_handled_component (rhs);
-      /* Then catch scalar stores.  */
-      else if (TREE_CODE (lhs) == VAR_DECL)
-       {
-         if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
-           gimple_assign_set_lhs (stmt, build1 (VIEW_CONVERT_EXPR,
-                                                TREE_TYPE (rhs), lhs));
-       }
-      else if (handled_component_p (lhs))
-       maybe_fixup_handled_component (lhs);
-    }
-  else if (is_gimple_call (stmt))
-    {
-      tree lhs = gimple_call_lhs (stmt);
-
-      if (lhs && TREE_CODE (lhs) == VAR_DECL)
-       {
-         if (!useless_type_conversion_p (TREE_TYPE (lhs),
-                                         gimple_call_return_type (stmt)))
-           gimple_call_set_lhs (stmt, build1 (VIEW_CONVERT_EXPR,
-                                              gimple_call_return_type (stmt),
-                                              lhs));
-       }
-      else if (lhs && handled_component_p (lhs))
-       maybe_fixup_handled_component (lhs);
-
-      /* Arguments, especially for varargs functions will be funny...  */
     }
 }
 
@@ -1006,20 +945,19 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
   enum gimple_code code;
   unsigned HOST_WIDE_INT num_ops;
   size_t i;
-  struct bitpack_d *bp;
+  struct bitpack_d bp;
 
   code = lto_tag_to_gimple_code (tag);
 
   /* Read the tuple header.  */
   bp = lto_input_bitpack (ib);
-  num_ops = bp_unpack_value (bp, sizeof (unsigned) * 8);
+  num_ops = bp_unpack_var_len_unsigned (&bp);
   stmt = gimple_alloc (code, num_ops);
-  stmt->gsbase.no_warning = bp_unpack_value (bp, 1);
+  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_value (bp, 16);
-  bitpack_delete (bp);
+    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));
@@ -1049,6 +987,7 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
        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);
       }
@@ -1066,37 +1005,86 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
        {
          tree op = lto_input_tree (ib, data_in);
          gimple_set_op (stmt, i, op);
-
-         /* Fixup FIELD_DECLs.  */
-         while (op && handled_component_p (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
-                         || (TREE_TYPE (tem) == TREE_TYPE (field)
-                             && (DECL_FIELD_OFFSET (tem)
-                                 == DECL_FIELD_OFFSET (field))
-                             && (DECL_FIELD_BIT_OFFSET (tem)
-                                 == DECL_FIELD_BIT_OFFSET (field))
-                             && (DECL_OFFSET_ALIGN (tem)
-                                 == DECL_OFFSET_ALIGN (field))))
+                     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.  Just do nothing in this case.  */
-                 if (tem != NULL_TREE)
+                    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:
@@ -1131,9 +1119,9 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
        }
     }
 
-  /* Fixup reference tree operands for substituted prevailing decls
-     with mismatched types.  */
-  maybe_fixup_decls (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);
@@ -1141,13 +1129,14 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
   return stmt;
 }
 
+
 /* Read a basic block with tag TAG from DATA_IN using input block IB.
    FN is the function being processed.  */
 
 static void
-input_bb (struct lto_input_block *ib, enum LTO_tags tag, 
-         struct data_in *data_in, struct function *fn)
+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;
@@ -1160,7 +1149,8 @@ input_bb (struct lto_input_block *ib, enum LTO_tags tag,
   index = lto_input_uleb128 (ib);
   bb = BASIC_BLOCK_FOR_FUNCTION (fn, index);
 
-  bb->count = lto_input_sleb128 (ib);
+  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);
@@ -1174,15 +1164,8 @@ input_bb (struct lto_input_block *ib, enum LTO_tags tag,
   while (tag)
     {
       gimple stmt = input_gimple_stmt (ib, data_in, fn, tag);
-
-      /* Change debug stmts to nops on-the-fly if we do not have VTA enabled.
-        This allows us to build for example static libs with debugging
-        enabled and do the final link without.  */
-      if (!MAY_HAVE_DEBUG_STMTS
-         && is_gimple_debug (stmt))
-       stmt = gimple_build_nop ();
-
-      find_referenced_vars_in (stmt);
+      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
@@ -1218,6 +1201,8 @@ fixup_call_stmt_edges_1 (struct cgraph_node *node, gimple *stmts)
   struct cgraph_edge *cedge;
   for (cedge = node->callees; cedge; cedge = cedge->next_callee)
     cedge->call_stmt = stmts[cedge->lto_stmt_uid];
+  for (cedge = node->indirect_calls; cedge; cedge = cedge->next_callee)
+    cedge->call_stmt = stmts[cedge->lto_stmt_uid];
 }
 
 /* Fixup call_stmt pointers in NODE and all clones.  */
@@ -1252,14 +1237,17 @@ fixup_call_stmt_edges (struct cgraph_node *orig, gimple *stmts)
 /* 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, 
+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 bitpack_d *bp;
+  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);
@@ -1270,29 +1258,60 @@ input_function (tree fn_decl, struct data_in *data_in,
 
   /* Read all the attributes for FN.  */
   bp = lto_input_bitpack (ib);
-  fn->is_thunk = bp_unpack_value (bp, 1);
-  fn->has_local_explicit_reg_vars = bp_unpack_value (bp, 1);
-  fn->after_tree_profile = bp_unpack_value (bp, 1);
-  fn->returns_pcc_struct = bp_unpack_value (bp, 1);
-  fn->returns_struct = bp_unpack_value (bp, 1);
-  fn->always_inline_functions_inlined = bp_unpack_value (bp, 1);
-  fn->after_inlining = bp_unpack_value (bp, 1);
-  fn->dont_save_pending_sizes_p = bp_unpack_value (bp, 1);
-  fn->stdarg = bp_unpack_value (bp, 1);
-  fn->has_nonlocal_label = bp_unpack_value (bp, 1);
-  fn->calls_alloca = bp_unpack_value (bp, 1);
-  fn->calls_setjmp = bp_unpack_value (bp, 1);
-  fn->function_frequency = (enum function_frequency) bp_unpack_value (bp, 2);
-  fn->va_list_fpr_size = bp_unpack_value (bp, 8);
-  fn->va_list_gpr_size = bp_unpack_value (bp, 8);
-  bitpack_delete (bp);
+  fn->is_thunk = bp_unpack_value (&bp, 1);
+  fn->has_local_explicit_reg_vars = bp_unpack_value (&bp, 1);
+  fn->after_tree_profile = bp_unpack_value (&bp, 1);
+  fn->returns_pcc_struct = bp_unpack_value (&bp, 1);
+  fn->returns_struct = bp_unpack_value (&bp, 1);
+  fn->can_throw_non_call_exceptions = bp_unpack_value (&bp, 1);
+  fn->always_inline_functions_inlined = bp_unpack_value (&bp, 1);
+  fn->after_inlining = bp_unpack_value (&bp, 1);
+  fn->stdarg = bp_unpack_value (&bp, 1);
+  fn->has_nonlocal_label = bp_unpack_value (&bp, 1);
+  fn->calls_alloca = bp_unpack_value (&bp, 1);
+  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 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.  */
-  fn->local_decls = lto_input_tree (ib, data_in);
+  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);
+       }
+    }
+
+  /* Read all function arguments.  We need to re-map them here to the
+     arguments of the merged function declaration.  */
+  args = lto_input_tree (ib, data_in);
+  for (oarg = args, narg = DECL_ARGUMENTS (fn_decl);
+       oarg && narg;
+       oarg = TREE_CHAIN (oarg), narg = TREE_CHAIN (narg))
+    {
+      unsigned ix;
+      bool res;
+      res = lto_streamer_cache_lookup (data_in->reader_cache, oarg, &ix);
+      gcc_assert (res);
+      /* Replace the argument in the streamer cache.  */
+      lto_streamer_cache_insert_at (data_in->reader_cache, narg, ix);
+    }
+  gcc_assert (!oarg && !narg);
 
   /* Read all the SSA names.  */
   input_ssa_names (ib, data_in, fn);
@@ -1304,29 +1323,52 @@ input_function (tree fn_decl, struct data_in *data_in,
   DECL_INITIAL (fn_decl) = lto_input_tree (ib, data_in);
   gcc_assert (DECL_INITIAL (fn_decl));
   DECL_SAVED_TREE (fn_decl) = NULL_TREE;
-
-  /* Read all function arguments.  */
-  DECL_ARGUMENTS (fn_decl) = lto_input_tree (ib, data_in); 
+  node = cgraph_get_create_node (fn_decl);
 
   /* Read all the basic blocks.  */
   tag = input_record_start (ib);
   while (tag)
     {
-      input_bb (ib, tag, data_in, fn);
+      input_bb (ib, tag, data_in, fn,
+               node->count_materialization_scale);
       tag = input_record_start (ib);
     }
 
   /* Fix up the call statements that are mentioned in the callgraph
      edges.  */
-  renumber_gimple_stmt_uids ();
+  set_gimple_stmt_max_uid (cfun, 0);
+  FOR_ALL_BB (bb)
+    {
+      gimple_stmt_iterator gsi;
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+       {
+         gimple stmt = gsi_stmt (gsi);
+         gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
+       }
+    }
   stmts = (gimple *) xcalloc (gimple_stmt_max_uid (fn), sizeof (gimple));
   FOR_ALL_BB (bb)
     {
-      gimple_stmt_iterator bsi;
-      for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
+      gimple_stmt_iterator bsi = gsi_start_bb (bb);
+      while (!gsi_end_p (bsi))
        {
          gimple stmt = gsi_stmt (bsi);
-         stmts[gimple_uid (stmt)] = stmt;
+         /* If we're recompiling LTO objects with debug stmts but
+            we're not supposed to have debug stmts, remove them now.
+            We can't remove them earlier because this would cause uid
+            mismatches in fixups, but we can do it at this point, as
+            long as debug stmts don't require fixups.  */
+         if (!MAY_HAVE_DEBUG_STMTS && is_gimple_debug (stmt))
+           {
+             gimple_stmt_iterator gsi = bsi;
+             gsi_next (&bsi);
+             gsi_remove (&gsi, true);
+           }
+         else
+           {
+             gsi_next (&bsi);
+             stmts[gimple_uid (stmt)] = stmt;
+           }
        }
     }
 
@@ -1339,9 +1381,10 @@ input_function (tree fn_decl, struct data_in *data_in,
     gimple_set_body (fn_decl, bb_seq (ei_edge (ei)->dest));
   }
 
-  fixup_call_stmt_edges (cgraph_node (fn_decl), stmts);
+  fixup_call_stmt_edges (node, stmts);
+  execute_all_ipa_stmt_fixups (node, stmts);
 
-  update_ssa (TODO_update_ssa_only_virtuals); 
+  update_ssa (TODO_update_ssa_only_virtuals);
   free_dominance_info (CDI_DOMINATORS);
   free_dominance_info (CDI_POST_DOMINATORS);
   free (stmts);
@@ -1358,17 +1401,12 @@ input_alias_pairs (struct lto_input_block *ib, struct data_in *data_in)
 
   clear_line_info (data_in);
 
-  /* Skip over all the unreferenced globals.  */
-  do
-    var = lto_input_tree (ib, data_in);
-  while (var);
-
   var = lto_input_tree (ib, data_in);
   while (var)
     {
       const char *orig_name, *new_name;
       alias_pair *p;
-      
+
       p = VEC_safe_push (alias_pair, gc, alias_pairs, NULL);
       p->decl = var;
       p->target = lto_input_tree (ib, data_in);
@@ -1392,7 +1430,7 @@ input_alias_pairs (struct lto_input_block *ib, struct data_in *data_in)
    section type is LTO_section_function_body, FN must be the decl for
    that function.  */
 
-static void 
+static void
 lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
               const char *data, enum lto_section_type section_type)
 {
@@ -1405,7 +1443,7 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
   struct lto_input_block ib_main;
 
   header = (const struct lto_function_header *) data;
-  cfg_offset = sizeof (struct lto_function_header); 
+  cfg_offset = sizeof (struct lto_function_header);
   main_offset = cfg_offset + header->cfg_size;
   string_offset = main_offset + header->main_size;
 
@@ -1418,7 +1456,7 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
                        data + main_offset,
                        0,
                        header->main_size);
-  
+
   data_in = lto_data_in_create (file_data, data + string_offset,
                                header->string_size, NULL);
 
@@ -1430,7 +1468,9 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
     {
       struct function *fn = DECL_STRUCT_FUNCTION (fn_decl);
       struct lto_in_decl_state *decl_state;
+      struct cgraph_node *node = cgraph_get_node (fn_decl);
 
+      gcc_checking_assert (node);
       push_cfun (fn);
       init_tree_ssa (fn);
 
@@ -1439,7 +1479,7 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
       gcc_assert (decl_state);
       file_data->current_decl_state = decl_state;
 
-      input_cfg (&ib_cfg, fn);
+      input_cfg (&ib_cfg, fn, node->count_materialization_scale);
 
       /* Set up the struct function.  */
       input_function (fn_decl, data_in, &ib_main);
@@ -1447,29 +1487,12 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
       /* We should now be in SSA.  */
       cfun->gimple_df->in_ssa_p = true;
 
-      /* Fill in properties we know hold for the rebuilt CFG.  */
-      cfun->curr_properties = PROP_ssa
-                             | PROP_cfg
-                             | PROP_gimple_any
-                             | PROP_gimple_lcf
-                             | PROP_gimple_leh
-                             | PROP_referenced_vars;
-
       /* Restore decl state */
       file_data->current_decl_state = file_data->global_decl_state;
 
-      /* FIXME: ipa_transforms_to_apply holds list of passes that have optimization
-         summaries computed and needs to apply changes.  At the moment WHOPR only
-         supports inlining, so we can push it here by hand.  In future we need to stream
-         this field into ltrans compilation.  This will also need to move the field
-        from struct function into cgraph node where it belongs.  */
-      if (flag_ltrans && !cgraph_node (fn_decl)->global.inlined_to)
-        VEC_safe_push (ipa_opt_pass, heap,
-                       cfun->ipa_transforms_to_apply,
-                       (ipa_opt_pass)&pass_ipa_inline);
       pop_cfun ();
     }
-  else 
+  else
     {
       input_alias_pairs (&ib_main, data_in);
     }
@@ -1482,7 +1505,7 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
 /* Read the body of FN_DECL using DATA.  FILE_DATA holds the global
    decls and types.  */
 
-void 
+void
 lto_input_function_body (struct lto_file_decl_data *file_data,
                         tree fn_decl, const char *data)
 {
@@ -1494,7 +1517,7 @@ lto_input_function_body (struct lto_file_decl_data *file_data,
 /* Read in VAR_DECL using DATA.  FILE_DATA holds the global decls and
    types.  */
 
-void 
+void
 lto_input_constructors_and_inits (struct lto_file_decl_data *file_data,
                                  const char *data)
 {
@@ -1502,28 +1525,6 @@ lto_input_constructors_and_inits (struct lto_file_decl_data *file_data,
 }
 
 
-/* Return the resolution for the decl with index INDEX from DATA_IN. */
-
-static enum ld_plugin_symbol_resolution
-get_resolution (struct data_in *data_in, unsigned index)
-{
-  if (data_in->globals_resolution)
-    {
-      ld_plugin_symbol_resolution_t ret;
-      gcc_assert (index < VEC_length (ld_plugin_symbol_resolution_t,
-                                     data_in->globals_resolution));
-      ret = VEC_index (ld_plugin_symbol_resolution_t,
-                      data_in->globals_resolution,
-                      index);
-      gcc_assert (ret != LDPR_UNKNOWN);
-      return ret;
-    }
-  else
-    /* Delay resolution finding until decl merging.  */
-    return LDPR_UNKNOWN;
-}
-
-
 /* Unpack all the non-pointer fields of the TS_BASE structure of
    expression EXPR from bitpack BP.  */
 
@@ -1543,14 +1544,21 @@ unpack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
         so we skip it here.  */
       TREE_PUBLIC (expr) = (unsigned) bp_unpack_value (bp, 1);
     }
+  else
+    bp_unpack_value (bp, 4);
   TREE_ADDRESSABLE (expr) = (unsigned) bp_unpack_value (bp, 1);
   TREE_THIS_VOLATILE (expr) = (unsigned) bp_unpack_value (bp, 1);
   if (DECL_P (expr))
     DECL_UNSIGNED (expr) = (unsigned) bp_unpack_value (bp, 1);
   else if (TYPE_P (expr))
     TYPE_UNSIGNED (expr) = (unsigned) bp_unpack_value (bp, 1);
+  else
+    bp_unpack_value (bp, 1);
   TREE_ASM_WRITTEN (expr) = (unsigned) bp_unpack_value (bp, 1);
-  TREE_NO_WARNING (expr) = (unsigned) bp_unpack_value (bp, 1);
+  if (TYPE_P (expr))
+    TYPE_ARTIFICIAL (expr) = (unsigned) bp_unpack_value (bp, 1);
+  else
+    TREE_NO_WARNING (expr) = (unsigned) bp_unpack_value (bp, 1);
   TREE_USED (expr) = (unsigned) bp_unpack_value (bp, 1);
   TREE_NOTHROW (expr) = (unsigned) bp_unpack_value (bp, 1);
   TREE_STATIC (expr) = (unsigned) bp_unpack_value (bp, 1);
@@ -1559,8 +1567,10 @@ unpack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
   TREE_DEPRECATED (expr) = (unsigned) bp_unpack_value (bp, 1);
   if (TYPE_P (expr))
     TYPE_SATURATING (expr) = (unsigned) bp_unpack_value (bp, 1);
-  if (TREE_CODE (expr) == SSA_NAME)
+  else if (TREE_CODE (expr) == SSA_NAME)
     SSA_NAME_IS_DEFAULT_DEF (expr) = (unsigned) bp_unpack_value (bp, 1);
+  else
+    bp_unpack_value (bp, 1);
 }
 
 
@@ -1573,7 +1583,7 @@ unpack_ts_real_cst_value_fields (struct bitpack_d *bp, tree expr)
   unsigned i;
   REAL_VALUE_TYPE r;
   REAL_VALUE_TYPE *rp;
-  
+
   r.cl = (unsigned) bp_unpack_value (bp, 2);
   r.decimal = (unsigned) bp_unpack_value (bp, 1);
   r.sign = (unsigned) bp_unpack_value (bp, 1);
@@ -1583,7 +1593,7 @@ unpack_ts_real_cst_value_fields (struct bitpack_d *bp, tree expr)
   for (i = 0; i < SIGSZ; i++)
     r.sig[i] = (unsigned long) bp_unpack_value (bp, HOST_BITS_PER_LONG);
 
-  rp = GGC_NEW (REAL_VALUE_TYPE);
+  rp = ggc_alloc_real_value ();
   memcpy (rp, &r, sizeof (REAL_VALUE_TYPE));
   TREE_REAL_CST_PTR (expr) = rp;
 }
@@ -1596,9 +1606,10 @@ static void
 unpack_ts_fixed_cst_value_fields (struct bitpack_d *bp, tree expr)
 {
   struct fixed_value fv;
-  
-  fv.data.low = (HOST_WIDE_INT) bp_unpack_value (bp, HOST_BITS_PER_WIDE_INT);
-  fv.data.high = (HOST_WIDE_INT) bp_unpack_value (bp, HOST_BITS_PER_WIDE_INT);
+
+  fv.mode = bp_unpack_enum (bp, machine_mode, MAX_MACHINE_MODE);
+  fv.data.low = bp_unpack_var_len_int (bp);
+  fv.data.high = bp_unpack_var_len_int (bp);
   TREE_FIXED_CST (expr) = fv;
 }
 
@@ -1609,7 +1620,7 @@ unpack_ts_fixed_cst_value_fields (struct bitpack_d *bp, tree expr)
 static void
 unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
 {
-  DECL_MODE (expr) = (enum machine_mode) bp_unpack_value (bp, 8);
+  DECL_MODE (expr) = bp_unpack_enum (bp, machine_mode, MAX_MACHINE_MODE);
   DECL_NONLOCAL (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_VIRTUAL_P (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_IGNORED_P (expr) = (unsigned) bp_unpack_value (bp, 1);
@@ -1620,12 +1631,12 @@ unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
   DECL_DEBUG_EXPR_IS_FROM (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_EXTERNAL (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_GIMPLE_REG_P (expr) = (unsigned) bp_unpack_value (bp, 1);
-  DECL_ALIGN (expr) = (unsigned) bp_unpack_value (bp, HOST_BITS_PER_INT);
+  DECL_ALIGN (expr) = (unsigned) bp_unpack_var_len_unsigned (bp);
 
   if (TREE_CODE (expr) == LABEL_DECL)
     {
       DECL_ERROR_ISSUED (expr) = (unsigned) bp_unpack_value (bp, 1);
-      EH_LANDING_PAD_NR (expr) = (int) bp_unpack_value (bp, HOST_BITS_PER_INT);
+      EH_LANDING_PAD_NR (expr) = (int) bp_unpack_var_len_unsigned (bp);
 
       /* Always assume an initial value of -1 for LABEL_DECL_UID to
         force gimple_set_bb to recreate label_to_block_map.  */
@@ -1634,11 +1645,9 @@ unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
 
   if (TREE_CODE (expr) == FIELD_DECL)
     {
-      unsigned HOST_WIDE_INT off_align;
       DECL_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1);
       DECL_NONADDRESSABLE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
-      off_align = (unsigned HOST_WIDE_INT) bp_unpack_value (bp, 8);
-      SET_DECL_OFFSET_ALIGN (expr, off_align);
+      expr->decl_common.off_align = bp_unpack_value (bp, 8);
     }
 
   if (TREE_CODE (expr) == RESULT_DECL
@@ -1649,6 +1658,7 @@ unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
       if (TREE_CODE (expr) == VAR_DECL
          || TREE_CODE (expr) == PARM_DECL)
        DECL_HAS_VALUE_EXPR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
+      DECL_RESTRICTED_P (expr) = (unsigned) bp_unpack_value (bp, 1);
     }
 }
 
@@ -1682,13 +1692,14 @@ unpack_ts_decl_with_vis_value_fields (struct bitpack_d *bp, tree expr)
     {
       DECL_HARD_REGISTER (expr) = (unsigned) bp_unpack_value (bp, 1);
       DECL_IN_TEXT_SECTION (expr) = (unsigned) bp_unpack_value (bp, 1);
+      DECL_IN_CONSTANT_POOL (expr) = (unsigned) bp_unpack_value (bp, 1);
       DECL_TLS_MODEL (expr) = (enum tls_model) bp_unpack_value (bp,  3);
     }
 
   if (VAR_OR_FUNCTION_DECL_P (expr))
     {
       priority_type p;
-      p = (priority_type) bp_unpack_value (bp, HOST_BITS_PER_SHORT);
+      p = (priority_type) bp_unpack_var_len_unsigned (bp);
       SET_DECL_INIT_PRIORITY (expr, p);
     }
 }
@@ -1700,8 +1711,8 @@ unpack_ts_decl_with_vis_value_fields (struct bitpack_d *bp, tree expr)
 static void
 unpack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
 {
-  DECL_FUNCTION_CODE (expr) = (enum built_in_function) bp_unpack_value (bp, 11);
-  DECL_BUILT_IN_CLASS (expr) = (enum built_in_class) bp_unpack_value (bp, 2);
+  DECL_BUILT_IN_CLASS (expr) = bp_unpack_enum (bp, built_in_class,
+                                              BUILT_IN_LAST);
   DECL_STATIC_CONSTRUCTOR (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_STATIC_DESTRUCTOR (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_UNINLINABLE (expr) = (unsigned) bp_unpack_value (bp, 1);
@@ -1719,33 +1730,52 @@ unpack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
   DECL_DISREGARD_INLINE_LIMITS (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_PURE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_LOOPING_CONST_OR_PURE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
+  if (DECL_BUILT_IN_CLASS (expr) != NOT_BUILT_IN)
+    {
+      DECL_FUNCTION_CODE (expr) = (enum built_in_function) bp_unpack_value (bp, 11);
+      if (DECL_BUILT_IN_CLASS (expr) == BUILT_IN_NORMAL
+         && DECL_FUNCTION_CODE (expr) >= END_BUILTINS)
+       fatal_error ("machine independent builtin code out of range");
+      else if (DECL_BUILT_IN_CLASS (expr) == BUILT_IN_MD)
+       {
+          tree result = targetm.builtin_decl (DECL_FUNCTION_CODE (expr), true);
+         if (!result || result == error_mark_node)
+           fatal_error ("target specific builtin not available");
+       }
+    }
+  if (DECL_STATIC_DESTRUCTOR (expr))
+    {
+      priority_type p;
+      p = (priority_type) bp_unpack_var_len_unsigned (bp);
+      SET_DECL_FINI_PRIORITY (expr, p);
+    }
 }
 
 
-/* Unpack all the non-pointer fields of the TS_TYPE structure
+/* Unpack all the non-pointer fields of the TS_TYPE_COMMON structure
    of expression EXPR from bitpack BP.  */
 
 static void
-unpack_ts_type_value_fields (struct bitpack_d *bp, tree expr)
+unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
 {
   enum machine_mode mode;
 
-  TYPE_PRECISION (expr) = (unsigned) bp_unpack_value (bp, 9);
-  mode = (enum machine_mode) bp_unpack_value (bp, 7);
+  mode = bp_unpack_enum (bp, machine_mode, MAX_MACHINE_MODE);
   SET_TYPE_MODE (expr, mode);
   TYPE_STRING_FLAG (expr) = (unsigned) bp_unpack_value (bp, 1);
   TYPE_NO_FORCE_BLK (expr) = (unsigned) bp_unpack_value (bp, 1);
-  TYPE_NEEDS_CONSTRUCTING(expr) = (unsigned) bp_unpack_value (bp, 1);
-  if (TREE_CODE (expr) == UNION_TYPE)
-    TYPE_TRANSPARENT_UNION (expr) = (unsigned) bp_unpack_value (bp, 1);
+  TYPE_NEEDS_CONSTRUCTING (expr) = (unsigned) bp_unpack_value (bp, 1);
+  if (RECORD_OR_UNION_TYPE_P (expr))
+    TYPE_TRANSPARENT_AGGR (expr) = (unsigned) bp_unpack_value (bp, 1);
   TYPE_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1);
   TYPE_RESTRICT (expr) = (unsigned) bp_unpack_value (bp, 1);
   TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr)
        = (unsigned) bp_unpack_value (bp, 2);
   TYPE_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1);
   TYPE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1);
-  TYPE_ALIGN (expr) = (unsigned) bp_unpack_value (bp, HOST_BITS_PER_INT);
-  TYPE_ALIAS_SET (expr) = bp_unpack_value (bp, HOST_BITS_PER_INT);
+  TYPE_PRECISION (expr) = bp_unpack_var_len_unsigned (bp);
+  TYPE_ALIGN (expr) = bp_unpack_var_len_unsigned (bp);
+  TYPE_ALIAS_SET (expr) = bp_unpack_var_len_int (bp);
 }
 
 
@@ -1756,9 +1786,16 @@ static void
 unpack_ts_block_value_fields (struct bitpack_d *bp, tree expr)
 {
   BLOCK_ABSTRACT (expr) = (unsigned) bp_unpack_value (bp, 1);
-  BLOCK_NUMBER (expr) = (unsigned) bp_unpack_value (bp, 31);
+  /* BLOCK_NUMBER is recomputed.  */
 }
 
+/* Unpack all the non-pointer fields of the TS_TRANSLATION_UNIT_DECL
+   structure of expression EXPR from bitpack BP.  */
+
+static void
+unpack_ts_translation_unit_decl_value_fields (struct bitpack_d *bp ATTRIBUTE_UNUSED, tree expr ATTRIBUTE_UNUSED)
+{
+}
 
 /* Unpack all the non-pointer fields in EXPR into a bit pack.  */
 
@@ -1791,55 +1828,17 @@ unpack_value_fields (struct bitpack_d *bp, tree expr)
   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
     unpack_ts_function_decl_value_fields (bp, expr);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_TYPE))
-    unpack_ts_type_value_fields (bp, expr);
+  if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
+    unpack_ts_type_common_value_fields (bp, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
     unpack_ts_block_value_fields (bp, expr);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_SSA_NAME))
-    {
-      /* We only stream the version number of SSA names.  */
-      gcc_unreachable ();
-    }
-
-  if (CODE_CONTAINS_STRUCT (code, TS_STATEMENT_LIST))
-    {
-      /* This is only used by GENERIC.  */
-      gcc_unreachable ();
-    }
-
-  if (CODE_CONTAINS_STRUCT (code, TS_OMP_CLAUSE))
-    {
-      /* This is only used by High GIMPLE.  */
-      gcc_unreachable ();
-    }
-}
-
-
-/* Read a bitpack from input block IB.  */
-
-struct bitpack_d *
-lto_input_bitpack (struct lto_input_block *ib)
-{
-  unsigned i, num_words;
-  struct bitpack_d *bp;
-
-  bp = bitpack_create ();
-
-  /* If we are about to read more than a handful of words, something
-     is wrong.  This check is overly strict, but it acts as an early
-     warning.  No streamed object has hundreds of bits in its fields.  */
-  num_words = lto_input_uleb128 (ib);
-  gcc_assert (num_words < 20);
+  if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
+    unpack_ts_translation_unit_decl_value_fields (bp, expr);
 
-  for (i = 0; i < num_words; i++)
-    {
-      bitpack_word_t w = lto_input_uleb128 (ib);
-      VEC_safe_push (bitpack_word_t, heap, bp->values, w);
-    }
-
-  return bp;
+  if (streamer_hooks.unpack_value_fields)
+    streamer_hooks.unpack_value_fields (bp, expr);
 }
 
 
@@ -1849,23 +1848,17 @@ lto_input_bitpack (struct lto_input_block *ib)
 
 static tree
 lto_materialize_tree (struct lto_input_block *ib, struct data_in *data_in,
-                     enum LTO_tags tag, int *ix_p)
+                     enum LTO_tags tag)
 {
-  struct bitpack_d *bp;
+  struct bitpack_d bp;
   enum tree_code code;
   tree result;
 #ifdef LTO_STREAMER_DEBUG
   HOST_WIDEST_INT orig_address_in_writer;
 #endif
-  HOST_WIDE_INT ix;
 
   result = NULL_TREE;
 
-  /* Read the header of the node we are about to create.  */
-  ix = lto_input_sleb128 (ib);
-  gcc_assert ((int) ix == ix);
-  *ix_p = (int) ix;
-
 #ifdef LTO_STREAMER_DEBUG
   /* Read the word representing the memory address for the tree
      as it was written by the writer.  This is useful when
@@ -1897,9 +1890,15 @@ lto_materialize_tree (struct lto_input_block *ib, struct data_in *data_in,
     }
   else
     {
-      /* All other nodes can be materialized with a raw make_node
-        call.  */
-      result = make_node (code);
+      /* For all other nodes, see if the streamer knows how to allocate
+        it.  */
+      if (streamer_hooks.alloc_tree)
+       result = streamer_hooks.alloc_tree (code, ib, data_in);
+
+      /* If the hook did not handle it, materialize the tree with a raw
+        make_node call.  */
+      if (result == NULL_TREE)
+       result = make_node (code);
     }
 
 #ifdef LTO_STREAMER_DEBUG
@@ -1916,49 +1915,21 @@ lto_materialize_tree (struct lto_input_block *ib, struct data_in *data_in,
 
   /* The first word in BP contains the code of the tree that we
      are about to read.  */
-  code = (enum tree_code) bp_unpack_value (bp, 16);
+  code = (enum tree_code) bp_unpack_value (&bp, 16);
   lto_tag_check (lto_tree_code_to_tag (code), tag);
 
   /* Unpack all the value fields from BP.  */
-  unpack_value_fields (bp, result);
-  bitpack_delete (bp);
+  unpack_value_fields (&bp, result);
 
   /* Enter RESULT in the reader cache.  This will make RESULT
      available so that circular references in the rest of the tree
      structure can be resolved in subsequent calls to lto_input_tree.  */
-  lto_streamer_cache_insert_at (data_in->reader_cache, result, ix);
+  lto_streamer_cache_append (data_in->reader_cache, result);
 
   return result;
 }
 
 
-/* Read a chain of tree nodes from input block IB. DATA_IN contains
-   tables and descriptors for the file being read.  */
-
-static tree
-lto_input_chain (struct lto_input_block *ib, struct data_in *data_in)
-{
-  int i, count;
-  tree first, prev, curr;
-  
-  first = prev = NULL_TREE;
-  count = lto_input_sleb128 (ib);
-  for (i = 0; i < count; i++)
-    {
-      curr = lto_input_tree (ib, data_in);
-      if (prev)
-       TREE_CHAIN (prev) = curr;
-      else
-       first = curr;
-
-      TREE_CHAIN (curr) = NULL_TREE;
-      prev = curr;
-    }
-
-  return first;
-}
-
-  
 /* Read all pointer fields in the TS_COMMON structure of EXPR from input
    block IB.  DATA_IN contains tables and descriptors for the
    file being read.  */
@@ -1968,7 +1939,8 @@ static void
 lto_input_ts_common_tree_pointers (struct lto_input_block *ib,
                                   struct data_in *data_in, tree expr)
 {
-  TREE_TYPE (expr) = lto_input_tree (ib, data_in);
+  if (TREE_CODE (expr) != IDENTIFIER_NODE)
+    TREE_TYPE (expr) = lto_input_tree (ib, data_in);
 }
 
 
@@ -2021,15 +1993,26 @@ lto_input_ts_decl_common_tree_pointers (struct lto_input_block *ib,
 {
   DECL_SIZE (expr) = lto_input_tree (ib, data_in);
   DECL_SIZE_UNIT (expr) = lto_input_tree (ib, data_in);
-
-  if (TREE_CODE (expr) != FUNCTION_DECL)
-    DECL_INITIAL (expr) = lto_input_tree (ib, data_in);
-
   DECL_ATTRIBUTES (expr) = lto_input_tree (ib, data_in);
-  DECL_ABSTRACT_ORIGIN (expr) = lto_input_tree (ib, data_in);
+
+  /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
+     for early inlining so drop it on the floor instead of ICEing in
+     dwarf2out.c.  */
 
   if (TREE_CODE (expr) == PARM_DECL)
     TREE_CHAIN (expr) = lto_input_chain (ib, data_in);
+
+  if ((TREE_CODE (expr) == VAR_DECL
+       || TREE_CODE (expr) == PARM_DECL)
+      && DECL_HAS_VALUE_EXPR_P (expr))
+    SET_DECL_VALUE_EXPR (expr, lto_input_tree (ib, data_in));
+
+  if (TREE_CODE (expr) == VAR_DECL)
+    {
+      tree dexpr = lto_input_tree (ib, data_in);
+      if (dexpr)
+       SET_DECL_DEBUG_EXPR (expr, dexpr);
+    }
 }
 
 
@@ -2059,7 +2042,7 @@ lto_input_ts_decl_with_vis_tree_pointers (struct lto_input_block *ib,
                                          struct data_in *data_in, tree expr)
 {
   tree id;
-  
+
   id = lto_input_tree (ib, data_in);
   if (id)
     {
@@ -2102,44 +2085,62 @@ lto_input_ts_function_decl_tree_pointers (struct lto_input_block *ib,
   DECL_FUNCTION_PERSONALITY (expr) = lto_input_tree (ib, data_in);
   DECL_FUNCTION_SPECIFIC_TARGET (expr) = lto_input_tree (ib, data_in);
   DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr) = lto_input_tree (ib, data_in);
+
+  /* If the file contains a function with an EH personality set,
+     then it was compiled with -fexceptions.  In that case, initialize
+     the backend EH machinery.  */
+  if (DECL_FUNCTION_PERSONALITY (expr))
+    lto_init_eh ();
 }
 
 
-/* Read all pointer fields in the TS_TYPE structure of EXPR from input
-   block IB.  DATA_IN contains tables and descriptors for the
+/* Read all pointer fields in the TS_TYPE_COMMON structure of EXPR from
+   input block IB.  DATA_IN contains tables and descriptors for the file
+   being read.  */
+
+static void
+lto_input_ts_type_common_tree_pointers (struct lto_input_block *ib,
+                                       struct data_in *data_in, tree expr)
+{
+  TYPE_SIZE (expr) = lto_input_tree (ib, data_in);
+  TYPE_SIZE_UNIT (expr) = lto_input_tree (ib, data_in);
+  TYPE_ATTRIBUTES (expr) = lto_input_tree (ib, data_in);
+  TYPE_NAME (expr) = lto_input_tree (ib, data_in);
+  /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO.  They will be
+     reconstructed during fixup.  */
+  /* Do not stream TYPE_NEXT_VARIANT, we reconstruct the variant lists
+     during fixup.  */
+  TYPE_MAIN_VARIANT (expr) = lto_input_tree (ib, data_in);
+  TYPE_CONTEXT (expr) = lto_input_tree (ib, data_in);
+  /* TYPE_CANONICAL gets re-computed during type merging.  */
+  TYPE_CANONICAL (expr) = NULL_TREE;
+  TYPE_STUB_DECL (expr) = lto_input_tree (ib, data_in);
+}
+
+/* Read all pointer fields in the TS_TYPE_NON_COMMON structure of EXPR
+   from input block IB.  DATA_IN contains tables and descriptors for the
    file being read.  */
 
 static void
-lto_input_ts_type_tree_pointers (struct lto_input_block *ib,
-                                struct data_in *data_in, tree expr)
+lto_input_ts_type_non_common_tree_pointers (struct lto_input_block *ib,
+                                           struct data_in *data_in,
+                                           tree expr)
 {
   if (TREE_CODE (expr) == ENUMERAL_TYPE)
     TYPE_VALUES (expr) = lto_input_tree (ib, data_in);
   else if (TREE_CODE (expr) == ARRAY_TYPE)
     TYPE_DOMAIN (expr) = lto_input_tree (ib, data_in);
-  else if (TREE_CODE (expr) == RECORD_TYPE || TREE_CODE (expr) == UNION_TYPE)
+  else if (RECORD_OR_UNION_TYPE_P (expr))
     TYPE_FIELDS (expr) = lto_input_tree (ib, data_in);
-  else if (TREE_CODE (expr) == FUNCTION_TYPE || TREE_CODE (expr) == METHOD_TYPE)
+  else if (TREE_CODE (expr) == FUNCTION_TYPE
+          || TREE_CODE (expr) == METHOD_TYPE)
     TYPE_ARG_TYPES (expr) = lto_input_tree (ib, data_in);
-  else if (TREE_CODE (expr) == VECTOR_TYPE)
-    TYPE_DEBUG_REPRESENTATION_TYPE (expr) = lto_input_tree (ib, data_in);
 
-  TYPE_SIZE (expr) = lto_input_tree (ib, data_in);
-  TYPE_SIZE_UNIT (expr) = lto_input_tree (ib, data_in);
-  TYPE_ATTRIBUTES (expr) = lto_input_tree (ib, data_in);
-  TYPE_NAME (expr) = lto_input_tree (ib, data_in);
-  /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO nor
-     TYPE_NEXT_PTR_TO or TYPE_NEXT_REF_TO.  */
   if (!POINTER_TYPE_P (expr))
     TYPE_MINVAL (expr) = lto_input_tree (ib, data_in);
   TYPE_MAXVAL (expr) = lto_input_tree (ib, data_in);
-  TYPE_MAIN_VARIANT (expr) = lto_input_tree (ib, data_in);
-  /* Do not stream TYPE_NEXT_VARIANT, we reconstruct the variant lists
-     during fixup.  */
   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);
 }
 
 
@@ -2206,23 +2207,37 @@ static void
 lto_input_ts_block_tree_pointers (struct lto_input_block *ib,
                                  struct data_in *data_in, tree expr)
 {
-  unsigned i, len;
-
-  BLOCK_SOURCE_LOCATION (expr) = lto_input_location (ib, data_in);
+  /* Do not stream BLOCK_SOURCE_LOCATION.  We cannot handle debug information
+     for early inlining so drop it on the floor instead of ICEing in
+     dwarf2out.c.  */
   BLOCK_VARS (expr) = lto_input_chain (ib, data_in);
 
-  len = lto_input_uleb128 (ib);
-  for (i = 0; i < len; i++)
-    {
-      tree t = lto_input_tree (ib, data_in);
-      VEC_safe_push (tree, gc, BLOCK_NONLOCALIZED_VARS (expr), t);
-    }
+  /* Do not stream BLOCK_NONLOCALIZED_VARS.  We cannot handle debug information
+     for early inlining so drop it on the floor instead of ICEing in
+     dwarf2out.c.  */
 
   BLOCK_SUPERCONTEXT (expr) = lto_input_tree (ib, data_in);
-  BLOCK_ABSTRACT_ORIGIN (expr) = lto_input_tree (ib, data_in);
+  /* Do not stream BLOCK_ABSTRACT_ORIGIN.  We cannot handle debug information
+     for early inlining so drop it on the floor instead of ICEing in
+     dwarf2out.c.  */
   BLOCK_FRAGMENT_ORIGIN (expr) = lto_input_tree (ib, data_in);
   BLOCK_FRAGMENT_CHAIN (expr) = lto_input_tree (ib, data_in);
-  BLOCK_SUBBLOCKS (expr) = lto_input_chain (ib, data_in);
+  /* We re-compute BLOCK_SUBBLOCKS of our parent here instead
+     of streaming it.  For non-BLOCK BLOCK_SUPERCONTEXTs we still
+     stream the child relationship explicitly.  */
+  if (BLOCK_SUPERCONTEXT (expr)
+      && TREE_CODE (BLOCK_SUPERCONTEXT (expr)) == BLOCK)
+    {
+      BLOCK_CHAIN (expr) = BLOCK_SUBBLOCKS (BLOCK_SUPERCONTEXT (expr));
+      BLOCK_SUBBLOCKS (BLOCK_SUPERCONTEXT (expr)) = expr;
+    }
+  /* The global block is rooted at the TU decl.  Hook it here to
+     avoid the need to stream in this block during WPA time.  */
+  else if (BLOCK_SUPERCONTEXT (expr)
+          && TREE_CODE (BLOCK_SUPERCONTEXT (expr)) == TRANSLATION_UNIT_DECL)
+    DECL_INITIAL (BLOCK_SUPERCONTEXT (expr)) = expr;
+  /* The function-level block is connected at the time we read in
+     function bodies for the same reason.  */
 }
 
 
@@ -2256,10 +2271,14 @@ lto_input_ts_binfo_tree_pointers (struct lto_input_block *ib,
   BINFO_VPTR_FIELD (expr) = lto_input_tree (ib, data_in);
 
   len = lto_input_uleb128 (ib);
-  for (i = 0; i < len; i++)
+  if (len > 0)
     {
-      tree a = lto_input_tree (ib, data_in);
-      VEC_safe_push (tree, gc, BINFO_BASE_ACCESSES (expr), a);
+      VEC_reserve_exact (tree, gc, BINFO_BASE_ACCESSES (expr), len);
+      for (i = 0; i < len; i++)
+       {
+         tree a = lto_input_tree (ib, data_in);
+         VEC_quick_push (tree, BINFO_BASE_ACCESSES (expr), a);
+       }
     }
 
   BINFO_INHERITANCE_CHAIN (expr) = lto_input_tree (ib, data_in);
@@ -2290,6 +2309,34 @@ lto_input_ts_constructor_tree_pointers (struct lto_input_block *ib,
 }
 
 
+/* Input a TS_TARGET_OPTION tree from IB into EXPR.  */
+
+static void
+lto_input_ts_target_option (struct lto_input_block *ib, tree expr)
+{
+  unsigned i, len;
+  struct bitpack_d bp;
+  struct cl_target_option *t = TREE_TARGET_OPTION (expr);
+
+  bp = lto_input_bitpack (ib);
+  len = sizeof (struct cl_target_option);
+  for (i = 0; i < len; i++)
+    ((unsigned char *)t)[i] = bp_unpack_value (&bp, 8);
+  if (bp_unpack_value (&bp, 32) != 0x12345678)
+    fatal_error ("cl_target_option size mismatch in LTO reader and writer");
+}
+
+/* Input a TS_TRANSLATION_UNIT_DECL tree from IB and DATA_IN into EXPR.  */
+
+static void
+lto_input_ts_translation_unit_decl_tree_pointers (struct lto_input_block *ib,
+                                                 struct data_in *data_in,
+                                                 tree expr)
+{
+  TRANSLATION_UNIT_LANGUAGE (expr) = xstrdup (lto_input_string (data_in, ib));
+  VEC_safe_push (tree, gc, all_translation_units, expr);
+}
+
 /* Helper for lto_input_tree.  Read all pointer fields in EXPR from
    input block IB.  DATA_IN contains tables and descriptors for the
    file being read.  */
@@ -2302,7 +2349,7 @@ lto_input_tree_pointers (struct lto_input_block *ib, struct data_in *data_in,
 
   code = TREE_CODE (expr);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
+  if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
     lto_input_ts_common_tree_pointers (ib, data_in, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
@@ -2329,8 +2376,11 @@ lto_input_tree_pointers (struct lto_input_block *ib, struct data_in *data_in,
   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
     lto_input_ts_function_decl_tree_pointers (ib, data_in, expr);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_TYPE))
-    lto_input_ts_type_tree_pointers (ib, data_in, expr);
+  if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
+    lto_input_ts_type_common_tree_pointers (ib, data_in, expr);
+
+  if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
+    lto_input_ts_type_non_common_tree_pointers (ib, data_in, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_LIST))
     lto_input_ts_list_tree_pointers (ib, data_in, expr);
@@ -2341,152 +2391,20 @@ lto_input_tree_pointers (struct lto_input_block *ib, struct data_in *data_in,
   if (CODE_CONTAINS_STRUCT (code, TS_EXP))
     lto_input_ts_exp_tree_pointers (ib, data_in, expr);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_SSA_NAME))
-    {
-      /* We only stream the version number of SSA names.  */
-      gcc_unreachable ();
-    }
-
   if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
     lto_input_ts_block_tree_pointers (ib, data_in, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
     lto_input_ts_binfo_tree_pointers (ib, data_in, expr);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_STATEMENT_LIST))
-    {
-      /* This should only appear in GENERIC.  */
-      gcc_unreachable ();
-    }
-
   if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
     lto_input_ts_constructor_tree_pointers (ib, data_in, expr);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_OMP_CLAUSE))
-    {
-      /* This should only appear in High GIMPLE.  */
-      gcc_unreachable ();
-    }
-
-  if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION))
-    {
-      sorry ("optimization options not supported yet");
-    }
-
   if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION))
-    {
-      sorry ("target optimization options not supported yet");
-    }
-}
+    lto_input_ts_target_option (ib, expr);
 
-
-/* Register DECL with the global symbol table and change its
-   name if necessary to avoid name clashes for static globals across
-   different files.  */
-
-static void
-lto_register_var_decl_in_symtab (struct data_in *data_in, tree decl)
-{
-  /* Register symbols with file or global scope to mark what input
-     file has their definition.  */
-  if (decl_function_context (decl) == NULL_TREE)
-    {
-      /* Variable has file scope, not local. Need to ensure static variables
-        between different files don't clash unexpectedly.  */
-      if (!TREE_PUBLIC (decl))
-        {
-         /* ??? 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;
-      
-         ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
-         SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label));
-          rest_of_decl_compilation (decl, 1, 0);
-        }
-    }
-
-  /* If this variable has already been declared, queue the
-     declaration for merging.  */
-  if (TREE_PUBLIC (decl))
-    {
-      int ix;
-      if (!lto_streamer_cache_lookup (data_in->reader_cache, decl, &ix))
-       gcc_unreachable ();
-      lto_symtab_register_decl (decl, get_resolution (data_in, ix),
-                               data_in->file_data);
-    }
-}
-
-
-
-/* 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 contains descriptors and tables for the
-   file being read.  */
-
-static void
-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.  */
-  if (!TREE_PUBLIC (decl))
-    {
-      /* We must not use the DECL_ASSEMBLER_NAME macro here, as it
-        may set the assembler name where it was previously empty.  */
-      tree old_assembler_name = decl->decl_with_vis.assembler_name;
-
-      /* 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.  */
-      const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-      char *label;
-      
-      ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
-      SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label));
-
-      /* We may arrive here with the old assembler name not set
-        if the function body is not needed, e.g., it has been
-        inlined away and does not appear in the cgraph.  */
-      if (old_assembler_name)
-       {
-         tree new_assembler_name = DECL_ASSEMBLER_NAME (decl);
-
-         /* Make the original assembler name available for later use.
-            We may have used it to indicate the section within its
-            object file where the function body may be found.
-            FIXME lto: Find a better way to maintain the function decl
-            to body section mapping so we don't need this hack.  */
-         lto_record_renamed_decl (data_in->file_data,
-                                  IDENTIFIER_POINTER (old_assembler_name),
-                                  IDENTIFIER_POINTER (new_assembler_name));
-
-         /* Also register the reverse mapping so that we can find the
-            new name given to an existing assembler name (used when
-            restoring alias pairs in input_constructors_or_inits.  */ 
-         lto_record_renamed_decl (data_in->file_data,
-                                  IDENTIFIER_POINTER (new_assembler_name),
-                                  IDENTIFIER_POINTER (old_assembler_name));
-       }                                  
-    }
-
-  /* If this variable has already been declared, queue the
-     declaration for merging.  */
-  if (TREE_PUBLIC (decl) && !DECL_ABSTRACT (decl))
-    {
-      int ix;
-      if (!lto_streamer_cache_lookup (data_in->reader_cache, decl, &ix))
-       gcc_unreachable ();
-      lto_symtab_register_decl (decl, get_resolution (data_in, ix),
-                               data_in->file_data);
-    }
+  if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
+    lto_input_ts_translation_unit_decl_tree_pointers (ib, data_in, expr);
 }
 
 
@@ -2496,35 +2414,14 @@ lto_register_function_decl_in_symtab (struct data_in *data_in, tree decl)
 static tree
 lto_get_pickled_tree (struct lto_input_block *ib, struct data_in *data_in)
 {
-  HOST_WIDE_INT ix;
+  unsigned HOST_WIDE_INT ix;
   tree result;
   enum LTO_tags expected_tag;
-  unsigned HOST_WIDE_INT orig_offset;
-
-  ix = lto_input_sleb128 (ib);
-  expected_tag = (enum LTO_tags) lto_input_uleb128 (ib);
 
-  orig_offset = lto_input_uleb128 (ib);
-  gcc_assert (orig_offset == (unsigned) orig_offset);
+  ix = lto_input_uleb128 (ib);
+  expected_tag = lto_input_enum (ib, LTO_tags, LTO_NUM_TAGS);
 
   result = lto_streamer_cache_get (data_in->reader_cache, ix);
-  if (result == NULL_TREE)
-    {
-      /* We have not yet read the cache slot IX.  Go to the offset
-        in the stream where the physical tree node is, and materialize
-        it from there.  */
-      struct lto_input_block fwd_ib;
-
-      /* If we are trying to go back in the stream, something is wrong.
-        We should've read the node at the earlier position already.  */
-      if (ib->p >= orig_offset)
-       internal_error ("bytecode stream: tried to jump backwards in the "
-                       "stream");
-
-      LTO_INIT_INPUT_BLOCK (fwd_ib, ib->data, orig_offset, ib->len);
-      result = lto_input_tree (&fwd_ib, data_in);
-    }
-
   gcc_assert (result
               && TREE_CODE (result) == lto_tag_to_tree_code (expected_tag));
 
@@ -2542,19 +2439,16 @@ lto_get_builtin_tree (struct lto_input_block *ib, struct data_in *data_in)
   enum built_in_function fcode;
   const char *asmname;
   tree result;
-  int ix;
 
-  fclass = (enum built_in_class) lto_input_uleb128 (ib);
+  fclass = lto_input_enum (ib, built_in_class, BUILT_IN_LAST);
   gcc_assert (fclass == BUILT_IN_NORMAL || fclass == BUILT_IN_MD);
 
   fcode = (enum built_in_function) lto_input_uleb128 (ib);
 
-  ix = lto_input_sleb128 (ib);
-  gcc_assert (ix == (int) ix);
-
   if (fclass == BUILT_IN_NORMAL)
     {
-      gcc_assert (fcode < END_BUILTINS);
+      if (fcode >= END_BUILTINS)
+       fatal_error ("machine independent builtin code out of range");
       result = built_in_decls[fcode];
       gcc_assert (result);
     }
@@ -2564,12 +2458,14 @@ lto_get_builtin_tree (struct lto_input_block *ib, struct data_in *data_in)
       if (!result || result == error_mark_node)
        fatal_error ("target specific builtin not available");
     }
+  else
+    gcc_unreachable ();
 
-  asmname = input_string (data_in, ib);
+  asmname = lto_input_string (data_in, ib);
   if (asmname)
     set_builtin_user_assembler_name (result, asmname);
 
-  lto_streamer_cache_insert_at (data_in->reader_cache, result, ix);
+  lto_streamer_cache_append (data_in->reader_cache, result);
 
   return result;
 }
@@ -2583,24 +2479,22 @@ lto_read_tree (struct lto_input_block *ib, struct data_in *data_in,
               enum LTO_tags tag)
 {
   tree result;
-  char end_marker;
-  int ix;
 
-  result = lto_materialize_tree (ib, data_in, tag, &ix);
+  result = lto_materialize_tree (ib, data_in, tag);
 
   /* Read all the pointer fields in RESULT.  */
   lto_input_tree_pointers (ib, data_in, result);
 
+  /* Call back into the streaming module to read anything else it
+     may need.  */
+  if (streamer_hooks.read_tree)
+    streamer_hooks.read_tree (ib, data_in, result);
+
   /* We should never try to instantiate an MD or NORMAL builtin here.  */
   if (TREE_CODE (result) == FUNCTION_DECL)
     gcc_assert (!lto_stream_as_builtin_p (result));
 
-  if (TREE_CODE (result) == VAR_DECL)
-    lto_register_var_decl_in_symtab (data_in, 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);
+  /* end_marker = */ lto_input_1_unsigned (ib);
 
 #ifdef LTO_STREAMER_DEBUG
   /* Remove the mapping to RESULT's original address set by
@@ -2612,6 +2506,21 @@ lto_read_tree (struct lto_input_block *ib, struct data_in *data_in,
 }
 
 
+/* LTO streamer hook for reading GIMPLE trees.  IB and DATA_IN are as in
+   lto_read_tree.  EXPR is the tree was materialized by lto_read_tree and
+   needs GIMPLE specific data to be filled in.  */
+
+void
+lto_streamer_read_tree (struct lto_input_block *ib, struct data_in *data_in,
+                       tree expr)
+{
+  if (DECL_P (expr)
+      && TREE_CODE (expr) != FUNCTION_DECL
+      && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
+    DECL_INITIAL (expr) = lto_input_tree (ib, data_in);
+}
+
+
 /* Read and INTEGER_CST node from input block IB using the per-file
    context in DATA_IN.  */
 
@@ -2649,7 +2558,7 @@ lto_input_tree (struct lto_input_block *ib, struct data_in *data_in)
 {
   enum LTO_tags tag;
   tree result;
-  
+
   tag = input_record_start (ib);
   gcc_assert ((unsigned) tag < (unsigned) LTO_NUM_TAGS);
 
@@ -2693,17 +2602,11 @@ lto_input_tree (struct lto_input_block *ib, struct data_in *data_in)
 /* Initialization for the LTO reader.  */
 
 void
-lto_init_reader (void)
+lto_reader_init (void)
 {
   lto_streamer_init ();
-
-  memset (&lto_stats, 0, sizeof (lto_stats));
-  bitmap_obstack_initialize (NULL);
-
   file_name_hash_table = htab_create (37, hash_string_slot_node,
                                      eq_string_slot_node, free);
-
-  gimple_register_cfg_hooks ();
 }