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)
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/>. */
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
29 #include "coretypes.h"
38 #include "fold-const.h"
41 #include "hard-reg-set.h"
44 #include "basic-block.h"
45 #include "tree-ssa-alias.h"
46 #include "internal-fn.h"
47 #include "gimple-expr.h"
50 #include "diagnostic-core.h"
51 #include "langhooks.h"
53 #include "plugin-api.h"
56 #include "lto-streamer.h"
57 #include "lto-compress.h"
59 /* Compression stream structure, holds the flush callback and opaque token,
60 the buffered data, and a note of whether compressing or uncompressing. */
62 struct lto_compression_stream
64 void (*callback
) (const char *, unsigned, void *);
72 /* Overall compression constants for zlib. */
74 static const size_t Z_BUFFER_LENGTH
= 4096;
75 static const size_t MIN_STREAM_ALLOCATION
= 1024;
77 /* For zlib, allocate SIZE count of ITEMS and return the address, OPAQUE
81 lto_zalloc (void *opaque
, unsigned items
, unsigned size
)
83 gcc_assert (opaque
== Z_NULL
);
84 return xmalloc (items
* size
);
87 /* For zlib, free memory at ADDRESS, OPAQUE is unused. */
90 lto_zfree (void *opaque
, void *address
)
92 gcc_assert (opaque
== Z_NULL
);
96 /* Return a zlib compression level that zlib will not reject. Normalizes
97 the compression level from the command line flag, clamping non-default
98 values to the appropriate end of their valid range. */
101 lto_normalized_zlib_level (void)
103 int level
= flag_lto_compression_level
;
105 if (level
!= Z_DEFAULT_COMPRESSION
)
107 if (level
< Z_NO_COMPRESSION
)
108 level
= Z_NO_COMPRESSION
;
109 else if (level
> Z_BEST_COMPRESSION
)
110 level
= Z_BEST_COMPRESSION
;
116 /* Create a new compression stream, with CALLBACK flush function passed
117 OPAQUE token, IS_COMPRESSION indicates if compressing or uncompressing. */
119 static struct lto_compression_stream
*
120 lto_new_compression_stream (void (*callback
) (const char *, unsigned, void *),
121 void *opaque
, bool is_compression
)
123 struct lto_compression_stream
*stream
124 = (struct lto_compression_stream
*) xmalloc (sizeof (*stream
));
126 memset (stream
, 0, sizeof (*stream
));
127 stream
->callback
= callback
;
128 stream
->opaque
= opaque
;
129 stream
->is_compression
= is_compression
;
134 /* Append NUM_CHARS from address BASE to STREAM. */
137 lto_append_to_compression_stream (struct lto_compression_stream
*stream
,
138 const char *base
, size_t num_chars
)
140 size_t required
= stream
->bytes
+ num_chars
;
142 if (stream
->allocation
< required
)
144 if (stream
->allocation
== 0)
145 stream
->allocation
= MIN_STREAM_ALLOCATION
;
146 while (stream
->allocation
< required
)
147 stream
->allocation
*= 2;
149 stream
->buffer
= (char *) xrealloc (stream
->buffer
, stream
->allocation
);
152 memcpy (stream
->buffer
+ stream
->bytes
, base
, num_chars
);
153 stream
->bytes
+= num_chars
;
156 /* Free the buffer and memory associated with STREAM. */
159 lto_destroy_compression_stream (struct lto_compression_stream
*stream
)
161 free (stream
->buffer
);
165 /* Return a new compression stream, with CALLBACK flush function passed
168 struct lto_compression_stream
*
169 lto_start_compression (void (*callback
) (const char *, unsigned, void *),
172 return lto_new_compression_stream (callback
, opaque
, true);
175 /* Append NUM_CHARS from address BASE to STREAM. */
178 lto_compress_block (struct lto_compression_stream
*stream
,
179 const char *base
, size_t num_chars
)
181 gcc_assert (stream
->is_compression
);
183 lto_append_to_compression_stream (stream
, base
, num_chars
);
184 lto_stats
.num_output_il_bytes
+= num_chars
;
187 /* Finalize STREAM compression, and free stream allocations. */
190 lto_end_compression (struct lto_compression_stream
*stream
)
192 unsigned char *cursor
= (unsigned char *) stream
->buffer
;
193 size_t remaining
= stream
->bytes
;
194 const size_t outbuf_length
= Z_BUFFER_LENGTH
;
195 unsigned char *outbuf
= (unsigned char *) xmalloc (outbuf_length
);
197 size_t compressed_bytes
= 0;
200 gcc_assert (stream
->is_compression
);
202 out_stream
.next_out
= outbuf
;
203 out_stream
.avail_out
= outbuf_length
;
204 out_stream
.next_in
= cursor
;
205 out_stream
.avail_in
= remaining
;
206 out_stream
.zalloc
= lto_zalloc
;
207 out_stream
.zfree
= lto_zfree
;
208 out_stream
.opaque
= Z_NULL
;
210 status
= deflateInit (&out_stream
, lto_normalized_zlib_level ());
212 internal_error ("compressed stream: %s", zError (status
));
216 size_t in_bytes
, out_bytes
;
218 status
= deflate (&out_stream
, Z_FINISH
);
219 if (status
!= Z_OK
&& status
!= Z_STREAM_END
)
220 internal_error ("compressed stream: %s", zError (status
));
222 in_bytes
= remaining
- out_stream
.avail_in
;
223 out_bytes
= outbuf_length
- out_stream
.avail_out
;
225 stream
->callback ((const char *) outbuf
, out_bytes
, stream
->opaque
);
226 lto_stats
.num_compressed_il_bytes
+= out_bytes
;
227 compressed_bytes
+= out_bytes
;
230 remaining
-= in_bytes
;
232 out_stream
.next_out
= outbuf
;
233 out_stream
.avail_out
= outbuf_length
;
234 out_stream
.next_in
= cursor
;
235 out_stream
.avail_in
= remaining
;
237 while (status
!= Z_STREAM_END
);
239 status
= deflateEnd (&out_stream
);
241 internal_error ("compressed stream: %s", zError (status
));
243 lto_destroy_compression_stream (stream
);
247 /* Return a new uncompression stream, with CALLBACK flush function passed
250 struct lto_compression_stream
*
251 lto_start_uncompression (void (*callback
) (const char *, unsigned, void *),
254 return lto_new_compression_stream (callback
, opaque
, false);
257 /* Append NUM_CHARS from address BASE to STREAM. */
260 lto_uncompress_block (struct lto_compression_stream
*stream
,
261 const char *base
, size_t num_chars
)
263 gcc_assert (!stream
->is_compression
);
265 lto_append_to_compression_stream (stream
, base
, num_chars
);
266 lto_stats
.num_input_il_bytes
+= num_chars
;
269 /* Finalize STREAM uncompression, and free stream allocations.
271 Because of the way LTO IL streams are compressed, there may be several
272 concatenated compressed segments in the accumulated data, so for this
273 function we iterate decompressions until no data remains. */
276 lto_end_uncompression (struct lto_compression_stream
*stream
)
278 unsigned char *cursor
= (unsigned char *) stream
->buffer
;
279 size_t remaining
= stream
->bytes
;
280 const size_t outbuf_length
= Z_BUFFER_LENGTH
;
281 unsigned char *outbuf
= (unsigned char *) xmalloc (outbuf_length
);
282 size_t uncompressed_bytes
= 0;
284 gcc_assert (!stream
->is_compression
);
286 while (remaining
> 0)
292 in_stream
.next_out
= outbuf
;
293 in_stream
.avail_out
= outbuf_length
;
294 in_stream
.next_in
= cursor
;
295 in_stream
.avail_in
= remaining
;
296 in_stream
.zalloc
= lto_zalloc
;
297 in_stream
.zfree
= lto_zfree
;
298 in_stream
.opaque
= Z_NULL
;
300 status
= inflateInit (&in_stream
);
302 internal_error ("compressed stream: %s", zError (status
));
308 status
= inflate (&in_stream
, Z_SYNC_FLUSH
);
309 if (status
!= Z_OK
&& status
!= Z_STREAM_END
)
310 internal_error ("compressed stream: %s", zError (status
));
312 in_bytes
= remaining
- in_stream
.avail_in
;
313 out_bytes
= outbuf_length
- in_stream
.avail_out
;
315 stream
->callback ((const char *) outbuf
, out_bytes
, stream
->opaque
);
316 lto_stats
.num_uncompressed_il_bytes
+= out_bytes
;
317 uncompressed_bytes
+= out_bytes
;
320 remaining
-= in_bytes
;
322 in_stream
.next_out
= outbuf
;
323 in_stream
.avail_out
= outbuf_length
;
324 in_stream
.next_in
= cursor
;
325 in_stream
.avail_in
= remaining
;
327 while (!(status
== Z_STREAM_END
&& out_bytes
== 0));
329 status
= inflateEnd (&in_stream
);
331 internal_error ("compressed stream: %s", zError (status
));
334 lto_destroy_compression_stream (stream
);