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