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