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