re PR debug/66691 (ICE on valid code at -O3 with -g enabled in simplify_subreg, at...
[gcc.git] / gcc / lto-compress.c
1 /* LTO IL compression streams.
2
3 Copyright (C) 2009-2015 Free Software Foundation, Inc.
4 Contributed by Simon Baldwin <simonb@google.com>
5
6 This file is part of GCC.
7
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.
12
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.
17
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/>. */
21
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 "cgraph.h"
47 #include "lto-streamer.h"
48 #include "lto-compress.h"
49
50 /* Compression stream structure, holds the flush callback and opaque token,
51 the buffered data, and a note of whether compressing or uncompressing. */
52
53 struct lto_compression_stream
54 {
55 void (*callback) (const char *, unsigned, void *);
56 void *opaque;
57 char *buffer;
58 size_t bytes;
59 size_t allocation;
60 bool is_compression;
61 };
62
63 /* Overall compression constants for zlib. */
64
65 static const size_t Z_BUFFER_LENGTH = 4096;
66 static const size_t MIN_STREAM_ALLOCATION = 1024;
67
68 /* For zlib, allocate SIZE count of ITEMS and return the address, OPAQUE
69 is unused. */
70
71 static void *
72 lto_zalloc (void *opaque, unsigned items, unsigned size)
73 {
74 gcc_assert (opaque == Z_NULL);
75 return xmalloc (items * size);
76 }
77
78 /* For zlib, free memory at ADDRESS, OPAQUE is unused. */
79
80 static void
81 lto_zfree (void *opaque, void *address)
82 {
83 gcc_assert (opaque == Z_NULL);
84 free (address);
85 }
86
87 /* Return a zlib compression level that zlib will not reject. Normalizes
88 the compression level from the command line flag, clamping non-default
89 values to the appropriate end of their valid range. */
90
91 static int
92 lto_normalized_zlib_level (void)
93 {
94 int level = flag_lto_compression_level;
95
96 if (level != Z_DEFAULT_COMPRESSION)
97 {
98 if (level < Z_NO_COMPRESSION)
99 level = Z_NO_COMPRESSION;
100 else if (level > Z_BEST_COMPRESSION)
101 level = Z_BEST_COMPRESSION;
102 }
103
104 return level;
105 }
106
107 /* Create a new compression stream, with CALLBACK flush function passed
108 OPAQUE token, IS_COMPRESSION indicates if compressing or uncompressing. */
109
110 static struct lto_compression_stream *
111 lto_new_compression_stream (void (*callback) (const char *, unsigned, void *),
112 void *opaque, bool is_compression)
113 {
114 struct lto_compression_stream *stream
115 = (struct lto_compression_stream *) xmalloc (sizeof (*stream));
116
117 memset (stream, 0, sizeof (*stream));
118 stream->callback = callback;
119 stream->opaque = opaque;
120 stream->is_compression = is_compression;
121
122 return stream;
123 }
124
125 /* Append NUM_CHARS from address BASE to STREAM. */
126
127 static void
128 lto_append_to_compression_stream (struct lto_compression_stream *stream,
129 const char *base, size_t num_chars)
130 {
131 size_t required = stream->bytes + num_chars;
132
133 if (stream->allocation < required)
134 {
135 if (stream->allocation == 0)
136 stream->allocation = MIN_STREAM_ALLOCATION;
137 while (stream->allocation < required)
138 stream->allocation *= 2;
139
140 stream->buffer = (char *) xrealloc (stream->buffer, stream->allocation);
141 }
142
143 memcpy (stream->buffer + stream->bytes, base, num_chars);
144 stream->bytes += num_chars;
145 }
146
147 /* Free the buffer and memory associated with STREAM. */
148
149 static void
150 lto_destroy_compression_stream (struct lto_compression_stream *stream)
151 {
152 free (stream->buffer);
153 free (stream);
154 }
155
156 /* Return a new compression stream, with CALLBACK flush function passed
157 OPAQUE token. */
158
159 struct lto_compression_stream *
160 lto_start_compression (void (*callback) (const char *, unsigned, void *),
161 void *opaque)
162 {
163 return lto_new_compression_stream (callback, opaque, true);
164 }
165
166 /* Append NUM_CHARS from address BASE to STREAM. */
167
168 void
169 lto_compress_block (struct lto_compression_stream *stream,
170 const char *base, size_t num_chars)
171 {
172 gcc_assert (stream->is_compression);
173
174 lto_append_to_compression_stream (stream, base, num_chars);
175 lto_stats.num_output_il_bytes += num_chars;
176 }
177
178 /* Finalize STREAM compression, and free stream allocations. */
179
180 void
181 lto_end_compression (struct lto_compression_stream *stream)
182 {
183 unsigned char *cursor = (unsigned char *) stream->buffer;
184 size_t remaining = stream->bytes;
185 const size_t outbuf_length = Z_BUFFER_LENGTH;
186 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
187 z_stream out_stream;
188 size_t compressed_bytes = 0;
189 int status;
190
191 gcc_assert (stream->is_compression);
192
193 out_stream.next_out = outbuf;
194 out_stream.avail_out = outbuf_length;
195 out_stream.next_in = cursor;
196 out_stream.avail_in = remaining;
197 out_stream.zalloc = lto_zalloc;
198 out_stream.zfree = lto_zfree;
199 out_stream.opaque = Z_NULL;
200
201 status = deflateInit (&out_stream, lto_normalized_zlib_level ());
202 if (status != Z_OK)
203 internal_error ("compressed stream: %s", zError (status));
204
205 do
206 {
207 size_t in_bytes, out_bytes;
208
209 status = deflate (&out_stream, Z_FINISH);
210 if (status != Z_OK && status != Z_STREAM_END)
211 internal_error ("compressed stream: %s", zError (status));
212
213 in_bytes = remaining - out_stream.avail_in;
214 out_bytes = outbuf_length - out_stream.avail_out;
215
216 stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
217 lto_stats.num_compressed_il_bytes += out_bytes;
218 compressed_bytes += out_bytes;
219
220 cursor += in_bytes;
221 remaining -= in_bytes;
222
223 out_stream.next_out = outbuf;
224 out_stream.avail_out = outbuf_length;
225 out_stream.next_in = cursor;
226 out_stream.avail_in = remaining;
227 }
228 while (status != Z_STREAM_END);
229
230 status = deflateEnd (&out_stream);
231 if (status != Z_OK)
232 internal_error ("compressed stream: %s", zError (status));
233
234 lto_destroy_compression_stream (stream);
235 free (outbuf);
236 }
237
238 /* Return a new uncompression stream, with CALLBACK flush function passed
239 OPAQUE token. */
240
241 struct lto_compression_stream *
242 lto_start_uncompression (void (*callback) (const char *, unsigned, void *),
243 void *opaque)
244 {
245 return lto_new_compression_stream (callback, opaque, false);
246 }
247
248 /* Append NUM_CHARS from address BASE to STREAM. */
249
250 void
251 lto_uncompress_block (struct lto_compression_stream *stream,
252 const char *base, size_t num_chars)
253 {
254 gcc_assert (!stream->is_compression);
255
256 lto_append_to_compression_stream (stream, base, num_chars);
257 lto_stats.num_input_il_bytes += num_chars;
258 }
259
260 /* Finalize STREAM uncompression, and free stream allocations.
261
262 Because of the way LTO IL streams are compressed, there may be several
263 concatenated compressed segments in the accumulated data, so for this
264 function we iterate decompressions until no data remains. */
265
266 void
267 lto_end_uncompression (struct lto_compression_stream *stream)
268 {
269 unsigned char *cursor = (unsigned char *) stream->buffer;
270 size_t remaining = stream->bytes;
271 const size_t outbuf_length = Z_BUFFER_LENGTH;
272 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
273 size_t uncompressed_bytes = 0;
274
275 gcc_assert (!stream->is_compression);
276
277 while (remaining > 0)
278 {
279 z_stream in_stream;
280 size_t out_bytes;
281 int status;
282
283 in_stream.next_out = outbuf;
284 in_stream.avail_out = outbuf_length;
285 in_stream.next_in = cursor;
286 in_stream.avail_in = remaining;
287 in_stream.zalloc = lto_zalloc;
288 in_stream.zfree = lto_zfree;
289 in_stream.opaque = Z_NULL;
290
291 status = inflateInit (&in_stream);
292 if (status != Z_OK)
293 internal_error ("compressed stream: %s", zError (status));
294
295 do
296 {
297 size_t in_bytes;
298
299 status = inflate (&in_stream, Z_SYNC_FLUSH);
300 if (status != Z_OK && status != Z_STREAM_END)
301 internal_error ("compressed stream: %s", zError (status));
302
303 in_bytes = remaining - in_stream.avail_in;
304 out_bytes = outbuf_length - in_stream.avail_out;
305
306 stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
307 lto_stats.num_uncompressed_il_bytes += out_bytes;
308 uncompressed_bytes += out_bytes;
309
310 cursor += in_bytes;
311 remaining -= in_bytes;
312
313 in_stream.next_out = outbuf;
314 in_stream.avail_out = outbuf_length;
315 in_stream.next_in = cursor;
316 in_stream.avail_in = remaining;
317 }
318 while (!(status == Z_STREAM_END && out_bytes == 0));
319
320 status = inflateEnd (&in_stream);
321 if (status != Z_OK)
322 internal_error ("compressed stream: %s", zError (status));
323 }
324
325 lto_destroy_compression_stream (stream);
326 free (outbuf);
327 }