On Thu, 7 Aug 2014, Richard Biener wrote:

> 
> 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.

The following is the update I promised on IRC.  It fixes a
small memory leak from read_string () and should restore
performance of streamer_read_uhwi.

Richard.


Index: gcc/data-streamer-out.c
===================================================================
*** gcc/data-streamer-out.c.orig        2014-08-07 13:47:46.007359525 +0200
--- gcc/data-streamer-out.c     2014-08-07 15:21:50.153970932 +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-08-07 13:47:46.007359525 +0200
--- gcc/lto-section-out.c       2014-08-07 15:21:50.153970932 +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-08-07 13:47:46.007359525 +0200
--- gcc/data-streamer.h 2014-08-07 15:36:52.565908802 +0200
*************** const char *bp_unpack_string (struct dat
*** 85,90 ****
--- 85,91 ----
  unsigned HOST_WIDE_INT streamer_read_uhwi (struct lto_input_block *);
  HOST_WIDE_INT streamer_read_hwi (struct lto_input_block *);
  gcov_type streamer_read_gcov_count (struct lto_input_block *);
+ void streamer_read_data_stream (struct lto_input_block *, void *, size_t);
  
  /* Returns a new bit-packing context for bit-packing into S.  */
  static inline struct bitpack_d
*************** 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;
--- 183,189 ----
  {
    /* 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
--- 199,211 ----
  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-08-07 13:47:46.007359525 +0200
--- gcc/lto-opts.c      2014-08-07 15:21:50.154970932 +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-08-07 13:47:46.007359525 +0200
--- gcc/lto-streamer-out.c      2014-08-07 15:21:50.155970932 +0200
*************** create_output_block (enum lto_section_ty
*** 80,91 ****
  
    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);
  
--- 80,93 ----
  
    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
*** 106,115 ****
    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);
--- 108,117 ----
    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
*** 1895,1903 ****
    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
--- 1897,1905 ----
    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)
*** 2129,2136 ****
    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
--- 2131,2138 ----
    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)
*** 2678,2685 ****
      }
    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);
  
--- 2680,2687 ----
      }
    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-08-07 13:47:46.007359525 +0200
--- gcc/lto-streamer.h  2014-08-07 15:21:50.156970932 +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-08-07 13:47:46.007359525 +0200
--- gcc/lto-section-in.c        2014-08-07 15:21:50.156970932 +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-08-07 13:47:46.007359525 +0200
--- gcc/lto-cgraph.c    2014-08-07 15:39:05.967899618 +0200
*************** lto_output_node (struct lto_simple_outpu
*** 484,490 ****
      comdat = IDENTIFIER_POINTER (group);
    else
      comdat = "";
!   streamer_write_data_stream (ob->main_stream, comdat, strlen (comdat) + 1);
  
    if (group)
      {
--- 484,491 ----
      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
*** 542,548 ****
    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)
      {
--- 543,550 ----
    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
*** 618,624 ****
      comdat = IDENTIFIER_POINTER (group);
    else
      comdat = "";
!   streamer_write_data_stream (ob->main_stream, comdat, strlen (comdat) + 1);
  
    if (group)
      {
--- 620,627 ----
      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
*** 636,642 ****
    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);
--- 639,646 ----
    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)
*** 988,1025 ****
  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.  */
  
! 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;
  }
  
--- 992,1018 ----
  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.  */
  
! static 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);
!   streamer_read_data_stream (ib, str, len);
!   str[len] = '\0';
    return str;
  }
  
