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]

[PATCH][LTO] Streamer re-org (what's left)


The following are the non-cleanup parts.  The patch moves us
to compress streams (what data-streamer thinks of "streams")
instead of whole sections.  This enables us to only need
a single compressed and uncompressed block of data "live"
as opposed to a whole section (well, in theory - we still
do mmap based I/O).  The disadvantage is that you really
have to go through the data-streamer interface to access
data at read-in.

As is the patch doesn't improve virtual memory usage a lot
(according to Martins tests) but it increases compile-time
(we now compress LTRANs streams - reducing their size to 1/3).

What the patch still misses is to re-do the string part
of the decl streams to make them compressed again.  It also
misses ripping out the section-compression code entirely
(lto-compress.c).

Oh, and it misses a ChangeLog.

Now the question is whether we want this or not.  It's certainly
not perfect in it's current state.

But I wouldn't want to tie the merge-SCCs-from-disk stuff to
the data-streamer internals too much (even if it seems tempting
and easy in it's current form).

Any comments appreciated.

Thanks,
Richard.


Index: gcc/data-streamer-out.c
===================================================================
*** gcc/data-streamer-out.c.orig	2014-07-31 10:49:00.079737742 +0200
--- gcc/data-streamer-out.c	2014-07-31 12:08:48.364408075 +0200
*************** along with GCC; see the file COPYING3.
*** 22,27 ****
--- 22,32 ----
  
  #include "config.h"
  #include "system.h"
+ /* zlib.h includes other system headers.  Those headers may test feature
+    test macros.  config.h may define feature test macros.  For this reason,
+    zlib.h needs to be included after, rather than before, config.h and
+    system.h.  */
+ #include <zlib.h>
  #include "coretypes.h"
  #include "tree.h"
  #include "basic-block.h"
*************** along with GCC; see the file COPYING3.
*** 33,79 ****
  #include "data-streamer.h"
  
  
  /* Adds a new block to output stream OBS.  */
  
  void
! lto_append_block (struct lto_output_stream *obs)
  {
    struct lto_char_ptr_base *new_block;
  
!   gcc_assert (obs->left_in_block == 0);
  
!   if (obs->first_block == NULL)
      {
!       /* This is the first time the stream has been written
! 	 into.  */
!       obs->block_size = 1024;
!       new_block = (struct lto_char_ptr_base*) xmalloc (obs->block_size);
!       obs->first_block = new_block;
      }
    else
      {
!       struct lto_char_ptr_base *tptr;
!       /* Get a new block that is twice as big as the last block
! 	 and link it into the list.  */
!       obs->block_size *= 2;
!       new_block = (struct lto_char_ptr_base*) xmalloc (obs->block_size);
!       /* The first bytes of the block are reserved as a pointer to
! 	 the next block.  Set the chain of the full block to the
! 	 pointer to the new block.  */
!       tptr = obs->current_block;
!       tptr->ptr = (char *) new_block;
      }
  
    /* Set the place for the next char at the first position after the
       chain to the next block.  */
!   obs->current_pointer
      = ((char *) new_block) + sizeof (struct lto_char_ptr_base);
!   obs->current_block = new_block;
    /* Null out the newly allocated block's pointer to the next block.  */
    new_block->ptr = NULL;
!   obs->left_in_block = obs->block_size - sizeof (struct lto_char_ptr_base);
  }
  
  
  /* Return index used to reference STRING of LEN characters in the string table
     in OB.  The string might or might not include a trailing '\0'.
--- 38,193 ----
  #include "data-streamer.h"
  
  
+ /* Finishes the last block, eventually compressing it, and returns the
+    total size of the stream.  */
+ 
+ unsigned int
+ lto_output_stream::finish ()
+ {
+   if (compress
+       && current_pointer)
+     {
+       /* Compress the last (partial) block.  */
+       compress_current_block (true);
+       left_in_block = zlib_stream->avail_out;
+       free (current_block);
+       current_block = NULL;
+       int status = deflateEnd (zlib_stream);
+       if (status != Z_OK)
+ 	internal_error ("compressed stream: %s", zError (status));
+       free (zlib_stream);
+     }
+   current_pointer = NULL;
+ 
+   unsigned int size = 0;
+   for (lto_char_ptr_base *b = first_block; b; b = (lto_char_ptr_base *)b->ptr)
+     size += block_size - sizeof (lto_char_ptr_base);
+   size -= left_in_block;
+   return size;
+ }
+ 
+ /* Returns a pointer to the first block of the chain of blocks to output.  */
+ 
+ lto_char_ptr_base *
+ lto_output_stream::get_blocks ()
+ {
+   finish ();
+   return first_block;
+ }
+ 
  /* Adds a new block to output stream OBS.  */
  
  void
! lto_output_stream::append_block ()
  {
    struct lto_char_ptr_base *new_block;
  
!   gcc_assert (left_in_block == 0 && block_size > sizeof (lto_char_ptr_base));
  
!   if (first_block == NULL)
      {
!       /* This is the first time the stream has been written into.  */
!       new_block = (struct lto_char_ptr_base*) xmalloc (block_size);
!       first_block = new_block;
      }
    else
      {
!       if (compress)
! 	{
! 	  /* Compress the current block and link it into the list.  */
! 	  compress_current_block (false);
! 	  /* Re-use the uncompressed buffer.  */
! 	  new_block = current_block;
! 	}
!       else
! 	{
! 	  /* Get a new block and link it into the list.  */
! 	  new_block = (struct lto_char_ptr_base*) xmalloc (block_size);
! 	  /* The first bytes of the block are reserved as a pointer to
! 	     the next block.  Set the chain of the full block to the
! 	     pointer to the new block.  */
! 	  lto_char_ptr_base *tptr = current_block;
! 	  tptr->ptr = (char *) new_block;
! 	}
      }
  
    /* Set the place for the next char at the first position after the
       chain to the next block.  */
!   current_pointer
      = ((char *) new_block) + sizeof (struct lto_char_ptr_base);
!   current_block = new_block;
    /* Null out the newly allocated block's pointer to the next block.  */
    new_block->ptr = NULL;
!   left_in_block = block_size - sizeof (struct lto_char_ptr_base);
! }
! 
! /* Return a zlib compression level that zlib will not reject.  Normalizes
!    the compression level from the command line flag, clamping non-default
!    values to the appropriate end of their valid range.  */
! 
! static int
! lto_normalized_zlib_level (void)
! {
!   int level = flag_lto_compression_level;
! 
!   if (level != Z_DEFAULT_COMPRESSION)
!     {
!       if (level < Z_NO_COMPRESSION)
! 	level = Z_NO_COMPRESSION;
!       else if (level > Z_BEST_COMPRESSION)
! 	level = Z_BEST_COMPRESSION;
!     }
! 
!   return level;
  }
  
+ void
+ lto_output_stream::compress_current_block (bool last)
+ {
+   int status;
+ 
+   /* If this is the first block we compress, initialize compression.  */
+   if (first_block == current_block)
+     {
+       zlib_stream = XCNEW (z_stream);
+       zlib_stream->zalloc = NULL;
+       zlib_stream->zfree = NULL;
+       zlib_stream->opaque = NULL;
+       status = deflateInit (zlib_stream, lto_normalized_zlib_level ());
+       if (status != Z_OK)
+ 	internal_error ("compressed stream: %s", zError (status));
+ 
+       current_z_block = first_block
+ 	= (lto_char_ptr_base *) xmalloc (block_size);
+       first_block->ptr = NULL;
+       zlib_stream->next_out = (unsigned char *)first_block + sizeof (lto_char_ptr_base);
+       zlib_stream->avail_out = block_size - sizeof (lto_char_ptr_base);
+     }
+ 
+   zlib_stream->next_in = (unsigned char *)current_block + sizeof (lto_char_ptr_base);
+   zlib_stream->avail_in
+     = block_size - sizeof (lto_char_ptr_base) - left_in_block;
+   do
+     {
+       status = deflate (zlib_stream, last ? Z_FINISH : Z_NO_FLUSH);
+       if (status != Z_OK && status != Z_STREAM_END && status != Z_BUF_ERROR)
+ 	internal_error ("compressed stream: %s", zError (status));
+ 
+       if (status == Z_OK
+ 	  && zlib_stream->avail_out == 0)
+ 	{
+ 	  lto_char_ptr_base *new_block
+ 	      = (lto_char_ptr_base *) xmalloc (block_size);
+ 	  current_z_block->ptr = (char *)new_block;
+ 	  current_z_block = new_block;
+ 	  current_z_block->ptr = NULL;
+ 	  zlib_stream->next_out = (unsigned char *)new_block + sizeof (lto_char_ptr_base);
+ 	  zlib_stream->avail_out = block_size - sizeof (lto_char_ptr_base);
+ 	}
+     }
+   while (zlib_stream->avail_in > 0);
+   gcc_assert (zlib_stream->avail_in == 0);
+ }
  
  /* Return index used to reference STRING of LEN characters in the string table
     in OB.  The string might or might not include a trailing '\0'.
*************** streamer_write_uhwi_stream (struct lto_o
*** 238,244 ****
                              unsigned HOST_WIDE_INT work)
  {
    if (obs->left_in_block == 0)
!     lto_append_block (obs);
    char *current_pointer = obs->current_pointer;
    unsigned int left_in_block = obs->left_in_block;
    unsigned int size = 0;
--- 352,358 ----
                              unsigned HOST_WIDE_INT work)
  {
    if (obs->left_in_block == 0)
!     obs->append_block ();
    char *current_pointer = obs->current_pointer;
    unsigned int left_in_block = obs->left_in_block;
    unsigned int size = 0;
*************** streamer_write_uhwi_stream (struct lto_o
*** 258,264 ****
    if (work != 0)
      {
        obs->left_in_block = 0;
!       lto_append_block (obs);
        current_pointer = obs->current_pointer;
        left_in_block = obs->left_in_block;
        do
--- 372,378 ----
    if (work != 0)
      {
        obs->left_in_block = 0;
!       obs->append_block ();
        current_pointer = obs->current_pointer;
        left_in_block = obs->left_in_block;
        do
*************** void
*** 287,293 ****
  streamer_write_hwi_stream (struct lto_output_stream *obs, HOST_WIDE_INT work)
  {
    if (obs->left_in_block == 0)
!     lto_append_block (obs);
    char *current_pointer = obs->current_pointer;
    unsigned int left_in_block = obs->left_in_block;
    unsigned int size = 0;
--- 401,407 ----
  streamer_write_hwi_stream (struct lto_output_stream *obs, HOST_WIDE_INT work)
  {
    if (obs->left_in_block == 0)
!     obs->append_block ();
    char *current_pointer = obs->current_pointer;
    unsigned int left_in_block = obs->left_in_block;
    unsigned int size = 0;
*************** streamer_write_hwi_stream (struct lto_ou
*** 313,319 ****
    if (more)
      {
        obs->left_in_block = 0;
!       lto_append_block (obs);
        current_pointer = obs->current_pointer;
        left_in_block = obs->left_in_block;
        do
--- 427,433 ----
    if (more)
      {
        obs->left_in_block = 0;
!       obs->append_block ();
        current_pointer = obs->current_pointer;
        left_in_block = obs->left_in_block;
        do
*************** streamer_write_data_stream (struct lto_o
*** 360,366 ****
  
        /* No space left.  */
        if (obs->left_in_block == 0)
! 	lto_append_block (obs);
  
        /* Determine how many bytes to copy in this loop.  */
        if (len <= obs->left_in_block)
--- 474,480 ----
  
        /* No space left.  */
        if (obs->left_in_block == 0)
! 	obs->append_block ();
  
        /* Determine how many bytes to copy in this loop.  */
        if (len <= obs->left_in_block)
Index: gcc/lto-section-out.c
===================================================================
*** gcc/lto-section-out.c.orig	2014-07-31 10:49:00.079737742 +0200
--- gcc/lto-section-out.c	2014-07-31 12:08:48.364408075 +0200
*************** lto_begin_section (const char *name, boo
*** 80,86 ****
       data is anything other than assembler output.  The effect here is that
       we get compression of IL only in non-ltrans object files.  */
    gcc_assert (compression_stream == NULL);
!   if (compress)
      compression_stream = lto_start_compression (lto_append_data, NULL);
  }
  
--- 80,86 ----
       data is anything other than assembler output.  The effect here is that
       we get compression of IL only in non-ltrans object files.  */
    gcc_assert (compression_stream == NULL);
!   if (compress && 0)
      compression_stream = lto_start_compression (lto_append_data, NULL);
  }
  
*************** lto_write_data (const void *data, unsign
*** 115,130 ****
  void
  lto_write_stream (struct lto_output_stream *obs)
  {
-   unsigned int block_size = 1024;
    struct lto_char_ptr_base *block;
    struct lto_char_ptr_base *next_block;
-   if (!obs->first_block)
-     return;
  
!   for (block = obs->first_block; block; block = next_block)
      {
        const char *base = ((char *)block) + sizeof (struct lto_char_ptr_base);
!       unsigned int num_chars = block_size - sizeof (struct lto_char_ptr_base);
  
        /* If this is not the last block, it is full.  If it is the last
  	 block, left_in_block indicates how many chars are unoccupied in
--- 115,127 ----
  void
  lto_write_stream (struct lto_output_stream *obs)
  {
    struct lto_char_ptr_base *block;
    struct lto_char_ptr_base *next_block;
  
!   for (block = obs->get_blocks (); block; block = next_block)
      {
        const char *base = ((char *)block) + sizeof (struct lto_char_ptr_base);
!       size_t num_chars = obs->block_size - sizeof (struct lto_char_ptr_base);
  
        /* If this is not the last block, it is full.  If it is the last
  	 block, left_in_block indicates how many chars are unoccupied in
*************** lto_write_stream (struct lto_output_stre
*** 142,148 ****
        else
  	lang_hooks.lto.append_data (base, num_chars, block);
        free (block);
-       block_size *= 2;
      }
  }
  
--- 139,144 ----
*************** lto_create_simple_output_block (enum lto
*** 256,263 ****
  
    ob->section_type = section_type;
    ob->decl_state = lto_get_out_decl_state ();
!   ob->main_stream = ((struct lto_output_stream *)
! 		     xcalloc (1, sizeof (struct lto_output_stream)));
  
    return ob;
  }
--- 252,258 ----
  
    ob->section_type = section_type;
    ob->decl_state = lto_get_out_decl_state ();
!   ob->main_stream = new lto_output_stream;
  
    return ob;
  }
*************** lto_destroy_simple_output_block (struct
*** 281,287 ****
    header.lto_header.major_version = LTO_major_version;
    header.lto_header.minor_version = LTO_minor_version;
    header.compressed_size = 0;
!   header.main_size = ob->main_stream->total_size;
    lto_write_data (&header, sizeof header);
  
    lto_write_stream (ob->main_stream);
--- 276,282 ----
    header.lto_header.major_version = LTO_major_version;
    header.lto_header.minor_version = LTO_minor_version;
    header.compressed_size = 0;
!   header.main_size = ob->main_stream->finish ();
    lto_write_data (&header, sizeof header);
  
    lto_write_stream (ob->main_stream);
*************** lto_destroy_simple_output_block (struct
*** 290,296 ****
       writing lto info.  */
    lto_end_section ();
  
!   free (ob->main_stream);
    free (ob);
  }
  
--- 285,291 ----
       writing lto info.  */
    lto_end_section ();
  
!   delete ob->main_stream;
    free (ob);
  }
  
Index: gcc/data-streamer.h
===================================================================
*** gcc/data-streamer.h.orig	2014-07-31 10:49:00.079737742 +0200
--- gcc/data-streamer.h	2014-07-31 12:08:48.386408073 +0200
*************** streamer_write_char_stream (struct lto_o
*** 182,188 ****
  {
    /* No space left.  */
    if (obs->left_in_block == 0)
!     lto_append_block (obs);
  
    /* Write the actual character.  */
    char *current_pointer = obs->current_pointer;
--- 182,188 ----
  {
    /* No space left.  */
    if (obs->left_in_block == 0)
!     obs->append_block ();
  
    /* Write the actual character.  */
    char *current_pointer = obs->current_pointer;
*************** streamer_write_char_stream (struct lto_o
*** 198,206 ****
  static inline unsigned char
  streamer_read_uchar (struct lto_input_block *ib)
  {
!   if (ib->p >= ib->len)
!     lto_section_overrun (ib);
!   return (ib->data[ib->p++]);
  }
  
  /* Output VAL into OBS and verify it is in range MIN...MAX that is supposed
--- 198,210 ----
  static inline unsigned char
  streamer_read_uchar (struct lto_input_block *ib)
  {
!   /* No data left.  */
!   if (ib->left_in_block == 0)
!     ib->append_block ();
! 
!   /* Read a character.  */
!   ib->left_in_block--;
!   return *(ib->current_pointer++);
  }
  
  /* Output VAL into OBS and verify it is in range MIN...MAX that is supposed
Index: gcc/lto-opts.c
===================================================================
*** gcc/lto-opts.c.orig	2014-07-31 10:49:00.079737742 +0200
--- gcc/lto-opts.c	2014-07-31 12:08:48.386408073 +0200
*************** along with GCC; see the file COPYING3.
*** 37,42 ****
--- 37,43 ----
  #include "common/common-target.h"
  #include "diagnostic.h"
  #include "lto-streamer.h"
+ #include "data-streamer.h"
  #include "toplev.h"
  
  /* Append the option piece OPT to the COLLECT_GCC_OPTIONS string
Index: gcc/lto-streamer-out.c
===================================================================
*** gcc/lto-streamer-out.c.orig	2014-07-31 11:18:45.208614838 +0200
--- gcc/lto-streamer-out.c	2014-07-31 12:08:48.388408073 +0200
*************** create_output_block (enum lto_section_ty
*** 79,90 ****
  
    ob->section_type = section_type;
    ob->decl_state = lto_get_out_decl_state ();
!   ob->main_stream = XCNEW (struct lto_output_stream);
!   ob->string_stream = XCNEW (struct lto_output_stream);
    ob->writer_cache = streamer_tree_cache_create (!flag_wpa, true, false);
  
    if (section_type == LTO_section_function_body)
!     ob->cfg_stream = XCNEW (struct lto_output_stream);
  
    clear_line_info (ob);
  
--- 79,92 ----
  
    ob->section_type = section_type;
    ob->decl_state = lto_get_out_decl_state ();
!   ob->main_stream = new lto_output_stream;
!   // The way we use this stream prevents its compression as we basically
!   // perform random access
!   ob->string_stream = new lto_output_stream (2 * 1024 * 1024, false);
    ob->writer_cache = streamer_tree_cache_create (!flag_wpa, true, false);
  
    if (section_type == LTO_section_function_body)
!     ob->cfg_stream = new lto_output_stream;
  
    clear_line_info (ob);
  
*************** destroy_output_block (struct output_bloc
*** 105,114 ****
    delete ob->string_hash_table;
    ob->string_hash_table = NULL;
  
!   free (ob->main_stream);
!   free (ob->string_stream);
    if (section_type == LTO_section_function_body)
!     free (ob->cfg_stream);
  
    streamer_tree_cache_delete (ob->writer_cache);
    obstack_free (&ob->obstack, NULL);
--- 107,116 ----
    delete ob->string_hash_table;
    ob->string_hash_table = NULL;
  
!   delete ob->main_stream;
!   delete ob->string_stream;
    if (section_type == LTO_section_function_body)
!     delete ob->cfg_stream;
  
    streamer_tree_cache_delete (ob->writer_cache);
    obstack_free (&ob->obstack, NULL);
*************** produce_asm (struct output_block *ob, tr
*** 1894,1902 ****
    header.compressed_size = 0;
  
    if (section_type == LTO_section_function_body)
!     header.cfg_size = ob->cfg_stream->total_size;
!   header.main_size = ob->main_stream->total_size;
!   header.string_size = ob->string_stream->total_size;
    lto_write_data (&header, sizeof header);
  
    /* Put all of the gimple and the string table out the asm file as a
--- 1896,1904 ----
    header.compressed_size = 0;
  
    if (section_type == LTO_section_function_body)
!     header.cfg_size = ob->cfg_stream->finish ();
!   header.main_size = ob->main_stream->finish ();
!   header.string_size = ob->string_stream->finish ();
    lto_write_data (&header, sizeof header);
  
    /* Put all of the gimple and the string table out the asm file as a
*************** lto_output_toplevel_asms (void)
*** 2128,2135 ****
    header.lto_header.major_version = LTO_major_version;
    header.lto_header.minor_version = LTO_minor_version;
  
!   header.main_size = ob->main_stream->total_size;
!   header.string_size = ob->string_stream->total_size;
    lto_write_data (&header, sizeof header);
  
    /* Put all of the gimple and the string table out the asm file as a
--- 2130,2137 ----
    header.lto_header.major_version = LTO_major_version;
    header.lto_header.minor_version = LTO_minor_version;
  
!   header.main_size = ob->main_stream->finish ();
!   header.string_size = ob->string_stream->finish ();
    lto_write_data (&header, sizeof header);
  
    /* Put all of the gimple and the string table out the asm file as a
*************** produce_asm_for_decls (void)
*** 2681,2688 ****
      }
    header.decl_state_size = decl_state_size;
  
!   header.main_size = ob->main_stream->total_size;
!   header.string_size = ob->string_stream->total_size;
  
    lto_write_data (&header, sizeof header);
  
--- 2683,2690 ----
      }
    header.decl_state_size = decl_state_size;
  
!   header.main_size = ob->main_stream->finish ();
!   header.string_size = ob->string_stream->finish ();
  
    lto_write_data (&header, sizeof header);
  
Index: gcc/lto-streamer.h
===================================================================
*** gcc/lto-streamer.h.orig	2014-07-31 11:18:03.998617676 +0200
--- gcc/lto-streamer.h	2014-07-31 12:08:48.389408073 +0200
*************** typedef void (lto_free_section_data_f) (
*** 308,333 ****
  					size_t);
  
  /* Structure used as buffer for reading an LTO file.  */
! struct lto_input_block
  {
    const char *data;
    unsigned int p;
    unsigned int len;
  };
  
! #define LTO_INIT_INPUT_BLOCK(BASE,D,P,L)   \
!   do {                                     \
!     BASE.data = D;                         \
!     BASE.p = P;                            \
!     BASE.len = L;                          \
!   } while (0)
! 
! #define LTO_INIT_INPUT_BLOCK_PTR(BASE,D,P,L) \
!   do {                                       \
!     BASE->data = D;                          \
!     BASE->p = P;                             \
!     BASE->len = L;                           \
!   } while (0)
  
  
  /* The is the first part of the record for a function or constructor
--- 308,344 ----
  					size_t);
  
  /* Structure used as buffer for reading an LTO file.  */
! class lto_input_block
  {
+ public:
+   /* Special constructor for the string table, it abuses this to
+      do random access but use the uhwi decoder.  */
+   lto_input_block (const char *data_, unsigned int p_, unsigned int len_)
+       : current_pointer (data_ + p_), left_in_block (len_), compress (false),
+         data (NULL), p (0), len (0) {};
+   lto_input_block (const char *data_, unsigned int len_, bool compress_ = true)
+       : current_pointer (NULL), left_in_block (0), compress (compress_),
+         data (data_), p (0), len (len_), zbuf (NULL), zlib_stream (NULL) {};
+   ~lto_input_block ();
+   void append_block ();
+   inline bool eof ();
+   const char *current_pointer;
+   unsigned int left_in_block;
+ 
+ private:
+   const bool compress;
    const char *data;
    unsigned int p;
    unsigned int len;
+   char *zbuf;
+   struct z_stream_s *zlib_stream;
  };
  
! inline bool
! lto_input_block::eof ()
! {
!   return left_in_block == 0 && len == p;
! }
  
  
  /* The is the first part of the record for a function or constructor
*************** struct lto_char_ptr_base
*** 575,584 ****
     The entire structure should be zeroed when created.  The record
     consists of a set of blocks.  The first sizeof (ptr) bytes are used
     as a chain, and the rest store the bytes to be written.  */
! struct lto_output_stream
  {
!   /* The pointer to the first block in the stream.  */
!   struct lto_char_ptr_base * first_block;
  
    /* The pointer to the last and current block in the stream.  */
    struct lto_char_ptr_base * current_block;
--- 586,608 ----
     The entire structure should be zeroed when created.  The record
     consists of a set of blocks.  The first sizeof (ptr) bytes are used
     as a chain, and the rest store the bytes to be written.  */
! class lto_output_stream
  {
! public:
!   lto_output_stream (size_t block_size_ = 2 * 1024 * 1024,
! 		     bool compress_ = true)
!       : current_block (NULL), current_pointer (NULL),
!         left_in_block (0), block_size (block_size_), total_size (0),
!         first_block (NULL), current_z_block (NULL), compress (compress_),
! 	zlib_stream (NULL)
!   {
!     gcc_assert (block_size > sizeof (lto_char_ptr_base));
!   }
! 
!   unsigned int finish();
!   lto_char_ptr_base *get_blocks ();
! 
!   void append_block ();
  
    /* The pointer to the last and current block in the stream.  */
    struct lto_char_ptr_base * current_block;
*************** struct lto_output_stream
*** 589,599 ****
    /* The number of characters left in the current block.  */
    unsigned int left_in_block;
  
!   /* The block size of the last block allocated.  */
!   unsigned int block_size;
  
!   /* The total number of characters written.  */
    unsigned int total_size;
  };
  
  /* The is the first part of the record in an LTO file for many of the
--- 613,636 ----
    /* The number of characters left in the current block.  */
    unsigned int left_in_block;
  
!   /* The block size to use.  */
!   const unsigned int block_size;
  
!   /* The total number of uncompressed characters written.  */
    unsigned int total_size;
+ 
+ private:
+   void compress_current_block (bool);
+ 
+   /* The pointer to the first block in the stream.  */
+   struct lto_char_ptr_base * first_block;
+ 
+   struct lto_char_ptr_base * current_z_block;
+ 
+   /* Whether to compress this stream.  */
+   const bool compress;
+ 
+   struct z_stream_s *zlib_stream;
  };
  
  /* The is the first part of the record in an LTO file for many of the
*************** extern struct lto_in_decl_state *lto_get
*** 756,762 ****
  				      struct lto_file_decl_data *, tree);
  extern void lto_free_function_in_decl_state (struct lto_in_decl_state *);
  extern void lto_free_function_in_decl_state_for_node (symtab_node *);
- extern void lto_section_overrun (struct lto_input_block *) ATTRIBUTE_NORETURN;
  extern void lto_value_range_error (const char *,
  				   HOST_WIDE_INT, HOST_WIDE_INT,
  				   HOST_WIDE_INT) ATTRIBUTE_NORETURN;
--- 793,798 ----
*************** extern void lto_push_out_decl_state (str
*** 791,797 ****
  extern struct lto_out_decl_state *lto_pop_out_decl_state (void);
  extern void lto_record_function_out_decl_state (tree,
  						struct lto_out_decl_state *);
- extern void lto_append_block (struct lto_output_stream *);
  
  
  /* In lto-streamer.c.  */
--- 827,832 ----
Index: gcc/lto-section-in.c
===================================================================
*** gcc/lto-section-in.c.orig	2014-07-31 10:49:00.079737742 +0200
--- gcc/lto-section-in.c	2014-07-31 12:08:48.389408073 +0200
*************** lto_get_section_data (struct lto_file_de
*** 153,159 ****
  
    /* FIXME lto: WPA mode does not write compressed sections, so for now
       suppress uncompression if flag_ltrans.  */
!   if (!flag_ltrans)
      {
        /* Create a mapping header containing the underlying data and length,
  	 and prepend this to the uncompression buffer.  The uncompressed data
--- 153,159 ----
  
    /* FIXME lto: WPA mode does not write compressed sections, so for now
       suppress uncompression if flag_ltrans.  */
!   if (!flag_ltrans && 0)
      {
        /* Create a mapping header containing the underlying data and length,
  	 and prepend this to the uncompression buffer.  The uncompressed data
*************** lto_free_section_data (struct lto_file_d
*** 200,206 ****
  
    /* FIXME lto: WPA mode does not write compressed sections, so for now
       suppress uncompression mapping if flag_ltrans.  */
!   if (flag_ltrans)
      {
        (free_section_f) (file_data, section_type, name, data, len);
        return;
--- 200,206 ----
  
    /* FIXME lto: WPA mode does not write compressed sections, so for now
       suppress uncompression mapping if flag_ltrans.  */
!   if (flag_ltrans || 1)
      {
        (free_section_f) (file_data, section_type, name, data, len);
        return;
*************** lto_create_simple_input_block (struct lt
*** 227,245 ****
    const struct lto_simple_header * header
      = (const struct lto_simple_header *) data;
  
-   struct lto_input_block* ib_main;
    int main_offset = sizeof (struct lto_simple_header);
  
    if (!data)
      return NULL;
  
-   ib_main = XNEW (struct lto_input_block);
- 
    *datar = data;
!   LTO_INIT_INPUT_BLOCK_PTR (ib_main, data + main_offset,
! 			    0, header->main_size);
! 
!   return ib_main;
  }
  
  
--- 227,239 ----
    const struct lto_simple_header * header
      = (const struct lto_simple_header *) data;
  
    int main_offset = sizeof (struct lto_simple_header);
  
    if (!data)
      return NULL;
  
    *datar = data;
!   return new lto_input_block (data + main_offset, header->main_size);
  }
  
  
*************** lto_destroy_simple_input_block (struct l
*** 255,261 ****
  				struct lto_input_block *ib,
  				const char *data, size_t len)
  {
!   free (ib);
    lto_free_section_data (file_data, section_type, NULL, data, len);
  }
  
--- 249,255 ----
  				struct lto_input_block *ib,
  				const char *data, size_t len)
  {
!   delete ib;
    lto_free_section_data (file_data, section_type, NULL, data, len);
  }
  
*************** lto_free_function_in_decl_state_for_node
*** 454,468 ****
  }
  
  
- /* Report read pass end of the section.  */
- 
- void
- lto_section_overrun (struct lto_input_block *ib)
- {
-   fatal_error ("bytecode stream: trying to read %d bytes "
- 	       "after the end of the input buffer", ib->p - ib->len);
- }
- 
  /* Report out of range value.  */
  
  void
--- 448,453 ----
Index: gcc/lto-cgraph.c
===================================================================
*** gcc/lto-cgraph.c.orig	2014-07-31 10:49:00.079737742 +0200
--- gcc/lto-cgraph.c	2014-07-31 12:08:48.390408073 +0200
*************** lto_output_node (struct lto_simple_outpu
*** 488,494 ****
      comdat = IDENTIFIER_POINTER (group);
    else
      comdat = "";
!   streamer_write_data_stream (ob->main_stream, comdat, strlen (comdat) + 1);
  
    if (group)
      {
--- 488,495 ----
      comdat = IDENTIFIER_POINTER (group);
    else
      comdat = "";
!   streamer_write_uhwi_stream (ob->main_stream, strlen (comdat));
!   streamer_write_data_stream (ob->main_stream, comdat, strlen (comdat));
  
    if (group)
      {
*************** lto_output_node (struct lto_simple_outpu
*** 546,552 ****
    bp_pack_enum (&bp, ld_plugin_symbol_resolution,
  	        LDPR_NUM_KNOWN, node->resolution);
    streamer_write_bitpack (&bp);
!   streamer_write_data_stream (ob->main_stream, section, strlen (section) + 1);
  
    if (node->thunk.thunk_p && !boundary_p)
      {
--- 547,554 ----
    bp_pack_enum (&bp, ld_plugin_symbol_resolution,
  	        LDPR_NUM_KNOWN, node->resolution);
    streamer_write_bitpack (&bp);
!   streamer_write_uhwi_stream (ob->main_stream, strlen (section));
!   streamer_write_data_stream (ob->main_stream, section, strlen (section));
  
    if (node->thunk.thunk_p && !boundary_p)
      {
*************** lto_output_varpool_node (struct lto_simp
*** 622,628 ****
      comdat = IDENTIFIER_POINTER (group);
    else
      comdat = "";
!   streamer_write_data_stream (ob->main_stream, comdat, strlen (comdat) + 1);
  
    if (group)
      {
--- 624,631 ----
      comdat = IDENTIFIER_POINTER (group);
    else
      comdat = "";
!   streamer_write_uhwi_stream (ob->main_stream, strlen (comdat));
!   streamer_write_data_stream (ob->main_stream, comdat, strlen (comdat));
  
    if (group)
      {
*************** lto_output_varpool_node (struct lto_simp
*** 640,646 ****
    section = node->get_section ();
    if (!section)
      section = "";
!   streamer_write_data_stream (ob->main_stream, section, strlen (section) + 1);
  
    streamer_write_enum (ob->main_stream, ld_plugin_symbol_resolution,
  		       LDPR_NUM_KNOWN, node->resolution);
--- 643,650 ----
    section = node->get_section ();
    if (!section)
      section = "";
!   streamer_write_uhwi_stream (ob->main_stream, strlen (section));
!   streamer_write_data_stream (ob->main_stream, section, strlen (section));
  
    streamer_write_enum (ob->main_stream, ld_plugin_symbol_resolution,
  		       LDPR_NUM_KNOWN, node->resolution);
*************** output_symtab (void)
*** 994,1012 ****
  static tree
  read_identifier (struct lto_input_block *ib)
  {
!   unsigned int len = strnlen (ib->data + ib->p, ib->len - ib->p - 1);
!   tree id;
! 
!   if (ib->data[ib->p + len])
!     lto_section_overrun (ib);
    if (!len)
!     {
!       ib->p++;
!       return NULL;
!     }
!   id = get_identifier (ib->data + ib->p);
!   ib->p += len + 1;
!   return id;
  }
  
  /* Return string encoded in IB, NULL if string is empty.  */
--- 998,1011 ----
  static tree
  read_identifier (struct lto_input_block *ib)
  {
!   unsigned int len = streamer_read_uhwi (ib);
    if (!len)
!     return NULL;
!   char *str = XALLOCAVEC (char, len + 1);
!   for (unsigned i = 0; i < len; ++i)
!     str[i] = streamer_read_uchar (ib);
!   str[len] = '\0';
!   return get_identifier (str);
  }
  
  /* Return string encoded in IB, NULL if string is empty.  */
*************** read_identifier (struct lto_input_block
*** 1014,1031 ****
  static const char *
  read_string (struct lto_input_block *ib)
  {
!   unsigned int len = strnlen (ib->data + ib->p, ib->len - ib->p - 1);
!   const char *str;
! 
!   if (ib->data[ib->p + len])
!     lto_section_overrun (ib);
    if (!len)
!     {
!       ib->p++;
!       return NULL;
!     }
!   str = ib->data + ib->p;
!   ib->p += len + 1;
    return str;
  }
  
--- 1013,1025 ----
  static const char *
  read_string (struct lto_input_block *ib)
  {
!   unsigned int len = streamer_read_uhwi (ib);
    if (!len)
!     return NULL;
!   char *str = (char *)xmalloc (len + 1);
!   for (unsigned i = 0; i < len; ++i)
!     str[i] = streamer_read_uchar (ib);
!   str[len] = '\0';
    return str;
  }
  
*************** input_cgraph_opt_section (struct lto_fil
*** 1902,1913 ****
    const int main_offset = cfg_offset + header->cfg_size;
    const int string_offset = main_offset + header->main_size;
    struct data_in *data_in;
-   struct lto_input_block ib_main;
    unsigned int i;
    unsigned int count;
  
!   LTO_INIT_INPUT_BLOCK (ib_main, (const char *) data + main_offset, 0,
! 			header->main_size);
  
    data_in =
      lto_data_in_create (file_data, (const char *) data + string_offset,
--- 1896,1906 ----
    const int main_offset = cfg_offset + header->cfg_size;
    const int string_offset = main_offset + header->main_size;
    struct data_in *data_in;
    unsigned int i;
    unsigned int count;
  
!   lto_input_block ib_main ((const char *) data + main_offset,
! 			   header->main_size);
  
    data_in =
      lto_data_in_create (file_data, (const char *) data + string_offset,
Index: gcc/data-streamer-in.c
===================================================================
*** gcc/data-streamer-in.c.orig	2014-07-31 10:49:00.079737742 +0200
--- gcc/data-streamer-in.c	2014-07-31 12:08:48.391408073 +0200
*************** along with GCC; see the file COPYING3.
*** 22,27 ****
--- 22,32 ----
  
  #include "config.h"
  #include "system.h"
+ /* zlib.h includes other system headers.  Those headers may test feature
+    test macros.  config.h may define feature test macros.  For this reason,
+    zlib.h needs to be included after, rather than before, config.h and
+    system.h.  */
+ #include <zlib.h>
  #include "coretypes.h"
  #include "diagnostic.h"
  #include "tree.h"
*************** along with GCC; see the file COPYING3.
*** 33,45 ****
  #include "gimple.h"
  #include "data-streamer.h"
  
  /* Read a string from the string table in DATA_IN using input block
     IB.  Write the length to RLEN.  */
  
  const char *
  string_for_index (struct data_in *data_in, unsigned int loc, unsigned int *rlen)
  {
-   struct lto_input_block str_tab;
    unsigned int len;
    const char *result;
  
--- 38,107 ----
  #include "gimple.h"
  #include "data-streamer.h"
  
+ 
+ void
+ lto_input_block::append_block ()
+ {
+   gcc_assert (left_in_block == 0 && data);
+   if (!compress)
+     {
+       current_pointer = data + p;
+       left_in_block = MIN (4096, len - p);
+       p += left_in_block;
+     }
+   else
+     {
+       int status;
+ 
+       if (!zlib_stream)
+ 	{
+ 	  zlib_stream = XCNEW (z_stream);
+ 	  zlib_stream->zalloc = NULL;
+ 	  zlib_stream->zfree = NULL;
+ 	  zlib_stream->opaque = NULL;
+ 	  zlib_stream->avail_in = len;
+ 	  zlib_stream->next_in = (Bytef*)const_cast<char *>(data + p);
+ 	  status = inflateInit (zlib_stream);
+ 	  if (status != Z_OK)
+ 	    internal_error ("compressed stream: %s", zError (status));
+ 	  zbuf = XNEWVEC (char, 2 * 1024 * 1024);
+ 	}
+ 
+       zlib_stream->avail_out = 2 * 1024 * 1024;
+       zlib_stream->next_out = (Bytef*)zbuf;
+       status = inflate (zlib_stream, Z_NO_FLUSH);
+       if (status != Z_OK && status != Z_STREAM_END)
+ 	internal_error ("compressed stream: %s", zError (status));
+ 
+       current_pointer = zbuf;
+       left_in_block = 2 * 1024 * 1024 - zlib_stream->avail_out;
+       p = len - zlib_stream->avail_in;
+     }
+   if (left_in_block == 0)
+     fatal_error ("bytecode stream: trying to read bytes "
+ 		 "after the end of the input buffer");
+ }
+ 
+ lto_input_block::~lto_input_block ()
+ {
+   if (compress)
+     {
+       if (zlib_stream)
+ 	{
+ 	  inflateEnd (zlib_stream);
+ 	  free (zlib_stream);
+ 	}
+       if (zbuf)
+ 	free (zbuf);
+     }
+ }
+ 
  /* Read a string from the string table in DATA_IN using input block
     IB.  Write the length to RLEN.  */
  
  const char *
  string_for_index (struct data_in *data_in, unsigned int loc, unsigned int *rlen)
  {
    unsigned int len;
    const char *result;
  
*************** string_for_index (struct data_in *data_i
*** 50,64 ****
      }
  
    /* 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 = streamer_read_uhwi (&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;
  }
--- 112,126 ----
      }
  
    /* Get the string stored at location LOC in DATA_IN->STRINGS.  */
!   lto_input_block str_tab (data_in->strings, loc - 1,
! 			   data_in->strings_len - (loc - 1));
    len = streamer_read_uhwi (&str_tab);
    *rlen = len;
  
!   if (str_tab.left_in_block < len)
      internal_error ("bytecode stream: string too long for the string table");
  
!   result = str_tab.current_pointer;
  
    return result;
  }
*************** bp_unpack_string (struct data_in *data_i
*** 127,158 ****
  unsigned HOST_WIDE_INT
  streamer_read_uhwi (struct lto_input_block *ib)
  {
!   unsigned HOST_WIDE_INT result;
!   int shift;
!   unsigned HOST_WIDE_INT byte;
!   unsigned int p = ib->p;
!   unsigned int len = ib->len;
! 
!   const char *data = ib->data;
!   result = data[p++];
    if ((result & 0x80) != 0)
      {
        result &= 0x7f;
        shift = 7;
        do
  	{
! 	  byte = data[p++];
  	  result |= (byte & 0x7f) << shift;
  	  shift += 7;
  	}
        while ((byte & 0x80) != 0);
      }
  
-   /* We check for section overrun after the fact for performance reason.  */
-   if (p > len)
-     lto_section_overrun (ib);
- 
-   ib->p = p;
    return result;
  }
  
--- 189,210 ----
  unsigned HOST_WIDE_INT
  streamer_read_uhwi (struct lto_input_block *ib)
  {
!   unsigned HOST_WIDE_INT result = streamer_read_uchar (ib);
    if ((result & 0x80) != 0)
      {
+       unsigned HOST_WIDE_INT byte;
+       int shift;
        result &= 0x7f;
        shift = 7;
        do
  	{
! 	  byte = streamer_read_uchar (ib);
  	  result |= (byte & 0x7f) << shift;
  	  shift += 7;
  	}
        while ((byte & 0x80) != 0);
      }
  
    return result;
  }
  
Index: gcc/ipa-inline-analysis.c
===================================================================
*** gcc/ipa-inline-analysis.c.orig	2014-07-31 10:49:00.079737742 +0200
--- gcc/ipa-inline-analysis.c	2014-07-31 12:08:48.392408073 +0200
*************** inline_read_section (struct lto_file_dec
*** 4086,4097 ****
    const int main_offset = cfg_offset + header->cfg_size;
    const int string_offset = main_offset + header->main_size;
    struct data_in *data_in;
-   struct lto_input_block ib;
    unsigned int i, count2, j;
    unsigned int f_count;
  
!   LTO_INIT_INPUT_BLOCK (ib, (const char *) data + main_offset, 0,
! 			header->main_size);
  
    data_in =
      lto_data_in_create (file_data, (const char *) data + string_offset,
--- 4086,4095 ----
    const int main_offset = cfg_offset + header->cfg_size;
    const int string_offset = main_offset + header->main_size;
    struct data_in *data_in;
    unsigned int i, count2, j;
    unsigned int f_count;
  
!   lto_input_block ib ((const char *) data + main_offset, header->main_size);
  
    data_in =
      lto_data_in_create (file_data, (const char *) data + string_offset,
Index: gcc/ipa-prop.c
===================================================================
*** gcc/ipa-prop.c.orig	2014-07-31 10:49:00.079737742 +0200
--- gcc/ipa-prop.c	2014-07-31 12:08:48.394408073 +0200
*************** ipa_prop_read_section (struct lto_file_d
*** 4895,4906 ****
    const int main_offset = cfg_offset + header->cfg_size;
    const int string_offset = main_offset + header->main_size;
    struct data_in *data_in;
-   struct lto_input_block ib_main;
    unsigned int i;
    unsigned int count;
  
!   LTO_INIT_INPUT_BLOCK (ib_main, (const char *) data + main_offset, 0,
! 			header->main_size);
  
    data_in =
      lto_data_in_create (file_data, (const char *) data + string_offset,
--- 4895,4905 ----
    const int main_offset = cfg_offset + header->cfg_size;
    const int string_offset = main_offset + header->main_size;
    struct data_in *data_in;
    unsigned int i;
    unsigned int count;
  
!   lto_input_block ib_main ((const char *) data + main_offset,
! 			   header->main_size);
  
    data_in =
      lto_data_in_create (file_data, (const char *) data + string_offset,
*************** read_replacements_section (struct lto_fi
*** 5073,5084 ****
    const int main_offset = cfg_offset + header->cfg_size;
    const int string_offset = main_offset + header->main_size;
    struct data_in *data_in;
-   struct lto_input_block ib_main;
    unsigned int i;
    unsigned int count;
  
!   LTO_INIT_INPUT_BLOCK (ib_main, (const char *) data + main_offset, 0,
! 			header->main_size);
  
    data_in = lto_data_in_create (file_data, (const char *) data + string_offset,
  				header->string_size, vNULL);
--- 5072,5082 ----
    const int main_offset = cfg_offset + header->cfg_size;
    const int string_offset = main_offset + header->main_size;
    struct data_in *data_in;
    unsigned int i;
    unsigned int count;
  
!   lto_input_block ib_main ((const char *) data + main_offset,
! 			   header->main_size);
  
    data_in = lto_data_in_create (file_data, (const char *) data + string_offset,
  				header->string_size, vNULL);
Index: gcc/lto-streamer-in.c
===================================================================
*** gcc/lto-streamer-in.c.orig	2014-07-31 10:49:30.181735670 +0200
--- gcc/lto-streamer-in.c	2014-07-31 12:08:48.395408073 +0200
*************** lto_read_body_or_constructor (struct lto
*** 1054,1061 ****
    int cfg_offset;
    int main_offset;
    int string_offset;
-   struct lto_input_block ib_cfg;
-   struct lto_input_block ib_main;
    tree fn_decl = node->decl;
  
    header = (const struct lto_function_header *) data;
--- 1054,1059 ----
*************** lto_read_body_or_constructor (struct lto
*** 1064,1089 ****
        cfg_offset = sizeof (struct lto_function_header);
        main_offset = cfg_offset + header->cfg_size;
        string_offset = main_offset + header->main_size;
- 
-       LTO_INIT_INPUT_BLOCK (ib_cfg,
- 			    data + cfg_offset,
- 			    0,
- 			    header->cfg_size);
- 
-       LTO_INIT_INPUT_BLOCK (ib_main,
- 			    data + main_offset,
- 			    0,
- 			    header->main_size);
      }
    else
      {
        main_offset = sizeof (struct lto_function_header);
        string_offset = main_offset + header->main_size;
- 
-       LTO_INIT_INPUT_BLOCK (ib_main,
- 			    data + main_offset,
- 			    0,
- 			    header->main_size);
      }
  
    data_in = lto_data_in_create (file_data, data + string_offset,
--- 1062,1072 ----
*************** lto_read_body_or_constructor (struct lto
*** 1104,1111 ****
  
        /* Set up the struct function.  */
        from = data_in->reader_cache->nodes.length ();
        if (TREE_CODE (node->decl) == FUNCTION_DECL)
!         input_function (fn_decl, data_in, &ib_main, &ib_cfg);
        else
          input_constructor (fn_decl, data_in, &ib_main);
        /* And fixup types we streamed locally.  */
--- 1087,1098 ----
  
        /* Set up the struct function.  */
        from = data_in->reader_cache->nodes.length ();
+       lto_input_block ib_main (data + main_offset, header->main_size);
        if (TREE_CODE (node->decl) == FUNCTION_DECL)
! 	{
! 	  lto_input_block ib_cfg (data + cfg_offset, header->cfg_size);
! 	  input_function (fn_decl, data_in, &ib_main, &ib_cfg);
! 	}
        else
          input_constructor (fn_decl, data_in, &ib_main);
        /* And fixup types we streamed locally.  */
*************** lto_input_toplevel_asms (struct lto_file
*** 1360,1366 ****
    const struct lto_asm_header *header = (const struct lto_asm_header *) data;
    int string_offset;
    struct data_in *data_in;
-   struct lto_input_block ib;
    tree str;
  
    if (! data)
--- 1347,1352 ----
*************** lto_input_toplevel_asms (struct lto_file
*** 1368,1377 ****
  
    string_offset = sizeof (*header) + header->main_size;
  
!   LTO_INIT_INPUT_BLOCK (ib,
! 			data + sizeof (*header),
! 			0,
! 			header->main_size);
  
    data_in = lto_data_in_create (file_data, data + string_offset,
  			      header->string_size, vNULL);
--- 1354,1360 ----
  
    string_offset = sizeof (*header) + header->main_size;
  
!   lto_input_block ib (data + sizeof (*header), header->main_size);
  
    data_in = lto_data_in_create (file_data, data + string_offset,
  			      header->string_size, vNULL);
Index: gcc/lto/lto.c
===================================================================
*** gcc/lto/lto.c.orig	2014-07-31 10:49:00.079737742 +0200
--- gcc/lto/lto.c	2014-07-31 12:08:48.396408073 +0200
*************** lto_read_decls (struct lto_file_decl_dat
*** 1843,1856 ****
    const int decl_offset = sizeof (struct lto_decl_header);
    const int main_offset = decl_offset + header->decl_state_size;
    const int string_offset = main_offset + header->main_size;
-   struct lto_input_block ib_main;
    struct data_in *data_in;
    unsigned int i;
    const uint32_t *data_ptr, *data_end;
    uint32_t num_decl_states;
  
!   LTO_INIT_INPUT_BLOCK (ib_main, (const char *) data + main_offset, 0,
! 			header->main_size);
  
    data_in = lto_data_in_create (decl_data, (const char *) data + string_offset,
  				header->string_size, resolutions);
--- 1843,1855 ----
    const int decl_offset = sizeof (struct lto_decl_header);
    const int main_offset = decl_offset + header->decl_state_size;
    const int string_offset = main_offset + header->main_size;
    struct data_in *data_in;
    unsigned int i;
    const uint32_t *data_ptr, *data_end;
    uint32_t num_decl_states;
  
!   lto_input_block ib_main ((const char *) data + main_offset,
! 			   header->main_size);
  
    data_in = lto_data_in_create (decl_data, (const char *) data + string_offset,
  				header->string_size, resolutions);
*************** lto_read_decls (struct lto_file_decl_dat
*** 1859,1865 ****
       internal types that should not be merged.  */
  
    /* Read the global declarations and types.  */
!   while (ib_main.p < ib_main.len)
      {
        tree t;
        unsigned from = data_in->reader_cache->nodes.length ();
--- 1858,1864 ----
       internal types that should not be merged.  */
  
    /* Read the global declarations and types.  */
!   while (!ib_main.eof ())
      {
        tree t;
        unsigned from = data_in->reader_cache->nodes.length ();


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