1 |
280 |
jeremybenn |
/* Write the GIMPLE representation to a file stream.
|
2 |
|
|
|
3 |
|
|
Copyright 2009, 2010 Free Software Foundation, Inc.
|
4 |
|
|
Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
|
5 |
|
|
Re-implemented by Diego Novillo <dnovillo@google.com>
|
6 |
|
|
|
7 |
|
|
This file is part of GCC.
|
8 |
|
|
|
9 |
|
|
GCC is free software; you can redistribute it and/or modify it under
|
10 |
|
|
the terms of the GNU General Public License as published by the Free
|
11 |
|
|
Software Foundation; either version 3, or (at your option) any later
|
12 |
|
|
version.
|
13 |
|
|
|
14 |
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
15 |
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
16 |
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
17 |
|
|
for more details.
|
18 |
|
|
|
19 |
|
|
You should have received a copy of the GNU General Public License
|
20 |
|
|
along with GCC; see the file COPYING3. If not see
|
21 |
|
|
<http://www.gnu.org/licenses/>. */
|
22 |
|
|
|
23 |
|
|
#include "config.h"
|
24 |
|
|
#include "system.h"
|
25 |
|
|
#include "coretypes.h"
|
26 |
|
|
#include "tm.h"
|
27 |
|
|
#include "toplev.h"
|
28 |
|
|
#include "tree.h"
|
29 |
|
|
#include "expr.h"
|
30 |
|
|
#include "flags.h"
|
31 |
|
|
#include "params.h"
|
32 |
|
|
#include "input.h"
|
33 |
|
|
#include "varray.h"
|
34 |
|
|
#include "hashtab.h"
|
35 |
|
|
#include "basic-block.h"
|
36 |
|
|
#include "tree-flow.h"
|
37 |
|
|
#include "tree-pass.h"
|
38 |
|
|
#include "cgraph.h"
|
39 |
|
|
#include "function.h"
|
40 |
|
|
#include "ggc.h"
|
41 |
|
|
#include "diagnostic.h"
|
42 |
|
|
#include "except.h"
|
43 |
|
|
#include "vec.h"
|
44 |
|
|
#include "lto-symtab.h"
|
45 |
|
|
#include "lto-streamer.h"
|
46 |
|
|
|
47 |
|
|
|
48 |
|
|
struct string_slot
|
49 |
|
|
{
|
50 |
|
|
const char *s;
|
51 |
|
|
int len;
|
52 |
|
|
unsigned int slot_num;
|
53 |
|
|
};
|
54 |
|
|
|
55 |
|
|
|
56 |
|
|
/* Returns a hash code for P. */
|
57 |
|
|
|
58 |
|
|
static hashval_t
|
59 |
|
|
hash_string_slot_node (const void *p)
|
60 |
|
|
{
|
61 |
|
|
const struct string_slot *ds = (const struct string_slot *) p;
|
62 |
|
|
return (hashval_t) htab_hash_string (ds->s);
|
63 |
|
|
}
|
64 |
|
|
|
65 |
|
|
|
66 |
|
|
/* Returns nonzero if P1 and P2 are equal. */
|
67 |
|
|
|
68 |
|
|
static int
|
69 |
|
|
eq_string_slot_node (const void *p1, const void *p2)
|
70 |
|
|
{
|
71 |
|
|
const struct string_slot *ds1 = (const struct string_slot *) p1;
|
72 |
|
|
const struct string_slot *ds2 = (const struct string_slot *) p2;
|
73 |
|
|
|
74 |
|
|
if (ds1->len == ds2->len)
|
75 |
|
|
{
|
76 |
|
|
int i;
|
77 |
|
|
for (i = 0; i < ds1->len; i++)
|
78 |
|
|
if (ds1->s[i] != ds2->s[i])
|
79 |
|
|
return 0;
|
80 |
|
|
return 1;
|
81 |
|
|
}
|
82 |
|
|
|
83 |
|
|
return 0;
|
84 |
|
|
}
|
85 |
|
|
|
86 |
|
|
|
87 |
|
|
/* Free the string slot pointed-to by P. */
|
88 |
|
|
|
89 |
|
|
static void
|
90 |
|
|
string_slot_free (void *p)
|
91 |
|
|
{
|
92 |
|
|
struct string_slot *slot = (struct string_slot *) p;
|
93 |
|
|
free (CONST_CAST (void *, (const void *) slot->s));
|
94 |
|
|
free (slot);
|
95 |
|
|
}
|
96 |
|
|
|
97 |
|
|
|
98 |
|
|
/* Clear the line info stored in DATA_IN. */
|
99 |
|
|
|
100 |
|
|
static void
|
101 |
|
|
clear_line_info (struct output_block *ob)
|
102 |
|
|
{
|
103 |
|
|
ob->current_file = NULL;
|
104 |
|
|
ob->current_line = 0;
|
105 |
|
|
ob->current_col = 0;
|
106 |
|
|
}
|
107 |
|
|
|
108 |
|
|
|
109 |
|
|
/* Create the output block and return it. SECTION_TYPE is
|
110 |
|
|
LTO_section_function_body or LTO_static_initializer. */
|
111 |
|
|
|
112 |
|
|
struct output_block *
|
113 |
|
|
create_output_block (enum lto_section_type section_type)
|
114 |
|
|
{
|
115 |
|
|
struct output_block *ob = XCNEW (struct output_block);
|
116 |
|
|
|
117 |
|
|
ob->section_type = section_type;
|
118 |
|
|
ob->decl_state = lto_get_out_decl_state ();
|
119 |
|
|
ob->main_stream = XCNEW (struct lto_output_stream);
|
120 |
|
|
ob->string_stream = XCNEW (struct lto_output_stream);
|
121 |
|
|
ob->writer_cache = lto_streamer_cache_create ();
|
122 |
|
|
|
123 |
|
|
if (section_type == LTO_section_function_body)
|
124 |
|
|
ob->cfg_stream = XCNEW (struct lto_output_stream);
|
125 |
|
|
|
126 |
|
|
clear_line_info (ob);
|
127 |
|
|
|
128 |
|
|
ob->string_hash_table = htab_create (37, hash_string_slot_node,
|
129 |
|
|
eq_string_slot_node, string_slot_free);
|
130 |
|
|
|
131 |
|
|
return ob;
|
132 |
|
|
}
|
133 |
|
|
|
134 |
|
|
|
135 |
|
|
/* Destroy the output block OB. */
|
136 |
|
|
|
137 |
|
|
void
|
138 |
|
|
destroy_output_block (struct output_block *ob)
|
139 |
|
|
{
|
140 |
|
|
enum lto_section_type section_type = ob->section_type;
|
141 |
|
|
|
142 |
|
|
htab_delete (ob->string_hash_table);
|
143 |
|
|
|
144 |
|
|
free (ob->main_stream);
|
145 |
|
|
free (ob->string_stream);
|
146 |
|
|
if (section_type == LTO_section_function_body)
|
147 |
|
|
free (ob->cfg_stream);
|
148 |
|
|
|
149 |
|
|
lto_streamer_cache_delete (ob->writer_cache);
|
150 |
|
|
|
151 |
|
|
free (ob);
|
152 |
|
|
}
|
153 |
|
|
|
154 |
|
|
|
155 |
|
|
/* Output bitpack BP to output stream S. */
|
156 |
|
|
|
157 |
|
|
void
|
158 |
|
|
lto_output_bitpack (struct lto_output_stream *s, struct bitpack_d *bp)
|
159 |
|
|
{
|
160 |
|
|
unsigned i;
|
161 |
|
|
bitpack_word_t v;
|
162 |
|
|
|
163 |
|
|
lto_output_uleb128_stream (s, VEC_length (bitpack_word_t, bp->values));
|
164 |
|
|
for (i = 0; VEC_iterate (bitpack_word_t, bp->values, i, v); i++)
|
165 |
|
|
lto_output_uleb128_stream (s, v);
|
166 |
|
|
}
|
167 |
|
|
|
168 |
|
|
|
169 |
|
|
/* Output STRING of LEN characters to the string
|
170 |
|
|
table in OB. The string might or might not include a trailing '\0'.
|
171 |
|
|
Then put the index onto the INDEX_STREAM. */
|
172 |
|
|
|
173 |
|
|
static void
|
174 |
|
|
output_string_with_length (struct output_block *ob,
|
175 |
|
|
struct lto_output_stream *index_stream,
|
176 |
|
|
const char *s,
|
177 |
|
|
unsigned int len)
|
178 |
|
|
{
|
179 |
|
|
struct string_slot **slot;
|
180 |
|
|
struct string_slot s_slot;
|
181 |
|
|
char *string = (char *) xmalloc (len + 1);
|
182 |
|
|
memcpy (string, s, len);
|
183 |
|
|
string[len] = '\0';
|
184 |
|
|
|
185 |
|
|
s_slot.s = string;
|
186 |
|
|
s_slot.len = len;
|
187 |
|
|
s_slot.slot_num = 0;
|
188 |
|
|
|
189 |
|
|
slot = (struct string_slot **) htab_find_slot (ob->string_hash_table,
|
190 |
|
|
&s_slot, INSERT);
|
191 |
|
|
if (*slot == NULL)
|
192 |
|
|
{
|
193 |
|
|
struct lto_output_stream *string_stream = ob->string_stream;
|
194 |
|
|
unsigned int start = string_stream->total_size;
|
195 |
|
|
struct string_slot *new_slot
|
196 |
|
|
= (struct string_slot *) xmalloc (sizeof (struct string_slot));
|
197 |
|
|
unsigned int i;
|
198 |
|
|
|
199 |
|
|
new_slot->s = string;
|
200 |
|
|
new_slot->len = len;
|
201 |
|
|
new_slot->slot_num = start;
|
202 |
|
|
*slot = new_slot;
|
203 |
|
|
lto_output_uleb128_stream (index_stream, start);
|
204 |
|
|
lto_output_uleb128_stream (string_stream, len);
|
205 |
|
|
for (i = 0; i < len; i++)
|
206 |
|
|
lto_output_1_stream (string_stream, string[i]);
|
207 |
|
|
}
|
208 |
|
|
else
|
209 |
|
|
{
|
210 |
|
|
struct string_slot *old_slot = (struct string_slot *)*slot;
|
211 |
|
|
lto_output_uleb128_stream (index_stream, old_slot->slot_num);
|
212 |
|
|
free (string);
|
213 |
|
|
}
|
214 |
|
|
}
|
215 |
|
|
|
216 |
|
|
/* Output the '\0' terminated STRING to the string
|
217 |
|
|
table in OB. Then put the index onto the INDEX_STREAM. */
|
218 |
|
|
|
219 |
|
|
static void
|
220 |
|
|
output_string (struct output_block *ob,
|
221 |
|
|
struct lto_output_stream *index_stream,
|
222 |
|
|
const char *string)
|
223 |
|
|
{
|
224 |
|
|
if (string)
|
225 |
|
|
{
|
226 |
|
|
lto_output_uleb128_stream (index_stream, 0);
|
227 |
|
|
output_string_with_length (ob, index_stream, string, strlen (string) + 1);
|
228 |
|
|
}
|
229 |
|
|
else
|
230 |
|
|
lto_output_uleb128_stream (index_stream, 1);
|
231 |
|
|
}
|
232 |
|
|
|
233 |
|
|
|
234 |
|
|
/* Output the STRING constant to the string
|
235 |
|
|
table in OB. Then put the index onto the INDEX_STREAM. */
|
236 |
|
|
|
237 |
|
|
static void
|
238 |
|
|
output_string_cst (struct output_block *ob,
|
239 |
|
|
struct lto_output_stream *index_stream,
|
240 |
|
|
tree string)
|
241 |
|
|
{
|
242 |
|
|
if (string)
|
243 |
|
|
{
|
244 |
|
|
lto_output_uleb128_stream (index_stream, 0);
|
245 |
|
|
output_string_with_length (ob, index_stream,
|
246 |
|
|
TREE_STRING_POINTER (string),
|
247 |
|
|
TREE_STRING_LENGTH (string));
|
248 |
|
|
}
|
249 |
|
|
else
|
250 |
|
|
lto_output_uleb128_stream (index_stream, 1);
|
251 |
|
|
}
|
252 |
|
|
|
253 |
|
|
|
254 |
|
|
/* Output the identifier ID to the string
|
255 |
|
|
table in OB. Then put the index onto the INDEX_STREAM. */
|
256 |
|
|
|
257 |
|
|
static void
|
258 |
|
|
output_identifier (struct output_block *ob,
|
259 |
|
|
struct lto_output_stream *index_stream,
|
260 |
|
|
tree id)
|
261 |
|
|
{
|
262 |
|
|
if (id)
|
263 |
|
|
{
|
264 |
|
|
lto_output_uleb128_stream (index_stream, 0);
|
265 |
|
|
output_string_with_length (ob, index_stream,
|
266 |
|
|
IDENTIFIER_POINTER (id),
|
267 |
|
|
IDENTIFIER_LENGTH (id));
|
268 |
|
|
}
|
269 |
|
|
else
|
270 |
|
|
lto_output_uleb128_stream (index_stream, 1);
|
271 |
|
|
}
|
272 |
|
|
|
273 |
|
|
/* Write a zero to the output stream. */
|
274 |
|
|
|
275 |
|
|
static void
|
276 |
|
|
output_zero (struct output_block *ob)
|
277 |
|
|
{
|
278 |
|
|
lto_output_1_stream (ob->main_stream, 0);
|
279 |
|
|
}
|
280 |
|
|
|
281 |
|
|
|
282 |
|
|
/* Output an unsigned LEB128 quantity to OB->main_stream. */
|
283 |
|
|
|
284 |
|
|
static void
|
285 |
|
|
output_uleb128 (struct output_block *ob, unsigned HOST_WIDE_INT work)
|
286 |
|
|
{
|
287 |
|
|
lto_output_uleb128_stream (ob->main_stream, work);
|
288 |
|
|
}
|
289 |
|
|
|
290 |
|
|
|
291 |
|
|
/* Output a signed LEB128 quantity to OB->main_stream. */
|
292 |
|
|
|
293 |
|
|
static void
|
294 |
|
|
output_sleb128 (struct output_block *ob, HOST_WIDE_INT work)
|
295 |
|
|
{
|
296 |
|
|
lto_output_sleb128_stream (ob->main_stream, work);
|
297 |
|
|
}
|
298 |
|
|
|
299 |
|
|
|
300 |
|
|
/* Output the start of a record with TAG to output block OB. */
|
301 |
|
|
|
302 |
|
|
static void
|
303 |
|
|
output_record_start (struct output_block *ob, enum LTO_tags tag)
|
304 |
|
|
{
|
305 |
|
|
/* Make sure TAG fits inside an unsigned int. */
|
306 |
|
|
gcc_assert (tag == (enum LTO_tags) (unsigned) tag);
|
307 |
|
|
output_uleb128 (ob, tag);
|
308 |
|
|
}
|
309 |
|
|
|
310 |
|
|
|
311 |
|
|
/* Look up NODE in the type table and write the index for it to OB. */
|
312 |
|
|
|
313 |
|
|
static void
|
314 |
|
|
output_type_ref (struct output_block *ob, tree node)
|
315 |
|
|
{
|
316 |
|
|
output_record_start (ob, LTO_type_ref);
|
317 |
|
|
lto_output_type_ref_index (ob->decl_state, ob->main_stream, node);
|
318 |
|
|
}
|
319 |
|
|
|
320 |
|
|
|
321 |
|
|
/* Pack all the non-pointer fields of the TS_BASE structure of
|
322 |
|
|
expression EXPR into bitpack BP. */
|
323 |
|
|
|
324 |
|
|
static void
|
325 |
|
|
pack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
|
326 |
|
|
{
|
327 |
|
|
bp_pack_value (bp, TREE_CODE (expr), 16);
|
328 |
|
|
if (!TYPE_P (expr))
|
329 |
|
|
{
|
330 |
|
|
bp_pack_value (bp, TREE_SIDE_EFFECTS (expr), 1);
|
331 |
|
|
bp_pack_value (bp, TREE_CONSTANT (expr), 1);
|
332 |
|
|
bp_pack_value (bp, TREE_READONLY (expr), 1);
|
333 |
|
|
|
334 |
|
|
/* TREE_PUBLIC is used on types to indicate that the type
|
335 |
|
|
has a TYPE_CACHED_VALUES vector. This is not streamed out,
|
336 |
|
|
so we skip it here. */
|
337 |
|
|
bp_pack_value (bp, TREE_PUBLIC (expr), 1);
|
338 |
|
|
}
|
339 |
|
|
bp_pack_value (bp, TREE_ADDRESSABLE (expr), 1);
|
340 |
|
|
bp_pack_value (bp, TREE_THIS_VOLATILE (expr), 1);
|
341 |
|
|
if (DECL_P (expr))
|
342 |
|
|
bp_pack_value (bp, DECL_UNSIGNED (expr), 1);
|
343 |
|
|
else if (TYPE_P (expr))
|
344 |
|
|
bp_pack_value (bp, TYPE_UNSIGNED (expr), 1);
|
345 |
|
|
/* We write debug info two times, do not confuse the second one. */
|
346 |
|
|
bp_pack_value (bp, TYPE_P (expr) ? 0 : TREE_ASM_WRITTEN (expr), 1);
|
347 |
|
|
bp_pack_value (bp, TREE_NO_WARNING (expr), 1);
|
348 |
|
|
bp_pack_value (bp, TREE_USED (expr), 1);
|
349 |
|
|
bp_pack_value (bp, TREE_NOTHROW (expr), 1);
|
350 |
|
|
bp_pack_value (bp, TREE_STATIC (expr), 1);
|
351 |
|
|
bp_pack_value (bp, TREE_PRIVATE (expr), 1);
|
352 |
|
|
bp_pack_value (bp, TREE_PROTECTED (expr), 1);
|
353 |
|
|
bp_pack_value (bp, TREE_DEPRECATED (expr), 1);
|
354 |
|
|
if (TYPE_P (expr))
|
355 |
|
|
bp_pack_value (bp, TYPE_SATURATING (expr), 1);
|
356 |
|
|
if (TREE_CODE (expr) == SSA_NAME)
|
357 |
|
|
bp_pack_value (bp, SSA_NAME_IS_DEFAULT_DEF (expr), 1);
|
358 |
|
|
}
|
359 |
|
|
|
360 |
|
|
|
361 |
|
|
/* Pack all the non-pointer fields of the TS_REAL_CST structure of
|
362 |
|
|
expression EXPR into bitpack BP. */
|
363 |
|
|
|
364 |
|
|
static void
|
365 |
|
|
pack_ts_real_cst_value_fields (struct bitpack_d *bp, tree expr)
|
366 |
|
|
{
|
367 |
|
|
unsigned i;
|
368 |
|
|
REAL_VALUE_TYPE r;
|
369 |
|
|
|
370 |
|
|
r = TREE_REAL_CST (expr);
|
371 |
|
|
bp_pack_value (bp, r.cl, 2);
|
372 |
|
|
bp_pack_value (bp, r.decimal, 1);
|
373 |
|
|
bp_pack_value (bp, r.sign, 1);
|
374 |
|
|
bp_pack_value (bp, r.signalling, 1);
|
375 |
|
|
bp_pack_value (bp, r.canonical, 1);
|
376 |
|
|
bp_pack_value (bp, r.uexp, EXP_BITS);
|
377 |
|
|
for (i = 0; i < SIGSZ; i++)
|
378 |
|
|
bp_pack_value (bp, r.sig[i], HOST_BITS_PER_LONG);
|
379 |
|
|
}
|
380 |
|
|
|
381 |
|
|
|
382 |
|
|
/* Pack all the non-pointer fields of the TS_FIXED_CST structure of
|
383 |
|
|
expression EXPR into bitpack BP. */
|
384 |
|
|
|
385 |
|
|
static void
|
386 |
|
|
pack_ts_fixed_cst_value_fields (struct bitpack_d *bp, tree expr)
|
387 |
|
|
{
|
388 |
|
|
struct fixed_value fv = TREE_FIXED_CST (expr);
|
389 |
|
|
bp_pack_value (bp, fv.data.low, HOST_BITS_PER_WIDE_INT);
|
390 |
|
|
bp_pack_value (bp, fv.data.high, HOST_BITS_PER_WIDE_INT);
|
391 |
|
|
bp_pack_value (bp, fv.mode, HOST_BITS_PER_INT);
|
392 |
|
|
}
|
393 |
|
|
|
394 |
|
|
|
395 |
|
|
/* Pack all the non-pointer fields of the TS_DECL_COMMON structure
|
396 |
|
|
of expression EXPR into bitpack BP. */
|
397 |
|
|
|
398 |
|
|
static void
|
399 |
|
|
pack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
|
400 |
|
|
{
|
401 |
|
|
bp_pack_value (bp, DECL_MODE (expr), 8);
|
402 |
|
|
bp_pack_value (bp, DECL_NONLOCAL (expr), 1);
|
403 |
|
|
bp_pack_value (bp, DECL_VIRTUAL_P (expr), 1);
|
404 |
|
|
bp_pack_value (bp, DECL_IGNORED_P (expr), 1);
|
405 |
|
|
bp_pack_value (bp, DECL_ABSTRACT (expr), 1);
|
406 |
|
|
bp_pack_value (bp, DECL_ARTIFICIAL (expr), 1);
|
407 |
|
|
bp_pack_value (bp, DECL_USER_ALIGN (expr), 1);
|
408 |
|
|
bp_pack_value (bp, DECL_PRESERVE_P (expr), 1);
|
409 |
|
|
bp_pack_value (bp, DECL_DEBUG_EXPR_IS_FROM (expr), 1);
|
410 |
|
|
bp_pack_value (bp, DECL_EXTERNAL (expr), 1);
|
411 |
|
|
bp_pack_value (bp, DECL_GIMPLE_REG_P (expr), 1);
|
412 |
|
|
bp_pack_value (bp, DECL_ALIGN (expr), HOST_BITS_PER_INT);
|
413 |
|
|
|
414 |
|
|
if (TREE_CODE (expr) == LABEL_DECL)
|
415 |
|
|
{
|
416 |
|
|
/* Note that we do not write LABEL_DECL_UID. The reader will
|
417 |
|
|
always assume an initial value of -1 so that the
|
418 |
|
|
label_to_block_map is recreated by gimple_set_bb. */
|
419 |
|
|
bp_pack_value (bp, DECL_ERROR_ISSUED (expr), 1);
|
420 |
|
|
bp_pack_value (bp, EH_LANDING_PAD_NR (expr), HOST_BITS_PER_INT);
|
421 |
|
|
}
|
422 |
|
|
|
423 |
|
|
if (TREE_CODE (expr) == FIELD_DECL)
|
424 |
|
|
{
|
425 |
|
|
bp_pack_value (bp, DECL_PACKED (expr), 1);
|
426 |
|
|
bp_pack_value (bp, DECL_NONADDRESSABLE_P (expr), 1);
|
427 |
|
|
bp_pack_value (bp, DECL_OFFSET_ALIGN (expr), 8);
|
428 |
|
|
}
|
429 |
|
|
|
430 |
|
|
if (TREE_CODE (expr) == RESULT_DECL
|
431 |
|
|
|| TREE_CODE (expr) == PARM_DECL
|
432 |
|
|
|| TREE_CODE (expr) == VAR_DECL)
|
433 |
|
|
{
|
434 |
|
|
bp_pack_value (bp, DECL_BY_REFERENCE (expr), 1);
|
435 |
|
|
if (TREE_CODE (expr) == VAR_DECL
|
436 |
|
|
|| TREE_CODE (expr) == PARM_DECL)
|
437 |
|
|
bp_pack_value (bp, DECL_HAS_VALUE_EXPR_P (expr), 1);
|
438 |
|
|
bp_pack_value (bp, DECL_RESTRICTED_P (expr), 1);
|
439 |
|
|
}
|
440 |
|
|
}
|
441 |
|
|
|
442 |
|
|
|
443 |
|
|
/* Pack all the non-pointer fields of the TS_DECL_WRTL structure
|
444 |
|
|
of expression EXPR into bitpack BP. */
|
445 |
|
|
|
446 |
|
|
static void
|
447 |
|
|
pack_ts_decl_wrtl_value_fields (struct bitpack_d *bp, tree expr)
|
448 |
|
|
{
|
449 |
|
|
bp_pack_value (bp, DECL_REGISTER (expr), 1);
|
450 |
|
|
}
|
451 |
|
|
|
452 |
|
|
|
453 |
|
|
/* Pack all the non-pointer fields of the TS_DECL_WITH_VIS structure
|
454 |
|
|
of expression EXPR into bitpack BP. */
|
455 |
|
|
|
456 |
|
|
static void
|
457 |
|
|
pack_ts_decl_with_vis_value_fields (struct bitpack_d *bp, tree expr)
|
458 |
|
|
{
|
459 |
|
|
bp_pack_value (bp, DECL_DEFER_OUTPUT (expr), 1);
|
460 |
|
|
bp_pack_value (bp, DECL_COMMON (expr), 1);
|
461 |
|
|
bp_pack_value (bp, DECL_DLLIMPORT_P (expr), 1);
|
462 |
|
|
bp_pack_value (bp, DECL_WEAK (expr), 1);
|
463 |
|
|
bp_pack_value (bp, DECL_SEEN_IN_BIND_EXPR_P (expr), 1);
|
464 |
|
|
bp_pack_value (bp, DECL_COMDAT (expr), 1);
|
465 |
|
|
bp_pack_value (bp, DECL_VISIBILITY (expr), 2);
|
466 |
|
|
bp_pack_value (bp, DECL_VISIBILITY_SPECIFIED (expr), 1);
|
467 |
|
|
|
468 |
|
|
if (TREE_CODE (expr) == VAR_DECL)
|
469 |
|
|
{
|
470 |
|
|
bp_pack_value (bp, DECL_HARD_REGISTER (expr), 1);
|
471 |
|
|
bp_pack_value (bp, DECL_IN_TEXT_SECTION (expr), 1);
|
472 |
|
|
bp_pack_value (bp, DECL_TLS_MODEL (expr), 3);
|
473 |
|
|
}
|
474 |
|
|
|
475 |
|
|
if (VAR_OR_FUNCTION_DECL_P (expr))
|
476 |
|
|
bp_pack_value (bp, DECL_INIT_PRIORITY (expr), HOST_BITS_PER_SHORT);
|
477 |
|
|
}
|
478 |
|
|
|
479 |
|
|
|
480 |
|
|
/* Pack all the non-pointer fields of the TS_FUNCTION_DECL structure
|
481 |
|
|
of expression EXPR into bitpack BP. */
|
482 |
|
|
|
483 |
|
|
static void
|
484 |
|
|
pack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
|
485 |
|
|
{
|
486 |
|
|
/* For normal/md builtins we only write the class and code, so they
|
487 |
|
|
should never be handled here. */
|
488 |
|
|
gcc_assert (!lto_stream_as_builtin_p (expr));
|
489 |
|
|
|
490 |
|
|
bp_pack_value (bp, DECL_FUNCTION_CODE (expr), 11);
|
491 |
|
|
bp_pack_value (bp, DECL_BUILT_IN_CLASS (expr), 2);
|
492 |
|
|
bp_pack_value (bp, DECL_STATIC_CONSTRUCTOR (expr), 1);
|
493 |
|
|
bp_pack_value (bp, DECL_STATIC_DESTRUCTOR (expr), 1);
|
494 |
|
|
bp_pack_value (bp, DECL_UNINLINABLE (expr), 1);
|
495 |
|
|
bp_pack_value (bp, DECL_POSSIBLY_INLINED (expr), 1);
|
496 |
|
|
bp_pack_value (bp, DECL_IS_NOVOPS (expr), 1);
|
497 |
|
|
bp_pack_value (bp, DECL_IS_RETURNS_TWICE (expr), 1);
|
498 |
|
|
bp_pack_value (bp, DECL_IS_MALLOC (expr), 1);
|
499 |
|
|
bp_pack_value (bp, DECL_IS_OPERATOR_NEW (expr), 1);
|
500 |
|
|
bp_pack_value (bp, DECL_DECLARED_INLINE_P (expr), 1);
|
501 |
|
|
bp_pack_value (bp, DECL_STATIC_CHAIN (expr), 1);
|
502 |
|
|
bp_pack_value (bp, DECL_NO_INLINE_WARNING_P (expr), 1);
|
503 |
|
|
bp_pack_value (bp, DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (expr), 1);
|
504 |
|
|
bp_pack_value (bp, DECL_NO_LIMIT_STACK (expr), 1);
|
505 |
|
|
bp_pack_value (bp, DECL_DISREGARD_INLINE_LIMITS (expr), 1);
|
506 |
|
|
bp_pack_value (bp, DECL_PURE_P (expr), 1);
|
507 |
|
|
bp_pack_value (bp, DECL_LOOPING_CONST_OR_PURE_P (expr), 1);
|
508 |
|
|
}
|
509 |
|
|
|
510 |
|
|
|
511 |
|
|
/* Pack all the non-pointer fields of the TS_TYPE structure
|
512 |
|
|
of expression EXPR into bitpack BP. */
|
513 |
|
|
|
514 |
|
|
static void
|
515 |
|
|
pack_ts_type_value_fields (struct bitpack_d *bp, tree expr)
|
516 |
|
|
{
|
517 |
|
|
bp_pack_value (bp, TYPE_PRECISION (expr), 10);
|
518 |
|
|
bp_pack_value (bp, TYPE_MODE (expr), 8);
|
519 |
|
|
bp_pack_value (bp, TYPE_STRING_FLAG (expr), 1);
|
520 |
|
|
bp_pack_value (bp, TYPE_NO_FORCE_BLK (expr), 1);
|
521 |
|
|
bp_pack_value (bp, TYPE_NEEDS_CONSTRUCTING (expr), 1);
|
522 |
|
|
if (RECORD_OR_UNION_TYPE_P (expr))
|
523 |
|
|
bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1);
|
524 |
|
|
bp_pack_value (bp, TYPE_PACKED (expr), 1);
|
525 |
|
|
bp_pack_value (bp, TYPE_RESTRICT (expr), 1);
|
526 |
|
|
bp_pack_value (bp, TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr), 2);
|
527 |
|
|
bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1);
|
528 |
|
|
bp_pack_value (bp, TYPE_READONLY (expr), 1);
|
529 |
|
|
bp_pack_value (bp, TYPE_ALIGN (expr), HOST_BITS_PER_INT);
|
530 |
|
|
bp_pack_value (bp, TYPE_ALIAS_SET (expr) == 0 ? 0 : -1, HOST_BITS_PER_INT);
|
531 |
|
|
}
|
532 |
|
|
|
533 |
|
|
|
534 |
|
|
/* Pack all the non-pointer fields of the TS_BLOCK structure
|
535 |
|
|
of expression EXPR into bitpack BP. */
|
536 |
|
|
|
537 |
|
|
static void
|
538 |
|
|
pack_ts_block_value_fields (struct bitpack_d *bp, tree expr)
|
539 |
|
|
{
|
540 |
|
|
bp_pack_value (bp, BLOCK_ABSTRACT (expr), 1);
|
541 |
|
|
bp_pack_value (bp, BLOCK_NUMBER (expr), 31);
|
542 |
|
|
}
|
543 |
|
|
|
544 |
|
|
|
545 |
|
|
/* Pack all the non-pointer fields in EXPR into a bit pack. */
|
546 |
|
|
|
547 |
|
|
static struct bitpack_d *
|
548 |
|
|
pack_value_fields (tree expr)
|
549 |
|
|
{
|
550 |
|
|
enum tree_code code;
|
551 |
|
|
struct bitpack_d *bp;
|
552 |
|
|
|
553 |
|
|
code = TREE_CODE (expr);
|
554 |
|
|
bp = bitpack_create ();
|
555 |
|
|
|
556 |
|
|
/* Note that all these functions are highly sensitive to changes in
|
557 |
|
|
the types and sizes of each of the fields being packed. */
|
558 |
|
|
pack_ts_base_value_fields (bp, expr);
|
559 |
|
|
|
560 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_REAL_CST))
|
561 |
|
|
pack_ts_real_cst_value_fields (bp, expr);
|
562 |
|
|
|
563 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_FIXED_CST))
|
564 |
|
|
pack_ts_fixed_cst_value_fields (bp, expr);
|
565 |
|
|
|
566 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
|
567 |
|
|
pack_ts_decl_common_value_fields (bp, expr);
|
568 |
|
|
|
569 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL))
|
570 |
|
|
pack_ts_decl_wrtl_value_fields (bp, expr);
|
571 |
|
|
|
572 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
|
573 |
|
|
pack_ts_decl_with_vis_value_fields (bp, expr);
|
574 |
|
|
|
575 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
|
576 |
|
|
pack_ts_function_decl_value_fields (bp, expr);
|
577 |
|
|
|
578 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_TYPE))
|
579 |
|
|
pack_ts_type_value_fields (bp, expr);
|
580 |
|
|
|
581 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
|
582 |
|
|
pack_ts_block_value_fields (bp, expr);
|
583 |
|
|
|
584 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_SSA_NAME))
|
585 |
|
|
{
|
586 |
|
|
/* We only stream the version number of SSA names. */
|
587 |
|
|
gcc_unreachable ();
|
588 |
|
|
}
|
589 |
|
|
|
590 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_STATEMENT_LIST))
|
591 |
|
|
{
|
592 |
|
|
/* This is only used by GENERIC. */
|
593 |
|
|
gcc_unreachable ();
|
594 |
|
|
}
|
595 |
|
|
|
596 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_OMP_CLAUSE))
|
597 |
|
|
{
|
598 |
|
|
/* This is only used by High GIMPLE. */
|
599 |
|
|
gcc_unreachable ();
|
600 |
|
|
}
|
601 |
|
|
|
602 |
|
|
return bp;
|
603 |
|
|
}
|
604 |
|
|
|
605 |
|
|
|
606 |
|
|
/* Emit location LOC to output block OB. */
|
607 |
|
|
|
608 |
|
|
static void
|
609 |
|
|
lto_output_location (struct output_block *ob, location_t loc)
|
610 |
|
|
{
|
611 |
|
|
expanded_location xloc;
|
612 |
|
|
|
613 |
|
|
if (loc == UNKNOWN_LOCATION)
|
614 |
|
|
{
|
615 |
|
|
output_string (ob, ob->main_stream, NULL);
|
616 |
|
|
return;
|
617 |
|
|
}
|
618 |
|
|
|
619 |
|
|
xloc = expand_location (loc);
|
620 |
|
|
|
621 |
|
|
output_string (ob, ob->main_stream, xloc.file);
|
622 |
|
|
output_sleb128 (ob, xloc.line);
|
623 |
|
|
output_sleb128 (ob, xloc.column);
|
624 |
|
|
output_sleb128 (ob, xloc.sysp);
|
625 |
|
|
|
626 |
|
|
ob->current_file = xloc.file;
|
627 |
|
|
ob->current_line = xloc.line;
|
628 |
|
|
ob->current_col = xloc.column;
|
629 |
|
|
}
|
630 |
|
|
|
631 |
|
|
|
632 |
|
|
/* Return true if tree node T is written to various tables. For these
|
633 |
|
|
nodes, we sometimes want to write their phyiscal representation
|
634 |
|
|
(via lto_output_tree), and sometimes we need to emit an index
|
635 |
|
|
reference into a table (via lto_output_tree_ref). */
|
636 |
|
|
|
637 |
|
|
static bool
|
638 |
|
|
tree_is_indexable (tree t)
|
639 |
|
|
{
|
640 |
|
|
if (TREE_CODE (t) == PARM_DECL)
|
641 |
|
|
return false;
|
642 |
|
|
else if (TREE_CODE (t) == VAR_DECL && decl_function_context (t)
|
643 |
|
|
&& !TREE_STATIC (t))
|
644 |
|
|
return false;
|
645 |
|
|
else
|
646 |
|
|
return (TYPE_P (t) || DECL_P (t) || TREE_CODE (t) == SSA_NAME);
|
647 |
|
|
}
|
648 |
|
|
|
649 |
|
|
|
650 |
|
|
/* If EXPR is an indexable tree node, output a reference to it to
|
651 |
|
|
output block OB. Otherwise, output the physical representation of
|
652 |
|
|
EXPR to OB. */
|
653 |
|
|
|
654 |
|
|
static void
|
655 |
|
|
lto_output_tree_ref (struct output_block *ob, tree expr)
|
656 |
|
|
{
|
657 |
|
|
enum tree_code code;
|
658 |
|
|
|
659 |
|
|
if (expr == NULL_TREE)
|
660 |
|
|
{
|
661 |
|
|
output_zero (ob);
|
662 |
|
|
return;
|
663 |
|
|
}
|
664 |
|
|
|
665 |
|
|
if (!tree_is_indexable (expr))
|
666 |
|
|
{
|
667 |
|
|
/* Even though we are emitting the physical representation of
|
668 |
|
|
EXPR, its leaves must be emitted as references. */
|
669 |
|
|
lto_output_tree (ob, expr, true);
|
670 |
|
|
return;
|
671 |
|
|
}
|
672 |
|
|
|
673 |
|
|
if (TYPE_P (expr))
|
674 |
|
|
{
|
675 |
|
|
output_type_ref (ob, expr);
|
676 |
|
|
return;
|
677 |
|
|
}
|
678 |
|
|
|
679 |
|
|
code = TREE_CODE (expr);
|
680 |
|
|
switch (code)
|
681 |
|
|
{
|
682 |
|
|
case SSA_NAME:
|
683 |
|
|
output_record_start (ob, LTO_ssa_name_ref);
|
684 |
|
|
output_uleb128 (ob, SSA_NAME_VERSION (expr));
|
685 |
|
|
break;
|
686 |
|
|
|
687 |
|
|
case FIELD_DECL:
|
688 |
|
|
output_record_start (ob, LTO_field_decl_ref);
|
689 |
|
|
lto_output_field_decl_index (ob->decl_state, ob->main_stream, expr);
|
690 |
|
|
break;
|
691 |
|
|
|
692 |
|
|
case FUNCTION_DECL:
|
693 |
|
|
output_record_start (ob, LTO_function_decl_ref);
|
694 |
|
|
lto_output_fn_decl_index (ob->decl_state, ob->main_stream, expr);
|
695 |
|
|
break;
|
696 |
|
|
|
697 |
|
|
case VAR_DECL:
|
698 |
|
|
case DEBUG_EXPR_DECL:
|
699 |
|
|
gcc_assert (decl_function_context (expr) == NULL
|
700 |
|
|
|| TREE_STATIC (expr));
|
701 |
|
|
output_record_start (ob, LTO_global_decl_ref);
|
702 |
|
|
lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
|
703 |
|
|
break;
|
704 |
|
|
|
705 |
|
|
case CONST_DECL:
|
706 |
|
|
output_record_start (ob, LTO_const_decl_ref);
|
707 |
|
|
lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
|
708 |
|
|
break;
|
709 |
|
|
|
710 |
|
|
case IMPORTED_DECL:
|
711 |
|
|
gcc_assert (decl_function_context (expr) == NULL);
|
712 |
|
|
output_record_start (ob, LTO_imported_decl_ref);
|
713 |
|
|
lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
|
714 |
|
|
break;
|
715 |
|
|
|
716 |
|
|
case TYPE_DECL:
|
717 |
|
|
output_record_start (ob, LTO_type_decl_ref);
|
718 |
|
|
lto_output_type_decl_index (ob->decl_state, ob->main_stream, expr);
|
719 |
|
|
break;
|
720 |
|
|
|
721 |
|
|
case NAMESPACE_DECL:
|
722 |
|
|
output_record_start (ob, LTO_namespace_decl_ref);
|
723 |
|
|
lto_output_namespace_decl_index (ob->decl_state, ob->main_stream, expr);
|
724 |
|
|
break;
|
725 |
|
|
|
726 |
|
|
case LABEL_DECL:
|
727 |
|
|
output_record_start (ob, LTO_label_decl_ref);
|
728 |
|
|
lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
|
729 |
|
|
break;
|
730 |
|
|
|
731 |
|
|
case RESULT_DECL:
|
732 |
|
|
output_record_start (ob, LTO_result_decl_ref);
|
733 |
|
|
lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
|
734 |
|
|
break;
|
735 |
|
|
|
736 |
|
|
default:
|
737 |
|
|
/* No other node is indexable, so it should have been handled
|
738 |
|
|
by lto_output_tree. */
|
739 |
|
|
gcc_unreachable ();
|
740 |
|
|
}
|
741 |
|
|
}
|
742 |
|
|
|
743 |
|
|
|
744 |
|
|
/* If REF_P is true, emit a reference to EXPR in output block OB,
|
745 |
|
|
otherwise emit the physical representation of EXPR in OB. */
|
746 |
|
|
|
747 |
|
|
static inline void
|
748 |
|
|
lto_output_tree_or_ref (struct output_block *ob, tree expr, bool ref_p)
|
749 |
|
|
{
|
750 |
|
|
if (ref_p)
|
751 |
|
|
lto_output_tree_ref (ob, expr);
|
752 |
|
|
else
|
753 |
|
|
lto_output_tree (ob, expr, false);
|
754 |
|
|
}
|
755 |
|
|
|
756 |
|
|
|
757 |
|
|
/* Emit the chain of tree nodes starting at T. OB is the output block
|
758 |
|
|
to write to. REF_P is true if chain elements should be emitted
|
759 |
|
|
as references. */
|
760 |
|
|
|
761 |
|
|
static void
|
762 |
|
|
lto_output_chain (struct output_block *ob, tree t, bool ref_p)
|
763 |
|
|
{
|
764 |
|
|
int i, count;
|
765 |
|
|
|
766 |
|
|
count = list_length (t);
|
767 |
|
|
output_sleb128 (ob, count);
|
768 |
|
|
for (i = 0; i < count; i++)
|
769 |
|
|
{
|
770 |
|
|
tree saved_chain;
|
771 |
|
|
|
772 |
|
|
/* Clear TREE_CHAIN to avoid blindly recursing into the rest
|
773 |
|
|
of the list. */
|
774 |
|
|
saved_chain = TREE_CHAIN (t);
|
775 |
|
|
TREE_CHAIN (t) = NULL_TREE;
|
776 |
|
|
|
777 |
|
|
lto_output_tree_or_ref (ob, t, ref_p);
|
778 |
|
|
|
779 |
|
|
TREE_CHAIN (t) = saved_chain;
|
780 |
|
|
t = TREE_CHAIN (t);
|
781 |
|
|
}
|
782 |
|
|
}
|
783 |
|
|
|
784 |
|
|
|
785 |
|
|
/* Write all pointer fields in the TS_COMMON structure of EXPR to output
|
786 |
|
|
block OB. If REF_P is true, write a reference to EXPR's pointer
|
787 |
|
|
fields. */
|
788 |
|
|
|
789 |
|
|
static void
|
790 |
|
|
lto_output_ts_common_tree_pointers (struct output_block *ob, tree expr,
|
791 |
|
|
bool ref_p)
|
792 |
|
|
{
|
793 |
|
|
lto_output_tree_or_ref (ob, TREE_TYPE (expr), ref_p);
|
794 |
|
|
}
|
795 |
|
|
|
796 |
|
|
|
797 |
|
|
/* Write all pointer fields in the TS_VECTOR structure of EXPR to output
|
798 |
|
|
block OB. If REF_P is true, write a reference to EXPR's pointer
|
799 |
|
|
fields. */
|
800 |
|
|
|
801 |
|
|
static void
|
802 |
|
|
lto_output_ts_vector_tree_pointers (struct output_block *ob, tree expr,
|
803 |
|
|
bool ref_p)
|
804 |
|
|
{
|
805 |
|
|
lto_output_chain (ob, TREE_VECTOR_CST_ELTS (expr), ref_p);
|
806 |
|
|
}
|
807 |
|
|
|
808 |
|
|
|
809 |
|
|
/* Write all pointer fields in the TS_COMPLEX structure of EXPR to output
|
810 |
|
|
block OB. If REF_P is true, write a reference to EXPR's pointer
|
811 |
|
|
fields. */
|
812 |
|
|
|
813 |
|
|
static void
|
814 |
|
|
lto_output_ts_complex_tree_pointers (struct output_block *ob, tree expr,
|
815 |
|
|
bool ref_p)
|
816 |
|
|
{
|
817 |
|
|
lto_output_tree_or_ref (ob, TREE_REALPART (expr), ref_p);
|
818 |
|
|
lto_output_tree_or_ref (ob, TREE_IMAGPART (expr), ref_p);
|
819 |
|
|
}
|
820 |
|
|
|
821 |
|
|
|
822 |
|
|
/* Write all pointer fields in the TS_DECL_MINIMAL structure of EXPR
|
823 |
|
|
to output block OB. If REF_P is true, write a reference to EXPR's
|
824 |
|
|
pointer fields. */
|
825 |
|
|
|
826 |
|
|
static void
|
827 |
|
|
lto_output_ts_decl_minimal_tree_pointers (struct output_block *ob, tree expr,
|
828 |
|
|
bool ref_p)
|
829 |
|
|
{
|
830 |
|
|
lto_output_tree_or_ref (ob, DECL_NAME (expr), ref_p);
|
831 |
|
|
lto_output_tree_or_ref (ob, DECL_CONTEXT (expr), ref_p);
|
832 |
|
|
lto_output_location (ob, DECL_SOURCE_LOCATION (expr));
|
833 |
|
|
}
|
834 |
|
|
|
835 |
|
|
|
836 |
|
|
/* Write all pointer fields in the TS_DECL_COMMON structure of EXPR to
|
837 |
|
|
output block OB. If REF_P is true, write a reference to EXPR's
|
838 |
|
|
pointer fields. */
|
839 |
|
|
|
840 |
|
|
static void
|
841 |
|
|
lto_output_ts_decl_common_tree_pointers (struct output_block *ob, tree expr,
|
842 |
|
|
bool ref_p)
|
843 |
|
|
{
|
844 |
|
|
lto_output_tree_or_ref (ob, DECL_SIZE (expr), ref_p);
|
845 |
|
|
lto_output_tree_or_ref (ob, DECL_SIZE_UNIT (expr), ref_p);
|
846 |
|
|
|
847 |
|
|
if (TREE_CODE (expr) != FUNCTION_DECL)
|
848 |
|
|
lto_output_tree_or_ref (ob, DECL_INITIAL (expr), ref_p);
|
849 |
|
|
|
850 |
|
|
lto_output_tree_or_ref (ob, DECL_ATTRIBUTES (expr), ref_p);
|
851 |
|
|
lto_output_tree_or_ref (ob, DECL_ABSTRACT_ORIGIN (expr), ref_p);
|
852 |
|
|
|
853 |
|
|
if (TREE_CODE (expr) == PARM_DECL)
|
854 |
|
|
lto_output_chain (ob, TREE_CHAIN (expr), ref_p);
|
855 |
|
|
|
856 |
|
|
if ((TREE_CODE (expr) == VAR_DECL
|
857 |
|
|
|| TREE_CODE (expr) == PARM_DECL)
|
858 |
|
|
&& DECL_HAS_VALUE_EXPR_P (expr))
|
859 |
|
|
lto_output_tree_or_ref (ob, DECL_VALUE_EXPR (expr), ref_p);
|
860 |
|
|
}
|
861 |
|
|
|
862 |
|
|
|
863 |
|
|
/* Write all pointer fields in the TS_DECL_NON_COMMON structure of
|
864 |
|
|
EXPR to output block OB. If REF_P is true, write a reference to EXPR's
|
865 |
|
|
pointer fields. */
|
866 |
|
|
|
867 |
|
|
static void
|
868 |
|
|
lto_output_ts_decl_non_common_tree_pointers (struct output_block *ob,
|
869 |
|
|
tree expr, bool ref_p)
|
870 |
|
|
{
|
871 |
|
|
if (TREE_CODE (expr) == FUNCTION_DECL)
|
872 |
|
|
{
|
873 |
|
|
/* DECL_SAVED_TREE holds the GENERIC representation for DECL.
|
874 |
|
|
At this point, it should not exist. Either because it was
|
875 |
|
|
converted to gimple or because DECL didn't have a GENERIC
|
876 |
|
|
representation in this TU. */
|
877 |
|
|
gcc_assert (DECL_SAVED_TREE (expr) == NULL_TREE);
|
878 |
|
|
lto_output_tree_or_ref (ob, DECL_ARGUMENTS (expr), ref_p);
|
879 |
|
|
lto_output_tree_or_ref (ob, DECL_RESULT (expr), ref_p);
|
880 |
|
|
}
|
881 |
|
|
lto_output_tree_or_ref (ob, DECL_VINDEX (expr), ref_p);
|
882 |
|
|
}
|
883 |
|
|
|
884 |
|
|
|
885 |
|
|
/* Write all pointer fields in the TS_DECL_WITH_VIS structure of EXPR
|
886 |
|
|
to output block OB. If REF_P is true, write a reference to EXPR's
|
887 |
|
|
pointer fields. */
|
888 |
|
|
|
889 |
|
|
static void
|
890 |
|
|
lto_output_ts_decl_with_vis_tree_pointers (struct output_block *ob, tree expr,
|
891 |
|
|
bool ref_p)
|
892 |
|
|
{
|
893 |
|
|
/* Make sure we don't inadvertently set the assembler name. */
|
894 |
|
|
if (DECL_ASSEMBLER_NAME_SET_P (expr))
|
895 |
|
|
lto_output_tree_or_ref (ob, DECL_ASSEMBLER_NAME (expr), ref_p);
|
896 |
|
|
else
|
897 |
|
|
output_zero (ob);
|
898 |
|
|
|
899 |
|
|
lto_output_tree_or_ref (ob, DECL_SECTION_NAME (expr), ref_p);
|
900 |
|
|
lto_output_tree_or_ref (ob, DECL_COMDAT_GROUP (expr), ref_p);
|
901 |
|
|
}
|
902 |
|
|
|
903 |
|
|
|
904 |
|
|
/* Write all pointer fields in the TS_FIELD_DECL structure of EXPR to
|
905 |
|
|
output block OB. If REF_P is true, write a reference to EXPR's
|
906 |
|
|
pointer fields. */
|
907 |
|
|
|
908 |
|
|
static void
|
909 |
|
|
lto_output_ts_field_decl_tree_pointers (struct output_block *ob, tree expr,
|
910 |
|
|
bool ref_p)
|
911 |
|
|
{
|
912 |
|
|
lto_output_tree_or_ref (ob, DECL_FIELD_OFFSET (expr), ref_p);
|
913 |
|
|
lto_output_tree_or_ref (ob, DECL_BIT_FIELD_TYPE (expr), ref_p);
|
914 |
|
|
lto_output_tree_or_ref (ob, DECL_QUALIFIER (expr), ref_p);
|
915 |
|
|
lto_output_tree_or_ref (ob, DECL_FIELD_BIT_OFFSET (expr), ref_p);
|
916 |
|
|
lto_output_tree_or_ref (ob, DECL_FCONTEXT (expr), ref_p);
|
917 |
|
|
lto_output_chain (ob, TREE_CHAIN (expr), ref_p);
|
918 |
|
|
}
|
919 |
|
|
|
920 |
|
|
|
921 |
|
|
/* Write all pointer fields in the TS_FUNCTION_DECL structure of EXPR
|
922 |
|
|
to output block OB. If REF_P is true, write a reference to EXPR's
|
923 |
|
|
pointer fields. */
|
924 |
|
|
|
925 |
|
|
static void
|
926 |
|
|
lto_output_ts_function_decl_tree_pointers (struct output_block *ob, tree expr,
|
927 |
|
|
bool ref_p)
|
928 |
|
|
{
|
929 |
|
|
/* DECL_STRUCT_FUNCTION is handled by lto_output_function. FIXME lto,
|
930 |
|
|
maybe it should be handled here? */
|
931 |
|
|
lto_output_tree_or_ref (ob, DECL_FUNCTION_PERSONALITY (expr), ref_p);
|
932 |
|
|
lto_output_tree_or_ref (ob, DECL_FUNCTION_SPECIFIC_TARGET (expr), ref_p);
|
933 |
|
|
lto_output_tree_or_ref (ob, DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr),
|
934 |
|
|
ref_p);
|
935 |
|
|
}
|
936 |
|
|
|
937 |
|
|
|
938 |
|
|
/* Write all pointer fields in the TS_TYPE structure of EXPR to output
|
939 |
|
|
block OB. If REF_P is true, write a reference to EXPR's pointer
|
940 |
|
|
fields. */
|
941 |
|
|
|
942 |
|
|
static void
|
943 |
|
|
lto_output_ts_type_tree_pointers (struct output_block *ob, tree expr,
|
944 |
|
|
bool ref_p)
|
945 |
|
|
{
|
946 |
|
|
if (TREE_CODE (expr) == ENUMERAL_TYPE)
|
947 |
|
|
lto_output_tree_or_ref (ob, TYPE_VALUES (expr), ref_p);
|
948 |
|
|
else if (TREE_CODE (expr) == ARRAY_TYPE)
|
949 |
|
|
lto_output_tree_or_ref (ob, TYPE_DOMAIN (expr), ref_p);
|
950 |
|
|
else if (RECORD_OR_UNION_TYPE_P (expr))
|
951 |
|
|
lto_output_tree_or_ref (ob, TYPE_FIELDS (expr), ref_p);
|
952 |
|
|
else if (TREE_CODE (expr) == FUNCTION_TYPE
|
953 |
|
|
|| TREE_CODE (expr) == METHOD_TYPE)
|
954 |
|
|
lto_output_tree_or_ref (ob, TYPE_ARG_TYPES (expr), ref_p);
|
955 |
|
|
else if (TREE_CODE (expr) == VECTOR_TYPE)
|
956 |
|
|
lto_output_tree_or_ref (ob, TYPE_DEBUG_REPRESENTATION_TYPE (expr), ref_p);
|
957 |
|
|
|
958 |
|
|
lto_output_tree_or_ref (ob, TYPE_SIZE (expr), ref_p);
|
959 |
|
|
lto_output_tree_or_ref (ob, TYPE_SIZE_UNIT (expr), ref_p);
|
960 |
|
|
lto_output_tree_or_ref (ob, TYPE_ATTRIBUTES (expr), ref_p);
|
961 |
|
|
lto_output_tree_or_ref (ob, TYPE_NAME (expr), ref_p);
|
962 |
|
|
/* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO nor
|
963 |
|
|
TYPE_NEXT_PTR_TO or TYPE_NEXT_REF_TO. */
|
964 |
|
|
if (!POINTER_TYPE_P (expr))
|
965 |
|
|
lto_output_tree_or_ref (ob, TYPE_MINVAL (expr), ref_p);
|
966 |
|
|
lto_output_tree_or_ref (ob, TYPE_MAXVAL (expr), ref_p);
|
967 |
|
|
lto_output_tree_or_ref (ob, TYPE_MAIN_VARIANT (expr), ref_p);
|
968 |
|
|
/* Do not stream TYPE_NEXT_VARIANT, we reconstruct the variant lists
|
969 |
|
|
during fixup. */
|
970 |
|
|
if (RECORD_OR_UNION_TYPE_P (expr))
|
971 |
|
|
lto_output_tree_or_ref (ob, TYPE_BINFO (expr), ref_p);
|
972 |
|
|
lto_output_tree_or_ref (ob, TYPE_CONTEXT (expr), ref_p);
|
973 |
|
|
lto_output_tree_or_ref (ob, TYPE_CANONICAL (expr), ref_p);
|
974 |
|
|
lto_output_tree_or_ref (ob, TYPE_STUB_DECL (expr), ref_p);
|
975 |
|
|
}
|
976 |
|
|
|
977 |
|
|
|
978 |
|
|
/* Write all pointer fields in the TS_LIST structure of EXPR to output
|
979 |
|
|
block OB. If REF_P is true, write a reference to EXPR's pointer
|
980 |
|
|
fields. */
|
981 |
|
|
|
982 |
|
|
static void
|
983 |
|
|
lto_output_ts_list_tree_pointers (struct output_block *ob, tree expr,
|
984 |
|
|
bool ref_p)
|
985 |
|
|
{
|
986 |
|
|
lto_output_tree_or_ref (ob, TREE_PURPOSE (expr), ref_p);
|
987 |
|
|
lto_output_tree_or_ref (ob, TREE_VALUE (expr), ref_p);
|
988 |
|
|
lto_output_chain (ob, TREE_CHAIN (expr), ref_p);
|
989 |
|
|
}
|
990 |
|
|
|
991 |
|
|
|
992 |
|
|
/* Write all pointer fields in the TS_VEC structure of EXPR to output
|
993 |
|
|
block OB. If REF_P is true, write a reference to EXPR's pointer
|
994 |
|
|
fields. */
|
995 |
|
|
|
996 |
|
|
static void
|
997 |
|
|
lto_output_ts_vec_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
|
998 |
|
|
{
|
999 |
|
|
int i;
|
1000 |
|
|
|
1001 |
|
|
/* Note that the number of slots for EXPR has already been emitted
|
1002 |
|
|
in EXPR's header (see lto_output_tree_header). */
|
1003 |
|
|
for (i = 0; i < TREE_VEC_LENGTH (expr); i++)
|
1004 |
|
|
lto_output_tree_or_ref (ob, TREE_VEC_ELT (expr, i), ref_p);
|
1005 |
|
|
}
|
1006 |
|
|
|
1007 |
|
|
|
1008 |
|
|
/* Write all pointer fields in the TS_EXP structure of EXPR to output
|
1009 |
|
|
block OB. If REF_P is true, write a reference to EXPR's pointer
|
1010 |
|
|
fields. */
|
1011 |
|
|
|
1012 |
|
|
static void
|
1013 |
|
|
lto_output_ts_exp_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
|
1014 |
|
|
{
|
1015 |
|
|
int i;
|
1016 |
|
|
|
1017 |
|
|
output_sleb128 (ob, TREE_OPERAND_LENGTH (expr));
|
1018 |
|
|
for (i = 0; i < TREE_OPERAND_LENGTH (expr); i++)
|
1019 |
|
|
lto_output_tree_or_ref (ob, TREE_OPERAND (expr, i), ref_p);
|
1020 |
|
|
lto_output_location (ob, EXPR_LOCATION (expr));
|
1021 |
|
|
lto_output_tree_or_ref (ob, TREE_BLOCK (expr), ref_p);
|
1022 |
|
|
}
|
1023 |
|
|
|
1024 |
|
|
|
1025 |
|
|
/* Write all pointer fields in the TS_BLOCK structure of EXPR to output
|
1026 |
|
|
block OB. If REF_P is true, write a reference to EXPR's pointer
|
1027 |
|
|
fields. */
|
1028 |
|
|
|
1029 |
|
|
static void
|
1030 |
|
|
lto_output_ts_block_tree_pointers (struct output_block *ob, tree expr,
|
1031 |
|
|
bool ref_p)
|
1032 |
|
|
{
|
1033 |
|
|
unsigned i;
|
1034 |
|
|
tree t;
|
1035 |
|
|
|
1036 |
|
|
lto_output_location (ob, BLOCK_SOURCE_LOCATION (expr));
|
1037 |
|
|
lto_output_chain (ob, BLOCK_VARS (expr), ref_p);
|
1038 |
|
|
|
1039 |
|
|
output_uleb128 (ob, VEC_length (tree, BLOCK_NONLOCALIZED_VARS (expr)));
|
1040 |
|
|
for (i = 0; VEC_iterate (tree, BLOCK_NONLOCALIZED_VARS (expr), i, t); i++)
|
1041 |
|
|
lto_output_tree_or_ref (ob, t, ref_p);
|
1042 |
|
|
|
1043 |
|
|
lto_output_tree_or_ref (ob, BLOCK_SUPERCONTEXT (expr), ref_p);
|
1044 |
|
|
lto_output_tree_or_ref (ob, BLOCK_ABSTRACT_ORIGIN (expr), ref_p);
|
1045 |
|
|
lto_output_tree_or_ref (ob, BLOCK_FRAGMENT_ORIGIN (expr), ref_p);
|
1046 |
|
|
lto_output_tree_or_ref (ob, BLOCK_FRAGMENT_CHAIN (expr), ref_p);
|
1047 |
|
|
lto_output_chain (ob, BLOCK_SUBBLOCKS (expr), ref_p);
|
1048 |
|
|
}
|
1049 |
|
|
|
1050 |
|
|
|
1051 |
|
|
/* Write all pointer fields in the TS_BINFO structure of EXPR to output
|
1052 |
|
|
block OB. If REF_P is true, write a reference to EXPR's pointer
|
1053 |
|
|
fields. */
|
1054 |
|
|
|
1055 |
|
|
static void
|
1056 |
|
|
lto_output_ts_binfo_tree_pointers (struct output_block *ob, tree expr,
|
1057 |
|
|
bool ref_p)
|
1058 |
|
|
{
|
1059 |
|
|
unsigned i;
|
1060 |
|
|
tree t;
|
1061 |
|
|
|
1062 |
|
|
/* Note that the number of BINFO slots has already been emitted in
|
1063 |
|
|
EXPR's header (see lto_output_tree_header) because this length
|
1064 |
|
|
is needed to build the empty BINFO node on the reader side. */
|
1065 |
|
|
for (i = 0; VEC_iterate (tree, BINFO_BASE_BINFOS (expr), i, t); i++)
|
1066 |
|
|
lto_output_tree_or_ref (ob, t, ref_p);
|
1067 |
|
|
output_zero (ob);
|
1068 |
|
|
|
1069 |
|
|
lto_output_tree_or_ref (ob, BINFO_OFFSET (expr), ref_p);
|
1070 |
|
|
lto_output_tree_or_ref (ob, BINFO_VTABLE (expr), ref_p);
|
1071 |
|
|
lto_output_tree_or_ref (ob, BINFO_VIRTUALS (expr), ref_p);
|
1072 |
|
|
lto_output_tree_or_ref (ob, BINFO_VPTR_FIELD (expr), ref_p);
|
1073 |
|
|
|
1074 |
|
|
output_uleb128 (ob, VEC_length (tree, BINFO_BASE_ACCESSES (expr)));
|
1075 |
|
|
for (i = 0; VEC_iterate (tree, BINFO_BASE_ACCESSES (expr), i, t); i++)
|
1076 |
|
|
lto_output_tree_or_ref (ob, t, ref_p);
|
1077 |
|
|
|
1078 |
|
|
lto_output_tree_or_ref (ob, BINFO_INHERITANCE_CHAIN (expr), ref_p);
|
1079 |
|
|
lto_output_tree_or_ref (ob, BINFO_SUBVTT_INDEX (expr), ref_p);
|
1080 |
|
|
lto_output_tree_or_ref (ob, BINFO_VPTR_INDEX (expr), ref_p);
|
1081 |
|
|
}
|
1082 |
|
|
|
1083 |
|
|
|
1084 |
|
|
/* Write all pointer fields in the TS_CONSTRUCTOR structure of EXPR to
|
1085 |
|
|
output block OB. If REF_P is true, write a reference to EXPR's
|
1086 |
|
|
pointer fields. */
|
1087 |
|
|
|
1088 |
|
|
static void
|
1089 |
|
|
lto_output_ts_constructor_tree_pointers (struct output_block *ob, tree expr,
|
1090 |
|
|
bool ref_p)
|
1091 |
|
|
{
|
1092 |
|
|
unsigned i;
|
1093 |
|
|
tree index, value;
|
1094 |
|
|
|
1095 |
|
|
output_uleb128 (ob, CONSTRUCTOR_NELTS (expr));
|
1096 |
|
|
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (expr), i, index, value)
|
1097 |
|
|
{
|
1098 |
|
|
lto_output_tree_or_ref (ob, index, ref_p);
|
1099 |
|
|
lto_output_tree_or_ref (ob, value, ref_p);
|
1100 |
|
|
}
|
1101 |
|
|
}
|
1102 |
|
|
|
1103 |
|
|
|
1104 |
|
|
/* Helper for lto_output_tree. Write all pointer fields in EXPR to output
|
1105 |
|
|
block OB. If REF_P is true, the leaves of EXPR are emitted as
|
1106 |
|
|
references. */
|
1107 |
|
|
|
1108 |
|
|
static void
|
1109 |
|
|
lto_output_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
|
1110 |
|
|
{
|
1111 |
|
|
enum tree_code code;
|
1112 |
|
|
|
1113 |
|
|
code = TREE_CODE (expr);
|
1114 |
|
|
|
1115 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
|
1116 |
|
|
lto_output_ts_common_tree_pointers (ob, expr, ref_p);
|
1117 |
|
|
|
1118 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
|
1119 |
|
|
lto_output_ts_vector_tree_pointers (ob, expr, ref_p);
|
1120 |
|
|
|
1121 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_COMPLEX))
|
1122 |
|
|
lto_output_ts_complex_tree_pointers (ob, expr, ref_p);
|
1123 |
|
|
|
1124 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_DECL_MINIMAL))
|
1125 |
|
|
lto_output_ts_decl_minimal_tree_pointers (ob, expr, ref_p);
|
1126 |
|
|
|
1127 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
|
1128 |
|
|
lto_output_ts_decl_common_tree_pointers (ob, expr, ref_p);
|
1129 |
|
|
|
1130 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
|
1131 |
|
|
lto_output_ts_decl_non_common_tree_pointers (ob, expr, ref_p);
|
1132 |
|
|
|
1133 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
|
1134 |
|
|
lto_output_ts_decl_with_vis_tree_pointers (ob, expr, ref_p);
|
1135 |
|
|
|
1136 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
|
1137 |
|
|
lto_output_ts_field_decl_tree_pointers (ob, expr, ref_p);
|
1138 |
|
|
|
1139 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
|
1140 |
|
|
lto_output_ts_function_decl_tree_pointers (ob, expr, ref_p);
|
1141 |
|
|
|
1142 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_TYPE))
|
1143 |
|
|
lto_output_ts_type_tree_pointers (ob, expr, ref_p);
|
1144 |
|
|
|
1145 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_LIST))
|
1146 |
|
|
lto_output_ts_list_tree_pointers (ob, expr, ref_p);
|
1147 |
|
|
|
1148 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_VEC))
|
1149 |
|
|
lto_output_ts_vec_tree_pointers (ob, expr, ref_p);
|
1150 |
|
|
|
1151 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_EXP))
|
1152 |
|
|
lto_output_ts_exp_tree_pointers (ob, expr, ref_p);
|
1153 |
|
|
|
1154 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_SSA_NAME))
|
1155 |
|
|
{
|
1156 |
|
|
/* We only stream the version number of SSA names. */
|
1157 |
|
|
gcc_unreachable ();
|
1158 |
|
|
}
|
1159 |
|
|
|
1160 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
|
1161 |
|
|
lto_output_ts_block_tree_pointers (ob, expr, ref_p);
|
1162 |
|
|
|
1163 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
|
1164 |
|
|
lto_output_ts_binfo_tree_pointers (ob, expr, ref_p);
|
1165 |
|
|
|
1166 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
|
1167 |
|
|
lto_output_ts_constructor_tree_pointers (ob, expr, ref_p);
|
1168 |
|
|
|
1169 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_STATEMENT_LIST))
|
1170 |
|
|
{
|
1171 |
|
|
/* This should only appear in GENERIC. */
|
1172 |
|
|
gcc_unreachable ();
|
1173 |
|
|
}
|
1174 |
|
|
|
1175 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_OMP_CLAUSE))
|
1176 |
|
|
{
|
1177 |
|
|
/* This should only appear in High GIMPLE. */
|
1178 |
|
|
gcc_unreachable ();
|
1179 |
|
|
}
|
1180 |
|
|
|
1181 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION))
|
1182 |
|
|
sorry ("gimple bytecode streams do not support the optimization attribute");
|
1183 |
|
|
|
1184 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION))
|
1185 |
|
|
sorry ("gimple bytecode streams do not support the target attribute");
|
1186 |
|
|
}
|
1187 |
|
|
|
1188 |
|
|
|
1189 |
|
|
/* Emit header information for tree EXPR to output block OB. The header
|
1190 |
|
|
contains everything needed to instantiate an empty skeleton for
|
1191 |
|
|
EXPR on the reading side. IX is the index into the streamer cache
|
1192 |
|
|
where EXPR is stored. REF_P is as in lto_output_tree. */
|
1193 |
|
|
|
1194 |
|
|
static void
|
1195 |
|
|
lto_output_tree_header (struct output_block *ob, tree expr, int ix)
|
1196 |
|
|
{
|
1197 |
|
|
enum LTO_tags tag;
|
1198 |
|
|
enum tree_code code;
|
1199 |
|
|
|
1200 |
|
|
/* We should not see any non-GIMPLE tree nodes here. */
|
1201 |
|
|
code = TREE_CODE (expr);
|
1202 |
|
|
if (!lto_is_streamable (expr))
|
1203 |
|
|
internal_error ("tree code %qs is not supported in gimple streams",
|
1204 |
|
|
tree_code_name[code]);
|
1205 |
|
|
|
1206 |
|
|
/* The header of a tree node consists of its tag, the size of
|
1207 |
|
|
the node, and any other information needed to instantiate
|
1208 |
|
|
EXPR on the reading side (such as the number of slots in
|
1209 |
|
|
variable sized nodes). */
|
1210 |
|
|
tag = lto_tree_code_to_tag (code);
|
1211 |
|
|
output_record_start (ob, tag);
|
1212 |
|
|
output_sleb128 (ob, ix);
|
1213 |
|
|
|
1214 |
|
|
/* The following will cause bootstrap miscomparisons. Enable with care. */
|
1215 |
|
|
#ifdef LTO_STREAMER_DEBUG
|
1216 |
|
|
/* This is used mainly for debugging purposes. When the reader
|
1217 |
|
|
and the writer do not agree on a streamed node, the pointer
|
1218 |
|
|
value for EXPR can be used to track down the differences in
|
1219 |
|
|
the debugger. */
|
1220 |
|
|
gcc_assert ((HOST_WIDEST_INT) (intptr_t) expr == (intptr_t) expr);
|
1221 |
|
|
output_sleb128 (ob, (HOST_WIDEST_INT) (intptr_t) expr);
|
1222 |
|
|
#endif
|
1223 |
|
|
|
1224 |
|
|
/* The text in strings and identifiers are completely emitted in
|
1225 |
|
|
the header. */
|
1226 |
|
|
if (CODE_CONTAINS_STRUCT (code, TS_STRING))
|
1227 |
|
|
output_string_cst (ob, ob->main_stream, expr);
|
1228 |
|
|
else if (CODE_CONTAINS_STRUCT (code, TS_IDENTIFIER))
|
1229 |
|
|
output_identifier (ob, ob->main_stream, expr);
|
1230 |
|
|
else if (CODE_CONTAINS_STRUCT (code, TS_VEC))
|
1231 |
|
|
output_sleb128 (ob, TREE_VEC_LENGTH (expr));
|
1232 |
|
|
else if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
|
1233 |
|
|
output_uleb128 (ob, BINFO_N_BASE_BINFOS (expr));
|
1234 |
|
|
}
|
1235 |
|
|
|
1236 |
|
|
|
1237 |
|
|
/* Write the code and class of builtin EXPR to output block OB. IX is
|
1238 |
|
|
the index into the streamer cache where EXPR is stored.*/
|
1239 |
|
|
|
1240 |
|
|
static void
|
1241 |
|
|
lto_output_builtin_tree (struct output_block *ob, tree expr, int ix)
|
1242 |
|
|
{
|
1243 |
|
|
gcc_assert (lto_stream_as_builtin_p (expr));
|
1244 |
|
|
|
1245 |
|
|
if (DECL_BUILT_IN_CLASS (expr) == BUILT_IN_MD
|
1246 |
|
|
&& !targetm.builtin_decl)
|
1247 |
|
|
sorry ("gimple bytecode streams do not support machine specific builtin "
|
1248 |
|
|
"functions on this target");
|
1249 |
|
|
|
1250 |
|
|
output_record_start (ob, LTO_builtin_decl);
|
1251 |
|
|
output_uleb128 (ob, DECL_BUILT_IN_CLASS (expr));
|
1252 |
|
|
output_uleb128 (ob, DECL_FUNCTION_CODE (expr));
|
1253 |
|
|
output_sleb128 (ob, ix);
|
1254 |
|
|
|
1255 |
|
|
if (DECL_ASSEMBLER_NAME_SET_P (expr))
|
1256 |
|
|
{
|
1257 |
|
|
/* When the assembler name of a builtin gets a user name,
|
1258 |
|
|
the new name is always prefixed with '*' by
|
1259 |
|
|
set_builtin_user_assembler_name. So, to prevent the
|
1260 |
|
|
reader side from adding a second '*', we omit it here. */
|
1261 |
|
|
const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (expr));
|
1262 |
|
|
if (strlen (str) > 1 && str[0] == '*')
|
1263 |
|
|
output_string (ob, ob->main_stream, &str[1]);
|
1264 |
|
|
else
|
1265 |
|
|
output_string (ob, ob->main_stream, NULL);
|
1266 |
|
|
}
|
1267 |
|
|
else
|
1268 |
|
|
output_string (ob, ob->main_stream, NULL);
|
1269 |
|
|
}
|
1270 |
|
|
|
1271 |
|
|
|
1272 |
|
|
/* Write a physical representation of tree node EXPR to output block
|
1273 |
|
|
OB. If REF_P is true, the leaves of EXPR are emitted as references
|
1274 |
|
|
via lto_output_tree_ref. IX is the index into the streamer cache
|
1275 |
|
|
where EXPR is stored. */
|
1276 |
|
|
|
1277 |
|
|
static void
|
1278 |
|
|
lto_write_tree (struct output_block *ob, tree expr, bool ref_p, int ix)
|
1279 |
|
|
{
|
1280 |
|
|
struct bitpack_d *bp;
|
1281 |
|
|
|
1282 |
|
|
/* Write the header, containing everything needed to materialize
|
1283 |
|
|
EXPR on the reading side. */
|
1284 |
|
|
lto_output_tree_header (ob, expr, ix);
|
1285 |
|
|
|
1286 |
|
|
/* Pack all the non-pointer fields in EXPR into a bitpack and write
|
1287 |
|
|
the resulting bitpack. */
|
1288 |
|
|
bp = pack_value_fields (expr);
|
1289 |
|
|
lto_output_bitpack (ob->main_stream, bp);
|
1290 |
|
|
bitpack_delete (bp);
|
1291 |
|
|
|
1292 |
|
|
/* Write all the pointer fields in EXPR. */
|
1293 |
|
|
lto_output_tree_pointers (ob, expr, ref_p);
|
1294 |
|
|
|
1295 |
|
|
/* Mark the end of EXPR. */
|
1296 |
|
|
output_zero (ob);
|
1297 |
|
|
}
|
1298 |
|
|
|
1299 |
|
|
|
1300 |
|
|
/* Emit the integer constant CST to output block OB. If REF_P is true,
|
1301 |
|
|
CST's type will be emitted as a reference. */
|
1302 |
|
|
|
1303 |
|
|
static void
|
1304 |
|
|
lto_output_integer_cst (struct output_block *ob, tree cst, bool ref_p)
|
1305 |
|
|
{
|
1306 |
|
|
output_record_start (ob, lto_tree_code_to_tag (INTEGER_CST));
|
1307 |
|
|
lto_output_tree_or_ref (ob, TREE_TYPE (cst), ref_p);
|
1308 |
|
|
lto_output_1_stream (ob->main_stream, TREE_OVERFLOW_P (cst));
|
1309 |
|
|
output_uleb128 (ob, TREE_INT_CST_LOW (cst));
|
1310 |
|
|
output_uleb128 (ob, TREE_INT_CST_HIGH (cst));
|
1311 |
|
|
}
|
1312 |
|
|
|
1313 |
|
|
|
1314 |
|
|
/* Emit the physical representation of tree node EXPR to output block
|
1315 |
|
|
OB. If REF_P is true, the leaves of EXPR are emitted as references
|
1316 |
|
|
via lto_output_tree_ref. */
|
1317 |
|
|
|
1318 |
|
|
void
|
1319 |
|
|
lto_output_tree (struct output_block *ob, tree expr, bool ref_p)
|
1320 |
|
|
{
|
1321 |
|
|
int ix;
|
1322 |
|
|
bool existed_p;
|
1323 |
|
|
unsigned offset;
|
1324 |
|
|
|
1325 |
|
|
if (expr == NULL_TREE)
|
1326 |
|
|
{
|
1327 |
|
|
output_zero (ob);
|
1328 |
|
|
return;
|
1329 |
|
|
}
|
1330 |
|
|
|
1331 |
|
|
/* INTEGER_CST nodes are special because they need their original type
|
1332 |
|
|
to be materialized by the reader (to implement TYPE_CACHED_VALUES). */
|
1333 |
|
|
if (TREE_CODE (expr) == INTEGER_CST)
|
1334 |
|
|
{
|
1335 |
|
|
lto_output_integer_cst (ob, expr, ref_p);
|
1336 |
|
|
return;
|
1337 |
|
|
}
|
1338 |
|
|
|
1339 |
|
|
/* Determine the offset in the stream where EXPR will be written.
|
1340 |
|
|
This is used when emitting pickle references so the reader knows
|
1341 |
|
|
where to reconstruct the pickled object from. This allows
|
1342 |
|
|
circular and forward references within the same stream. */
|
1343 |
|
|
offset = ob->main_stream->total_size;
|
1344 |
|
|
|
1345 |
|
|
existed_p = lto_streamer_cache_insert (ob->writer_cache, expr, &ix, &offset);
|
1346 |
|
|
if (existed_p)
|
1347 |
|
|
{
|
1348 |
|
|
/* If a node has already been streamed out, make sure that
|
1349 |
|
|
we don't write it more than once. Otherwise, the reader
|
1350 |
|
|
will instantiate two different nodes for the same object. */
|
1351 |
|
|
output_record_start (ob, LTO_tree_pickle_reference);
|
1352 |
|
|
output_sleb128 (ob, ix);
|
1353 |
|
|
output_uleb128 (ob, lto_tree_code_to_tag (TREE_CODE (expr)));
|
1354 |
|
|
output_uleb128 (ob, offset);
|
1355 |
|
|
}
|
1356 |
|
|
else if (lto_stream_as_builtin_p (expr))
|
1357 |
|
|
{
|
1358 |
|
|
/* MD and NORMAL builtins do not need to be written out
|
1359 |
|
|
completely as they are always instantiated by the
|
1360 |
|
|
compiler on startup. The only builtins that need to
|
1361 |
|
|
be written out are BUILT_IN_FRONTEND. For all other
|
1362 |
|
|
builtins, we simply write the class and code. */
|
1363 |
|
|
lto_output_builtin_tree (ob, expr, ix);
|
1364 |
|
|
}
|
1365 |
|
|
else
|
1366 |
|
|
{
|
1367 |
|
|
/* This is the first time we see EXPR, write its fields
|
1368 |
|
|
to OB. */
|
1369 |
|
|
lto_write_tree (ob, expr, ref_p, ix);
|
1370 |
|
|
}
|
1371 |
|
|
}
|
1372 |
|
|
|
1373 |
|
|
|
1374 |
|
|
/* Output to OB a list of try/catch handlers starting with FIRST. */
|
1375 |
|
|
|
1376 |
|
|
static void
|
1377 |
|
|
output_eh_try_list (struct output_block *ob, eh_catch first)
|
1378 |
|
|
{
|
1379 |
|
|
eh_catch n;
|
1380 |
|
|
|
1381 |
|
|
for (n = first; n; n = n->next_catch)
|
1382 |
|
|
{
|
1383 |
|
|
output_record_start (ob, LTO_eh_catch);
|
1384 |
|
|
lto_output_tree_ref (ob, n->type_list);
|
1385 |
|
|
lto_output_tree_ref (ob, n->filter_list);
|
1386 |
|
|
lto_output_tree_ref (ob, n->label);
|
1387 |
|
|
}
|
1388 |
|
|
|
1389 |
|
|
output_zero (ob);
|
1390 |
|
|
}
|
1391 |
|
|
|
1392 |
|
|
|
1393 |
|
|
/* Output EH region R in function FN to OB. CURR_RN is the slot index
|
1394 |
|
|
that is being emitted in FN->EH->REGION_ARRAY. This is used to
|
1395 |
|
|
detect EH region sharing. */
|
1396 |
|
|
|
1397 |
|
|
static void
|
1398 |
|
|
output_eh_region (struct output_block *ob, eh_region r)
|
1399 |
|
|
{
|
1400 |
|
|
enum LTO_tags tag;
|
1401 |
|
|
|
1402 |
|
|
if (r == NULL)
|
1403 |
|
|
{
|
1404 |
|
|
output_zero (ob);
|
1405 |
|
|
return;
|
1406 |
|
|
}
|
1407 |
|
|
|
1408 |
|
|
if (r->type == ERT_CLEANUP)
|
1409 |
|
|
tag = LTO_ert_cleanup;
|
1410 |
|
|
else if (r->type == ERT_TRY)
|
1411 |
|
|
tag = LTO_ert_try;
|
1412 |
|
|
else if (r->type == ERT_ALLOWED_EXCEPTIONS)
|
1413 |
|
|
tag = LTO_ert_allowed_exceptions;
|
1414 |
|
|
else if (r->type == ERT_MUST_NOT_THROW)
|
1415 |
|
|
tag = LTO_ert_must_not_throw;
|
1416 |
|
|
else
|
1417 |
|
|
gcc_unreachable ();
|
1418 |
|
|
|
1419 |
|
|
output_record_start (ob, tag);
|
1420 |
|
|
output_sleb128 (ob, r->index);
|
1421 |
|
|
|
1422 |
|
|
if (r->outer)
|
1423 |
|
|
output_sleb128 (ob, r->outer->index);
|
1424 |
|
|
else
|
1425 |
|
|
output_zero (ob);
|
1426 |
|
|
|
1427 |
|
|
if (r->inner)
|
1428 |
|
|
output_sleb128 (ob, r->inner->index);
|
1429 |
|
|
else
|
1430 |
|
|
output_zero (ob);
|
1431 |
|
|
|
1432 |
|
|
if (r->next_peer)
|
1433 |
|
|
output_sleb128 (ob, r->next_peer->index);
|
1434 |
|
|
else
|
1435 |
|
|
output_zero (ob);
|
1436 |
|
|
|
1437 |
|
|
if (r->type == ERT_TRY)
|
1438 |
|
|
{
|
1439 |
|
|
output_eh_try_list (ob, r->u.eh_try.first_catch);
|
1440 |
|
|
}
|
1441 |
|
|
else if (r->type == ERT_ALLOWED_EXCEPTIONS)
|
1442 |
|
|
{
|
1443 |
|
|
lto_output_tree_ref (ob, r->u.allowed.type_list);
|
1444 |
|
|
lto_output_tree_ref (ob, r->u.allowed.label);
|
1445 |
|
|
output_uleb128 (ob, r->u.allowed.filter);
|
1446 |
|
|
}
|
1447 |
|
|
else if (r->type == ERT_MUST_NOT_THROW)
|
1448 |
|
|
{
|
1449 |
|
|
lto_output_tree_ref (ob, r->u.must_not_throw.failure_decl);
|
1450 |
|
|
lto_output_location (ob, r->u.must_not_throw.failure_loc);
|
1451 |
|
|
}
|
1452 |
|
|
|
1453 |
|
|
if (r->landing_pads)
|
1454 |
|
|
output_sleb128 (ob, r->landing_pads->index);
|
1455 |
|
|
else
|
1456 |
|
|
output_zero (ob);
|
1457 |
|
|
}
|
1458 |
|
|
|
1459 |
|
|
|
1460 |
|
|
/* Output landing pad LP to OB. */
|
1461 |
|
|
|
1462 |
|
|
static void
|
1463 |
|
|
output_eh_lp (struct output_block *ob, eh_landing_pad lp)
|
1464 |
|
|
{
|
1465 |
|
|
if (lp == NULL)
|
1466 |
|
|
{
|
1467 |
|
|
output_zero (ob);
|
1468 |
|
|
return;
|
1469 |
|
|
}
|
1470 |
|
|
|
1471 |
|
|
output_record_start (ob, LTO_eh_landing_pad);
|
1472 |
|
|
output_sleb128 (ob, lp->index);
|
1473 |
|
|
if (lp->next_lp)
|
1474 |
|
|
output_sleb128 (ob, lp->next_lp->index);
|
1475 |
|
|
else
|
1476 |
|
|
output_zero (ob);
|
1477 |
|
|
|
1478 |
|
|
if (lp->region)
|
1479 |
|
|
output_sleb128 (ob, lp->region->index);
|
1480 |
|
|
else
|
1481 |
|
|
output_zero (ob);
|
1482 |
|
|
|
1483 |
|
|
lto_output_tree_ref (ob, lp->post_landing_pad);
|
1484 |
|
|
}
|
1485 |
|
|
|
1486 |
|
|
|
1487 |
|
|
/* Output the existing eh_table to OB. */
|
1488 |
|
|
|
1489 |
|
|
static void
|
1490 |
|
|
output_eh_regions (struct output_block *ob, struct function *fn)
|
1491 |
|
|
{
|
1492 |
|
|
if (fn->eh && fn->eh->region_tree)
|
1493 |
|
|
{
|
1494 |
|
|
unsigned i;
|
1495 |
|
|
eh_region eh;
|
1496 |
|
|
eh_landing_pad lp;
|
1497 |
|
|
tree ttype;
|
1498 |
|
|
|
1499 |
|
|
output_record_start (ob, LTO_eh_table);
|
1500 |
|
|
|
1501 |
|
|
/* Emit the index of the root of the EH region tree. */
|
1502 |
|
|
output_sleb128 (ob, fn->eh->region_tree->index);
|
1503 |
|
|
|
1504 |
|
|
/* Emit all the EH regions in the region array. */
|
1505 |
|
|
output_sleb128 (ob, VEC_length (eh_region, fn->eh->region_array));
|
1506 |
|
|
for (i = 0; VEC_iterate (eh_region, fn->eh->region_array, i, eh); i++)
|
1507 |
|
|
output_eh_region (ob, eh);
|
1508 |
|
|
|
1509 |
|
|
/* Emit all landing pads. */
|
1510 |
|
|
output_sleb128 (ob, VEC_length (eh_landing_pad, fn->eh->lp_array));
|
1511 |
|
|
for (i = 0; VEC_iterate (eh_landing_pad, fn->eh->lp_array, i, lp); i++)
|
1512 |
|
|
output_eh_lp (ob, lp);
|
1513 |
|
|
|
1514 |
|
|
/* Emit all the runtime type data. */
|
1515 |
|
|
output_sleb128 (ob, VEC_length (tree, fn->eh->ttype_data));
|
1516 |
|
|
for (i = 0; VEC_iterate (tree, fn->eh->ttype_data, i, ttype); i++)
|
1517 |
|
|
lto_output_tree_ref (ob, ttype);
|
1518 |
|
|
|
1519 |
|
|
/* Emit the table of action chains. */
|
1520 |
|
|
if (targetm.arm_eabi_unwinder)
|
1521 |
|
|
{
|
1522 |
|
|
tree t;
|
1523 |
|
|
output_sleb128 (ob, VEC_length (tree, fn->eh->ehspec_data.arm_eabi));
|
1524 |
|
|
for (i = 0;
|
1525 |
|
|
VEC_iterate (tree, fn->eh->ehspec_data.arm_eabi, i, t);
|
1526 |
|
|
i++)
|
1527 |
|
|
lto_output_tree_ref (ob, t);
|
1528 |
|
|
}
|
1529 |
|
|
else
|
1530 |
|
|
{
|
1531 |
|
|
uchar c;
|
1532 |
|
|
output_sleb128 (ob, VEC_length (uchar, fn->eh->ehspec_data.other));
|
1533 |
|
|
for (i = 0; VEC_iterate (uchar, fn->eh->ehspec_data.other, i, c); i++)
|
1534 |
|
|
lto_output_1_stream (ob->main_stream, c);
|
1535 |
|
|
}
|
1536 |
|
|
}
|
1537 |
|
|
|
1538 |
|
|
/* The 0 either terminates the record or indicates that there are no
|
1539 |
|
|
eh_records at all. */
|
1540 |
|
|
output_zero (ob);
|
1541 |
|
|
}
|
1542 |
|
|
|
1543 |
|
|
|
1544 |
|
|
/* Output all of the active ssa names to the ssa_names stream. */
|
1545 |
|
|
|
1546 |
|
|
static void
|
1547 |
|
|
output_ssa_names (struct output_block *ob, struct function *fn)
|
1548 |
|
|
{
|
1549 |
|
|
unsigned int i, len;
|
1550 |
|
|
|
1551 |
|
|
len = VEC_length (tree, SSANAMES (fn));
|
1552 |
|
|
output_uleb128 (ob, len);
|
1553 |
|
|
|
1554 |
|
|
for (i = 1; i < len; i++)
|
1555 |
|
|
{
|
1556 |
|
|
tree ptr = VEC_index (tree, SSANAMES (fn), i);
|
1557 |
|
|
|
1558 |
|
|
if (ptr == NULL_TREE
|
1559 |
|
|
|| SSA_NAME_IN_FREE_LIST (ptr)
|
1560 |
|
|
|| !is_gimple_reg (ptr))
|
1561 |
|
|
continue;
|
1562 |
|
|
|
1563 |
|
|
output_uleb128 (ob, i);
|
1564 |
|
|
lto_output_1_stream (ob->main_stream, SSA_NAME_IS_DEFAULT_DEF (ptr));
|
1565 |
|
|
lto_output_tree_ref (ob, SSA_NAME_VAR (ptr));
|
1566 |
|
|
}
|
1567 |
|
|
|
1568 |
|
|
output_zero (ob);
|
1569 |
|
|
}
|
1570 |
|
|
|
1571 |
|
|
|
1572 |
|
|
/* Output the cfg. */
|
1573 |
|
|
|
1574 |
|
|
static void
|
1575 |
|
|
output_cfg (struct output_block *ob, struct function *fn)
|
1576 |
|
|
{
|
1577 |
|
|
struct lto_output_stream *tmp_stream = ob->main_stream;
|
1578 |
|
|
basic_block bb;
|
1579 |
|
|
|
1580 |
|
|
ob->main_stream = ob->cfg_stream;
|
1581 |
|
|
|
1582 |
|
|
output_uleb128 (ob, profile_status_for_function (fn));
|
1583 |
|
|
|
1584 |
|
|
/* Output the number of the highest basic block. */
|
1585 |
|
|
output_uleb128 (ob, last_basic_block_for_function (fn));
|
1586 |
|
|
|
1587 |
|
|
FOR_ALL_BB_FN (bb, fn)
|
1588 |
|
|
{
|
1589 |
|
|
edge_iterator ei;
|
1590 |
|
|
edge e;
|
1591 |
|
|
|
1592 |
|
|
output_sleb128 (ob, bb->index);
|
1593 |
|
|
|
1594 |
|
|
/* Output the successors and the edge flags. */
|
1595 |
|
|
output_uleb128 (ob, EDGE_COUNT (bb->succs));
|
1596 |
|
|
FOR_EACH_EDGE (e, ei, bb->succs)
|
1597 |
|
|
{
|
1598 |
|
|
output_uleb128 (ob, e->dest->index);
|
1599 |
|
|
output_sleb128 (ob, e->probability);
|
1600 |
|
|
output_sleb128 (ob, e->count);
|
1601 |
|
|
output_uleb128 (ob, e->flags);
|
1602 |
|
|
}
|
1603 |
|
|
}
|
1604 |
|
|
|
1605 |
|
|
output_sleb128 (ob, -1);
|
1606 |
|
|
|
1607 |
|
|
bb = ENTRY_BLOCK_PTR;
|
1608 |
|
|
while (bb->next_bb)
|
1609 |
|
|
{
|
1610 |
|
|
output_sleb128 (ob, bb->next_bb->index);
|
1611 |
|
|
bb = bb->next_bb;
|
1612 |
|
|
}
|
1613 |
|
|
|
1614 |
|
|
output_sleb128 (ob, -1);
|
1615 |
|
|
|
1616 |
|
|
ob->main_stream = tmp_stream;
|
1617 |
|
|
}
|
1618 |
|
|
|
1619 |
|
|
|
1620 |
|
|
/* Output PHI function PHI to the main stream in OB. */
|
1621 |
|
|
|
1622 |
|
|
static void
|
1623 |
|
|
output_phi (struct output_block *ob, gimple phi)
|
1624 |
|
|
{
|
1625 |
|
|
unsigned i, len = gimple_phi_num_args (phi);
|
1626 |
|
|
|
1627 |
|
|
output_record_start (ob, lto_gimple_code_to_tag (GIMPLE_PHI));
|
1628 |
|
|
output_uleb128 (ob, SSA_NAME_VERSION (PHI_RESULT (phi)));
|
1629 |
|
|
|
1630 |
|
|
for (i = 0; i < len; i++)
|
1631 |
|
|
{
|
1632 |
|
|
lto_output_tree_ref (ob, gimple_phi_arg_def (phi, i));
|
1633 |
|
|
output_uleb128 (ob, gimple_phi_arg_edge (phi, i)->src->index);
|
1634 |
|
|
lto_output_location (ob, gimple_phi_arg_location (phi, i));
|
1635 |
|
|
}
|
1636 |
|
|
}
|
1637 |
|
|
|
1638 |
|
|
|
1639 |
|
|
/* Emit statement STMT on the main stream of output block OB. */
|
1640 |
|
|
|
1641 |
|
|
static void
|
1642 |
|
|
output_gimple_stmt (struct output_block *ob, gimple stmt)
|
1643 |
|
|
{
|
1644 |
|
|
unsigned i;
|
1645 |
|
|
enum gimple_code code;
|
1646 |
|
|
enum LTO_tags tag;
|
1647 |
|
|
struct bitpack_d *bp;
|
1648 |
|
|
|
1649 |
|
|
/* Emit identifying tag. */
|
1650 |
|
|
code = gimple_code (stmt);
|
1651 |
|
|
tag = lto_gimple_code_to_tag (code);
|
1652 |
|
|
output_record_start (ob, tag);
|
1653 |
|
|
|
1654 |
|
|
/* Emit the tuple header. */
|
1655 |
|
|
bp = bitpack_create ();
|
1656 |
|
|
bp_pack_value (bp, gimple_num_ops (stmt), sizeof (unsigned) * 8);
|
1657 |
|
|
bp_pack_value (bp, gimple_no_warning_p (stmt), 1);
|
1658 |
|
|
if (is_gimple_assign (stmt))
|
1659 |
|
|
bp_pack_value (bp, gimple_assign_nontemporal_move_p (stmt), 1);
|
1660 |
|
|
bp_pack_value (bp, gimple_has_volatile_ops (stmt), 1);
|
1661 |
|
|
bp_pack_value (bp, stmt->gsbase.subcode, 16);
|
1662 |
|
|
lto_output_bitpack (ob->main_stream, bp);
|
1663 |
|
|
bitpack_delete (bp);
|
1664 |
|
|
|
1665 |
|
|
/* Emit location information for the statement. */
|
1666 |
|
|
lto_output_location (ob, gimple_location (stmt));
|
1667 |
|
|
|
1668 |
|
|
/* Emit the lexical block holding STMT. */
|
1669 |
|
|
lto_output_tree (ob, gimple_block (stmt), true);
|
1670 |
|
|
|
1671 |
|
|
/* Emit the operands. */
|
1672 |
|
|
switch (gimple_code (stmt))
|
1673 |
|
|
{
|
1674 |
|
|
case GIMPLE_RESX:
|
1675 |
|
|
output_sleb128 (ob, gimple_resx_region (stmt));
|
1676 |
|
|
break;
|
1677 |
|
|
|
1678 |
|
|
case GIMPLE_EH_MUST_NOT_THROW:
|
1679 |
|
|
lto_output_tree_ref (ob, gimple_eh_must_not_throw_fndecl (stmt));
|
1680 |
|
|
break;
|
1681 |
|
|
|
1682 |
|
|
case GIMPLE_EH_DISPATCH:
|
1683 |
|
|
output_sleb128 (ob, gimple_eh_dispatch_region (stmt));
|
1684 |
|
|
break;
|
1685 |
|
|
|
1686 |
|
|
case GIMPLE_ASM:
|
1687 |
|
|
lto_output_uleb128_stream (ob->main_stream, gimple_asm_ninputs (stmt));
|
1688 |
|
|
lto_output_uleb128_stream (ob->main_stream, gimple_asm_noutputs (stmt));
|
1689 |
|
|
lto_output_uleb128_stream (ob->main_stream, gimple_asm_nclobbers (stmt));
|
1690 |
|
|
lto_output_uleb128_stream (ob->main_stream, gimple_asm_nlabels (stmt));
|
1691 |
|
|
output_string (ob, ob->main_stream, gimple_asm_string (stmt));
|
1692 |
|
|
/* Fallthru */
|
1693 |
|
|
|
1694 |
|
|
case GIMPLE_ASSIGN:
|
1695 |
|
|
case GIMPLE_CALL:
|
1696 |
|
|
case GIMPLE_RETURN:
|
1697 |
|
|
case GIMPLE_SWITCH:
|
1698 |
|
|
case GIMPLE_LABEL:
|
1699 |
|
|
case GIMPLE_COND:
|
1700 |
|
|
case GIMPLE_GOTO:
|
1701 |
|
|
case GIMPLE_DEBUG:
|
1702 |
|
|
for (i = 0; i < gimple_num_ops (stmt); i++)
|
1703 |
|
|
{
|
1704 |
|
|
tree op = gimple_op (stmt, i);
|
1705 |
|
|
lto_output_tree_ref (ob, op);
|
1706 |
|
|
}
|
1707 |
|
|
break;
|
1708 |
|
|
|
1709 |
|
|
case GIMPLE_NOP:
|
1710 |
|
|
case GIMPLE_PREDICT:
|
1711 |
|
|
break;
|
1712 |
|
|
|
1713 |
|
|
default:
|
1714 |
|
|
gcc_unreachable ();
|
1715 |
|
|
}
|
1716 |
|
|
}
|
1717 |
|
|
|
1718 |
|
|
|
1719 |
|
|
/* Output a basic block BB to the main stream in OB for this FN. */
|
1720 |
|
|
|
1721 |
|
|
static void
|
1722 |
|
|
output_bb (struct output_block *ob, basic_block bb, struct function *fn)
|
1723 |
|
|
{
|
1724 |
|
|
gimple_stmt_iterator bsi = gsi_start_bb (bb);
|
1725 |
|
|
|
1726 |
|
|
output_record_start (ob,
|
1727 |
|
|
(!gsi_end_p (bsi)) || phi_nodes (bb)
|
1728 |
|
|
? LTO_bb1
|
1729 |
|
|
: LTO_bb0);
|
1730 |
|
|
|
1731 |
|
|
output_uleb128 (ob, bb->index);
|
1732 |
|
|
output_sleb128 (ob, bb->count);
|
1733 |
|
|
output_sleb128 (ob, bb->loop_depth);
|
1734 |
|
|
output_sleb128 (ob, bb->frequency);
|
1735 |
|
|
output_sleb128 (ob, bb->flags);
|
1736 |
|
|
|
1737 |
|
|
if (!gsi_end_p (bsi) || phi_nodes (bb))
|
1738 |
|
|
{
|
1739 |
|
|
/* Output the statements. The list of statements is terminated
|
1740 |
|
|
with a zero. */
|
1741 |
|
|
for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
|
1742 |
|
|
{
|
1743 |
|
|
int region;
|
1744 |
|
|
gimple stmt = gsi_stmt (bsi);
|
1745 |
|
|
|
1746 |
|
|
output_gimple_stmt (ob, stmt);
|
1747 |
|
|
|
1748 |
|
|
/* Emit the EH region holding STMT. */
|
1749 |
|
|
region = lookup_stmt_eh_lp_fn (fn, stmt);
|
1750 |
|
|
if (region != 0)
|
1751 |
|
|
{
|
1752 |
|
|
output_record_start (ob, LTO_eh_region);
|
1753 |
|
|
output_sleb128 (ob, region);
|
1754 |
|
|
}
|
1755 |
|
|
else
|
1756 |
|
|
output_zero (ob);
|
1757 |
|
|
}
|
1758 |
|
|
|
1759 |
|
|
output_zero (ob);
|
1760 |
|
|
|
1761 |
|
|
for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi))
|
1762 |
|
|
{
|
1763 |
|
|
gimple phi = gsi_stmt (bsi);
|
1764 |
|
|
|
1765 |
|
|
/* Only emit PHIs for gimple registers. PHI nodes for .MEM
|
1766 |
|
|
will be filled in on reading when the SSA form is
|
1767 |
|
|
updated. */
|
1768 |
|
|
if (is_gimple_reg (gimple_phi_result (phi)))
|
1769 |
|
|
output_phi (ob, phi);
|
1770 |
|
|
}
|
1771 |
|
|
|
1772 |
|
|
output_zero (ob);
|
1773 |
|
|
}
|
1774 |
|
|
}
|
1775 |
|
|
|
1776 |
|
|
/* Create the header in the file using OB. If the section type is for
|
1777 |
|
|
a function, set FN to the decl for that function. */
|
1778 |
|
|
|
1779 |
|
|
void
|
1780 |
|
|
produce_asm (struct output_block *ob, tree fn)
|
1781 |
|
|
{
|
1782 |
|
|
enum lto_section_type section_type = ob->section_type;
|
1783 |
|
|
struct lto_function_header header;
|
1784 |
|
|
char *section_name;
|
1785 |
|
|
struct lto_output_stream *header_stream;
|
1786 |
|
|
|
1787 |
|
|
if (section_type == LTO_section_function_body)
|
1788 |
|
|
{
|
1789 |
|
|
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn));
|
1790 |
|
|
section_name = lto_get_section_name (section_type, name);
|
1791 |
|
|
}
|
1792 |
|
|
else
|
1793 |
|
|
section_name = lto_get_section_name (section_type, NULL);
|
1794 |
|
|
|
1795 |
|
|
lto_begin_section (section_name, !flag_wpa);
|
1796 |
|
|
free (section_name);
|
1797 |
|
|
|
1798 |
|
|
/* The entire header is stream computed here. */
|
1799 |
|
|
memset (&header, 0, sizeof (struct lto_function_header));
|
1800 |
|
|
|
1801 |
|
|
/* Write the header. */
|
1802 |
|
|
header.lto_header.major_version = LTO_major_version;
|
1803 |
|
|
header.lto_header.minor_version = LTO_minor_version;
|
1804 |
|
|
header.lto_header.section_type = section_type;
|
1805 |
|
|
|
1806 |
|
|
header.compressed_size = 0;
|
1807 |
|
|
|
1808 |
|
|
if (section_type == LTO_section_function_body)
|
1809 |
|
|
header.cfg_size = ob->cfg_stream->total_size;
|
1810 |
|
|
header.main_size = ob->main_stream->total_size;
|
1811 |
|
|
header.string_size = ob->string_stream->total_size;
|
1812 |
|
|
|
1813 |
|
|
header_stream = XCNEW (struct lto_output_stream);
|
1814 |
|
|
lto_output_data_stream (header_stream, &header, sizeof header);
|
1815 |
|
|
lto_write_stream (header_stream);
|
1816 |
|
|
free (header_stream);
|
1817 |
|
|
|
1818 |
|
|
/* Put all of the gimple and the string table out the asm file as a
|
1819 |
|
|
block of text. */
|
1820 |
|
|
if (section_type == LTO_section_function_body)
|
1821 |
|
|
lto_write_stream (ob->cfg_stream);
|
1822 |
|
|
lto_write_stream (ob->main_stream);
|
1823 |
|
|
lto_write_stream (ob->string_stream);
|
1824 |
|
|
|
1825 |
|
|
lto_end_section ();
|
1826 |
|
|
}
|
1827 |
|
|
|
1828 |
|
|
|
1829 |
|
|
/* Output the body of function NODE->DECL. */
|
1830 |
|
|
|
1831 |
|
|
static void
|
1832 |
|
|
output_function (struct cgraph_node *node)
|
1833 |
|
|
{
|
1834 |
|
|
struct bitpack_d *bp;
|
1835 |
|
|
tree function;
|
1836 |
|
|
struct function *fn;
|
1837 |
|
|
basic_block bb;
|
1838 |
|
|
struct output_block *ob;
|
1839 |
|
|
|
1840 |
|
|
function = node->decl;
|
1841 |
|
|
fn = DECL_STRUCT_FUNCTION (function);
|
1842 |
|
|
ob = create_output_block (LTO_section_function_body);
|
1843 |
|
|
|
1844 |
|
|
clear_line_info (ob);
|
1845 |
|
|
ob->cgraph_node = node;
|
1846 |
|
|
|
1847 |
|
|
gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
|
1848 |
|
|
|
1849 |
|
|
/* Set current_function_decl and cfun. */
|
1850 |
|
|
current_function_decl = function;
|
1851 |
|
|
push_cfun (fn);
|
1852 |
|
|
|
1853 |
|
|
/* Make string 0 be a NULL string. */
|
1854 |
|
|
lto_output_1_stream (ob->string_stream, 0);
|
1855 |
|
|
|
1856 |
|
|
output_record_start (ob, LTO_function);
|
1857 |
|
|
|
1858 |
|
|
/* Write all the attributes for FN. */
|
1859 |
|
|
bp = bitpack_create ();
|
1860 |
|
|
bp_pack_value (bp, fn->is_thunk, 1);
|
1861 |
|
|
bp_pack_value (bp, fn->has_local_explicit_reg_vars, 1);
|
1862 |
|
|
bp_pack_value (bp, fn->after_tree_profile, 1);
|
1863 |
|
|
bp_pack_value (bp, fn->returns_pcc_struct, 1);
|
1864 |
|
|
bp_pack_value (bp, fn->returns_struct, 1);
|
1865 |
|
|
bp_pack_value (bp, fn->always_inline_functions_inlined, 1);
|
1866 |
|
|
bp_pack_value (bp, fn->after_inlining, 1);
|
1867 |
|
|
bp_pack_value (bp, fn->dont_save_pending_sizes_p, 1);
|
1868 |
|
|
bp_pack_value (bp, fn->stdarg, 1);
|
1869 |
|
|
bp_pack_value (bp, fn->has_nonlocal_label, 1);
|
1870 |
|
|
bp_pack_value (bp, fn->calls_alloca, 1);
|
1871 |
|
|
bp_pack_value (bp, fn->calls_setjmp, 1);
|
1872 |
|
|
bp_pack_value (bp, fn->function_frequency, 2);
|
1873 |
|
|
bp_pack_value (bp, fn->va_list_fpr_size, 8);
|
1874 |
|
|
bp_pack_value (bp, fn->va_list_gpr_size, 8);
|
1875 |
|
|
lto_output_bitpack (ob->main_stream, bp);
|
1876 |
|
|
bitpack_delete (bp);
|
1877 |
|
|
|
1878 |
|
|
/* Output current IL state of the function. */
|
1879 |
|
|
output_uleb128 (ob, fn->curr_properties);
|
1880 |
|
|
|
1881 |
|
|
/* Output the static chain and non-local goto save area. */
|
1882 |
|
|
lto_output_tree_ref (ob, fn->static_chain_decl);
|
1883 |
|
|
lto_output_tree_ref (ob, fn->nonlocal_goto_save_area);
|
1884 |
|
|
|
1885 |
|
|
/* Output all the local variables in the function. */
|
1886 |
|
|
lto_output_tree_ref (ob, fn->local_decls);
|
1887 |
|
|
|
1888 |
|
|
/* Output the head of the arguments list. */
|
1889 |
|
|
lto_output_tree_ref (ob, DECL_ARGUMENTS (function));
|
1890 |
|
|
|
1891 |
|
|
/* Output all the SSA names used in the function. */
|
1892 |
|
|
output_ssa_names (ob, fn);
|
1893 |
|
|
|
1894 |
|
|
/* Output any exception handling regions. */
|
1895 |
|
|
output_eh_regions (ob, fn);
|
1896 |
|
|
|
1897 |
|
|
/* Output DECL_INITIAL for the function, which contains the tree of
|
1898 |
|
|
lexical scopes. */
|
1899 |
|
|
lto_output_tree (ob, DECL_INITIAL (function), true);
|
1900 |
|
|
|
1901 |
|
|
/* We will renumber the statements. The code that does this uses
|
1902 |
|
|
the same ordering that we use for serializing them so we can use
|
1903 |
|
|
the same code on the other end and not have to write out the
|
1904 |
|
|
statement numbers. */
|
1905 |
|
|
renumber_gimple_stmt_uids ();
|
1906 |
|
|
|
1907 |
|
|
/* Output the code for the function. */
|
1908 |
|
|
FOR_ALL_BB_FN (bb, fn)
|
1909 |
|
|
output_bb (ob, bb, fn);
|
1910 |
|
|
|
1911 |
|
|
/* The terminator for this function. */
|
1912 |
|
|
output_zero (ob);
|
1913 |
|
|
|
1914 |
|
|
output_cfg (ob, fn);
|
1915 |
|
|
|
1916 |
|
|
/* Create a section to hold the pickled output of this function. */
|
1917 |
|
|
produce_asm (ob, function);
|
1918 |
|
|
|
1919 |
|
|
destroy_output_block (ob);
|
1920 |
|
|
|
1921 |
|
|
current_function_decl = NULL;
|
1922 |
|
|
pop_cfun ();
|
1923 |
|
|
}
|
1924 |
|
|
|
1925 |
|
|
|
1926 |
|
|
/* Return true if alias pair P belongs to the set of cgraph nodes in
|
1927 |
|
|
SET. If P is a an alias for a VAR_DECL, it can always be emitted.
|
1928 |
|
|
However, for FUNCTION_DECL aliases, we should only output the pair
|
1929 |
|
|
if it belongs to a function whose cgraph node is in SET.
|
1930 |
|
|
Otherwise, the LTRANS phase will get into trouble when finalizing
|
1931 |
|
|
aliases because the alias will refer to a function not defined in
|
1932 |
|
|
the file processed by LTRANS. */
|
1933 |
|
|
|
1934 |
|
|
static bool
|
1935 |
|
|
output_alias_pair_p (alias_pair *p, cgraph_node_set set)
|
1936 |
|
|
{
|
1937 |
|
|
cgraph_node_set_iterator csi;
|
1938 |
|
|
struct cgraph_node *target_node;
|
1939 |
|
|
|
1940 |
|
|
/* Always emit VAR_DECLs. FIXME lto, we should probably only emit
|
1941 |
|
|
those VAR_DECLs that are instantiated in this file partition, but
|
1942 |
|
|
we have no easy way of knowing this based on SET. */
|
1943 |
|
|
if (TREE_CODE (p->decl) == VAR_DECL)
|
1944 |
|
|
return true;
|
1945 |
|
|
|
1946 |
|
|
/* Check if the assembler name for P->TARGET has its cgraph node in SET. */
|
1947 |
|
|
gcc_assert (TREE_CODE (p->decl) == FUNCTION_DECL);
|
1948 |
|
|
target_node = cgraph_node_for_asm (p->target);
|
1949 |
|
|
csi = cgraph_node_set_find (set, target_node);
|
1950 |
|
|
return (!csi_end_p (csi));
|
1951 |
|
|
}
|
1952 |
|
|
|
1953 |
|
|
|
1954 |
|
|
/* Output any unreferenced global symbol defined in SET, alias pairs
|
1955 |
|
|
and labels. */
|
1956 |
|
|
|
1957 |
|
|
static void
|
1958 |
|
|
output_unreferenced_globals (cgraph_node_set set)
|
1959 |
|
|
{
|
1960 |
|
|
struct output_block *ob;
|
1961 |
|
|
alias_pair *p;
|
1962 |
|
|
unsigned i;
|
1963 |
|
|
struct varpool_node *vnode;
|
1964 |
|
|
|
1965 |
|
|
ob = create_output_block (LTO_section_static_initializer);
|
1966 |
|
|
ob->cgraph_node = NULL;
|
1967 |
|
|
|
1968 |
|
|
clear_line_info (ob);
|
1969 |
|
|
|
1970 |
|
|
/* Make string 0 be a NULL string. */
|
1971 |
|
|
lto_output_1_stream (ob->string_stream, 0);
|
1972 |
|
|
|
1973 |
|
|
/* Emit references for all the global symbols. If a global symbol
|
1974 |
|
|
was never referenced in any of the functions of this file, it
|
1975 |
|
|
would not be emitted otherwise. This will result in unreferenced
|
1976 |
|
|
symbols at link time if a file defines a global symbol but
|
1977 |
|
|
never references it. */
|
1978 |
|
|
FOR_EACH_STATIC_VARIABLE (vnode)
|
1979 |
|
|
{
|
1980 |
|
|
tree var = vnode->decl;
|
1981 |
|
|
|
1982 |
|
|
if (TREE_CODE (var) == VAR_DECL)
|
1983 |
|
|
{
|
1984 |
|
|
struct varpool_node *alias;
|
1985 |
|
|
|
1986 |
|
|
/* Output the object in order to output references used in the
|
1987 |
|
|
initialization. */
|
1988 |
|
|
lto_output_tree (ob, var, true);
|
1989 |
|
|
|
1990 |
|
|
/* If it is public we also need a reference to the object itself. */
|
1991 |
|
|
if (TREE_PUBLIC (var))
|
1992 |
|
|
lto_output_tree_ref (ob, var);
|
1993 |
|
|
|
1994 |
|
|
/* Also output any extra_name aliases for this variable. */
|
1995 |
|
|
for (alias = vnode->extra_name; alias; alias = alias->next)
|
1996 |
|
|
{
|
1997 |
|
|
lto_output_tree (ob, alias->decl, true);
|
1998 |
|
|
output_record_start (ob, LTO_var_decl_alias);
|
1999 |
|
|
lto_output_var_decl_index (ob->decl_state, ob->main_stream,
|
2000 |
|
|
alias->decl);
|
2001 |
|
|
lto_output_var_decl_index (ob->decl_state, ob->main_stream,
|
2002 |
|
|
var);
|
2003 |
|
|
}
|
2004 |
|
|
}
|
2005 |
|
|
}
|
2006 |
|
|
|
2007 |
|
|
output_zero (ob);
|
2008 |
|
|
|
2009 |
|
|
/* Emit the alias pairs for the nodes in SET. */
|
2010 |
|
|
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++)
|
2011 |
|
|
{
|
2012 |
|
|
if (output_alias_pair_p (p, set))
|
2013 |
|
|
{
|
2014 |
|
|
lto_output_tree_ref (ob, p->decl);
|
2015 |
|
|
lto_output_tree_ref (ob, p->target);
|
2016 |
|
|
}
|
2017 |
|
|
}
|
2018 |
|
|
|
2019 |
|
|
output_zero (ob);
|
2020 |
|
|
|
2021 |
|
|
produce_asm (ob, NULL);
|
2022 |
|
|
destroy_output_block (ob);
|
2023 |
|
|
}
|
2024 |
|
|
|
2025 |
|
|
|
2026 |
|
|
/* Copy the function body of NODE without deserializing. */
|
2027 |
|
|
|
2028 |
|
|
static void
|
2029 |
|
|
copy_function (struct cgraph_node *node)
|
2030 |
|
|
{
|
2031 |
|
|
tree function = node->decl;
|
2032 |
|
|
struct lto_file_decl_data *file_data = node->local.lto_file_data;
|
2033 |
|
|
struct lto_output_stream *output_stream = XCNEW (struct lto_output_stream);
|
2034 |
|
|
const char *data;
|
2035 |
|
|
size_t len;
|
2036 |
|
|
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function));
|
2037 |
|
|
char *section_name =
|
2038 |
|
|
lto_get_section_name (LTO_section_function_body, name);
|
2039 |
|
|
size_t i, j;
|
2040 |
|
|
struct lto_in_decl_state *in_state;
|
2041 |
|
|
struct lto_out_decl_state *out_state = lto_get_out_decl_state ();
|
2042 |
|
|
|
2043 |
|
|
lto_begin_section (section_name, !flag_wpa);
|
2044 |
|
|
free (section_name);
|
2045 |
|
|
|
2046 |
|
|
/* We may have renamed the declaration, e.g., a static function. */
|
2047 |
|
|
name = lto_get_decl_name_mapping (file_data, name);
|
2048 |
|
|
|
2049 |
|
|
data = lto_get_section_data (file_data, LTO_section_function_body,
|
2050 |
|
|
name, &len);
|
2051 |
|
|
gcc_assert (data);
|
2052 |
|
|
|
2053 |
|
|
/* Do a bit copy of the function body. */
|
2054 |
|
|
lto_output_data_stream (output_stream, data, len);
|
2055 |
|
|
lto_write_stream (output_stream);
|
2056 |
|
|
|
2057 |
|
|
/* Copy decls. */
|
2058 |
|
|
in_state =
|
2059 |
|
|
lto_get_function_in_decl_state (node->local.lto_file_data, function);
|
2060 |
|
|
gcc_assert (in_state);
|
2061 |
|
|
|
2062 |
|
|
for (i = 0; i < LTO_N_DECL_STREAMS; i++)
|
2063 |
|
|
{
|
2064 |
|
|
size_t n = in_state->streams[i].size;
|
2065 |
|
|
tree *trees = in_state->streams[i].trees;
|
2066 |
|
|
struct lto_tree_ref_encoder *encoder = &(out_state->streams[i]);
|
2067 |
|
|
|
2068 |
|
|
/* The out state must have the same indices and the in state.
|
2069 |
|
|
So just copy the vector. All the encoders in the in state
|
2070 |
|
|
must be empty where we reach here. */
|
2071 |
|
|
gcc_assert (lto_tree_ref_encoder_size (encoder) == 0);
|
2072 |
|
|
for (j = 0; j < n; j++)
|
2073 |
|
|
VEC_safe_push (tree, heap, encoder->trees, trees[j]);
|
2074 |
|
|
encoder->next_index = n;
|
2075 |
|
|
}
|
2076 |
|
|
|
2077 |
|
|
lto_free_section_data (file_data, LTO_section_function_body, name,
|
2078 |
|
|
data, len);
|
2079 |
|
|
free (output_stream);
|
2080 |
|
|
lto_end_section ();
|
2081 |
|
|
}
|
2082 |
|
|
|
2083 |
|
|
|
2084 |
|
|
/* Initialize the LTO writer. */
|
2085 |
|
|
|
2086 |
|
|
static void
|
2087 |
|
|
lto_writer_init (void)
|
2088 |
|
|
{
|
2089 |
|
|
lto_streamer_init ();
|
2090 |
|
|
}
|
2091 |
|
|
|
2092 |
|
|
|
2093 |
|
|
/* Main entry point from the pass manager. */
|
2094 |
|
|
|
2095 |
|
|
static void
|
2096 |
|
|
lto_output (cgraph_node_set set)
|
2097 |
|
|
{
|
2098 |
|
|
struct cgraph_node *node;
|
2099 |
|
|
struct lto_out_decl_state *decl_state;
|
2100 |
|
|
cgraph_node_set_iterator csi;
|
2101 |
|
|
bitmap output = lto_bitmap_alloc ();
|
2102 |
|
|
|
2103 |
|
|
lto_writer_init ();
|
2104 |
|
|
|
2105 |
|
|
/* Process only the functions with bodies. */
|
2106 |
|
|
for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
|
2107 |
|
|
{
|
2108 |
|
|
node = csi_node (csi);
|
2109 |
|
|
if (node->analyzed && !bitmap_bit_p (output, DECL_UID (node->decl)))
|
2110 |
|
|
{
|
2111 |
|
|
bitmap_set_bit (output, DECL_UID (node->decl));
|
2112 |
|
|
decl_state = lto_new_out_decl_state ();
|
2113 |
|
|
lto_push_out_decl_state (decl_state);
|
2114 |
|
|
if (!flag_wpa)
|
2115 |
|
|
output_function (node);
|
2116 |
|
|
else
|
2117 |
|
|
copy_function (node);
|
2118 |
|
|
gcc_assert (lto_get_out_decl_state () == decl_state);
|
2119 |
|
|
lto_pop_out_decl_state ();
|
2120 |
|
|
lto_record_function_out_decl_state (node->decl, decl_state);
|
2121 |
|
|
}
|
2122 |
|
|
}
|
2123 |
|
|
|
2124 |
|
|
/* Emit the callgraph after emitting function bodies. This needs to
|
2125 |
|
|
be done now to make sure that all the statements in every function
|
2126 |
|
|
have been renumbered so that edges can be associated with call
|
2127 |
|
|
statements using the statement UIDs. */
|
2128 |
|
|
output_cgraph (set);
|
2129 |
|
|
|
2130 |
|
|
lto_bitmap_free (output);
|
2131 |
|
|
}
|
2132 |
|
|
|
2133 |
|
|
struct ipa_opt_pass_d pass_ipa_lto_gimple_out =
|
2134 |
|
|
{
|
2135 |
|
|
{
|
2136 |
|
|
IPA_PASS,
|
2137 |
|
|
"lto_gimple_out", /* name */
|
2138 |
|
|
gate_lto_out, /* gate */
|
2139 |
|
|
NULL, /* execute */
|
2140 |
|
|
NULL, /* sub */
|
2141 |
|
|
NULL, /* next */
|
2142 |
|
|
0, /* static_pass_number */
|
2143 |
|
|
TV_IPA_LTO_GIMPLE_IO, /* tv_id */
|
2144 |
|
|
0, /* properties_required */
|
2145 |
|
|
0, /* properties_provided */
|
2146 |
|
|
0, /* properties_destroyed */
|
2147 |
|
|
0, /* todo_flags_start */
|
2148 |
|
|
TODO_dump_func /* todo_flags_finish */
|
2149 |
|
|
},
|
2150 |
|
|
NULL, /* generate_summary */
|
2151 |
|
|
lto_output, /* write_summary */
|
2152 |
|
|
NULL, /* read_summary */
|
2153 |
|
|
NULL, /* function_read_summary */
|
2154 |
|
|
NULL, /* stmt_fixup */
|
2155 |
|
|
0, /* TODOs */
|
2156 |
|
|
NULL, /* function_transform */
|
2157 |
|
|
NULL /* variable_transform */
|
2158 |
|
|
};
|
2159 |
|
|
|
2160 |
|
|
|
2161 |
|
|
/* Write each node in encoded by ENCODER to OB, as well as those reachable
|
2162 |
|
|
from it and required for correct representation of its semantics.
|
2163 |
|
|
Each node in ENCODER must be a global declaration or a type. A node
|
2164 |
|
|
is written only once, even if it appears multiple times in the
|
2165 |
|
|
vector. Certain transitively-reachable nodes, such as those
|
2166 |
|
|
representing expressions, may be duplicated, but such nodes
|
2167 |
|
|
must not appear in ENCODER itself. */
|
2168 |
|
|
|
2169 |
|
|
static void
|
2170 |
|
|
write_global_stream (struct output_block *ob,
|
2171 |
|
|
struct lto_tree_ref_encoder *encoder)
|
2172 |
|
|
{
|
2173 |
|
|
tree t;
|
2174 |
|
|
size_t index;
|
2175 |
|
|
const size_t size = lto_tree_ref_encoder_size (encoder);
|
2176 |
|
|
|
2177 |
|
|
for (index = 0; index < size; index++)
|
2178 |
|
|
{
|
2179 |
|
|
t = lto_tree_ref_encoder_get_tree (encoder, index);
|
2180 |
|
|
if (!lto_streamer_cache_lookup (ob->writer_cache, t, NULL))
|
2181 |
|
|
lto_output_tree (ob, t, false);
|
2182 |
|
|
|
2183 |
|
|
if (flag_wpa)
|
2184 |
|
|
{
|
2185 |
|
|
/* In WPA we should not emit multiple definitions of the
|
2186 |
|
|
same symbol to all the files in the link set. If
|
2187 |
|
|
T had already been emitted as the pervailing definition
|
2188 |
|
|
in one file, do not emit it in the others. */
|
2189 |
|
|
/* FIXME lto. We should check if T belongs to the
|
2190 |
|
|
file we are writing to. */
|
2191 |
|
|
if (TREE_CODE (t) == VAR_DECL
|
2192 |
|
|
&& TREE_PUBLIC (t)
|
2193 |
|
|
&& !DECL_EXTERNAL (t))
|
2194 |
|
|
TREE_ASM_WRITTEN (t) = 1;
|
2195 |
|
|
}
|
2196 |
|
|
}
|
2197 |
|
|
}
|
2198 |
|
|
|
2199 |
|
|
|
2200 |
|
|
/* Write a sequence of indices into the globals vector corresponding
|
2201 |
|
|
to the trees in ENCODER. These are used by the reader to map the
|
2202 |
|
|
indices used to refer to global entities within function bodies to
|
2203 |
|
|
their referents. */
|
2204 |
|
|
|
2205 |
|
|
static void
|
2206 |
|
|
write_global_references (struct output_block *ob,
|
2207 |
|
|
struct lto_output_stream *ref_stream,
|
2208 |
|
|
struct lto_tree_ref_encoder *encoder)
|
2209 |
|
|
{
|
2210 |
|
|
tree t;
|
2211 |
|
|
int32_t index;
|
2212 |
|
|
const int32_t size = lto_tree_ref_encoder_size (encoder);
|
2213 |
|
|
|
2214 |
|
|
/* Write size as 32-bit unsigned. */
|
2215 |
|
|
lto_output_data_stream (ref_stream, &size, sizeof (int32_t));
|
2216 |
|
|
|
2217 |
|
|
for (index = 0; index < size; index++)
|
2218 |
|
|
{
|
2219 |
|
|
int32_t slot_num;
|
2220 |
|
|
|
2221 |
|
|
t = lto_tree_ref_encoder_get_tree (encoder, index);
|
2222 |
|
|
lto_streamer_cache_lookup (ob->writer_cache, t, &slot_num);
|
2223 |
|
|
gcc_assert (slot_num >= 0);
|
2224 |
|
|
lto_output_data_stream (ref_stream, &slot_num, sizeof slot_num);
|
2225 |
|
|
}
|
2226 |
|
|
}
|
2227 |
|
|
|
2228 |
|
|
|
2229 |
|
|
/* Write all the streams in an lto_out_decl_state STATE using
|
2230 |
|
|
output block OB and output stream OUT_STREAM. */
|
2231 |
|
|
|
2232 |
|
|
static void
|
2233 |
|
|
lto_output_decl_state_streams (struct output_block *ob,
|
2234 |
|
|
struct lto_out_decl_state *state)
|
2235 |
|
|
{
|
2236 |
|
|
int i;
|
2237 |
|
|
|
2238 |
|
|
for (i = 0; i < LTO_N_DECL_STREAMS; i++)
|
2239 |
|
|
write_global_stream (ob, &state->streams[i]);
|
2240 |
|
|
}
|
2241 |
|
|
|
2242 |
|
|
|
2243 |
|
|
/* Write all the references in an lto_out_decl_state STATE using
|
2244 |
|
|
output block OB and output stream OUT_STREAM. */
|
2245 |
|
|
|
2246 |
|
|
static void
|
2247 |
|
|
lto_output_decl_state_refs (struct output_block *ob,
|
2248 |
|
|
struct lto_output_stream *out_stream,
|
2249 |
|
|
struct lto_out_decl_state *state)
|
2250 |
|
|
{
|
2251 |
|
|
unsigned i;
|
2252 |
|
|
int32_t ref;
|
2253 |
|
|
tree decl;
|
2254 |
|
|
|
2255 |
|
|
/* Write reference to FUNCTION_DECL. If there is not function,
|
2256 |
|
|
write reference to void_type_node. */
|
2257 |
|
|
decl = (state->fn_decl) ? state->fn_decl : void_type_node;
|
2258 |
|
|
lto_streamer_cache_lookup (ob->writer_cache, decl, &ref);
|
2259 |
|
|
gcc_assert (ref >= 0);
|
2260 |
|
|
lto_output_data_stream (out_stream, &ref, sizeof (int32_t));
|
2261 |
|
|
|
2262 |
|
|
for (i = 0; i < LTO_N_DECL_STREAMS; i++)
|
2263 |
|
|
write_global_references (ob, out_stream, &state->streams[i]);
|
2264 |
|
|
}
|
2265 |
|
|
|
2266 |
|
|
|
2267 |
|
|
/* Return the written size of STATE. */
|
2268 |
|
|
|
2269 |
|
|
static size_t
|
2270 |
|
|
lto_out_decl_state_written_size (struct lto_out_decl_state *state)
|
2271 |
|
|
{
|
2272 |
|
|
int i;
|
2273 |
|
|
size_t size;
|
2274 |
|
|
|
2275 |
|
|
size = sizeof (int32_t); /* fn_ref. */
|
2276 |
|
|
for (i = 0; i < LTO_N_DECL_STREAMS; i++)
|
2277 |
|
|
{
|
2278 |
|
|
size += sizeof (int32_t); /* vector size. */
|
2279 |
|
|
size += (lto_tree_ref_encoder_size (&state->streams[i])
|
2280 |
|
|
* sizeof (int32_t));
|
2281 |
|
|
}
|
2282 |
|
|
return size;
|
2283 |
|
|
}
|
2284 |
|
|
|
2285 |
|
|
|
2286 |
|
|
/* Helper function of write_symbols_of_kind. CACHE is the streamer
|
2287 |
|
|
cache with all the pickled nodes. STREAM is the stream where to
|
2288 |
|
|
write the table. V is a vector with the DECLs that should be on
|
2289 |
|
|
the table. SEEN is a bitmap of symbols written so far. */
|
2290 |
|
|
|
2291 |
|
|
static void
|
2292 |
|
|
write_symbol_vec (struct lto_streamer_cache_d *cache,
|
2293 |
|
|
struct lto_output_stream *stream,
|
2294 |
|
|
VEC(tree,heap) *v, bitmap seen)
|
2295 |
|
|
{
|
2296 |
|
|
tree t;
|
2297 |
|
|
int index;
|
2298 |
|
|
|
2299 |
|
|
for (index = 0; VEC_iterate(tree, v, index, t); index++)
|
2300 |
|
|
{
|
2301 |
|
|
const char *name;
|
2302 |
|
|
enum gcc_plugin_symbol_kind kind;
|
2303 |
|
|
enum gcc_plugin_symbol_visibility visibility;
|
2304 |
|
|
int slot_num;
|
2305 |
|
|
uint64_t size;
|
2306 |
|
|
const char *comdat;
|
2307 |
|
|
|
2308 |
|
|
/* None of the following kinds of symbols are needed in the
|
2309 |
|
|
symbol table. */
|
2310 |
|
|
if (!TREE_PUBLIC (t)
|
2311 |
|
|
|| is_builtin_fn (t)
|
2312 |
|
|
|| DECL_ABSTRACT (t)
|
2313 |
|
|
|| TREE_CODE (t) == RESULT_DECL)
|
2314 |
|
|
continue;
|
2315 |
|
|
|
2316 |
|
|
gcc_assert (TREE_CODE (t) == VAR_DECL
|
2317 |
|
|
|| TREE_CODE (t) == FUNCTION_DECL);
|
2318 |
|
|
|
2319 |
|
|
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t));
|
2320 |
|
|
|
2321 |
|
|
/* FIXME lto: this is from assemble_name_raw in varasm.c. For some
|
2322 |
|
|
architectures we might have to do the same name manipulations that
|
2323 |
|
|
ASM_OUTPUT_LABELREF does. */
|
2324 |
|
|
if (name[0] == '*')
|
2325 |
|
|
name = &name[1];
|
2326 |
|
|
|
2327 |
|
|
lto_streamer_cache_lookup (cache, t, &slot_num);
|
2328 |
|
|
gcc_assert (slot_num >= 0);
|
2329 |
|
|
|
2330 |
|
|
/* Avoid duplicate symbols. */
|
2331 |
|
|
if (bitmap_bit_p (seen, slot_num))
|
2332 |
|
|
continue;
|
2333 |
|
|
else
|
2334 |
|
|
bitmap_set_bit (seen, slot_num);
|
2335 |
|
|
|
2336 |
|
|
if (DECL_EXTERNAL (t))
|
2337 |
|
|
{
|
2338 |
|
|
if (DECL_WEAK (t))
|
2339 |
|
|
kind = GCCPK_WEAKUNDEF;
|
2340 |
|
|
else
|
2341 |
|
|
kind = GCCPK_UNDEF;
|
2342 |
|
|
}
|
2343 |
|
|
else
|
2344 |
|
|
{
|
2345 |
|
|
if (DECL_WEAK (t))
|
2346 |
|
|
kind = GCCPK_WEAKDEF;
|
2347 |
|
|
else if (DECL_COMMON (t))
|
2348 |
|
|
kind = GCCPK_COMMON;
|
2349 |
|
|
else
|
2350 |
|
|
kind = GCCPK_DEF;
|
2351 |
|
|
}
|
2352 |
|
|
|
2353 |
|
|
switch (DECL_VISIBILITY(t))
|
2354 |
|
|
{
|
2355 |
|
|
case VISIBILITY_DEFAULT:
|
2356 |
|
|
visibility = GCCPV_DEFAULT;
|
2357 |
|
|
break;
|
2358 |
|
|
case VISIBILITY_PROTECTED:
|
2359 |
|
|
visibility = GCCPV_PROTECTED;
|
2360 |
|
|
break;
|
2361 |
|
|
case VISIBILITY_HIDDEN:
|
2362 |
|
|
visibility = GCCPV_HIDDEN;
|
2363 |
|
|
break;
|
2364 |
|
|
case VISIBILITY_INTERNAL:
|
2365 |
|
|
visibility = GCCPV_INTERNAL;
|
2366 |
|
|
break;
|
2367 |
|
|
}
|
2368 |
|
|
|
2369 |
|
|
if (kind == GCCPK_COMMON
|
2370 |
|
|
&& DECL_SIZE (t)
|
2371 |
|
|
&& TREE_CODE (DECL_SIZE (t)) == INTEGER_CST)
|
2372 |
|
|
size = (((uint64_t) TREE_INT_CST_HIGH (DECL_SIZE (t))) << 32)
|
2373 |
|
|
| TREE_INT_CST_LOW (DECL_SIZE (t));
|
2374 |
|
|
else
|
2375 |
|
|
size = 0;
|
2376 |
|
|
|
2377 |
|
|
if (DECL_ONE_ONLY (t))
|
2378 |
|
|
comdat = IDENTIFIER_POINTER (DECL_COMDAT_GROUP (t));
|
2379 |
|
|
else
|
2380 |
|
|
comdat = "";
|
2381 |
|
|
|
2382 |
|
|
lto_output_data_stream (stream, name, strlen (name) + 1);
|
2383 |
|
|
lto_output_data_stream (stream, comdat, strlen (comdat) + 1);
|
2384 |
|
|
lto_output_data_stream (stream, &kind, 1);
|
2385 |
|
|
lto_output_data_stream (stream, &visibility, 1);
|
2386 |
|
|
lto_output_data_stream (stream, &size, 8);
|
2387 |
|
|
lto_output_data_stream (stream, &slot_num, 4);
|
2388 |
|
|
}
|
2389 |
|
|
}
|
2390 |
|
|
|
2391 |
|
|
|
2392 |
|
|
/* Write IL symbols of KIND. CACHE is the streamer cache with all the
|
2393 |
|
|
pickled nodes. SEEN is a bitmap of symbols written so far. */
|
2394 |
|
|
|
2395 |
|
|
static void
|
2396 |
|
|
write_symbols_of_kind (lto_decl_stream_e_t kind,
|
2397 |
|
|
struct lto_streamer_cache_d *cache, bitmap seen)
|
2398 |
|
|
{
|
2399 |
|
|
struct lto_out_decl_state *out_state;
|
2400 |
|
|
struct lto_output_stream stream;
|
2401 |
|
|
unsigned num_fns =
|
2402 |
|
|
VEC_length (lto_out_decl_state_ptr, lto_function_decl_states);
|
2403 |
|
|
unsigned idx;
|
2404 |
|
|
|
2405 |
|
|
memset (&stream, 0, sizeof (stream));
|
2406 |
|
|
out_state = lto_get_out_decl_state ();
|
2407 |
|
|
write_symbol_vec (cache, &stream, out_state->streams[kind].trees, seen);
|
2408 |
|
|
|
2409 |
|
|
for (idx = 0; idx < num_fns; idx++)
|
2410 |
|
|
{
|
2411 |
|
|
out_state =
|
2412 |
|
|
VEC_index (lto_out_decl_state_ptr, lto_function_decl_states, idx);
|
2413 |
|
|
write_symbol_vec (cache, &stream, out_state->streams[kind].trees, seen);
|
2414 |
|
|
}
|
2415 |
|
|
|
2416 |
|
|
lto_write_stream (&stream);
|
2417 |
|
|
}
|
2418 |
|
|
|
2419 |
|
|
|
2420 |
|
|
/* Write an IL symbol table. CACHE is the streamer cache with all the
|
2421 |
|
|
pickled nodes. */
|
2422 |
|
|
|
2423 |
|
|
static void
|
2424 |
|
|
produce_symtab (struct lto_streamer_cache_d *cache)
|
2425 |
|
|
{
|
2426 |
|
|
char *section_name = lto_get_section_name (LTO_section_symtab, NULL);
|
2427 |
|
|
bitmap seen;
|
2428 |
|
|
|
2429 |
|
|
lto_begin_section (section_name, false);
|
2430 |
|
|
free (section_name);
|
2431 |
|
|
|
2432 |
|
|
seen = lto_bitmap_alloc ();
|
2433 |
|
|
write_symbols_of_kind (LTO_DECL_STREAM_FN_DECL, cache, seen);
|
2434 |
|
|
write_symbols_of_kind (LTO_DECL_STREAM_VAR_DECL, cache, seen);
|
2435 |
|
|
lto_bitmap_free (seen);
|
2436 |
|
|
|
2437 |
|
|
lto_end_section ();
|
2438 |
|
|
}
|
2439 |
|
|
|
2440 |
|
|
|
2441 |
|
|
/* This pass is run after all of the functions are serialized and all
|
2442 |
|
|
of the IPA passes have written their serialized forms. This pass
|
2443 |
|
|
causes the vector of all of the global decls and types used from
|
2444 |
|
|
this file to be written in to a section that can then be read in to
|
2445 |
|
|
recover these on other side. */
|
2446 |
|
|
|
2447 |
|
|
static void
|
2448 |
|
|
produce_asm_for_decls (cgraph_node_set set)
|
2449 |
|
|
{
|
2450 |
|
|
struct lto_out_decl_state *out_state;
|
2451 |
|
|
struct lto_out_decl_state *fn_out_state;
|
2452 |
|
|
struct lto_decl_header header;
|
2453 |
|
|
char *section_name;
|
2454 |
|
|
struct output_block *ob;
|
2455 |
|
|
struct lto_output_stream *header_stream, *decl_state_stream;
|
2456 |
|
|
unsigned idx, num_fns;
|
2457 |
|
|
size_t decl_state_size;
|
2458 |
|
|
int32_t num_decl_states;
|
2459 |
|
|
|
2460 |
|
|
ob = create_output_block (LTO_section_decls);
|
2461 |
|
|
ob->global = true;
|
2462 |
|
|
|
2463 |
|
|
/* Write out unreferenced globals, alias pairs and labels. We defer
|
2464 |
|
|
doing this until now so that we can write out only what is
|
2465 |
|
|
needed. */
|
2466 |
|
|
output_unreferenced_globals (set);
|
2467 |
|
|
|
2468 |
|
|
memset (&header, 0, sizeof (struct lto_decl_header));
|
2469 |
|
|
|
2470 |
|
|
section_name = lto_get_section_name (LTO_section_decls, NULL);
|
2471 |
|
|
lto_begin_section (section_name, !flag_wpa);
|
2472 |
|
|
free (section_name);
|
2473 |
|
|
|
2474 |
|
|
/* Make string 0 be a NULL string. */
|
2475 |
|
|
lto_output_1_stream (ob->string_stream, 0);
|
2476 |
|
|
|
2477 |
|
|
/* Write the global symbols. */
|
2478 |
|
|
out_state = lto_get_out_decl_state ();
|
2479 |
|
|
num_fns = VEC_length (lto_out_decl_state_ptr, lto_function_decl_states);
|
2480 |
|
|
lto_output_decl_state_streams (ob, out_state);
|
2481 |
|
|
for (idx = 0; idx < num_fns; idx++)
|
2482 |
|
|
{
|
2483 |
|
|
fn_out_state =
|
2484 |
|
|
VEC_index (lto_out_decl_state_ptr, lto_function_decl_states, idx);
|
2485 |
|
|
lto_output_decl_state_streams (ob, fn_out_state);
|
2486 |
|
|
}
|
2487 |
|
|
|
2488 |
|
|
header.lto_header.major_version = LTO_major_version;
|
2489 |
|
|
header.lto_header.minor_version = LTO_minor_version;
|
2490 |
|
|
header.lto_header.section_type = LTO_section_decls;
|
2491 |
|
|
|
2492 |
|
|
/* Currently not used. This field would allow us to preallocate
|
2493 |
|
|
the globals vector, so that it need not be resized as it is extended. */
|
2494 |
|
|
header.num_nodes = -1;
|
2495 |
|
|
|
2496 |
|
|
/* Compute the total size of all decl out states. */
|
2497 |
|
|
decl_state_size = sizeof (int32_t);
|
2498 |
|
|
decl_state_size += lto_out_decl_state_written_size (out_state);
|
2499 |
|
|
for (idx = 0; idx < num_fns; idx++)
|
2500 |
|
|
{
|
2501 |
|
|
fn_out_state =
|
2502 |
|
|
VEC_index (lto_out_decl_state_ptr, lto_function_decl_states, idx);
|
2503 |
|
|
decl_state_size += lto_out_decl_state_written_size (fn_out_state);
|
2504 |
|
|
}
|
2505 |
|
|
header.decl_state_size = decl_state_size;
|
2506 |
|
|
|
2507 |
|
|
header.main_size = ob->main_stream->total_size;
|
2508 |
|
|
header.string_size = ob->string_stream->total_size;
|
2509 |
|
|
|
2510 |
|
|
header_stream = XCNEW (struct lto_output_stream);
|
2511 |
|
|
lto_output_data_stream (header_stream, &header, sizeof header);
|
2512 |
|
|
lto_write_stream (header_stream);
|
2513 |
|
|
free (header_stream);
|
2514 |
|
|
|
2515 |
|
|
/* Write the main out-decl state, followed by out-decl states of
|
2516 |
|
|
functions. */
|
2517 |
|
|
decl_state_stream = ((struct lto_output_stream *)
|
2518 |
|
|
xcalloc (1, sizeof (struct lto_output_stream)));
|
2519 |
|
|
num_decl_states = num_fns + 1;
|
2520 |
|
|
lto_output_data_stream (decl_state_stream, &num_decl_states,
|
2521 |
|
|
sizeof (num_decl_states));
|
2522 |
|
|
lto_output_decl_state_refs (ob, decl_state_stream, out_state);
|
2523 |
|
|
for (idx = 0; idx < num_fns; idx++)
|
2524 |
|
|
{
|
2525 |
|
|
fn_out_state =
|
2526 |
|
|
VEC_index (lto_out_decl_state_ptr, lto_function_decl_states, idx);
|
2527 |
|
|
lto_output_decl_state_refs (ob, decl_state_stream, fn_out_state);
|
2528 |
|
|
}
|
2529 |
|
|
lto_write_stream (decl_state_stream);
|
2530 |
|
|
free(decl_state_stream);
|
2531 |
|
|
|
2532 |
|
|
lto_write_stream (ob->main_stream);
|
2533 |
|
|
lto_write_stream (ob->string_stream);
|
2534 |
|
|
|
2535 |
|
|
lto_end_section ();
|
2536 |
|
|
|
2537 |
|
|
/* Write the symbol table. */
|
2538 |
|
|
produce_symtab (ob->writer_cache);
|
2539 |
|
|
|
2540 |
|
|
/* Write command line opts. */
|
2541 |
|
|
lto_write_options ();
|
2542 |
|
|
|
2543 |
|
|
/* Deallocate memory and clean up. */
|
2544 |
|
|
lto_cgraph_encoder_delete (ob->decl_state->cgraph_node_encoder);
|
2545 |
|
|
VEC_free (lto_out_decl_state_ptr, heap, lto_function_decl_states);
|
2546 |
|
|
lto_function_decl_states = NULL;
|
2547 |
|
|
destroy_output_block (ob);
|
2548 |
|
|
}
|
2549 |
|
|
|
2550 |
|
|
|
2551 |
|
|
struct ipa_opt_pass_d pass_ipa_lto_finish_out =
|
2552 |
|
|
{
|
2553 |
|
|
{
|
2554 |
|
|
IPA_PASS,
|
2555 |
|
|
"lto_decls_out", /* name */
|
2556 |
|
|
gate_lto_out, /* gate */
|
2557 |
|
|
NULL, /* execute */
|
2558 |
|
|
NULL, /* sub */
|
2559 |
|
|
NULL, /* next */
|
2560 |
|
|
0, /* static_pass_number */
|
2561 |
|
|
TV_IPA_LTO_DECL_IO, /* tv_id */
|
2562 |
|
|
0, /* properties_required */
|
2563 |
|
|
0, /* properties_provided */
|
2564 |
|
|
0, /* properties_destroyed */
|
2565 |
|
|
0, /* todo_flags_start */
|
2566 |
|
|
|
2567 |
|
|
},
|
2568 |
|
|
NULL, /* generate_summary */
|
2569 |
|
|
produce_asm_for_decls, /* write_summary */
|
2570 |
|
|
NULL, /* read_summary */
|
2571 |
|
|
NULL, /* function_read_summary */
|
2572 |
|
|
NULL, /* stmt_fixup */
|
2573 |
|
|
0, /* TODOs */
|
2574 |
|
|
NULL, /* function_transform */
|
2575 |
|
|
NULL /* variable_transform */
|
2576 |
|
|
};
|