OSDN Git Service

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