[gcc/]
[official-gcc.git] / gcc / lto-compress.c
blob4d718d5c08e3b6ce6c001a9a6a0462debb0f7cea
1 /* LTO IL compression streams.
3 Copyright (C) 2009-2014 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 "tree.h"
31 #include "basic-block.h"
32 #include "tree-ssa-alias.h"
33 #include "internal-fn.h"
34 #include "gimple-expr.h"
35 #include "is-a.h"
36 #include "gimple.h"
37 #include "diagnostic-core.h"
38 #include "langhooks.h"
39 #include "lto-streamer.h"
40 #include "lto-compress.h"
42 /* Compression stream structure, holds the flush callback and opaque token,
43 the buffered data, and a note of whether compressing or uncompressing. */
45 struct lto_compression_stream
47 void (*callback) (const char *, unsigned, void *);
48 void *opaque;
49 char *buffer;
50 size_t bytes;
51 size_t allocation;
52 bool is_compression;
55 /* Overall compression constants for zlib. */
57 static const size_t Z_BUFFER_LENGTH = 4096;
58 static const size_t MIN_STREAM_ALLOCATION = 1024;
60 /* For zlib, allocate SIZE count of ITEMS and return the address, OPAQUE
61 is unused. */
63 static void *
64 lto_zalloc (void *opaque, unsigned items, unsigned size)
66 gcc_assert (opaque == Z_NULL);
67 return xmalloc (items * size);
70 /* For zlib, free memory at ADDRESS, OPAQUE is unused. */
72 static void
73 lto_zfree (void *opaque, void *address)
75 gcc_assert (opaque == Z_NULL);
76 free (address);
79 /* Return a zlib compression level that zlib will not reject. Normalizes
80 the compression level from the command line flag, clamping non-default
81 values to the appropriate end of their valid range. */
83 static int
84 lto_normalized_zlib_level (void)
86 int level = flag_lto_compression_level;
88 if (level != Z_DEFAULT_COMPRESSION)
90 if (level < Z_NO_COMPRESSION)
91 level = Z_NO_COMPRESSION;
92 else if (level > Z_BEST_COMPRESSION)
93 level = Z_BEST_COMPRESSION;
96 return level;
99 /* Create a new compression stream, with CALLBACK flush function passed
100 OPAQUE token, IS_COMPRESSION indicates if compressing or uncompressing. */
102 static struct lto_compression_stream *
103 lto_new_compression_stream (void (*callback) (const char *, unsigned, void *),
104 void *opaque, bool is_compression)
106 struct lto_compression_stream *stream
107 = (struct lto_compression_stream *) xmalloc (sizeof (*stream));
109 memset (stream, 0, sizeof (*stream));
110 stream->callback = callback;
111 stream->opaque = opaque;
112 stream->is_compression = is_compression;
114 return stream;
117 /* Append NUM_CHARS from address BASE to STREAM. */
119 static void
120 lto_append_to_compression_stream (struct lto_compression_stream *stream,
121 const char *base, size_t num_chars)
123 size_t required = stream->bytes + num_chars;
125 if (stream->allocation < required)
127 if (stream->allocation == 0)
128 stream->allocation = MIN_STREAM_ALLOCATION;
129 while (stream->allocation < required)
130 stream->allocation *= 2;
132 stream->buffer = (char *) xrealloc (stream->buffer, stream->allocation);
135 memcpy (stream->buffer + stream->bytes, base, num_chars);
136 stream->bytes += num_chars;
139 /* Free the buffer and memory associated with STREAM. */
141 static void
142 lto_destroy_compression_stream (struct lto_compression_stream *stream)
144 free (stream->buffer);
145 free (stream);
148 /* Return a new compression stream, with CALLBACK flush function passed
149 OPAQUE token. */
151 struct lto_compression_stream *
152 lto_start_compression (void (*callback) (const char *, unsigned, void *),
153 void *opaque)
155 return lto_new_compression_stream (callback, opaque, true);
158 /* Append NUM_CHARS from address BASE to STREAM. */
160 void
161 lto_compress_block (struct lto_compression_stream *stream,
162 const char *base, size_t num_chars)
164 gcc_assert (stream->is_compression);
166 lto_append_to_compression_stream (stream, base, num_chars);
167 lto_stats.num_output_il_bytes += num_chars;
170 /* Finalize STREAM compression, and free stream allocations. */
172 void
173 lto_end_compression (struct lto_compression_stream *stream)
175 unsigned char *cursor = (unsigned char *) stream->buffer;
176 size_t remaining = stream->bytes;
177 const size_t outbuf_length = Z_BUFFER_LENGTH;
178 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
179 z_stream out_stream;
180 size_t compressed_bytes = 0;
181 int status;
183 gcc_assert (stream->is_compression);
185 out_stream.next_out = outbuf;
186 out_stream.avail_out = outbuf_length;
187 out_stream.next_in = cursor;
188 out_stream.avail_in = remaining;
189 out_stream.zalloc = lto_zalloc;
190 out_stream.zfree = lto_zfree;
191 out_stream.opaque = Z_NULL;
193 status = deflateInit (&out_stream, lto_normalized_zlib_level ());
194 if (status != Z_OK)
195 internal_error ("compressed stream: %s", zError (status));
199 size_t in_bytes, out_bytes;
201 status = deflate (&out_stream, Z_FINISH);
202 if (status != Z_OK && status != Z_STREAM_END)
203 internal_error ("compressed stream: %s", zError (status));
205 in_bytes = remaining - out_stream.avail_in;
206 out_bytes = outbuf_length - out_stream.avail_out;
208 stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
209 lto_stats.num_compressed_il_bytes += out_bytes;
210 compressed_bytes += out_bytes;
212 cursor += in_bytes;
213 remaining -= in_bytes;
215 out_stream.next_out = outbuf;
216 out_stream.avail_out = outbuf_length;
217 out_stream.next_in = cursor;
218 out_stream.avail_in = remaining;
220 while (status != Z_STREAM_END);
222 status = deflateEnd (&out_stream);
223 if (status != Z_OK)
224 internal_error ("compressed stream: %s", zError (status));
226 lto_destroy_compression_stream (stream);
227 free (outbuf);
230 /* Return a new uncompression stream, with CALLBACK flush function passed
231 OPAQUE token. */
233 struct lto_compression_stream *
234 lto_start_uncompression (void (*callback) (const char *, unsigned, void *),
235 void *opaque)
237 return lto_new_compression_stream (callback, opaque, false);
240 /* Append NUM_CHARS from address BASE to STREAM. */
242 void
243 lto_uncompress_block (struct lto_compression_stream *stream,
244 const char *base, size_t num_chars)
246 gcc_assert (!stream->is_compression);
248 lto_append_to_compression_stream (stream, base, num_chars);
249 lto_stats.num_input_il_bytes += num_chars;
252 /* Finalize STREAM uncompression, and free stream allocations.
254 Because of the way LTO IL streams are compressed, there may be several
255 concatenated compressed segments in the accumulated data, so for this
256 function we iterate decompressions until no data remains. */
258 void
259 lto_end_uncompression (struct lto_compression_stream *stream)
261 unsigned char *cursor = (unsigned char *) stream->buffer;
262 size_t remaining = stream->bytes;
263 const size_t outbuf_length = Z_BUFFER_LENGTH;
264 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
265 size_t uncompressed_bytes = 0;
267 gcc_assert (!stream->is_compression);
269 while (remaining > 0)
271 z_stream in_stream;
272 size_t out_bytes;
273 int status;
275 in_stream.next_out = outbuf;
276 in_stream.avail_out = outbuf_length;
277 in_stream.next_in = cursor;
278 in_stream.avail_in = remaining;
279 in_stream.zalloc = lto_zalloc;
280 in_stream.zfree = lto_zfree;
281 in_stream.opaque = Z_NULL;
283 status = inflateInit (&in_stream);
284 if (status != Z_OK)
285 internal_error ("compressed stream: %s", zError (status));
289 size_t in_bytes;
291 status = inflate (&in_stream, Z_SYNC_FLUSH);
292 if (status != Z_OK && status != Z_STREAM_END)
293 internal_error ("compressed stream: %s", zError (status));
295 in_bytes = remaining - in_stream.avail_in;
296 out_bytes = outbuf_length - in_stream.avail_out;
298 stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
299 lto_stats.num_uncompressed_il_bytes += out_bytes;
300 uncompressed_bytes += out_bytes;
302 cursor += in_bytes;
303 remaining -= in_bytes;
305 in_stream.next_out = outbuf;
306 in_stream.avail_out = outbuf_length;
307 in_stream.next_in = cursor;
308 in_stream.avail_in = remaining;
310 while (!(status == Z_STREAM_END && out_bytes == 0));
312 status = inflateEnd (&in_stream);
313 if (status != Z_OK)
314 internal_error ("compressed stream: %s", zError (status));
317 lto_destroy_compression_stream (stream);
318 free (outbuf);