2015-06-24 François Dumont <fdumont@gcc.gnu.org>
[official-gcc.git] / gcc / lto-compress.c
blob2fb00e2401c54213ea00f5c8bb4d3998ae1d3651
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 "alias.h"
31 #include "symtab.h"
32 #include "options.h"
33 #include "tree.h"
34 #include "fold-const.h"
35 #include "predict.h"
36 #include "tm.h"
37 #include "hard-reg-set.h"
38 #include "function.h"
39 #include "basic-block.h"
40 #include "tree-ssa-alias.h"
41 #include "internal-fn.h"
42 #include "gimple-expr.h"
43 #include "gimple.h"
44 #include "diagnostic-core.h"
45 #include "langhooks.h"
46 #include "plugin-api.h"
47 #include "ipa-ref.h"
48 #include "cgraph.h"
49 #include "lto-streamer.h"
50 #include "lto-compress.h"
52 /* Compression stream structure, holds the flush callback and opaque token,
53 the buffered data, and a note of whether compressing or uncompressing. */
55 struct lto_compression_stream
57 void (*callback) (const char *, unsigned, void *);
58 void *opaque;
59 char *buffer;
60 size_t bytes;
61 size_t allocation;
62 bool is_compression;
65 /* Overall compression constants for zlib. */
67 static const size_t Z_BUFFER_LENGTH = 4096;
68 static const size_t MIN_STREAM_ALLOCATION = 1024;
70 /* For zlib, allocate SIZE count of ITEMS and return the address, OPAQUE
71 is unused. */
73 static void *
74 lto_zalloc (void *opaque, unsigned items, unsigned size)
76 gcc_assert (opaque == Z_NULL);
77 return xmalloc (items * size);
80 /* For zlib, free memory at ADDRESS, OPAQUE is unused. */
82 static void
83 lto_zfree (void *opaque, void *address)
85 gcc_assert (opaque == Z_NULL);
86 free (address);
89 /* Return a zlib compression level that zlib will not reject. Normalizes
90 the compression level from the command line flag, clamping non-default
91 values to the appropriate end of their valid range. */
93 static int
94 lto_normalized_zlib_level (void)
96 int level = flag_lto_compression_level;
98 if (level != Z_DEFAULT_COMPRESSION)
100 if (level < Z_NO_COMPRESSION)
101 level = Z_NO_COMPRESSION;
102 else if (level > Z_BEST_COMPRESSION)
103 level = Z_BEST_COMPRESSION;
106 return level;
109 /* Create a new compression stream, with CALLBACK flush function passed
110 OPAQUE token, IS_COMPRESSION indicates if compressing or uncompressing. */
112 static struct lto_compression_stream *
113 lto_new_compression_stream (void (*callback) (const char *, unsigned, void *),
114 void *opaque, bool is_compression)
116 struct lto_compression_stream *stream
117 = (struct lto_compression_stream *) xmalloc (sizeof (*stream));
119 memset (stream, 0, sizeof (*stream));
120 stream->callback = callback;
121 stream->opaque = opaque;
122 stream->is_compression = is_compression;
124 return stream;
127 /* Append NUM_CHARS from address BASE to STREAM. */
129 static void
130 lto_append_to_compression_stream (struct lto_compression_stream *stream,
131 const char *base, size_t num_chars)
133 size_t required = stream->bytes + num_chars;
135 if (stream->allocation < required)
137 if (stream->allocation == 0)
138 stream->allocation = MIN_STREAM_ALLOCATION;
139 while (stream->allocation < required)
140 stream->allocation *= 2;
142 stream->buffer = (char *) xrealloc (stream->buffer, stream->allocation);
145 memcpy (stream->buffer + stream->bytes, base, num_chars);
146 stream->bytes += num_chars;
149 /* Free the buffer and memory associated with STREAM. */
151 static void
152 lto_destroy_compression_stream (struct lto_compression_stream *stream)
154 free (stream->buffer);
155 free (stream);
158 /* Return a new compression stream, with CALLBACK flush function passed
159 OPAQUE token. */
161 struct lto_compression_stream *
162 lto_start_compression (void (*callback) (const char *, unsigned, void *),
163 void *opaque)
165 return lto_new_compression_stream (callback, opaque, true);
168 /* Append NUM_CHARS from address BASE to STREAM. */
170 void
171 lto_compress_block (struct lto_compression_stream *stream,
172 const char *base, size_t num_chars)
174 gcc_assert (stream->is_compression);
176 lto_append_to_compression_stream (stream, base, num_chars);
177 lto_stats.num_output_il_bytes += num_chars;
180 /* Finalize STREAM compression, and free stream allocations. */
182 void
183 lto_end_compression (struct lto_compression_stream *stream)
185 unsigned char *cursor = (unsigned char *) stream->buffer;
186 size_t remaining = stream->bytes;
187 const size_t outbuf_length = Z_BUFFER_LENGTH;
188 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
189 z_stream out_stream;
190 size_t compressed_bytes = 0;
191 int status;
193 gcc_assert (stream->is_compression);
195 out_stream.next_out = outbuf;
196 out_stream.avail_out = outbuf_length;
197 out_stream.next_in = cursor;
198 out_stream.avail_in = remaining;
199 out_stream.zalloc = lto_zalloc;
200 out_stream.zfree = lto_zfree;
201 out_stream.opaque = Z_NULL;
203 status = deflateInit (&out_stream, lto_normalized_zlib_level ());
204 if (status != Z_OK)
205 internal_error ("compressed stream: %s", zError (status));
209 size_t in_bytes, out_bytes;
211 status = deflate (&out_stream, Z_FINISH);
212 if (status != Z_OK && status != Z_STREAM_END)
213 internal_error ("compressed stream: %s", zError (status));
215 in_bytes = remaining - out_stream.avail_in;
216 out_bytes = outbuf_length - out_stream.avail_out;
218 stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
219 lto_stats.num_compressed_il_bytes += out_bytes;
220 compressed_bytes += out_bytes;
222 cursor += in_bytes;
223 remaining -= in_bytes;
225 out_stream.next_out = outbuf;
226 out_stream.avail_out = outbuf_length;
227 out_stream.next_in = cursor;
228 out_stream.avail_in = remaining;
230 while (status != Z_STREAM_END);
232 status = deflateEnd (&out_stream);
233 if (status != Z_OK)
234 internal_error ("compressed stream: %s", zError (status));
236 lto_destroy_compression_stream (stream);
237 free (outbuf);
240 /* Return a new uncompression stream, with CALLBACK flush function passed
241 OPAQUE token. */
243 struct lto_compression_stream *
244 lto_start_uncompression (void (*callback) (const char *, unsigned, void *),
245 void *opaque)
247 return lto_new_compression_stream (callback, opaque, false);
250 /* Append NUM_CHARS from address BASE to STREAM. */
252 void
253 lto_uncompress_block (struct lto_compression_stream *stream,
254 const char *base, size_t num_chars)
256 gcc_assert (!stream->is_compression);
258 lto_append_to_compression_stream (stream, base, num_chars);
259 lto_stats.num_input_il_bytes += num_chars;
262 /* Finalize STREAM uncompression, and free stream allocations.
264 Because of the way LTO IL streams are compressed, there may be several
265 concatenated compressed segments in the accumulated data, so for this
266 function we iterate decompressions until no data remains. */
268 void
269 lto_end_uncompression (struct lto_compression_stream *stream)
271 unsigned char *cursor = (unsigned char *) stream->buffer;
272 size_t remaining = stream->bytes;
273 const size_t outbuf_length = Z_BUFFER_LENGTH;
274 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
275 size_t uncompressed_bytes = 0;
277 gcc_assert (!stream->is_compression);
279 while (remaining > 0)
281 z_stream in_stream;
282 size_t out_bytes;
283 int status;
285 in_stream.next_out = outbuf;
286 in_stream.avail_out = outbuf_length;
287 in_stream.next_in = cursor;
288 in_stream.avail_in = remaining;
289 in_stream.zalloc = lto_zalloc;
290 in_stream.zfree = lto_zfree;
291 in_stream.opaque = Z_NULL;
293 status = inflateInit (&in_stream);
294 if (status != Z_OK)
295 internal_error ("compressed stream: %s", zError (status));
299 size_t in_bytes;
301 status = inflate (&in_stream, Z_SYNC_FLUSH);
302 if (status != Z_OK && status != Z_STREAM_END)
303 internal_error ("compressed stream: %s", zError (status));
305 in_bytes = remaining - in_stream.avail_in;
306 out_bytes = outbuf_length - in_stream.avail_out;
308 stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
309 lto_stats.num_uncompressed_il_bytes += out_bytes;
310 uncompressed_bytes += out_bytes;
312 cursor += in_bytes;
313 remaining -= in_bytes;
315 in_stream.next_out = outbuf;
316 in_stream.avail_out = outbuf_length;
317 in_stream.next_in = cursor;
318 in_stream.avail_in = remaining;
320 while (!(status == Z_STREAM_END && out_bytes == 0));
322 status = inflateEnd (&in_stream);
323 if (status != Z_OK)
324 internal_error ("compressed stream: %s", zError (status));
327 lto_destroy_compression_stream (stream);
328 free (outbuf);