/cp
[official-gcc.git] / gcc / lto-compress.c
blobc688caec21508456273f83fe629cc1c3f9df8b5e
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 "backend.h"
32 #include "tree.h"
33 #include "gimple.h"
34 #include "hard-reg-set.h"
35 #include "options.h"
36 #include "fold-const.h"
37 #include "internal-fn.h"
38 #include "diagnostic-core.h"
39 #include "langhooks.h"
40 #include "cgraph.h"
41 #include "lto-streamer.h"
42 #include "lto-compress.h"
44 /* Compression stream structure, holds the flush callback and opaque token,
45 the buffered data, and a note of whether compressing or uncompressing. */
47 struct lto_compression_stream
49 void (*callback) (const char *, unsigned, void *);
50 void *opaque;
51 char *buffer;
52 size_t bytes;
53 size_t allocation;
54 bool is_compression;
57 /* Overall compression constants for zlib. */
59 static const size_t Z_BUFFER_LENGTH = 4096;
60 static const size_t MIN_STREAM_ALLOCATION = 1024;
62 /* For zlib, allocate SIZE count of ITEMS and return the address, OPAQUE
63 is unused. */
65 static void *
66 lto_zalloc (void *opaque, unsigned items, unsigned size)
68 gcc_assert (opaque == Z_NULL);
69 return xmalloc (items * size);
72 /* For zlib, free memory at ADDRESS, OPAQUE is unused. */
74 static void
75 lto_zfree (void *opaque, void *address)
77 gcc_assert (opaque == Z_NULL);
78 free (address);
81 /* Return a zlib compression level that zlib will not reject. Normalizes
82 the compression level from the command line flag, clamping non-default
83 values to the appropriate end of their valid range. */
85 static int
86 lto_normalized_zlib_level (void)
88 int level = flag_lto_compression_level;
90 if (level != Z_DEFAULT_COMPRESSION)
92 if (level < Z_NO_COMPRESSION)
93 level = Z_NO_COMPRESSION;
94 else if (level > Z_BEST_COMPRESSION)
95 level = Z_BEST_COMPRESSION;
98 return level;
101 /* Create a new compression stream, with CALLBACK flush function passed
102 OPAQUE token, IS_COMPRESSION indicates if compressing or uncompressing. */
104 static struct lto_compression_stream *
105 lto_new_compression_stream (void (*callback) (const char *, unsigned, void *),
106 void *opaque, bool is_compression)
108 struct lto_compression_stream *stream
109 = (struct lto_compression_stream *) xmalloc (sizeof (*stream));
111 memset (stream, 0, sizeof (*stream));
112 stream->callback = callback;
113 stream->opaque = opaque;
114 stream->is_compression = is_compression;
116 return stream;
119 /* Append NUM_CHARS from address BASE to STREAM. */
121 static void
122 lto_append_to_compression_stream (struct lto_compression_stream *stream,
123 const char *base, size_t num_chars)
125 size_t required = stream->bytes + num_chars;
127 if (stream->allocation < required)
129 if (stream->allocation == 0)
130 stream->allocation = MIN_STREAM_ALLOCATION;
131 while (stream->allocation < required)
132 stream->allocation *= 2;
134 stream->buffer = (char *) xrealloc (stream->buffer, stream->allocation);
137 memcpy (stream->buffer + stream->bytes, base, num_chars);
138 stream->bytes += num_chars;
141 /* Free the buffer and memory associated with STREAM. */
143 static void
144 lto_destroy_compression_stream (struct lto_compression_stream *stream)
146 free (stream->buffer);
147 free (stream);
150 /* Return a new compression stream, with CALLBACK flush function passed
151 OPAQUE token. */
153 struct lto_compression_stream *
154 lto_start_compression (void (*callback) (const char *, unsigned, void *),
155 void *opaque)
157 return lto_new_compression_stream (callback, opaque, true);
160 /* Append NUM_CHARS from address BASE to STREAM. */
162 void
163 lto_compress_block (struct lto_compression_stream *stream,
164 const char *base, size_t num_chars)
166 gcc_assert (stream->is_compression);
168 lto_append_to_compression_stream (stream, base, num_chars);
169 lto_stats.num_output_il_bytes += num_chars;
172 /* Finalize STREAM compression, and free stream allocations. */
174 void
175 lto_end_compression (struct lto_compression_stream *stream)
177 unsigned char *cursor = (unsigned char *) stream->buffer;
178 size_t remaining = stream->bytes;
179 const size_t outbuf_length = Z_BUFFER_LENGTH;
180 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
181 z_stream out_stream;
182 size_t compressed_bytes = 0;
183 int status;
185 gcc_assert (stream->is_compression);
187 out_stream.next_out = outbuf;
188 out_stream.avail_out = outbuf_length;
189 out_stream.next_in = cursor;
190 out_stream.avail_in = remaining;
191 out_stream.zalloc = lto_zalloc;
192 out_stream.zfree = lto_zfree;
193 out_stream.opaque = Z_NULL;
195 status = deflateInit (&out_stream, lto_normalized_zlib_level ());
196 if (status != Z_OK)
197 internal_error ("compressed stream: %s", zError (status));
201 size_t in_bytes, out_bytes;
203 status = deflate (&out_stream, Z_FINISH);
204 if (status != Z_OK && status != Z_STREAM_END)
205 internal_error ("compressed stream: %s", zError (status));
207 in_bytes = remaining - out_stream.avail_in;
208 out_bytes = outbuf_length - out_stream.avail_out;
210 stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
211 lto_stats.num_compressed_il_bytes += out_bytes;
212 compressed_bytes += out_bytes;
214 cursor += in_bytes;
215 remaining -= in_bytes;
217 out_stream.next_out = outbuf;
218 out_stream.avail_out = outbuf_length;
219 out_stream.next_in = cursor;
220 out_stream.avail_in = remaining;
222 while (status != Z_STREAM_END);
224 status = deflateEnd (&out_stream);
225 if (status != Z_OK)
226 internal_error ("compressed stream: %s", zError (status));
228 lto_destroy_compression_stream (stream);
229 free (outbuf);
232 /* Return a new uncompression stream, with CALLBACK flush function passed
233 OPAQUE token. */
235 struct lto_compression_stream *
236 lto_start_uncompression (void (*callback) (const char *, unsigned, void *),
237 void *opaque)
239 return lto_new_compression_stream (callback, opaque, false);
242 /* Append NUM_CHARS from address BASE to STREAM. */
244 void
245 lto_uncompress_block (struct lto_compression_stream *stream,
246 const char *base, size_t num_chars)
248 gcc_assert (!stream->is_compression);
250 lto_append_to_compression_stream (stream, base, num_chars);
251 lto_stats.num_input_il_bytes += num_chars;
254 /* Finalize STREAM uncompression, and free stream allocations.
256 Because of the way LTO IL streams are compressed, there may be several
257 concatenated compressed segments in the accumulated data, so for this
258 function we iterate decompressions until no data remains. */
260 void
261 lto_end_uncompression (struct lto_compression_stream *stream)
263 unsigned char *cursor = (unsigned char *) stream->buffer;
264 size_t remaining = stream->bytes;
265 const size_t outbuf_length = Z_BUFFER_LENGTH;
266 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
267 size_t uncompressed_bytes = 0;
269 gcc_assert (!stream->is_compression);
271 while (remaining > 0)
273 z_stream in_stream;
274 size_t out_bytes;
275 int status;
277 in_stream.next_out = outbuf;
278 in_stream.avail_out = outbuf_length;
279 in_stream.next_in = cursor;
280 in_stream.avail_in = remaining;
281 in_stream.zalloc = lto_zalloc;
282 in_stream.zfree = lto_zfree;
283 in_stream.opaque = Z_NULL;
285 status = inflateInit (&in_stream);
286 if (status != Z_OK)
287 internal_error ("compressed stream: %s", zError (status));
291 size_t in_bytes;
293 status = inflate (&in_stream, Z_SYNC_FLUSH);
294 if (status != Z_OK && status != Z_STREAM_END)
295 internal_error ("compressed stream: %s", zError (status));
297 in_bytes = remaining - in_stream.avail_in;
298 out_bytes = outbuf_length - in_stream.avail_out;
300 stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
301 lto_stats.num_uncompressed_il_bytes += out_bytes;
302 uncompressed_bytes += out_bytes;
304 cursor += in_bytes;
305 remaining -= in_bytes;
307 in_stream.next_out = outbuf;
308 in_stream.avail_out = outbuf_length;
309 in_stream.next_in = cursor;
310 in_stream.avail_in = remaining;
312 while (!(status == Z_STREAM_END && out_bytes == 0));
314 status = inflateEnd (&in_stream);
315 if (status != Z_OK)
316 internal_error ("compressed stream: %s", zError (status));
319 lto_destroy_compression_stream (stream);
320 free (outbuf);