]>
Commit | Line | Data |
---|---|---|
d7f09764 DN |
1 | /* Read the GIMPLE representation from a file stream. |
2 | ||
c75c517d | 3 | Copyright 2009, 2010 Free Software Foundation, Inc. |
d7f09764 DN |
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" | |
d7f09764 DN |
33 | #include "hashtab.h" |
34 | #include "basic-block.h" | |
35 | #include "tree-flow.h" | |
36 | #include "tree-pass.h" | |
37 | #include "cgraph.h" | |
38 | #include "function.h" | |
39 | #include "ggc.h" | |
40 | #include "diagnostic.h" | |
41 | #include "libfuncs.h" | |
42 | #include "except.h" | |
43 | #include "debug.h" | |
44 | #include "vec.h" | |
45 | #include "timevar.h" | |
46 | #include "output.h" | |
47 | #include "ipa-utils.h" | |
f0efc7aa DN |
48 | #include "data-streamer.h" |
49 | #include "gimple-streamer.h" | |
d7f09764 | 50 | #include "lto-streamer.h" |
f0efc7aa | 51 | #include "tree-streamer.h" |
fb3f88cc | 52 | #include "tree-pass.h" |
a22286c3 | 53 | #include "streamer-hooks.h" |
d7f09764 | 54 | |
d7f09764 DN |
55 | /* The table to hold the file names. */ |
56 | static htab_t file_name_hash_table; | |
57 | ||
58 | ||
59 | /* Check that tag ACTUAL has one of the given values. NUM_TAGS is the | |
60 | number of valid tag values to check. */ | |
61 | ||
f0efc7aa | 62 | void |
d7f09764 DN |
63 | lto_tag_check_set (enum LTO_tags actual, int ntags, ...) |
64 | { | |
65 | va_list ap; | |
66 | int i; | |
67 | ||
68 | va_start (ap, ntags); | |
69 | for (i = 0; i < ntags; i++) | |
70 | if ((unsigned) actual == va_arg (ap, unsigned)) | |
71 | { | |
72 | va_end (ap); | |
73 | return; | |
74 | } | |
75 | ||
76 | va_end (ap); | |
77 | internal_error ("bytecode stream: unexpected tag %s", lto_tag_name (actual)); | |
78 | } | |
79 | ||
80 | ||
a183b5c7 DN |
81 | /* Read LENGTH bytes from STREAM to ADDR. */ |
82 | ||
83 | void | |
84 | lto_input_data_block (struct lto_input_block *ib, void *addr, size_t length) | |
85 | { | |
86 | size_t i; | |
87 | unsigned char *const buffer = (unsigned char *const) addr; | |
88 | ||
89 | for (i = 0; i < length; i++) | |
412288f1 | 90 | buffer[i] = streamer_read_uchar (ib); |
a183b5c7 DN |
91 | } |
92 | ||
93 | ||
d7f09764 DN |
94 | /* Lookup STRING in file_name_hash_table. If found, return the existing |
95 | string, otherwise insert STRING as the canonical version. */ | |
96 | ||
97 | static const char * | |
98 | canon_file_name (const char *string) | |
99 | { | |
100 | void **slot; | |
101 | struct string_slot s_slot; | |
0b11d702 MM |
102 | size_t len = strlen (string); |
103 | ||
d7f09764 | 104 | s_slot.s = string; |
0b11d702 | 105 | s_slot.len = len; |
d7f09764 DN |
106 | |
107 | slot = htab_find_slot (file_name_hash_table, &s_slot, INSERT); | |
108 | if (*slot == NULL) | |
109 | { | |
d7f09764 DN |
110 | char *saved_string; |
111 | struct string_slot *new_slot; | |
112 | ||
d7f09764 DN |
113 | saved_string = (char *) xmalloc (len + 1); |
114 | new_slot = XCNEW (struct string_slot); | |
0b11d702 | 115 | memcpy (saved_string, string, len + 1); |
d7f09764 | 116 | new_slot->s = saved_string; |
0b11d702 | 117 | new_slot->len = len; |
d7f09764 DN |
118 | *slot = new_slot; |
119 | return saved_string; | |
120 | } | |
121 | else | |
122 | { | |
123 | struct string_slot *old_slot = (struct string_slot *) *slot; | |
124 | return old_slot->s; | |
125 | } | |
126 | } | |
127 | ||
128 | ||
129 | /* Clear the line info stored in DATA_IN. */ | |
130 | ||
131 | static void | |
132 | clear_line_info (struct data_in *data_in) | |
133 | { | |
134 | if (data_in->current_file) | |
135 | linemap_add (line_table, LC_LEAVE, false, NULL, 0); | |
136 | data_in->current_file = NULL; | |
137 | data_in->current_line = 0; | |
138 | data_in->current_col = 0; | |
139 | } | |
140 | ||
141 | ||
51a9ed47 | 142 | /* Read a location bitpack from input block IB. */ |
d7f09764 DN |
143 | |
144 | static location_t | |
51a9ed47 | 145 | lto_input_location_bitpack (struct data_in *data_in, struct bitpack_d *bp) |
d7f09764 | 146 | { |
51a9ed47 JH |
147 | bool file_change, line_change, column_change; |
148 | unsigned len; | |
149 | bool prev_file = data_in->current_file != NULL; | |
d7f09764 | 150 | |
51a9ed47 | 151 | if (bp_unpack_value (bp, 1)) |
d7f09764 DN |
152 | return UNKNOWN_LOCATION; |
153 | ||
51a9ed47 JH |
154 | file_change = bp_unpack_value (bp, 1); |
155 | if (file_change) | |
156 | data_in->current_file = canon_file_name | |
157 | (string_for_index (data_in, | |
158 | bp_unpack_var_len_unsigned (bp), | |
159 | &len)); | |
160 | ||
161 | line_change = bp_unpack_value (bp, 1); | |
162 | if (line_change) | |
163 | data_in->current_line = bp_unpack_var_len_unsigned (bp); | |
d7f09764 | 164 | |
51a9ed47 JH |
165 | column_change = bp_unpack_value (bp, 1); |
166 | if (column_change) | |
167 | data_in->current_col = bp_unpack_var_len_unsigned (bp); | |
168 | ||
169 | if (file_change) | |
b7dae211 | 170 | { |
51a9ed47 | 171 | if (prev_file) |
b7dae211 | 172 | linemap_add (line_table, LC_LEAVE, false, NULL, 0); |
d7f09764 | 173 | |
51a9ed47 JH |
174 | linemap_add (line_table, LC_ENTER, false, data_in->current_file, |
175 | data_in->current_line); | |
b7dae211 | 176 | } |
51a9ed47 JH |
177 | else if (line_change) |
178 | linemap_line_start (line_table, data_in->current_line, data_in->current_col); | |
179 | ||
180 | return linemap_position_for_column (line_table, data_in->current_col); | |
181 | } | |
182 | ||
b7dae211 | 183 | |
a22286c3 GC |
184 | /* Read a location from input block IB. |
185 | If the input_location streamer hook exists, call it. | |
186 | Otherwise, proceed with reading the location from the | |
187 | expanded location bitpack. */ | |
d7f09764 | 188 | |
f0efc7aa | 189 | location_t |
51a9ed47 JH |
190 | lto_input_location (struct lto_input_block *ib, struct data_in *data_in) |
191 | { | |
a22286c3 GC |
192 | if (streamer_hooks.input_location) |
193 | return streamer_hooks.input_location (ib, data_in); | |
194 | else | |
195 | { | |
196 | struct bitpack_d bp; | |
51a9ed47 | 197 | |
a22286c3 GC |
198 | bp = streamer_read_bitpack (ib); |
199 | return lto_input_location_bitpack (data_in, &bp); | |
200 | } | |
d7f09764 DN |
201 | } |
202 | ||
203 | ||
204 | /* Read a reference to a tree node from DATA_IN using input block IB. | |
205 | TAG is the expected node that should be found in IB, if TAG belongs | |
206 | to one of the indexable trees, expect to read a reference index to | |
207 | be looked up in one of the symbol tables, otherwise read the pysical | |
b9393656 | 208 | representation of the tree using stream_read_tree. FN is the |
d7f09764 DN |
209 | function scope for the read tree. */ |
210 | ||
f0efc7aa | 211 | tree |
b8698a0f | 212 | lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in, |
d7f09764 DN |
213 | struct function *fn, enum LTO_tags tag) |
214 | { | |
215 | unsigned HOST_WIDE_INT ix_u; | |
216 | tree result = NULL_TREE; | |
217 | ||
218 | lto_tag_check_range (tag, LTO_field_decl_ref, LTO_global_decl_ref); | |
219 | ||
220 | switch (tag) | |
221 | { | |
222 | case LTO_type_ref: | |
412288f1 | 223 | ix_u = streamer_read_uhwi (ib); |
d7f09764 DN |
224 | result = lto_file_decl_data_get_type (data_in->file_data, ix_u); |
225 | break; | |
226 | ||
227 | case LTO_ssa_name_ref: | |
412288f1 | 228 | ix_u = streamer_read_uhwi (ib); |
d7f09764 DN |
229 | result = VEC_index (tree, SSANAMES (fn), ix_u); |
230 | break; | |
231 | ||
232 | case LTO_field_decl_ref: | |
412288f1 | 233 | ix_u = streamer_read_uhwi (ib); |
d7f09764 DN |
234 | result = lto_file_decl_data_get_field_decl (data_in->file_data, ix_u); |
235 | break; | |
236 | ||
237 | case LTO_function_decl_ref: | |
412288f1 | 238 | ix_u = streamer_read_uhwi (ib); |
d7f09764 DN |
239 | result = lto_file_decl_data_get_fn_decl (data_in->file_data, ix_u); |
240 | break; | |
241 | ||
242 | case LTO_type_decl_ref: | |
412288f1 | 243 | ix_u = streamer_read_uhwi (ib); |
d7f09764 DN |
244 | result = lto_file_decl_data_get_type_decl (data_in->file_data, ix_u); |
245 | break; | |
246 | ||
247 | case LTO_namespace_decl_ref: | |
412288f1 | 248 | ix_u = streamer_read_uhwi (ib); |
d7f09764 DN |
249 | result = lto_file_decl_data_get_namespace_decl (data_in->file_data, ix_u); |
250 | break; | |
251 | ||
252 | case LTO_global_decl_ref: | |
253 | case LTO_result_decl_ref: | |
254 | case LTO_const_decl_ref: | |
255 | case LTO_imported_decl_ref: | |
256 | case LTO_label_decl_ref: | |
6be14c0e | 257 | case LTO_translation_unit_decl_ref: |
412288f1 | 258 | ix_u = streamer_read_uhwi (ib); |
d7f09764 | 259 | result = lto_file_decl_data_get_var_decl (data_in->file_data, ix_u); |
d7f09764 DN |
260 | break; |
261 | ||
262 | default: | |
263 | gcc_unreachable (); | |
264 | } | |
265 | ||
266 | gcc_assert (result); | |
267 | ||
268 | return result; | |
269 | } | |
270 | ||
271 | ||
272 | /* Read and return a double-linked list of catch handlers from input | |
273 | block IB, using descriptors in DATA_IN. */ | |
274 | ||
275 | static struct eh_catch_d * | |
276 | lto_input_eh_catch_list (struct lto_input_block *ib, struct data_in *data_in, | |
277 | eh_catch *last_p) | |
278 | { | |
279 | eh_catch first; | |
280 | enum LTO_tags tag; | |
281 | ||
282 | *last_p = first = NULL; | |
412288f1 | 283 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
284 | while (tag) |
285 | { | |
286 | tree list; | |
287 | eh_catch n; | |
288 | ||
289 | lto_tag_check_range (tag, LTO_eh_catch, LTO_eh_catch); | |
290 | ||
291 | /* Read the catch node. */ | |
a9429e29 | 292 | n = ggc_alloc_cleared_eh_catch_d (); |
b9393656 DN |
293 | n->type_list = stream_read_tree (ib, data_in); |
294 | n->filter_list = stream_read_tree (ib, data_in); | |
295 | n->label = stream_read_tree (ib, data_in); | |
d7f09764 DN |
296 | |
297 | /* Register all the types in N->FILTER_LIST. */ | |
298 | for (list = n->filter_list; list; list = TREE_CHAIN (list)) | |
299 | add_type_for_runtime (TREE_VALUE (list)); | |
300 | ||
301 | /* Chain N to the end of the list. */ | |
302 | if (*last_p) | |
303 | (*last_p)->next_catch = n; | |
304 | n->prev_catch = *last_p; | |
305 | *last_p = n; | |
306 | ||
307 | /* Set the head of the list the first time through the loop. */ | |
308 | if (first == NULL) | |
309 | first = n; | |
310 | ||
412288f1 | 311 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
312 | } |
313 | ||
314 | return first; | |
315 | } | |
316 | ||
317 | ||
318 | /* Read and return EH region IX from input block IB, using descriptors | |
319 | in DATA_IN. */ | |
320 | ||
321 | static eh_region | |
322 | input_eh_region (struct lto_input_block *ib, struct data_in *data_in, int ix) | |
323 | { | |
324 | enum LTO_tags tag; | |
325 | eh_region r; | |
326 | ||
327 | /* Read the region header. */ | |
412288f1 | 328 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
329 | if (tag == LTO_null) |
330 | return NULL; | |
331 | ||
a9429e29 | 332 | r = ggc_alloc_cleared_eh_region_d (); |
412288f1 | 333 | r->index = streamer_read_hwi (ib); |
d7f09764 DN |
334 | |
335 | gcc_assert (r->index == ix); | |
336 | ||
337 | /* Read all the region pointers as region numbers. We'll fix up | |
338 | the pointers once the whole array has been read. */ | |
412288f1 DN |
339 | r->outer = (eh_region) (intptr_t) streamer_read_hwi (ib); |
340 | r->inner = (eh_region) (intptr_t) streamer_read_hwi (ib); | |
341 | r->next_peer = (eh_region) (intptr_t) streamer_read_hwi (ib); | |
d7f09764 DN |
342 | |
343 | switch (tag) | |
344 | { | |
345 | case LTO_ert_cleanup: | |
346 | r->type = ERT_CLEANUP; | |
347 | break; | |
348 | ||
349 | case LTO_ert_try: | |
350 | { | |
351 | struct eh_catch_d *last_catch; | |
352 | r->type = ERT_TRY; | |
353 | r->u.eh_try.first_catch = lto_input_eh_catch_list (ib, data_in, | |
354 | &last_catch); | |
355 | r->u.eh_try.last_catch = last_catch; | |
356 | break; | |
357 | } | |
358 | ||
359 | case LTO_ert_allowed_exceptions: | |
360 | { | |
361 | tree l; | |
362 | ||
363 | r->type = ERT_ALLOWED_EXCEPTIONS; | |
b9393656 DN |
364 | r->u.allowed.type_list = stream_read_tree (ib, data_in); |
365 | r->u.allowed.label = stream_read_tree (ib, data_in); | |
412288f1 | 366 | r->u.allowed.filter = streamer_read_uhwi (ib); |
d7f09764 DN |
367 | |
368 | for (l = r->u.allowed.type_list; l ; l = TREE_CHAIN (l)) | |
369 | add_type_for_runtime (TREE_VALUE (l)); | |
370 | } | |
371 | break; | |
372 | ||
373 | case LTO_ert_must_not_throw: | |
374 | r->type = ERT_MUST_NOT_THROW; | |
b9393656 | 375 | r->u.must_not_throw.failure_decl = stream_read_tree (ib, data_in); |
d7f09764 DN |
376 | r->u.must_not_throw.failure_loc = lto_input_location (ib, data_in); |
377 | break; | |
378 | ||
379 | default: | |
380 | gcc_unreachable (); | |
381 | } | |
382 | ||
412288f1 | 383 | r->landing_pads = (eh_landing_pad) (intptr_t) streamer_read_hwi (ib); |
d7f09764 DN |
384 | |
385 | return r; | |
386 | } | |
387 | ||
388 | ||
389 | /* Read and return EH landing pad IX from input block IB, using descriptors | |
390 | in DATA_IN. */ | |
391 | ||
392 | static eh_landing_pad | |
393 | input_eh_lp (struct lto_input_block *ib, struct data_in *data_in, int ix) | |
394 | { | |
395 | enum LTO_tags tag; | |
396 | eh_landing_pad lp; | |
397 | ||
398 | /* Read the landing pad header. */ | |
412288f1 | 399 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
400 | if (tag == LTO_null) |
401 | return NULL; | |
402 | ||
403 | lto_tag_check_range (tag, LTO_eh_landing_pad, LTO_eh_landing_pad); | |
404 | ||
a9429e29 | 405 | lp = ggc_alloc_cleared_eh_landing_pad_d (); |
412288f1 | 406 | lp->index = streamer_read_hwi (ib); |
d7f09764 | 407 | gcc_assert (lp->index == ix); |
412288f1 DN |
408 | lp->next_lp = (eh_landing_pad) (intptr_t) streamer_read_hwi (ib); |
409 | lp->region = (eh_region) (intptr_t) streamer_read_hwi (ib); | |
b9393656 | 410 | lp->post_landing_pad = stream_read_tree (ib, data_in); |
d7f09764 DN |
411 | |
412 | return lp; | |
413 | } | |
414 | ||
415 | ||
416 | /* After reading the EH regions, pointers to peer and children regions | |
417 | are region numbers. This converts all these region numbers into | |
418 | real pointers into the rematerialized regions for FN. ROOT_REGION | |
419 | is the region number for the root EH region in FN. */ | |
420 | ||
421 | static void | |
422 | fixup_eh_region_pointers (struct function *fn, HOST_WIDE_INT root_region) | |
423 | { | |
424 | unsigned i; | |
425 | VEC(eh_region,gc) *eh_array = fn->eh->region_array; | |
426 | VEC(eh_landing_pad,gc) *lp_array = fn->eh->lp_array; | |
427 | eh_region r; | |
428 | eh_landing_pad lp; | |
429 | ||
430 | gcc_assert (eh_array && lp_array); | |
431 | ||
432 | gcc_assert (root_region >= 0); | |
433 | fn->eh->region_tree = VEC_index (eh_region, eh_array, root_region); | |
434 | ||
435 | #define FIXUP_EH_REGION(r) (r) = VEC_index (eh_region, eh_array, \ | |
436 | (HOST_WIDE_INT) (intptr_t) (r)) | |
437 | #define FIXUP_EH_LP(p) (p) = VEC_index (eh_landing_pad, lp_array, \ | |
438 | (HOST_WIDE_INT) (intptr_t) (p)) | |
439 | ||
440 | /* Convert all the index numbers stored in pointer fields into | |
441 | pointers to the corresponding slots in the EH region array. */ | |
ac47786e | 442 | FOR_EACH_VEC_ELT (eh_region, eh_array, i, r) |
d7f09764 DN |
443 | { |
444 | /* The array may contain NULL regions. */ | |
445 | if (r == NULL) | |
446 | continue; | |
447 | ||
448 | gcc_assert (i == (unsigned) r->index); | |
449 | FIXUP_EH_REGION (r->outer); | |
450 | FIXUP_EH_REGION (r->inner); | |
451 | FIXUP_EH_REGION (r->next_peer); | |
452 | FIXUP_EH_LP (r->landing_pads); | |
453 | } | |
454 | ||
455 | /* Convert all the index numbers stored in pointer fields into | |
456 | pointers to the corresponding slots in the EH landing pad array. */ | |
ac47786e | 457 | FOR_EACH_VEC_ELT (eh_landing_pad, lp_array, i, lp) |
d7f09764 DN |
458 | { |
459 | /* The array may contain NULL landing pads. */ | |
460 | if (lp == NULL) | |
461 | continue; | |
462 | ||
463 | gcc_assert (i == (unsigned) lp->index); | |
464 | FIXUP_EH_LP (lp->next_lp); | |
465 | FIXUP_EH_REGION (lp->region); | |
466 | } | |
467 | ||
468 | #undef FIXUP_EH_REGION | |
469 | #undef FIXUP_EH_LP | |
470 | } | |
471 | ||
472 | ||
473 | /* Initialize EH support. */ | |
474 | ||
f0efc7aa | 475 | void |
d7f09764 DN |
476 | lto_init_eh (void) |
477 | { | |
dad02715 RG |
478 | static bool eh_initialized_p = false; |
479 | ||
480 | if (eh_initialized_p) | |
481 | return; | |
482 | ||
d7f09764 DN |
483 | /* Contrary to most other FEs, we only initialize EH support when at |
484 | least one of the files in the set contains exception regions in | |
485 | it. Since this happens much later than the call to init_eh in | |
486 | lang_dependent_init, we have to set flag_exceptions and call | |
487 | init_eh again to initialize the EH tables. */ | |
488 | flag_exceptions = 1; | |
489 | init_eh (); | |
490 | ||
dad02715 | 491 | eh_initialized_p = true; |
d7f09764 DN |
492 | } |
493 | ||
494 | ||
495 | /* Read the exception table for FN from IB using the data descriptors | |
496 | in DATA_IN. */ | |
497 | ||
498 | static void | |
499 | input_eh_regions (struct lto_input_block *ib, struct data_in *data_in, | |
500 | struct function *fn) | |
501 | { | |
502 | HOST_WIDE_INT i, root_region, len; | |
503 | enum LTO_tags tag; | |
b8698a0f | 504 | |
412288f1 | 505 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
506 | if (tag == LTO_null) |
507 | return; | |
508 | ||
509 | lto_tag_check_range (tag, LTO_eh_table, LTO_eh_table); | |
510 | ||
511 | /* If the file contains EH regions, then it was compiled with | |
512 | -fexceptions. In that case, initialize the backend EH | |
513 | machinery. */ | |
dad02715 | 514 | lto_init_eh (); |
d7f09764 DN |
515 | |
516 | gcc_assert (fn->eh); | |
517 | ||
412288f1 | 518 | root_region = streamer_read_hwi (ib); |
d7f09764 DN |
519 | gcc_assert (root_region == (int) root_region); |
520 | ||
521 | /* Read the EH region array. */ | |
412288f1 | 522 | len = streamer_read_hwi (ib); |
d7f09764 DN |
523 | gcc_assert (len == (int) len); |
524 | if (len > 0) | |
525 | { | |
526 | VEC_safe_grow (eh_region, gc, fn->eh->region_array, len); | |
527 | for (i = 0; i < len; i++) | |
528 | { | |
529 | eh_region r = input_eh_region (ib, data_in, i); | |
530 | VEC_replace (eh_region, fn->eh->region_array, i, r); | |
531 | } | |
532 | } | |
533 | ||
534 | /* Read the landing pads. */ | |
412288f1 | 535 | len = streamer_read_hwi (ib); |
d7f09764 DN |
536 | gcc_assert (len == (int) len); |
537 | if (len > 0) | |
538 | { | |
539 | VEC_safe_grow (eh_landing_pad, gc, fn->eh->lp_array, len); | |
540 | for (i = 0; i < len; i++) | |
541 | { | |
542 | eh_landing_pad lp = input_eh_lp (ib, data_in, i); | |
543 | VEC_replace (eh_landing_pad, fn->eh->lp_array, i, lp); | |
544 | } | |
545 | } | |
546 | ||
547 | /* Read the runtime type data. */ | |
412288f1 | 548 | len = streamer_read_hwi (ib); |
d7f09764 DN |
549 | gcc_assert (len == (int) len); |
550 | if (len > 0) | |
551 | { | |
552 | VEC_safe_grow (tree, gc, fn->eh->ttype_data, len); | |
553 | for (i = 0; i < len; i++) | |
554 | { | |
b9393656 | 555 | tree ttype = stream_read_tree (ib, data_in); |
d7f09764 DN |
556 | VEC_replace (tree, fn->eh->ttype_data, i, ttype); |
557 | } | |
558 | } | |
559 | ||
560 | /* Read the table of action chains. */ | |
412288f1 | 561 | len = streamer_read_hwi (ib); |
d7f09764 DN |
562 | gcc_assert (len == (int) len); |
563 | if (len > 0) | |
564 | { | |
565 | if (targetm.arm_eabi_unwinder) | |
566 | { | |
567 | VEC_safe_grow (tree, gc, fn->eh->ehspec_data.arm_eabi, len); | |
568 | for (i = 0; i < len; i++) | |
569 | { | |
b9393656 | 570 | tree t = stream_read_tree (ib, data_in); |
d7f09764 DN |
571 | VEC_replace (tree, fn->eh->ehspec_data.arm_eabi, i, t); |
572 | } | |
573 | } | |
574 | else | |
575 | { | |
576 | VEC_safe_grow (uchar, gc, fn->eh->ehspec_data.other, len); | |
577 | for (i = 0; i < len; i++) | |
578 | { | |
412288f1 | 579 | uchar c = streamer_read_uchar (ib); |
d7f09764 DN |
580 | VEC_replace (uchar, fn->eh->ehspec_data.other, i, c); |
581 | } | |
582 | } | |
583 | } | |
584 | ||
585 | /* Reconstruct the EH region tree by fixing up the peer/children | |
586 | pointers. */ | |
587 | fixup_eh_region_pointers (fn, root_region); | |
588 | ||
412288f1 | 589 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
590 | lto_tag_check_range (tag, LTO_null, LTO_null); |
591 | } | |
592 | ||
593 | ||
594 | /* Make a new basic block with index INDEX in function FN. */ | |
595 | ||
596 | static basic_block | |
597 | make_new_block (struct function *fn, unsigned int index) | |
598 | { | |
599 | basic_block bb = alloc_block (); | |
600 | bb->index = index; | |
601 | SET_BASIC_BLOCK_FOR_FUNCTION (fn, index, bb); | |
a9429e29 | 602 | bb->il.gimple = ggc_alloc_cleared_gimple_bb_info (); |
d7f09764 DN |
603 | n_basic_blocks_for_function (fn)++; |
604 | bb->flags = 0; | |
355a7673 | 605 | set_bb_seq (bb, NULL); |
d7f09764 DN |
606 | return bb; |
607 | } | |
608 | ||
609 | ||
610 | /* Read the CFG for function FN from input block IB. */ | |
611 | ||
b8698a0f | 612 | static void |
db0bf14f JH |
613 | input_cfg (struct lto_input_block *ib, struct function *fn, |
614 | int count_materialization_scale) | |
d7f09764 DN |
615 | { |
616 | unsigned int bb_count; | |
617 | basic_block p_bb; | |
618 | unsigned int i; | |
619 | int index; | |
620 | ||
621 | init_empty_tree_cfg_for_function (fn); | |
622 | init_ssa_operands (); | |
623 | ||
412288f1 DN |
624 | profile_status_for_function (fn) = streamer_read_enum (ib, profile_status_d, |
625 | PROFILE_LAST); | |
d7f09764 | 626 | |
412288f1 | 627 | bb_count = streamer_read_uhwi (ib); |
d7f09764 DN |
628 | |
629 | last_basic_block_for_function (fn) = bb_count; | |
630 | if (bb_count > VEC_length (basic_block, basic_block_info_for_function (fn))) | |
631 | VEC_safe_grow_cleared (basic_block, gc, | |
632 | basic_block_info_for_function (fn), bb_count); | |
633 | ||
634 | if (bb_count > VEC_length (basic_block, label_to_block_map_for_function (fn))) | |
b8698a0f | 635 | VEC_safe_grow_cleared (basic_block, gc, |
d7f09764 DN |
636 | label_to_block_map_for_function (fn), bb_count); |
637 | ||
412288f1 | 638 | index = streamer_read_hwi (ib); |
d7f09764 DN |
639 | while (index != -1) |
640 | { | |
641 | basic_block bb = BASIC_BLOCK_FOR_FUNCTION (fn, index); | |
642 | unsigned int edge_count; | |
643 | ||
644 | if (bb == NULL) | |
645 | bb = make_new_block (fn, index); | |
646 | ||
412288f1 | 647 | edge_count = streamer_read_uhwi (ib); |
d7f09764 DN |
648 | |
649 | /* Connect up the CFG. */ | |
650 | for (i = 0; i < edge_count; i++) | |
651 | { | |
652 | unsigned int dest_index; | |
653 | unsigned int edge_flags; | |
654 | basic_block dest; | |
655 | int probability; | |
656 | gcov_type count; | |
657 | edge e; | |
658 | ||
412288f1 DN |
659 | dest_index = streamer_read_uhwi (ib); |
660 | probability = (int) streamer_read_hwi (ib); | |
661 | count = ((gcov_type) streamer_read_hwi (ib) * count_materialization_scale | |
e7abfe07 | 662 | + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; |
412288f1 | 663 | edge_flags = streamer_read_uhwi (ib); |
d7f09764 DN |
664 | |
665 | dest = BASIC_BLOCK_FOR_FUNCTION (fn, dest_index); | |
666 | ||
b8698a0f | 667 | if (dest == NULL) |
d7f09764 DN |
668 | dest = make_new_block (fn, dest_index); |
669 | ||
670 | e = make_edge (bb, dest, edge_flags); | |
671 | e->probability = probability; | |
672 | e->count = count; | |
673 | } | |
674 | ||
412288f1 | 675 | index = streamer_read_hwi (ib); |
d7f09764 DN |
676 | } |
677 | ||
678 | p_bb = ENTRY_BLOCK_PTR_FOR_FUNCTION(fn); | |
412288f1 | 679 | index = streamer_read_hwi (ib); |
d7f09764 DN |
680 | while (index != -1) |
681 | { | |
682 | basic_block bb = BASIC_BLOCK_FOR_FUNCTION (fn, index); | |
683 | bb->prev_bb = p_bb; | |
684 | p_bb->next_bb = bb; | |
685 | p_bb = bb; | |
412288f1 | 686 | index = streamer_read_hwi (ib); |
d7f09764 DN |
687 | } |
688 | } | |
689 | ||
690 | ||
d7f09764 DN |
691 | /* Read the SSA names array for function FN from DATA_IN using input |
692 | block IB. */ | |
693 | ||
694 | static void | |
695 | input_ssa_names (struct lto_input_block *ib, struct data_in *data_in, | |
696 | struct function *fn) | |
697 | { | |
698 | unsigned int i, size; | |
699 | ||
412288f1 | 700 | size = streamer_read_uhwi (ib); |
d7f09764 DN |
701 | init_ssanames (fn, size); |
702 | ||
412288f1 | 703 | i = streamer_read_uhwi (ib); |
d7f09764 DN |
704 | while (i) |
705 | { | |
706 | tree ssa_name, name; | |
707 | bool is_default_def; | |
708 | ||
709 | /* Skip over the elements that had been freed. */ | |
710 | while (VEC_length (tree, SSANAMES (fn)) < i) | |
711 | VEC_quick_push (tree, SSANAMES (fn), NULL_TREE); | |
712 | ||
412288f1 | 713 | is_default_def = (streamer_read_uchar (ib) != 0); |
b9393656 | 714 | name = stream_read_tree (ib, data_in); |
d7f09764 DN |
715 | ssa_name = make_ssa_name_fn (fn, name, gimple_build_nop ()); |
716 | ||
717 | if (is_default_def) | |
718 | set_default_def (SSA_NAME_VAR (ssa_name), ssa_name); | |
719 | ||
412288f1 | 720 | i = streamer_read_uhwi (ib); |
b8698a0f | 721 | } |
d7f09764 DN |
722 | } |
723 | ||
d7f09764 DN |
724 | |
725 | /* Go through all NODE edges and fixup call_stmt pointers | |
726 | so they point to STMTS. */ | |
727 | ||
728 | static void | |
729 | fixup_call_stmt_edges_1 (struct cgraph_node *node, gimple *stmts) | |
730 | { | |
731 | struct cgraph_edge *cedge; | |
732 | for (cedge = node->callees; cedge; cedge = cedge->next_callee) | |
733 | cedge->call_stmt = stmts[cedge->lto_stmt_uid]; | |
e33c6cd6 MJ |
734 | for (cedge = node->indirect_calls; cedge; cedge = cedge->next_callee) |
735 | cedge->call_stmt = stmts[cedge->lto_stmt_uid]; | |
d7f09764 DN |
736 | } |
737 | ||
738 | /* Fixup call_stmt pointers in NODE and all clones. */ | |
739 | ||
740 | static void | |
741 | fixup_call_stmt_edges (struct cgraph_node *orig, gimple *stmts) | |
742 | { | |
743 | struct cgraph_node *node; | |
744 | ||
745 | while (orig->clone_of) | |
746 | orig = orig->clone_of; | |
747 | ||
748 | fixup_call_stmt_edges_1 (orig, stmts); | |
749 | if (orig->clones) | |
750 | for (node = orig->clones; node != orig;) | |
751 | { | |
752 | fixup_call_stmt_edges_1 (node, stmts); | |
753 | if (node->clones) | |
754 | node = node->clones; | |
755 | else if (node->next_sibling_clone) | |
756 | node = node->next_sibling_clone; | |
757 | else | |
758 | { | |
759 | while (node != orig && !node->next_sibling_clone) | |
760 | node = node->clone_of; | |
761 | if (node != orig) | |
762 | node = node->next_sibling_clone; | |
763 | } | |
764 | } | |
765 | } | |
766 | ||
35f5b1c1 LC |
767 | |
768 | /* Input the base body of struct function FN from DATA_IN | |
769 | using input block IB. */ | |
d7f09764 DN |
770 | |
771 | static void | |
35f5b1c1 LC |
772 | input_struct_function_base (struct function *fn, struct data_in *data_in, |
773 | struct lto_input_block *ib) | |
d7f09764 | 774 | { |
2465dcc2 | 775 | struct bitpack_d bp; |
c021f10b | 776 | int len; |
d7f09764 | 777 | |
35f5b1c1 LC |
778 | /* Read the static chain and non-local goto save area. */ |
779 | fn->static_chain_decl = stream_read_tree (ib, data_in); | |
780 | fn->nonlocal_goto_save_area = stream_read_tree (ib, data_in); | |
d7f09764 | 781 | |
35f5b1c1 LC |
782 | /* Read all the local symbols. */ |
783 | len = streamer_read_hwi (ib); | |
784 | if (len > 0) | |
785 | { | |
786 | int i; | |
787 | VEC_safe_grow (tree, gc, fn->local_decls, len); | |
788 | for (i = 0; i < len; i++) | |
789 | { | |
790 | tree t = stream_read_tree (ib, data_in); | |
791 | VEC_replace (tree, fn->local_decls, i, t); | |
792 | } | |
793 | } | |
794 | ||
795 | /* Input the function start and end loci. */ | |
796 | fn->function_start_locus = lto_input_location (ib, data_in); | |
797 | fn->function_end_locus = lto_input_location (ib, data_in); | |
798 | ||
799 | /* Input the current IL state of the function. */ | |
800 | fn->curr_properties = streamer_read_uhwi (ib); | |
d7f09764 DN |
801 | |
802 | /* Read all the attributes for FN. */ | |
412288f1 | 803 | bp = streamer_read_bitpack (ib); |
2465dcc2 RG |
804 | fn->is_thunk = bp_unpack_value (&bp, 1); |
805 | fn->has_local_explicit_reg_vars = bp_unpack_value (&bp, 1); | |
806 | fn->after_tree_profile = bp_unpack_value (&bp, 1); | |
807 | fn->returns_pcc_struct = bp_unpack_value (&bp, 1); | |
808 | fn->returns_struct = bp_unpack_value (&bp, 1); | |
809 | fn->can_throw_non_call_exceptions = bp_unpack_value (&bp, 1); | |
810 | fn->always_inline_functions_inlined = bp_unpack_value (&bp, 1); | |
811 | fn->after_inlining = bp_unpack_value (&bp, 1); | |
2465dcc2 RG |
812 | fn->stdarg = bp_unpack_value (&bp, 1); |
813 | fn->has_nonlocal_label = bp_unpack_value (&bp, 1); | |
814 | fn->calls_alloca = bp_unpack_value (&bp, 1); | |
815 | fn->calls_setjmp = bp_unpack_value (&bp, 1); | |
816 | fn->va_list_fpr_size = bp_unpack_value (&bp, 8); | |
817 | fn->va_list_gpr_size = bp_unpack_value (&bp, 8); | |
35f5b1c1 | 818 | } |
d7f09764 | 819 | |
ac364a48 | 820 | |
35f5b1c1 | 821 | /* Read the body of function FN_DECL from DATA_IN using input block IB. */ |
688a482d | 822 | |
35f5b1c1 LC |
823 | static void |
824 | input_function (tree fn_decl, struct data_in *data_in, | |
825 | struct lto_input_block *ib) | |
826 | { | |
827 | struct function *fn; | |
828 | enum LTO_tags tag; | |
829 | gimple *stmts; | |
830 | basic_block bb; | |
831 | struct cgraph_node *node; | |
832 | tree args, narg, oarg; | |
d7f09764 | 833 | |
35f5b1c1 LC |
834 | fn = DECL_STRUCT_FUNCTION (fn_decl); |
835 | tag = streamer_read_record_start (ib); | |
836 | clear_line_info (data_in); | |
837 | ||
838 | gimple_register_cfg_hooks (); | |
839 | lto_tag_check (tag, LTO_function); | |
840 | ||
841 | input_struct_function_base (fn, data_in, ib); | |
d7f09764 | 842 | |
811232fe JH |
843 | /* Read all function arguments. We need to re-map them here to the |
844 | arguments of the merged function declaration. */ | |
b9393656 | 845 | args = stream_read_tree (ib, data_in); |
811232fe JH |
846 | for (oarg = args, narg = DECL_ARGUMENTS (fn_decl); |
847 | oarg && narg; | |
848 | oarg = TREE_CHAIN (oarg), narg = TREE_CHAIN (narg)) | |
849 | { | |
e89964e3 | 850 | unsigned ix; |
811232fe | 851 | bool res; |
412288f1 | 852 | res = streamer_tree_cache_lookup (data_in->reader_cache, oarg, &ix); |
811232fe JH |
853 | gcc_assert (res); |
854 | /* Replace the argument in the streamer cache. */ | |
412288f1 | 855 | streamer_tree_cache_insert_at (data_in->reader_cache, narg, ix); |
811232fe JH |
856 | } |
857 | gcc_assert (!oarg && !narg); | |
858 | ||
d7f09764 DN |
859 | /* Read all the SSA names. */ |
860 | input_ssa_names (ib, data_in, fn); | |
861 | ||
862 | /* Read the exception handling regions in the function. */ | |
863 | input_eh_regions (ib, data_in, fn); | |
864 | ||
865 | /* Read the tree of lexical scopes for the function. */ | |
b9393656 | 866 | DECL_INITIAL (fn_decl) = stream_read_tree (ib, data_in); |
d7f09764 DN |
867 | gcc_assert (DECL_INITIAL (fn_decl)); |
868 | DECL_SAVED_TREE (fn_decl) = NULL_TREE; | |
a358e188 | 869 | node = cgraph_get_create_node (fn_decl); |
d7f09764 | 870 | |
d7f09764 | 871 | /* Read all the basic blocks. */ |
412288f1 | 872 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
873 | while (tag) |
874 | { | |
db0bf14f JH |
875 | input_bb (ib, tag, data_in, fn, |
876 | node->count_materialization_scale); | |
412288f1 | 877 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
878 | } |
879 | ||
880 | /* Fix up the call statements that are mentioned in the callgraph | |
881 | edges. */ | |
8f984534 RB |
882 | set_gimple_stmt_max_uid (cfun, 0); |
883 | FOR_ALL_BB (bb) | |
884 | { | |
885 | gimple_stmt_iterator gsi; | |
886 | for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | |
887 | { | |
888 | gimple stmt = gsi_stmt (gsi); | |
889 | gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun)); | |
890 | } | |
891 | } | |
d7f09764 DN |
892 | stmts = (gimple *) xcalloc (gimple_stmt_max_uid (fn), sizeof (gimple)); |
893 | FOR_ALL_BB (bb) | |
894 | { | |
7254364e AO |
895 | gimple_stmt_iterator bsi = gsi_start_bb (bb); |
896 | while (!gsi_end_p (bsi)) | |
d7f09764 DN |
897 | { |
898 | gimple stmt = gsi_stmt (bsi); | |
7254364e AO |
899 | /* If we're recompiling LTO objects with debug stmts but |
900 | we're not supposed to have debug stmts, remove them now. | |
901 | We can't remove them earlier because this would cause uid | |
902 | mismatches in fixups, but we can do it at this point, as | |
903 | long as debug stmts don't require fixups. */ | |
904 | if (!MAY_HAVE_DEBUG_STMTS && is_gimple_debug (stmt)) | |
905 | { | |
906 | gimple_stmt_iterator gsi = bsi; | |
907 | gsi_next (&bsi); | |
908 | gsi_remove (&gsi, true); | |
909 | } | |
910 | else | |
911 | { | |
912 | gsi_next (&bsi); | |
913 | stmts[gimple_uid (stmt)] = stmt; | |
914 | } | |
d7f09764 DN |
915 | } |
916 | } | |
917 | ||
918 | /* Set the gimple body to the statement sequence in the entry | |
919 | basic block. FIXME lto, this is fairly hacky. The existence | |
920 | of a gimple body is used by the cgraph routines, but we should | |
921 | really use the presence of the CFG. */ | |
922 | { | |
923 | edge_iterator ei = ei_start (ENTRY_BLOCK_PTR->succs); | |
924 | gimple_set_body (fn_decl, bb_seq (ei_edge (ei)->dest)); | |
925 | } | |
926 | ||
2c5721d9 MJ |
927 | fixup_call_stmt_edges (node, stmts); |
928 | execute_all_ipa_stmt_fixups (node, stmts); | |
d7f09764 | 929 | |
b8698a0f | 930 | update_ssa (TODO_update_ssa_only_virtuals); |
fb3f88cc JH |
931 | free_dominance_info (CDI_DOMINATORS); |
932 | free_dominance_info (CDI_POST_DOMINATORS); | |
d7f09764 DN |
933 | free (stmts); |
934 | } | |
935 | ||
936 | ||
937 | /* Read initializer expressions for public statics. DATA_IN is the | |
938 | file being read. IB is the input block used for reading. */ | |
939 | ||
940 | static void | |
941 | input_alias_pairs (struct lto_input_block *ib, struct data_in *data_in) | |
942 | { | |
943 | tree var; | |
944 | ||
945 | clear_line_info (data_in); | |
946 | ||
b9393656 | 947 | var = stream_read_tree (ib, data_in); |
d7f09764 DN |
948 | while (var) |
949 | { | |
950 | const char *orig_name, *new_name; | |
951 | alias_pair *p; | |
b8698a0f | 952 | |
d7f09764 DN |
953 | p = VEC_safe_push (alias_pair, gc, alias_pairs, NULL); |
954 | p->decl = var; | |
b9393656 | 955 | p->target = stream_read_tree (ib, data_in); |
d7f09764 DN |
956 | |
957 | /* If the target is a static object, we may have registered a | |
958 | new name for it to avoid clashes between statics coming from | |
959 | different files. In that case, use the new name. */ | |
960 | orig_name = IDENTIFIER_POINTER (p->target); | |
961 | new_name = lto_get_decl_name_mapping (data_in->file_data, orig_name); | |
962 | if (strcmp (orig_name, new_name) != 0) | |
963 | p->target = get_identifier (new_name); | |
964 | ||
b9393656 | 965 | var = stream_read_tree (ib, data_in); |
d7f09764 DN |
966 | } |
967 | } | |
968 | ||
969 | ||
970 | /* Read the body from DATA for function FN_DECL and fill it in. | |
971 | FILE_DATA are the global decls and types. SECTION_TYPE is either | |
972 | LTO_section_function_body or LTO_section_static_initializer. If | |
973 | section type is LTO_section_function_body, FN must be the decl for | |
974 | that function. */ | |
975 | ||
b8698a0f | 976 | static void |
d7f09764 DN |
977 | lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl, |
978 | const char *data, enum lto_section_type section_type) | |
979 | { | |
980 | const struct lto_function_header *header; | |
981 | struct data_in *data_in; | |
4ad9a9de EB |
982 | int cfg_offset; |
983 | int main_offset; | |
984 | int string_offset; | |
d7f09764 DN |
985 | struct lto_input_block ib_cfg; |
986 | struct lto_input_block ib_main; | |
987 | ||
988 | header = (const struct lto_function_header *) data; | |
b8698a0f | 989 | cfg_offset = sizeof (struct lto_function_header); |
d7f09764 DN |
990 | main_offset = cfg_offset + header->cfg_size; |
991 | string_offset = main_offset + header->main_size; | |
992 | ||
993 | LTO_INIT_INPUT_BLOCK (ib_cfg, | |
994 | data + cfg_offset, | |
995 | 0, | |
996 | header->cfg_size); | |
997 | ||
998 | LTO_INIT_INPUT_BLOCK (ib_main, | |
999 | data + main_offset, | |
1000 | 0, | |
1001 | header->main_size); | |
b8698a0f | 1002 | |
d7f09764 DN |
1003 | data_in = lto_data_in_create (file_data, data + string_offset, |
1004 | header->string_size, NULL); | |
1005 | ||
1006 | /* Make sure the file was generated by the exact same compiler. */ | |
1007 | lto_check_version (header->lto_header.major_version, | |
1008 | header->lto_header.minor_version); | |
1009 | ||
1010 | if (section_type == LTO_section_function_body) | |
1011 | { | |
1012 | struct function *fn = DECL_STRUCT_FUNCTION (fn_decl); | |
1013 | struct lto_in_decl_state *decl_state; | |
fe660d7b | 1014 | struct cgraph_node *node = cgraph_get_node (fn_decl); |
23ee14a5 | 1015 | unsigned from; |
d7f09764 | 1016 | |
fe660d7b | 1017 | gcc_checking_assert (node); |
d7f09764 DN |
1018 | push_cfun (fn); |
1019 | init_tree_ssa (fn); | |
1020 | ||
1021 | /* Use the function's decl state. */ | |
1022 | decl_state = lto_get_function_in_decl_state (file_data, fn_decl); | |
1023 | gcc_assert (decl_state); | |
1024 | file_data->current_decl_state = decl_state; | |
1025 | ||
db0bf14f | 1026 | input_cfg (&ib_cfg, fn, node->count_materialization_scale); |
d7f09764 DN |
1027 | |
1028 | /* Set up the struct function. */ | |
23ee14a5 | 1029 | from = VEC_length (tree, data_in->reader_cache->nodes); |
d7f09764 | 1030 | input_function (fn_decl, data_in, &ib_main); |
23ee14a5 RG |
1031 | /* And fixup types we streamed locally. */ |
1032 | { | |
1033 | struct streamer_tree_cache_d *cache = data_in->reader_cache; | |
1034 | unsigned len = VEC_length (tree, cache->nodes); | |
1035 | unsigned i; | |
1036 | for (i = len; i-- > from;) | |
1037 | { | |
1038 | tree t = VEC_index (tree, cache->nodes, i); | |
1039 | if (t == NULL_TREE) | |
1040 | continue; | |
1041 | ||
1042 | if (TYPE_P (t)) | |
1043 | { | |
1044 | gcc_assert (TYPE_CANONICAL (t) == NULL_TREE); | |
1045 | TYPE_CANONICAL (t) = TYPE_MAIN_VARIANT (t); | |
1046 | if (TYPE_MAIN_VARIANT (t) != t) | |
1047 | { | |
1048 | gcc_assert (TYPE_NEXT_VARIANT (t) == NULL_TREE); | |
1049 | TYPE_NEXT_VARIANT (t) | |
1050 | = TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (t)); | |
1051 | TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (t)) = t; | |
1052 | } | |
1053 | } | |
1054 | } | |
1055 | } | |
d7f09764 DN |
1056 | |
1057 | /* We should now be in SSA. */ | |
1058 | cfun->gimple_df->in_ssa_p = true; | |
1059 | ||
d7f09764 DN |
1060 | /* Restore decl state */ |
1061 | file_data->current_decl_state = file_data->global_decl_state; | |
1062 | ||
1063 | pop_cfun (); | |
1064 | } | |
b8698a0f | 1065 | else |
d7f09764 DN |
1066 | { |
1067 | input_alias_pairs (&ib_main, data_in); | |
1068 | } | |
1069 | ||
1070 | clear_line_info (data_in); | |
1071 | lto_data_in_delete (data_in); | |
1072 | } | |
1073 | ||
1074 | ||
1075 | /* Read the body of FN_DECL using DATA. FILE_DATA holds the global | |
1076 | decls and types. */ | |
1077 | ||
b8698a0f | 1078 | void |
d7f09764 DN |
1079 | lto_input_function_body (struct lto_file_decl_data *file_data, |
1080 | tree fn_decl, const char *data) | |
1081 | { | |
1082 | current_function_decl = fn_decl; | |
1083 | lto_read_body (file_data, fn_decl, data, LTO_section_function_body); | |
1084 | } | |
1085 | ||
1086 | ||
1087 | /* Read in VAR_DECL using DATA. FILE_DATA holds the global decls and | |
1088 | types. */ | |
1089 | ||
b8698a0f | 1090 | void |
d7f09764 DN |
1091 | lto_input_constructors_and_inits (struct lto_file_decl_data *file_data, |
1092 | const char *data) | |
1093 | { | |
1094 | lto_read_body (file_data, NULL, data, LTO_section_static_initializer); | |
1095 | } | |
1096 | ||
1097 | ||
b9393656 DN |
1098 | /* Read the physical representation of a tree node with tag TAG from |
1099 | input block IB using the per-file context in DATA_IN. */ | |
d7f09764 | 1100 | |
b9393656 DN |
1101 | static tree |
1102 | lto_read_tree (struct lto_input_block *ib, struct data_in *data_in, | |
1103 | enum LTO_tags tag) | |
47c79d56 | 1104 | { |
b9393656 | 1105 | /* Instantiate a new tree node. */ |
412288f1 | 1106 | tree result = streamer_alloc_tree (ib, data_in, tag); |
b9393656 DN |
1107 | |
1108 | /* Enter RESULT in the reader cache. This will make RESULT | |
1109 | available so that circular references in the rest of the tree | |
1110 | structure can be resolved in subsequent calls to stream_read_tree. */ | |
412288f1 | 1111 | streamer_tree_cache_append (data_in->reader_cache, result); |
b9393656 DN |
1112 | |
1113 | /* Read all the bitfield values in RESULT. Note that for LTO, we | |
1114 | only write language-independent bitfields, so no more unpacking is | |
1115 | needed. */ | |
412288f1 | 1116 | streamer_read_tree_bitfields (ib, result); |
b9393656 DN |
1117 | |
1118 | /* Read all the pointer fields in RESULT. */ | |
412288f1 | 1119 | streamer_read_tree_body (ib, data_in, result); |
b9393656 DN |
1120 | |
1121 | /* Read any LTO-specific data not read by the tree streamer. */ | |
1122 | if (DECL_P (result) | |
1123 | && TREE_CODE (result) != FUNCTION_DECL | |
1124 | && TREE_CODE (result) != TRANSLATION_UNIT_DECL) | |
1125 | DECL_INITIAL (result) = stream_read_tree (ib, data_in); | |
1126 | ||
1127 | /* We should never try to instantiate an MD or NORMAL builtin here. */ | |
1128 | if (TREE_CODE (result) == FUNCTION_DECL) | |
412288f1 | 1129 | gcc_assert (!streamer_handle_as_builtin_p (result)); |
b9393656 | 1130 | |
412288f1 | 1131 | /* end_marker = */ streamer_read_uchar (ib); |
b9393656 DN |
1132 | |
1133 | #ifdef LTO_STREAMER_DEBUG | |
1134 | /* Remove the mapping to RESULT's original address set by | |
412288f1 | 1135 | streamer_alloc_tree. */ |
b9393656 DN |
1136 | lto_orig_address_remove (result); |
1137 | #endif | |
1138 | ||
1139 | return result; | |
1140 | } | |
1141 | ||
1142 | ||
1143 | /* Read a tree from input block IB using the per-file context in | |
1144 | DATA_IN. This context is used, for example, to resolve references | |
1145 | to previously read nodes. */ | |
1146 | ||
1147 | tree | |
1148 | lto_input_tree (struct lto_input_block *ib, struct data_in *data_in) | |
1149 | { | |
1150 | enum LTO_tags tag; | |
1151 | tree result; | |
1152 | ||
412288f1 | 1153 | tag = streamer_read_record_start (ib); |
b9393656 DN |
1154 | gcc_assert ((unsigned) tag < (unsigned) LTO_NUM_TAGS); |
1155 | ||
1156 | if (tag == LTO_null) | |
1157 | result = NULL_TREE; | |
1158 | else if (tag >= LTO_field_decl_ref && tag <= LTO_global_decl_ref) | |
1159 | { | |
1160 | /* If TAG is a reference to an indexable tree, the next value | |
1161 | in IB is the index into the table where we expect to find | |
1162 | that tree. */ | |
1163 | result = lto_input_tree_ref (ib, data_in, cfun, tag); | |
1164 | } | |
1165 | else if (tag == LTO_tree_pickle_reference) | |
1166 | { | |
1167 | /* If TAG is a reference to a previously read tree, look it up in | |
1168 | the reader cache. */ | |
412288f1 | 1169 | result = streamer_get_pickled_tree (ib, data_in); |
b9393656 DN |
1170 | } |
1171 | else if (tag == LTO_builtin_decl) | |
1172 | { | |
1173 | /* If we are going to read a built-in function, all we need is | |
1174 | the code and class. */ | |
412288f1 | 1175 | result = streamer_get_builtin_tree (ib, data_in); |
b9393656 DN |
1176 | } |
1177 | else if (tag == lto_tree_code_to_tag (INTEGER_CST)) | |
1178 | { | |
1179 | /* For integer constants we only need the type and its hi/low | |
1180 | words. */ | |
412288f1 | 1181 | result = streamer_read_integer_cst (ib, data_in); |
b9393656 DN |
1182 | } |
1183 | else | |
1184 | { | |
1185 | /* Otherwise, materialize a new node from IB. */ | |
1186 | result = lto_read_tree (ib, data_in, tag); | |
1187 | } | |
1188 | ||
1189 | return result; | |
47c79d56 DN |
1190 | } |
1191 | ||
1192 | ||
49f836ba JB |
1193 | /* Input toplevel asms. */ |
1194 | ||
1195 | void | |
398f05da | 1196 | lto_input_toplevel_asms (struct lto_file_decl_data *file_data, int order_base) |
49f836ba JB |
1197 | { |
1198 | size_t len; | |
1199 | const char *data = lto_get_section_data (file_data, LTO_section_asm, | |
1200 | NULL, &len); | |
1201 | const struct lto_asm_header *header = (const struct lto_asm_header *) data; | |
4ad9a9de | 1202 | int string_offset; |
49f836ba JB |
1203 | struct data_in *data_in; |
1204 | struct lto_input_block ib; | |
1205 | tree str; | |
1206 | ||
1207 | if (! data) | |
1208 | return; | |
1209 | ||
1210 | string_offset = sizeof (*header) + header->main_size; | |
1211 | ||
1212 | LTO_INIT_INPUT_BLOCK (ib, | |
1213 | data + sizeof (*header), | |
1214 | 0, | |
1215 | header->main_size); | |
1216 | ||
1217 | data_in = lto_data_in_create (file_data, data + string_offset, | |
1218 | header->string_size, NULL); | |
1219 | ||
1220 | /* Make sure the file was generated by the exact same compiler. */ | |
1221 | lto_check_version (header->lto_header.major_version, | |
1222 | header->lto_header.minor_version); | |
1223 | ||
1224 | while ((str = streamer_read_string_cst (data_in, &ib))) | |
398f05da | 1225 | { |
65d630d4 | 1226 | struct asm_node *node = add_asm_node (str); |
398f05da | 1227 | node->order = streamer_read_hwi (&ib) + order_base; |
2aae7680 JH |
1228 | if (node->order >= symtab_order) |
1229 | symtab_order = node->order + 1; | |
398f05da | 1230 | } |
49f836ba JB |
1231 | |
1232 | clear_line_info (data_in); | |
1233 | lto_data_in_delete (data_in); | |
1234 | ||
1235 | lto_free_section_data (file_data, LTO_section_asm, NULL, data, len); | |
1236 | } | |
1237 | ||
1238 | ||
d7f09764 DN |
1239 | /* Initialization for the LTO reader. */ |
1240 | ||
1241 | void | |
47c79d56 | 1242 | lto_reader_init (void) |
d7f09764 DN |
1243 | { |
1244 | lto_streamer_init (); | |
d7f09764 DN |
1245 | file_name_hash_table = htab_create (37, hash_string_slot_node, |
1246 | eq_string_slot_node, free); | |
d7f09764 DN |
1247 | } |
1248 | ||
1249 | ||
1250 | /* Create a new data_in object for FILE_DATA. STRINGS is the string | |
1251 | table to use with LEN strings. RESOLUTIONS is the vector of linker | |
1252 | resolutions (NULL if not using a linker plugin). */ | |
1253 | ||
1254 | struct data_in * | |
1255 | lto_data_in_create (struct lto_file_decl_data *file_data, const char *strings, | |
1256 | unsigned len, | |
1257 | VEC(ld_plugin_symbol_resolution_t,heap) *resolutions) | |
1258 | { | |
1259 | struct data_in *data_in = XCNEW (struct data_in); | |
1260 | data_in->file_data = file_data; | |
1261 | data_in->strings = strings; | |
1262 | data_in->strings_len = len; | |
1263 | data_in->globals_resolution = resolutions; | |
412288f1 | 1264 | data_in->reader_cache = streamer_tree_cache_create (); |
d7f09764 DN |
1265 | |
1266 | return data_in; | |
1267 | } | |
1268 | ||
1269 | ||
1270 | /* Remove DATA_IN. */ | |
1271 | ||
1272 | void | |
1273 | lto_data_in_delete (struct data_in *data_in) | |
1274 | { | |
1275 | VEC_free (ld_plugin_symbol_resolution_t, heap, data_in->globals_resolution); | |
412288f1 | 1276 | streamer_tree_cache_delete (data_in->reader_cache); |
d7f09764 DN |
1277 | free (data_in->labels); |
1278 | free (data_in); | |
1279 | } |