2015-03-21 Sandra Loosemore <sandra@codesourcery.com>
[official-gcc.git] / gcc / lto-compress.c
blob0740112999870cfd2e8b3f808c6071a47bc4f602
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 "hash-set.h"
31 #include "machmode.h"
32 #include "vec.h"
33 #include "double-int.h"
34 #include "input.h"
35 #include "alias.h"
36 #include "symtab.h"
37 #include "options.h"
38 #include "wide-int.h"
39 #include "inchash.h"
40 #include "tree.h"
41 #include "fold-const.h"
42 #include "predict.h"
43 #include "tm.h"
44 #include "hard-reg-set.h"
45 #include "input.h"
46 #include "function.h"
47 #include "basic-block.h"
48 #include "tree-ssa-alias.h"
49 #include "internal-fn.h"
50 #include "gimple-expr.h"
51 #include "is-a.h"
52 #include "gimple.h"
53 #include "diagnostic-core.h"
54 #include "langhooks.h"
55 #include "hash-map.h"
56 #include "plugin-api.h"
57 #include "ipa-ref.h"
58 #include "cgraph.h"
59 #include "lto-streamer.h"
60 #include "lto-compress.h"
62 /* Compression stream structure, holds the flush callback and opaque token,
63 the buffered data, and a note of whether compressing or uncompressing. */
65 struct lto_compression_stream
67 void (*callback) (const char *, unsigned, void *);
68 void *opaque;
69 char *buffer;
70 size_t bytes;
71 size_t allocation;
72 bool is_compression;
75 /* Overall compression constants for zlib. */
77 static const size_t Z_BUFFER_LENGTH = 4096;
78 static const size_t MIN_STREAM_ALLOCATION = 1024;
80 /* For zlib, allocate SIZE count of ITEMS and return the address, OPAQUE
81 is unused. */
83 static void *
84 lto_zalloc (void *opaque, unsigned items, unsigned size)
86 gcc_assert (opaque == Z_NULL);
87 return xmalloc (items * size);
90 /* For zlib, free memory at ADDRESS, OPAQUE is unused. */
92 static void
93 lto_zfree (void *opaque, void *address)
95 gcc_assert (opaque == Z_NULL);
96 free (address);
99 /* Return a zlib compression level that zlib will not reject. Normalizes
100 the compression level from the command line flag, clamping non-default
101 values to the appropriate end of their valid range. */
103 static int
104 lto_normalized_zlib_level (void)
106 int level = flag_lto_compression_level;
108 if (level != Z_DEFAULT_COMPRESSION)
110 if (level < Z_NO_COMPRESSION)
111 level = Z_NO_COMPRESSION;
112 else if (level > Z_BEST_COMPRESSION)
113 level = Z_BEST_COMPRESSION;
116 return level;
119 /* Create a new compression stream, with CALLBACK flush function passed
120 OPAQUE token, IS_COMPRESSION indicates if compressing or uncompressing. */
122 static struct lto_compression_stream *
123 lto_new_compression_stream (void (*callback) (const char *, unsigned, void *),
124 void *opaque, bool is_compression)
126 struct lto_compression_stream *stream
127 = (struct lto_compression_stream *) xmalloc (sizeof (*stream));
129 memset (stream, 0, sizeof (*stream));
130 stream->callback = callback;
131 stream->opaque = opaque;
132 stream->is_compression = is_compression;
134 return stream;
137 /* Append NUM_CHARS from address BASE to STREAM. */
139 static void
140 lto_append_to_compression_stream (struct lto_compression_stream *stream,
141 const char *base, size_t num_chars)
143 size_t required = stream->bytes + num_chars;
145 if (stream->allocation < required)
147 if (stream->allocation == 0)
148 stream->allocation = MIN_STREAM_ALLOCATION;
149 while (stream->allocation < required)
150 stream->allocation *= 2;
152 stream->buffer = (char *) xrealloc (stream->buffer, stream->allocation);
155 memcpy (stream->buffer + stream->bytes, base, num_chars);
156 stream->bytes += num_chars;
159 /* Free the buffer and memory associated with STREAM. */
161 static void
162 lto_destroy_compression_stream (struct lto_compression_stream *stream)
164 free (stream->buffer);
165 free (stream);
168 /* Return a new compression stream, with CALLBACK flush function passed
169 OPAQUE token. */
171 struct lto_compression_stream *
172 lto_start_compression (void (*callback) (const char *, unsigned, void *),
173 void *opaque)
175 return lto_new_compression_stream (callback, opaque, true);
178 /* Append NUM_CHARS from address BASE to STREAM. */
180 void
181 lto_compress_block (struct lto_compression_stream *stream,
182 const char *base, size_t num_chars)
184 gcc_assert (stream->is_compression);
186 lto_append_to_compression_stream (stream, base, num_chars);
187 lto_stats.num_output_il_bytes += num_chars;
190 /* Finalize STREAM compression, and free stream allocations. */
192 void
193 lto_end_compression (struct lto_compression_stream *stream)
195 unsigned char *cursor = (unsigned char *) stream->buffer;
196 size_t remaining = stream->bytes;
197 const size_t outbuf_length = Z_BUFFER_LENGTH;
198 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
199 z_stream out_stream;
200 size_t compressed_bytes = 0;
201 int status;
203 gcc_assert (stream->is_compression);
205 out_stream.next_out = outbuf;
206 out_stream.avail_out = outbuf_length;
207 out_stream.next_in = cursor;
208 out_stream.avail_in = remaining;
209 out_stream.zalloc = lto_zalloc;
210 out_stream.zfree = lto_zfree;
211 out_stream.opaque = Z_NULL;
213 status = deflateInit (&out_stream, lto_normalized_zlib_level ());
214 if (status != Z_OK)
215 internal_error ("compressed stream: %s", zError (status));
219 size_t in_bytes, out_bytes;
221 status = deflate (&out_stream, Z_FINISH);
222 if (status != Z_OK && status != Z_STREAM_END)
223 internal_error ("compressed stream: %s", zError (status));
225 in_bytes = remaining - out_stream.avail_in;
226 out_bytes = outbuf_length - out_stream.avail_out;
228 stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
229 lto_stats.num_compressed_il_bytes += out_bytes;
230 compressed_bytes += out_bytes;
232 cursor += in_bytes;
233 remaining -= in_bytes;
235 out_stream.next_out = outbuf;
236 out_stream.avail_out = outbuf_length;
237 out_stream.next_in = cursor;
238 out_stream.avail_in = remaining;
240 while (status != Z_STREAM_END);
242 status = deflateEnd (&out_stream);
243 if (status != Z_OK)
244 internal_error ("compressed stream: %s", zError (status));
246 lto_destroy_compression_stream (stream);
247 free (outbuf);
250 /* Return a new uncompression stream, with CALLBACK flush function passed
251 OPAQUE token. */
253 struct lto_compression_stream *
254 lto_start_uncompression (void (*callback) (const char *, unsigned, void *),
255 void *opaque)
257 return lto_new_compression_stream (callback, opaque, false);
260 /* Append NUM_CHARS from address BASE to STREAM. */
262 void
263 lto_uncompress_block (struct lto_compression_stream *stream,
264 const char *base, size_t num_chars)
266 gcc_assert (!stream->is_compression);
268 lto_append_to_compression_stream (stream, base, num_chars);
269 lto_stats.num_input_il_bytes += num_chars;
272 /* Finalize STREAM uncompression, and free stream allocations.
274 Because of the way LTO IL streams are compressed, there may be several
275 concatenated compressed segments in the accumulated data, so for this
276 function we iterate decompressions until no data remains. */
278 void
279 lto_end_uncompression (struct lto_compression_stream *stream)
281 unsigned char *cursor = (unsigned char *) stream->buffer;
282 size_t remaining = stream->bytes;
283 const size_t outbuf_length = Z_BUFFER_LENGTH;
284 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
285 size_t uncompressed_bytes = 0;
287 gcc_assert (!stream->is_compression);
289 while (remaining > 0)
291 z_stream in_stream;
292 size_t out_bytes;
293 int status;
295 in_stream.next_out = outbuf;
296 in_stream.avail_out = outbuf_length;
297 in_stream.next_in = cursor;
298 in_stream.avail_in = remaining;
299 in_stream.zalloc = lto_zalloc;
300 in_stream.zfree = lto_zfree;
301 in_stream.opaque = Z_NULL;
303 status = inflateInit (&in_stream);
304 if (status != Z_OK)
305 internal_error ("compressed stream: %s", zError (status));
309 size_t in_bytes;
311 status = inflate (&in_stream, Z_SYNC_FLUSH);
312 if (status != Z_OK && status != Z_STREAM_END)
313 internal_error ("compressed stream: %s", zError (status));
315 in_bytes = remaining - in_stream.avail_in;
316 out_bytes = outbuf_length - in_stream.avail_out;
318 stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
319 lto_stats.num_uncompressed_il_bytes += out_bytes;
320 uncompressed_bytes += out_bytes;
322 cursor += in_bytes;
323 remaining -= in_bytes;
325 in_stream.next_out = outbuf;
326 in_stream.avail_out = outbuf_length;
327 in_stream.next_in = cursor;
328 in_stream.avail_in = remaining;
330 while (!(status == Z_STREAM_END && out_bytes == 0));
332 status = inflateEnd (&in_stream);
333 if (status != Z_OK)
334 internal_error ("compressed stream: %s", zError (status));
337 lto_destroy_compression_stream (stream);
338 free (outbuf);