comparison gcc/lto-compress.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
comparison
equal deleted inserted replaced
131:84e7813d76e9 145:1830386684a0
1 /* LTO IL compression streams. 1 /* LTO IL compression streams.
2 2
3 Copyright (C) 2009-2018 Free Software Foundation, Inc. 3 Copyright (C) 2009-2020 Free Software Foundation, Inc.
4 Contributed by Simon Baldwin <simonb@google.com> 4 Contributed by Simon Baldwin <simonb@google.com>
5 5
6 This file is part of GCC. 6 This file is part of GCC.
7 7
8 GCC is free software; you can redistribute it and/or modify it 8 GCC is free software; you can redistribute it and/or modify it
33 system.h. */ 33 system.h. */
34 #include <zlib.h> 34 #include <zlib.h>
35 #include "lto-compress.h" 35 #include "lto-compress.h"
36 #include "timevar.h" 36 #include "timevar.h"
37 37
38 #ifdef HAVE_ZSTD_H
39 #include <zstd.h>
40 #endif
41
38 /* Compression stream structure, holds the flush callback and opaque token, 42 /* Compression stream structure, holds the flush callback and opaque token,
39 the buffered data, and a note of whether compressing or uncompressing. */ 43 the buffered data, and a note of whether compressing or uncompressing. */
40 44
41 struct lto_compression_stream 45 struct lto_compression_stream
42 { 46 {
90 } 94 }
91 95
92 return level; 96 return level;
93 } 97 }
94 98
99 /* Free the buffer and memory associated with STREAM. */
100
101 static void
102 lto_destroy_compression_stream (struct lto_compression_stream *stream)
103 {
104 free (stream->buffer);
105 free (stream);
106 }
107
108 #ifdef HAVE_ZSTD_H
109 /* Return a zstd compression level that zstd will not reject. Normalizes
110 the compression level from the command line flag, clamping non-default
111 values to the appropriate end of their valid range. */
112
113 static int
114 lto_normalized_zstd_level (void)
115 {
116 int level = flag_lto_compression_level;
117
118 if (level < 0)
119 level = 0;
120 else if (level > ZSTD_maxCLevel ())
121 level = ZSTD_maxCLevel ();
122
123 return level;
124 }
125
126 /* Compress STREAM using ZSTD algorithm. */
127
128 static void
129 lto_compression_zstd (struct lto_compression_stream *stream)
130 {
131 unsigned char *cursor = (unsigned char *) stream->buffer;
132 size_t size = stream->bytes;
133
134 timevar_push (TV_IPA_LTO_COMPRESS);
135 size_t const outbuf_length = ZSTD_compressBound (size);
136 char *outbuf = (char *) xmalloc (outbuf_length);
137
138 size_t const csize = ZSTD_compress (outbuf, outbuf_length, cursor, size,
139 lto_normalized_zstd_level ());
140
141 if (ZSTD_isError (csize))
142 internal_error ("compressed stream: %s", ZSTD_getErrorName (csize));
143
144 stream->callback (outbuf, csize, NULL);
145
146 lto_destroy_compression_stream (stream);
147 free (outbuf);
148 timevar_pop (TV_IPA_LTO_COMPRESS);
149 }
150
151 /* Uncompress STREAM using ZSTD algorithm. */
152
153 static void
154 lto_uncompression_zstd (struct lto_compression_stream *stream)
155 {
156 unsigned char *cursor = (unsigned char *) stream->buffer;
157 size_t size = stream->bytes;
158
159 timevar_push (TV_IPA_LTO_DECOMPRESS);
160 unsigned long long const rsize = ZSTD_getFrameContentSize (cursor, size);
161 if (rsize == ZSTD_CONTENTSIZE_ERROR)
162 internal_error ("original not compressed with zstd");
163 else if (rsize == ZSTD_CONTENTSIZE_UNKNOWN)
164 internal_error ("original size unknown");
165
166 char *outbuf = (char *) xmalloc (rsize);
167 size_t const dsize = ZSTD_decompress (outbuf, rsize, cursor, size);
168
169 if (ZSTD_isError (dsize))
170 internal_error ("decompressed stream: %s", ZSTD_getErrorName (dsize));
171
172 stream->callback (outbuf, dsize, stream->opaque);
173
174 lto_destroy_compression_stream (stream);
175 free (outbuf);
176 timevar_pop (TV_IPA_LTO_DECOMPRESS);
177 }
178
179 #endif
180
95 /* Create a new compression stream, with CALLBACK flush function passed 181 /* Create a new compression stream, with CALLBACK flush function passed
96 OPAQUE token, IS_COMPRESSION indicates if compressing or uncompressing. */ 182 OPAQUE token, IS_COMPRESSION indicates if compressing or uncompressing. */
97 183
98 static struct lto_compression_stream * 184 static struct lto_compression_stream *
99 lto_new_compression_stream (void (*callback) (const char *, unsigned, void *), 185 lto_new_compression_stream (void (*callback) (const char *, unsigned, void *),
130 216
131 memcpy (stream->buffer + stream->bytes, base, num_chars); 217 memcpy (stream->buffer + stream->bytes, base, num_chars);
132 stream->bytes += num_chars; 218 stream->bytes += num_chars;
133 } 219 }
134 220
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 221 /* Return a new compression stream, with CALLBACK flush function passed
145 OPAQUE token. */ 222 OPAQUE token. */
146 223
147 struct lto_compression_stream * 224 struct lto_compression_stream *
148 lto_start_compression (void (*callback) (const char *, unsigned, void *), 225 lto_start_compression (void (*callback) (const char *, unsigned, void *),
161 238
162 lto_append_to_compression_stream (stream, base, num_chars); 239 lto_append_to_compression_stream (stream, base, num_chars);
163 lto_stats.num_output_il_bytes += num_chars; 240 lto_stats.num_output_il_bytes += num_chars;
164 } 241 }
165 242
166 /* Finalize STREAM compression, and free stream allocations. */ 243 static void ATTRIBUTE_UNUSED
167 244 lto_compression_zlib (struct lto_compression_stream *stream)
168 void
169 lto_end_compression (struct lto_compression_stream *stream)
170 { 245 {
171 unsigned char *cursor = (unsigned char *) stream->buffer; 246 unsigned char *cursor = (unsigned char *) stream->buffer;
172 size_t remaining = stream->bytes; 247 size_t remaining = stream->bytes;
173 const size_t outbuf_length = Z_BUFFER_LENGTH; 248 const size_t outbuf_length = Z_BUFFER_LENGTH;
174 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length); 249 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
224 lto_destroy_compression_stream (stream); 299 lto_destroy_compression_stream (stream);
225 free (outbuf); 300 free (outbuf);
226 timevar_pop (TV_IPA_LTO_COMPRESS); 301 timevar_pop (TV_IPA_LTO_COMPRESS);
227 } 302 }
228 303
304 void
305 lto_end_compression (struct lto_compression_stream *stream)
306 {
307 #ifdef HAVE_ZSTD_H
308 lto_compression_zstd (stream);
309 #else
310 lto_compression_zlib (stream);
311 #endif
312 }
313
229 /* Return a new uncompression stream, with CALLBACK flush function passed 314 /* Return a new uncompression stream, with CALLBACK flush function passed
230 OPAQUE token. */ 315 OPAQUE token. */
231 316
232 struct lto_compression_stream * 317 struct lto_compression_stream *
233 lto_start_uncompression (void (*callback) (const char *, unsigned, void *), 318 lto_start_uncompression (void (*callback) (const char *, unsigned, void *),
246 331
247 lto_append_to_compression_stream (stream, base, num_chars); 332 lto_append_to_compression_stream (stream, base, num_chars);
248 lto_stats.num_input_il_bytes += num_chars; 333 lto_stats.num_input_il_bytes += num_chars;
249 } 334 }
250 335
251 /* Finalize STREAM uncompression, and free stream allocations. 336 static void
252 337 lto_uncompression_zlib (struct lto_compression_stream *stream)
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 { 338 {
260 unsigned char *cursor = (unsigned char *) stream->buffer; 339 unsigned char *cursor = (unsigned char *) stream->buffer;
261 size_t remaining = stream->bytes; 340 size_t remaining = stream->bytes;
262 const size_t outbuf_length = Z_BUFFER_LENGTH; 341 const size_t outbuf_length = Z_BUFFER_LENGTH;
263 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length); 342 unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
316 395
317 lto_destroy_compression_stream (stream); 396 lto_destroy_compression_stream (stream);
318 free (outbuf); 397 free (outbuf);
319 timevar_pop (TV_IPA_LTO_DECOMPRESS); 398 timevar_pop (TV_IPA_LTO_DECOMPRESS);
320 } 399 }
400
401 void
402 lto_end_uncompression (struct lto_compression_stream *stream,
403 lto_compression compression)
404 {
405 #ifdef HAVE_ZSTD_H
406 if (compression == ZSTD)
407 {
408 lto_uncompression_zstd (stream);
409 return;
410 }
411 #endif
412 if (compression == ZSTD)
413 internal_error ("compiler does not support ZSTD LTO compression");
414
415 lto_uncompression_zlib (stream);
416 }