From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3180 invoked by alias); 7 Aug 2014 13:50:14 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 3168 invoked by uid 89); 7 Aug 2014 13:50:13 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.6 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx2.suse.de Received: from cantor2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Thu, 07 Aug 2014 13:50:08 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 79FB2ABBB; Thu, 7 Aug 2014 13:50:04 +0000 (UTC) Date: Thu, 07 Aug 2014 13:50:00 -0000 From: Richard Biener To: gcc-patches@gcc.gnu.org cc: Jan Hubicka Subject: Re: [PATCH][LTO] Streamer re-org (what's left) In-Reply-To: Message-ID: References: User-Agent: Alpine 2.11 (LSU 23 2013-08-11) MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-SW-Source: 2014-08/txt/msg00815.txt.bz2 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 #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 #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(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 ();