*************** input_node (struct lto_file_decl_data *f
*** 1113,1119 ****
    int order;
    int i, count;
    tree group;
!   const char *section;
  
    order = streamer_read_hwi (ib) + order_base;
    clone_ref = streamer_read_hwi (ib);
--- 1106,1112 ----
    int order;
    int i, count;
    tree group;
!   char *section;
  
    order = streamer_read_hwi (ib) + order_base;
    clone_ref = streamer_read_hwi (ib);
*************** input_node (struct lto_file_decl_data *f
*** 1190,1196 ****
      node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND;
    section = read_string (ib);
    if (section)
!     node->set_section_for_node (section);
  
    if (node->thunk.thunk_p)
      {
--- 1183,1192 ----
      node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND;
    section = read_string (ib);
    if (section)
!     {
!       node->set_section_for_node (section);
!       free (section);
!     }
  
    if (node->thunk.thunk_p)
      {
*************** input_varpool_node (struct lto_file_decl
*** 1227,1233 ****
    int ref = LCC_NOT_FOUND;
    int order;
    tree group;
!   const char *section;
  
    order = streamer_read_hwi (ib) + order_base;
    decl_index = streamer_read_uhwi (ib);
--- 1223,1229 ----
    int ref = LCC_NOT_FOUND;
    int order;
    tree group;
!   char *section;
  
    order = streamer_read_hwi (ib) + order_base;
    decl_index = streamer_read_uhwi (ib);
*************** input_varpool_node (struct lto_file_decl
*** 1280,1286 ****
      node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND;
    section = read_string (ib);
    if (section)
!     node->set_section_for_node (section);
    node->resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution,
                                                LDPR_NUM_KNOWN);
    gcc_assert (flag_ltrans
--- 1276,1285 ----
      node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND;
    section = read_string (ib);
    if (section)
!     {
!       node->set_section_for_node (section);
!       free (section);
!     }
    node->resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution,
                                                LDPR_NUM_KNOWN);
    gcc_assert (flag_ltrans
*************** input_cgraph_opt_section (struct lto_fil
*** 1896,1907 ****
    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,
--- 1895,1905 ----
    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-08-07 13:47:46.007359525 +0200
--- gcc/data-streamer-in.c      2014-08-07 15:44:12.833878490 +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 = 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,159 ****
  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,240 ----
  unsigned HOST_WIDE_INT
  streamer_read_uhwi (struct lto_input_block *ib)
  {
!   if (ib->left_in_block >= sizeof (unsigned HOST_WIDE_INT) + 1)
!     {
!       const char *current_pointer = ib->current_pointer;
!       int left_in_block = ib->left_in_block;
  
!       unsigned HOST_WIDE_INT result = *(current_pointer++);
!       --left_in_block;
!       if ((result & 0x80) != 0)
        {
!         unsigned HOST_WIDE_INT byte;
!         int shift;
!         result &= 0x7f;
!         shift = 7;
!         do
!           {
!             byte = *(current_pointer++);
!             --left_in_block;
!             result |= (byte & 0x7f) << shift;
!             shift += 7;
!           }
!         while ((byte & 0x80) != 0);
        }
!       ib->current_pointer = current_pointer;
!       ib->left_in_block = left_in_block;
!       gcc_checking_assert (left_in_block >= 0);
!       return result;
!     }
!   else
!     {
!       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;
      }
  }
  
  
*************** streamer_read_hwi (struct lto_input_bloc
*** 166,182 ****
    int shift = 0;
    unsigned HOST_WIDE_INT byte;
  
!   while (true)
      {
!       byte = streamer_read_uchar (ib);
!       result |= (byte & 0x7f) << shift;
!       shift += 7;
!       if ((byte & 0x80) == 0)
        {
!         if ((shift < HOST_BITS_PER_WIDE_INT) && (byte & 0x40))
!           result |= - (HOST_WIDE_INT_1U << shift);
  
!         return result;
        }
      }
  }
--- 247,288 ----
    int shift = 0;
    unsigned HOST_WIDE_INT byte;
  
!   if (ib->left_in_block >= sizeof (unsigned HOST_WIDE_INT) + 1)
      {
!       const char *current_pointer = ib->current_pointer;
!       int left_in_block = ib->left_in_block;
!       while (true)
        {
!         byte = *(current_pointer++);
!         --left_in_block;
!         result |= (byte & 0x7f) << shift;
!         shift += 7;
!         if ((byte & 0x80) == 0)
!           {
!             if ((shift < HOST_BITS_PER_WIDE_INT) && (byte & 0x40))
!               result |= - (HOST_WIDE_INT_1U << shift);
! 
!             ib->current_pointer = current_pointer;
!             ib->left_in_block = left_in_block;
!             gcc_checking_assert (left_in_block >= 0);
!             return result;
!           }
!       }
!     }
!   else
!     {
!       while (true)
!       {
!         byte = streamer_read_uchar (ib);
!         result |= (byte & 0x7f) << shift;
!         shift += 7;
!         if ((byte & 0x80) == 0)
!           {
!             if ((shift < HOST_BITS_PER_WIDE_INT) && (byte & 0x40))
!               result |= - (HOST_WIDE_INT_1U << shift);
  
!             return result;
!           }
        }
      }
  }
*************** streamer_read_gcov_count (struct lto_inp
*** 190,192 ****
--- 296,328 ----
    gcc_assert (ret >= 0);
    return ret;
  }
+ 
+ /* Read raw DATA of length LEN from IB.  */
+ 
+ void
+ streamer_read_data_stream (struct lto_input_block *ib, void *data,
+                          size_t len)
+ {
+   while (len)
+     {
+       size_t copy;
+ 
+       /* No space left.  */
+       if (ib->left_in_block == 0)
+       ib->append_block ();
+ 
+       /* Determine how many bytes to copy in this loop.  */
+       if (len <= ib->left_in_block)
+       copy = len;
+       else
+       copy = ib->left_in_block;
+ 
+       /* Copy the data and do bookkeeping.  */
+       memcpy (data, ib->current_pointer, copy);
+       ib->current_pointer += copy;
+       ib->left_in_block -= copy;
+       data = (char *) data + copy;
+       len -= copy;
+     }
+ }
+ 
Index: gcc/ipa-inline-analysis.c
===================================================================
*** gcc/ipa-inline-analysis.c.orig      2014-08-07 13:47:46.007359525 +0200
--- gcc/ipa-inline-analysis.c   2014-08-07 15:21:50.158970932 +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-08-07 13:47:46.007359525 +0200
--- gcc/ipa-prop.c      2014-08-07 15:21:50.160970932 +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-08-07 13:47:46.007359525 +0200
--- gcc/lto-streamer-in.c       2014-08-07 15:21:50.160970932 +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-08-07 13:47:46.007359525 +0200
--- gcc/lto/lto.c       2014-08-07 15:21:50.161970932 +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 ();

Reply via email to