2015-06-11 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / lto-compress.c
blobf2b780b4f0a4ba5d24eee57f2caa1c2c1a4c4f93
1 /* LTO IL compression streams.
3 Copyright (C) 2009-2015 Free Software Foundation, Inc.
4 Contributed by Simon Baldwin <simonb@google.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 #include "config.h"
23 #include "system.h"
24 /* zlib.h includes other system headers. Those headers may test feature
25 test macros. config.h may define feature test macros. For this reason,
26 zlib.h needs to be included after, rather than before, config.h and
27 system.h. */
28 #include <zlib.h>
29 #include "coretypes.h"
30 #include "input.h"
31 #include "alias.h"
32 #include "symtab.h"
33 #include "options.h"
34 #include "tree.h"
35 #include "fold-const.h"
36 #include "predict.h"
37 #include "tm.h"
38 #include "hard-reg-set.h"
39 #include "input.h"
40 #include "function.h"
41 #include "basic-block.h"
42 #include "tree-ssa-alias.h"
43 #include "internal-fn.h"
44 #include "gimple-expr.h"
45 #include "is-a.h"
46 #include "gimple.h"
47 #include "diagnostic-core.h"
48 #include "langhooks.h"
49 #include "plugin-api.h"
50 #include "ipa-ref.h"
51 #include "cgraph.h"
52 #include "lto-streamer.h"
53 #include "lto-compress.h"
55 /* Compression stream structure, holds the flush callback and opaque token,
56 the buffered data, and a note of whether compressing or uncompressing. */
58 struct lto_compression_stream
60 void (*callback) (const char *, unsigned, void *);
61 void *opaque;
62 char *buffer;
63 size_t bytes;
64 size_t allocation;
65 bool is_compression;
68 /* Overall compression constants for zlib. */
70 static const size_t Z_BUFFER_LENGTH = 4096;
71 static const size_t MIN_STREAM_ALLOCATION = 1024;
73 /* For zlib, allocate SIZE count of ITEMS and return the address, OPAQUE
74 is unused. */
76 static void *
77 lto_zalloc (void *opaque, unsigned items, unsigned size)
79 gcc_assert (opaque == Z_NULL);
80 return xmalloc (items * size);
83 /* For zlib, free memory at ADDRESS, OPAQUE is unused. */
85 static void
86 lto_zfree (void *opaque, void *address)
88 gcc_assert (opaque == Z_NULL);
89 free (address);
92 /* Return a zlib compression level that zlib will not reject. Normalizes
93 the compression level from the command line flag, clamping non-default
94 values to the appropriate end of their valid range. */
96 static int
97 lto_normalized_zlib_level (void)
99 int level = flag_lto_compression_level;
101 if (level != Z_DEFAULT_COMPRESSION)
103 if (level < Z_NO_COMPRESSION)
104 level = Z_NO_COMPRESSION;
105 else if (level > Z_BEST_COMPRESSION)
106 level = Z_BEST_COMPRESSION;
109 return level;
112 /* Create a new compression stream, with CALLBACK flush function passed
113 OPAQUE token, IS_COMPRESSION indicates if compressing or uncompressing. */
115 static struct lto_compression_stream *
116 lto_new_compression_stream (void (*callback) (const char *, unsigned, void *),
117 void *opaque, bool is_compression)
119 struct lto_compression_stream *stream
120 = (struct lto_compression_stream *) xmalloc (sizeof (*stream));
122 memset (stream, 0, sizeof (*stream));
123 stream->callback = callback;
124 stream->opaque = opaque;
125 stream->is_compression = is_compression;
127 return stream;
130 /* Append NUM_CHARS from address BASE to STREAM. */
132 static void
133 lto_append_to_compression_stream (struct lto_compression_stream *stream,
134 const char *base, size_t num_chars)
136 size_t required = stream->bytes + num_chars;
138 if (stream->allocation < required)
140 if (stream->allocation == 0)
141 stream->allocation = MIN_STREAM_ALLOCATION;
142 while (stream->allocation < required)
143 stream->allocation *= 2;
145 stream->buffer = (char *) xrealloc (stream->buffer, stream->allocation);
148 memcpy (stream->buffer + stream->bytes, base, num_chars);
149 stream->bytes += num_chars;
152 /* Free the buffer and memory associated with STREAM. */
154 static void
155 lto_destroy_compression_stream (struct lto_compression_stream *stream)
157 free (stream->buffer);
158 free (stream);
161 /* Return a new compression stream, with CALLBACK flush function passed
162 OPAQUE token. */
164 struct lto_compression_stream *
165 lto_start_compression (void (*callback) (const char *, unsigned, void *),
166 void *opaque)
168 return lto_new_compression_stream (callback, opaque, true);
171 /* Append NUM_CHARS from address BASE to STREAM. */
173 void
174 lto_compress_block (struct lto_compression_stream *stream,
175 const char *base, size_t num_chars)
177 gcc_assert (stream->is_compression);
179 lto_append_to_compression_stream (stream, base, num_chars);
180 lto_stats.num_output_il_bytes += num_chars;
183 /* Finalize STREAM compression, and free stream allocations. */
185 void
186 lto_end_compression (struct lto_compression_stream *stream)
188 unsigned char *cursor = (unsigned char *) stream->buffer;
189 size_t remaining = stream->bytes;
190 const size_t outbuf_length = Z_BUFFER_LENGTH;
191 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
192 z_stream out_stream;
193 size_t compressed_bytes = 0;
194 int status;
196 gcc_assert (stream->is_compression);
198 out_stream.next_out = outbuf;
199 out_stream.avail_out = outbuf_length;
200 out_stream.next_in = cursor;
201 out_stream.avail_in = remaining;
202 out_stream.zalloc = lto_zalloc;
203 out_stream.zfree = lto_zfree;
204 out_stream.opaque = Z_NULL;
206 status = deflateInit (&out_stream, lto_normalized_zlib_level ());
207 if (status != Z_OK)
208 internal_error ("compressed stream: %s", zError (status));
212 size_t in_bytes, out_bytes;
214 status = deflate (&out_stream, Z_FINISH);
215 if (status != Z_OK && status != Z_STREAM_END)
216 internal_error ("compressed stream: %s", zError (status));
218 in_bytes = remaining - out_stream.avail_in;
219 out_bytes = outbuf_length - out_stream.avail_out;
221 stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
222 lto_stats.num_compressed_il_bytes += out_bytes;
223 compressed_bytes += out_bytes;
225 cursor += in_bytes;
226 remaining -= in_bytes;
228 out_stream.next_out = outbuf;
229 out_stream.avail_out = outbuf_length;
230 out_stream.next_in = cursor;
231 out_stream.avail_in = remaining;
233 while (status != Z_STREAM_END);
235 status = deflateEnd (&out_stream);
236 if (status != Z_OK)
237 internal_error ("compressed stream: %s", zError (status));
239 lto_destroy_compression_stream (stream);
240 free (outbuf);
243 /* Return a new uncompression stream, with CALLBACK flush function passed
244 OPAQUE token. */
246 struct lto_compression_stream *
247 lto_start_uncompression (void (*callback) (const char *, unsigned, void *),
248 void *opaque)
250 return lto_new_compression_stream (callback, opaque, false);
253 /* Append NUM_CHARS from address BASE to STREAM. */
255 void
256 lto_uncompress_block (struct lto_compression_stream *stream,
257 const char *base, size_t num_chars)
259 gcc_assert (!stream->is_compression);
261 lto_append_to_compression_stream (stream, base, num_chars);
262 lto_stats.num_input_il_bytes += num_chars;
265 /* Finalize STREAM uncompression, and free stream allocations.
267 Because of the way LTO IL streams are compressed, there may be several
268 concatenated compressed segments in the accumulated data, so for this
269 function we iterate decompressions until no data remains. */
271 void
272 lto_end_uncompression (struct lto_compression_stream *stream)
274 unsigned char *cursor = (unsigned char *) stream->buffer;
275 size_t remaining = stream->bytes;
276 const size_t outbuf_length = Z_BUFFER_LENGTH;
277 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
278 size_t uncompressed_bytes = 0;
280 gcc_assert (!stream->is_compression);
282 while (remaining > 0)
284 z_stream in_stream;
285 size_t out_bytes;
286 int status;
288 in_stream.next_out = outbuf;
289 in_stream.avail_out = outbuf_length;
290 in_stream.next_in = cursor;
291 in_stream.avail_in = remaining;
292 in_stream.zalloc = lto_zalloc;
293 in_stream.zfree = lto_zfree;
294 in_stream.opaque = Z_NULL;
296 status = inflateInit (&in_stream);
297 if (status != Z_OK)
298 internal_error ("compressed stream: %s", zError (status));
302 size_t in_bytes;
304 status = inflate (&in_stream, Z_SYNC_FLUSH);
305 if (status != Z_OK && status != Z_STREAM_END)
306 internal_error ("compressed stream: %s", zError (status));
308 in_bytes = remaining - in_stream.avail_in;
309 out_bytes = outbuf_length - in_stream.avail_out;
311 stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
312 lto_stats.num_uncompressed_il_bytes += out_bytes;
313 uncompressed_bytes += out_bytes;
315 cursor += in_bytes;
316 remaining -= in_bytes;
318 in_stream.next_out = outbuf;
319 in_stream.avail_out = outbuf_length;
320 in_stream.next_in = cursor;
321 in_stream.avail_in = remaining;
323 while (!(status == Z_STREAM_END && out_bytes == 0));
325 status = inflateEnd (&in_stream);
326 if (status != Z_OK)
327 internal_error ("compressed stream: %s", zError (status));
330 lto_destroy_compression_stream (stream);
331 free (outbuf);