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