]>
Commit | Line | Data |
---|---|---|
d7f09764 DN |
1 | /* Read the GIMPLE representation from a file stream. |
2 | ||
5624e564 | 3 | Copyright (C) 2009-2015 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" | |
c7131fb2 AM |
26 | #include "backend.h" |
27 | #include "tree.h" | |
28 | #include "gimple.h" | |
29 | #include "rtl.h" | |
30 | #include "ssa.h" | |
d7f09764 | 31 | #include "toplev.h" |
40e23961 | 32 | #include "alias.h" |
40e23961 | 33 | #include "fold-const.h" |
d7f09764 | 34 | #include "flags.h" |
36566b39 PK |
35 | #include "insn-config.h" |
36 | #include "expmed.h" | |
37 | #include "dojump.h" | |
38 | #include "explow.h" | |
39 | #include "calls.h" | |
40 | #include "emit-rtl.h" | |
41 | #include "varasm.h" | |
42 | #include "stmt.h" | |
43 | #include "expr.h" | |
d7f09764 | 44 | #include "params.h" |
2fb9a547 | 45 | #include "internal-fn.h" |
5be5c238 | 46 | #include "gimple-iterator.h" |
442b4905 | 47 | #include "tree-cfg.h" |
442b4905 AM |
48 | #include "tree-into-ssa.h" |
49 | #include "tree-dfa.h" | |
7a300452 | 50 | #include "tree-ssa.h" |
d7f09764 | 51 | #include "tree-pass.h" |
d7f09764 | 52 | #include "diagnostic.h" |
d7f09764 DN |
53 | #include "except.h" |
54 | #include "debug.h" | |
c582198b | 55 | #include "cgraph.h" |
d7f09764 | 56 | #include "ipa-utils.h" |
f0efc7aa DN |
57 | #include "data-streamer.h" |
58 | #include "gimple-streamer.h" | |
d7f09764 | 59 | #include "lto-streamer.h" |
f0efc7aa | 60 | #include "tree-streamer.h" |
a22286c3 | 61 | #include "streamer-hooks.h" |
dd366ec3 RB |
62 | #include "cfgloop.h" |
63 | ||
d7f09764 | 64 | |
4a8fb1a1 LC |
65 | struct freeing_string_slot_hasher : string_slot_hasher |
66 | { | |
67 | static inline void remove (value_type *); | |
68 | }; | |
69 | ||
70 | inline void | |
71 | freeing_string_slot_hasher::remove (value_type *v) | |
72 | { | |
73 | free (v); | |
74 | } | |
75 | ||
d7f09764 | 76 | /* The table to hold the file names. */ |
c203e8a7 | 77 | static hash_table<freeing_string_slot_hasher> *file_name_hash_table; |
d7f09764 DN |
78 | |
79 | ||
80 | /* Check that tag ACTUAL has one of the given values. NUM_TAGS is the | |
81 | number of valid tag values to check. */ | |
82 | ||
f0efc7aa | 83 | void |
d7f09764 DN |
84 | lto_tag_check_set (enum LTO_tags actual, int ntags, ...) |
85 | { | |
86 | va_list ap; | |
87 | int i; | |
88 | ||
89 | va_start (ap, ntags); | |
90 | for (i = 0; i < ntags; i++) | |
91 | if ((unsigned) actual == va_arg (ap, unsigned)) | |
92 | { | |
93 | va_end (ap); | |
94 | return; | |
95 | } | |
96 | ||
97 | va_end (ap); | |
98 | internal_error ("bytecode stream: unexpected tag %s", lto_tag_name (actual)); | |
99 | } | |
100 | ||
101 | ||
a183b5c7 DN |
102 | /* Read LENGTH bytes from STREAM to ADDR. */ |
103 | ||
104 | void | |
105 | lto_input_data_block (struct lto_input_block *ib, void *addr, size_t length) | |
106 | { | |
107 | size_t i; | |
108 | unsigned char *const buffer = (unsigned char *const) addr; | |
109 | ||
110 | for (i = 0; i < length; i++) | |
412288f1 | 111 | buffer[i] = streamer_read_uchar (ib); |
a183b5c7 DN |
112 | } |
113 | ||
114 | ||
d7f09764 DN |
115 | /* Lookup STRING in file_name_hash_table. If found, return the existing |
116 | string, otherwise insert STRING as the canonical version. */ | |
117 | ||
118 | static const char * | |
119 | canon_file_name (const char *string) | |
120 | { | |
4a8fb1a1 | 121 | string_slot **slot; |
d7f09764 | 122 | struct string_slot s_slot; |
0b11d702 MM |
123 | size_t len = strlen (string); |
124 | ||
d7f09764 | 125 | s_slot.s = string; |
0b11d702 | 126 | s_slot.len = len; |
d7f09764 | 127 | |
c203e8a7 | 128 | slot = file_name_hash_table->find_slot (&s_slot, INSERT); |
d7f09764 DN |
129 | if (*slot == NULL) |
130 | { | |
d7f09764 DN |
131 | char *saved_string; |
132 | struct string_slot *new_slot; | |
133 | ||
d7f09764 DN |
134 | saved_string = (char *) xmalloc (len + 1); |
135 | new_slot = XCNEW (struct string_slot); | |
0b11d702 | 136 | memcpy (saved_string, string, len + 1); |
d7f09764 | 137 | new_slot->s = saved_string; |
0b11d702 | 138 | new_slot->len = len; |
d7f09764 DN |
139 | *slot = new_slot; |
140 | return saved_string; | |
141 | } | |
142 | else | |
143 | { | |
4a8fb1a1 | 144 | struct string_slot *old_slot = *slot; |
d7f09764 DN |
145 | return old_slot->s; |
146 | } | |
147 | } | |
148 | ||
eaeec5ec | 149 | /* Pointer to currently alive instance of lto_location_cache. */ |
d7f09764 | 150 | |
eaeec5ec | 151 | lto_location_cache *lto_location_cache::current_cache; |
d7f09764 | 152 | |
eaeec5ec JH |
153 | /* Sort locations in source order. Start with file from last application. */ |
154 | ||
155 | int | |
156 | lto_location_cache::cmp_loc (const void *pa, const void *pb) | |
157 | { | |
158 | const cached_location *a = ((const cached_location *)pa); | |
159 | const cached_location *b = ((const cached_location *)pb); | |
160 | const char *current_file = current_cache->current_file; | |
161 | int current_line = current_cache->current_line; | |
162 | ||
163 | if (a->file == current_file && b->file != current_file) | |
164 | return -1; | |
165 | if (a->file != current_file && b->file == current_file) | |
166 | return 1; | |
167 | if (a->file == current_file && b->file == current_file) | |
168 | { | |
169 | if (a->line == current_line && b->line != current_line) | |
170 | return -1; | |
171 | if (a->line != current_line && b->line == current_line) | |
172 | return 1; | |
173 | } | |
174 | if (a->file != b->file) | |
175 | return strcmp (a->file, b->file); | |
176 | if (a->line != b->line) | |
177 | return a->line - b->line; | |
178 | return a->col - b->col; | |
179 | } | |
180 | ||
181 | /* Apply all changes in location cache. Add locations into linemap and patch | |
182 | trees. */ | |
183 | ||
184 | bool | |
185 | lto_location_cache::apply_location_cache () | |
186 | { | |
187 | static const char *prev_file; | |
188 | if (!loc_cache.length ()) | |
189 | return false; | |
190 | if (loc_cache.length () > 1) | |
191 | loc_cache.qsort (cmp_loc); | |
192 | ||
193 | for (unsigned int i = 0; i < loc_cache.length (); i++) | |
194 | { | |
195 | struct cached_location loc = loc_cache[i]; | |
196 | ||
197 | if (current_file != loc.file) | |
198 | linemap_add (line_table, prev_file ? LC_RENAME : LC_ENTER, | |
199 | false, loc.file, loc.line); | |
200 | else if (current_line != loc.line) | |
201 | { | |
202 | int max = loc.col; | |
203 | ||
204 | for (unsigned int j = i + 1; j < loc_cache.length (); j++) | |
205 | if (loc.file != loc_cache[j].file | |
206 | || loc.line != loc_cache[j].line) | |
207 | break; | |
208 | else if (max < loc_cache[j].col) | |
209 | max = loc_cache[j].col; | |
210 | linemap_line_start (line_table, loc.line, max + 1); | |
211 | } | |
212 | gcc_assert (*loc.loc == BUILTINS_LOCATION + 1); | |
213 | if (current_file == loc.file && current_line == loc.line | |
214 | && current_col == loc.col) | |
215 | *loc.loc = current_loc; | |
216 | else | |
217 | current_loc = *loc.loc = linemap_position_for_column (line_table, | |
218 | loc.col); | |
219 | current_line = loc.line; | |
220 | prev_file = current_file = loc.file; | |
221 | current_col = loc.col; | |
222 | } | |
223 | loc_cache.truncate (0); | |
224 | accepted_length = 0; | |
225 | return true; | |
226 | } | |
227 | ||
228 | /* Tree merging did not suceed; mark all changes in the cache as accepted. */ | |
229 | ||
230 | void | |
231 | lto_location_cache::accept_location_cache () | |
232 | { | |
233 | gcc_assert (current_cache == this); | |
234 | accepted_length = loc_cache.length (); | |
235 | } | |
236 | ||
237 | /* Tree merging did suceed; throw away recent changes. */ | |
238 | ||
239 | void | |
240 | lto_location_cache::revert_location_cache () | |
241 | { | |
242 | loc_cache.truncate (accepted_length); | |
243 | } | |
244 | ||
245 | /* Read a location bitpack from input block IB and either update *LOC directly | |
246 | or add it to the location cache. | |
247 | It is neccesary to call apply_location_cache to get *LOC updated. */ | |
248 | ||
249 | void | |
250 | lto_location_cache::input_location (location_t *loc, struct bitpack_d *bp, | |
251 | struct data_in *data_in) | |
d7f09764 | 252 | { |
eaeec5ec JH |
253 | static const char *stream_file; |
254 | static int stream_line; | |
255 | static int stream_col; | |
51a9ed47 | 256 | bool file_change, line_change, column_change; |
eaeec5ec JH |
257 | |
258 | gcc_assert (current_cache == this); | |
d7f09764 | 259 | |
44433db0 JH |
260 | *loc = bp_unpack_int_in_range (bp, "location", 0, RESERVED_LOCATION_COUNT); |
261 | ||
262 | if (*loc < RESERVED_LOCATION_COUNT) | |
263 | return; | |
264 | ||
265 | /* Keep value RESERVED_LOCATION_COUNT in *loc as linemap lookups will | |
266 | ICE on it. */ | |
d7f09764 | 267 | |
51a9ed47 | 268 | file_change = bp_unpack_value (bp, 1); |
e45cde98 RB |
269 | line_change = bp_unpack_value (bp, 1); |
270 | column_change = bp_unpack_value (bp, 1); | |
271 | ||
51a9ed47 | 272 | if (file_change) |
eaeec5ec | 273 | stream_file = canon_file_name (bp_unpack_string (data_in, bp)); |
51a9ed47 | 274 | |
51a9ed47 | 275 | if (line_change) |
eaeec5ec | 276 | stream_line = bp_unpack_var_len_unsigned (bp); |
d7f09764 | 277 | |
51a9ed47 | 278 | if (column_change) |
eaeec5ec | 279 | stream_col = bp_unpack_var_len_unsigned (bp); |
51a9ed47 | 280 | |
eaeec5ec JH |
281 | /* This optimization saves location cache operations druing gimple |
282 | streaming. */ | |
283 | ||
284 | if (current_file == stream_file && current_line == stream_line | |
285 | && current_col == stream_col) | |
b7dae211 | 286 | { |
eaeec5ec JH |
287 | *loc = current_loc; |
288 | return; | |
b7dae211 | 289 | } |
51a9ed47 | 290 | |
eaeec5ec JH |
291 | struct cached_location entry = {stream_file, loc, stream_line, stream_col}; |
292 | loc_cache.safe_push (entry); | |
293 | } | |
294 | ||
295 | /* Read a location bitpack from input block IB and either update *LOC directly | |
296 | or add it to the location cache. | |
297 | It is neccesary to call apply_location_cache to get *LOC updated. */ | |
298 | ||
299 | void | |
300 | lto_input_location (location_t *loc, struct bitpack_d *bp, | |
301 | struct data_in *data_in) | |
302 | { | |
303 | data_in->location_cache.input_location (loc, bp, data_in); | |
51a9ed47 JH |
304 | } |
305 | ||
eaeec5ec JH |
306 | /* Read location and return it instead of going through location caching. |
307 | This should be used only when the resulting location is not going to be | |
308 | discarded. */ | |
309 | ||
310 | location_t | |
311 | stream_input_location_now (struct bitpack_d *bp, struct data_in *data_in) | |
312 | { | |
313 | location_t loc; | |
314 | stream_input_location (&loc, bp, data_in); | |
315 | data_in->location_cache.apply_location_cache (); | |
316 | return loc; | |
317 | } | |
b7dae211 | 318 | |
d7f09764 DN |
319 | /* Read a reference to a tree node from DATA_IN using input block IB. |
320 | TAG is the expected node that should be found in IB, if TAG belongs | |
321 | to one of the indexable trees, expect to read a reference index to | |
322 | be looked up in one of the symbol tables, otherwise read the pysical | |
b9393656 | 323 | representation of the tree using stream_read_tree. FN is the |
d7f09764 DN |
324 | function scope for the read tree. */ |
325 | ||
f0efc7aa | 326 | tree |
b8698a0f | 327 | lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in, |
d7f09764 DN |
328 | struct function *fn, enum LTO_tags tag) |
329 | { | |
330 | unsigned HOST_WIDE_INT ix_u; | |
331 | tree result = NULL_TREE; | |
332 | ||
5f673c6a | 333 | lto_tag_check_range (tag, LTO_field_decl_ref, LTO_namelist_decl_ref); |
d7f09764 DN |
334 | |
335 | switch (tag) | |
336 | { | |
337 | case LTO_type_ref: | |
412288f1 | 338 | ix_u = streamer_read_uhwi (ib); |
d7f09764 DN |
339 | result = lto_file_decl_data_get_type (data_in->file_data, ix_u); |
340 | break; | |
341 | ||
342 | case LTO_ssa_name_ref: | |
412288f1 | 343 | ix_u = streamer_read_uhwi (ib); |
9771b263 | 344 | result = (*SSANAMES (fn))[ix_u]; |
d7f09764 DN |
345 | break; |
346 | ||
347 | case LTO_field_decl_ref: | |
412288f1 | 348 | ix_u = streamer_read_uhwi (ib); |
d7f09764 DN |
349 | result = lto_file_decl_data_get_field_decl (data_in->file_data, ix_u); |
350 | break; | |
351 | ||
352 | case LTO_function_decl_ref: | |
412288f1 | 353 | ix_u = streamer_read_uhwi (ib); |
d7f09764 DN |
354 | result = lto_file_decl_data_get_fn_decl (data_in->file_data, ix_u); |
355 | break; | |
356 | ||
357 | case LTO_type_decl_ref: | |
412288f1 | 358 | ix_u = streamer_read_uhwi (ib); |
d7f09764 DN |
359 | result = lto_file_decl_data_get_type_decl (data_in->file_data, ix_u); |
360 | break; | |
361 | ||
362 | case LTO_namespace_decl_ref: | |
412288f1 | 363 | ix_u = streamer_read_uhwi (ib); |
d7f09764 DN |
364 | result = lto_file_decl_data_get_namespace_decl (data_in->file_data, ix_u); |
365 | break; | |
366 | ||
367 | case LTO_global_decl_ref: | |
368 | case LTO_result_decl_ref: | |
369 | case LTO_const_decl_ref: | |
370 | case LTO_imported_decl_ref: | |
371 | case LTO_label_decl_ref: | |
6be14c0e | 372 | case LTO_translation_unit_decl_ref: |
c39276b8 | 373 | case LTO_namelist_decl_ref: |
412288f1 | 374 | ix_u = streamer_read_uhwi (ib); |
d7f09764 | 375 | result = lto_file_decl_data_get_var_decl (data_in->file_data, ix_u); |
d7f09764 DN |
376 | break; |
377 | ||
378 | default: | |
379 | gcc_unreachable (); | |
380 | } | |
381 | ||
382 | gcc_assert (result); | |
383 | ||
384 | return result; | |
385 | } | |
386 | ||
387 | ||
388 | /* Read and return a double-linked list of catch handlers from input | |
389 | block IB, using descriptors in DATA_IN. */ | |
390 | ||
391 | static struct eh_catch_d * | |
392 | lto_input_eh_catch_list (struct lto_input_block *ib, struct data_in *data_in, | |
393 | eh_catch *last_p) | |
394 | { | |
395 | eh_catch first; | |
396 | enum LTO_tags tag; | |
397 | ||
398 | *last_p = first = NULL; | |
412288f1 | 399 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
400 | while (tag) |
401 | { | |
402 | tree list; | |
403 | eh_catch n; | |
404 | ||
405 | lto_tag_check_range (tag, LTO_eh_catch, LTO_eh_catch); | |
406 | ||
407 | /* Read the catch node. */ | |
766090c2 | 408 | n = ggc_cleared_alloc<eh_catch_d> (); |
b9393656 DN |
409 | n->type_list = stream_read_tree (ib, data_in); |
410 | n->filter_list = stream_read_tree (ib, data_in); | |
411 | n->label = stream_read_tree (ib, data_in); | |
d7f09764 DN |
412 | |
413 | /* Register all the types in N->FILTER_LIST. */ | |
414 | for (list = n->filter_list; list; list = TREE_CHAIN (list)) | |
415 | add_type_for_runtime (TREE_VALUE (list)); | |
416 | ||
417 | /* Chain N to the end of the list. */ | |
418 | if (*last_p) | |
419 | (*last_p)->next_catch = n; | |
420 | n->prev_catch = *last_p; | |
421 | *last_p = n; | |
422 | ||
423 | /* Set the head of the list the first time through the loop. */ | |
424 | if (first == NULL) | |
425 | first = n; | |
426 | ||
412288f1 | 427 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
428 | } |
429 | ||
430 | return first; | |
431 | } | |
432 | ||
433 | ||
434 | /* Read and return EH region IX from input block IB, using descriptors | |
435 | in DATA_IN. */ | |
436 | ||
437 | static eh_region | |
438 | input_eh_region (struct lto_input_block *ib, struct data_in *data_in, int ix) | |
439 | { | |
440 | enum LTO_tags tag; | |
441 | eh_region r; | |
442 | ||
443 | /* Read the region header. */ | |
412288f1 | 444 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
445 | if (tag == LTO_null) |
446 | return NULL; | |
447 | ||
766090c2 | 448 | r = ggc_cleared_alloc<eh_region_d> (); |
412288f1 | 449 | r->index = streamer_read_hwi (ib); |
d7f09764 DN |
450 | |
451 | gcc_assert (r->index == ix); | |
452 | ||
453 | /* Read all the region pointers as region numbers. We'll fix up | |
454 | the pointers once the whole array has been read. */ | |
412288f1 DN |
455 | r->outer = (eh_region) (intptr_t) streamer_read_hwi (ib); |
456 | r->inner = (eh_region) (intptr_t) streamer_read_hwi (ib); | |
457 | r->next_peer = (eh_region) (intptr_t) streamer_read_hwi (ib); | |
d7f09764 DN |
458 | |
459 | switch (tag) | |
460 | { | |
461 | case LTO_ert_cleanup: | |
462 | r->type = ERT_CLEANUP; | |
463 | break; | |
464 | ||
465 | case LTO_ert_try: | |
466 | { | |
467 | struct eh_catch_d *last_catch; | |
468 | r->type = ERT_TRY; | |
469 | r->u.eh_try.first_catch = lto_input_eh_catch_list (ib, data_in, | |
470 | &last_catch); | |
471 | r->u.eh_try.last_catch = last_catch; | |
472 | break; | |
473 | } | |
474 | ||
475 | case LTO_ert_allowed_exceptions: | |
476 | { | |
477 | tree l; | |
478 | ||
479 | r->type = ERT_ALLOWED_EXCEPTIONS; | |
b9393656 DN |
480 | r->u.allowed.type_list = stream_read_tree (ib, data_in); |
481 | r->u.allowed.label = stream_read_tree (ib, data_in); | |
412288f1 | 482 | r->u.allowed.filter = streamer_read_uhwi (ib); |
d7f09764 DN |
483 | |
484 | for (l = r->u.allowed.type_list; l ; l = TREE_CHAIN (l)) | |
485 | add_type_for_runtime (TREE_VALUE (l)); | |
486 | } | |
487 | break; | |
488 | ||
489 | case LTO_ert_must_not_throw: | |
7cb7d208 RB |
490 | { |
491 | r->type = ERT_MUST_NOT_THROW; | |
492 | r->u.must_not_throw.failure_decl = stream_read_tree (ib, data_in); | |
493 | bitpack_d bp = streamer_read_bitpack (ib); | |
494 | r->u.must_not_throw.failure_loc | |
eaeec5ec | 495 | = stream_input_location_now (&bp, data_in); |
7cb7d208 | 496 | } |
d7f09764 DN |
497 | break; |
498 | ||
499 | default: | |
500 | gcc_unreachable (); | |
501 | } | |
502 | ||
412288f1 | 503 | r->landing_pads = (eh_landing_pad) (intptr_t) streamer_read_hwi (ib); |
d7f09764 DN |
504 | |
505 | return r; | |
506 | } | |
507 | ||
508 | ||
509 | /* Read and return EH landing pad IX from input block IB, using descriptors | |
510 | in DATA_IN. */ | |
511 | ||
512 | static eh_landing_pad | |
513 | input_eh_lp (struct lto_input_block *ib, struct data_in *data_in, int ix) | |
514 | { | |
515 | enum LTO_tags tag; | |
516 | eh_landing_pad lp; | |
517 | ||
518 | /* Read the landing pad header. */ | |
412288f1 | 519 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
520 | if (tag == LTO_null) |
521 | return NULL; | |
522 | ||
523 | lto_tag_check_range (tag, LTO_eh_landing_pad, LTO_eh_landing_pad); | |
524 | ||
766090c2 | 525 | lp = ggc_cleared_alloc<eh_landing_pad_d> (); |
412288f1 | 526 | lp->index = streamer_read_hwi (ib); |
d7f09764 | 527 | gcc_assert (lp->index == ix); |
412288f1 DN |
528 | lp->next_lp = (eh_landing_pad) (intptr_t) streamer_read_hwi (ib); |
529 | lp->region = (eh_region) (intptr_t) streamer_read_hwi (ib); | |
b9393656 | 530 | lp->post_landing_pad = stream_read_tree (ib, data_in); |
d7f09764 DN |
531 | |
532 | return lp; | |
533 | } | |
534 | ||
535 | ||
536 | /* After reading the EH regions, pointers to peer and children regions | |
537 | are region numbers. This converts all these region numbers into | |
538 | real pointers into the rematerialized regions for FN. ROOT_REGION | |
539 | is the region number for the root EH region in FN. */ | |
540 | ||
541 | static void | |
542 | fixup_eh_region_pointers (struct function *fn, HOST_WIDE_INT root_region) | |
543 | { | |
544 | unsigned i; | |
9771b263 DN |
545 | vec<eh_region, va_gc> *eh_array = fn->eh->region_array; |
546 | vec<eh_landing_pad, va_gc> *lp_array = fn->eh->lp_array; | |
d7f09764 DN |
547 | eh_region r; |
548 | eh_landing_pad lp; | |
549 | ||
550 | gcc_assert (eh_array && lp_array); | |
551 | ||
552 | gcc_assert (root_region >= 0); | |
9771b263 | 553 | fn->eh->region_tree = (*eh_array)[root_region]; |
d7f09764 | 554 | |
9771b263 DN |
555 | #define FIXUP_EH_REGION(r) (r) = (*eh_array)[(HOST_WIDE_INT) (intptr_t) (r)] |
556 | #define FIXUP_EH_LP(p) (p) = (*lp_array)[(HOST_WIDE_INT) (intptr_t) (p)] | |
d7f09764 DN |
557 | |
558 | /* Convert all the index numbers stored in pointer fields into | |
559 | pointers to the corresponding slots in the EH region array. */ | |
9771b263 | 560 | FOR_EACH_VEC_ELT (*eh_array, i, r) |
d7f09764 DN |
561 | { |
562 | /* The array may contain NULL regions. */ | |
563 | if (r == NULL) | |
564 | continue; | |
565 | ||
566 | gcc_assert (i == (unsigned) r->index); | |
567 | FIXUP_EH_REGION (r->outer); | |
568 | FIXUP_EH_REGION (r->inner); | |
569 | FIXUP_EH_REGION (r->next_peer); | |
570 | FIXUP_EH_LP (r->landing_pads); | |
571 | } | |
572 | ||
573 | /* Convert all the index numbers stored in pointer fields into | |
574 | pointers to the corresponding slots in the EH landing pad array. */ | |
9771b263 | 575 | FOR_EACH_VEC_ELT (*lp_array, i, lp) |
d7f09764 DN |
576 | { |
577 | /* The array may contain NULL landing pads. */ | |
578 | if (lp == NULL) | |
579 | continue; | |
580 | ||
581 | gcc_assert (i == (unsigned) lp->index); | |
582 | FIXUP_EH_LP (lp->next_lp); | |
583 | FIXUP_EH_REGION (lp->region); | |
584 | } | |
585 | ||
586 | #undef FIXUP_EH_REGION | |
587 | #undef FIXUP_EH_LP | |
588 | } | |
589 | ||
590 | ||
591 | /* Initialize EH support. */ | |
592 | ||
f0efc7aa | 593 | void |
d7f09764 DN |
594 | lto_init_eh (void) |
595 | { | |
dad02715 RG |
596 | static bool eh_initialized_p = false; |
597 | ||
598 | if (eh_initialized_p) | |
599 | return; | |
600 | ||
d7f09764 DN |
601 | /* Contrary to most other FEs, we only initialize EH support when at |
602 | least one of the files in the set contains exception regions in | |
603 | it. Since this happens much later than the call to init_eh in | |
604 | lang_dependent_init, we have to set flag_exceptions and call | |
605 | init_eh again to initialize the EH tables. */ | |
606 | flag_exceptions = 1; | |
607 | init_eh (); | |
608 | ||
dad02715 | 609 | eh_initialized_p = true; |
d7f09764 DN |
610 | } |
611 | ||
612 | ||
613 | /* Read the exception table for FN from IB using the data descriptors | |
614 | in DATA_IN. */ | |
615 | ||
616 | static void | |
617 | input_eh_regions (struct lto_input_block *ib, struct data_in *data_in, | |
618 | struct function *fn) | |
619 | { | |
620 | HOST_WIDE_INT i, root_region, len; | |
621 | enum LTO_tags tag; | |
b8698a0f | 622 | |
412288f1 | 623 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
624 | if (tag == LTO_null) |
625 | return; | |
626 | ||
627 | lto_tag_check_range (tag, LTO_eh_table, LTO_eh_table); | |
628 | ||
629 | /* If the file contains EH regions, then it was compiled with | |
630 | -fexceptions. In that case, initialize the backend EH | |
631 | machinery. */ | |
dad02715 | 632 | lto_init_eh (); |
d7f09764 DN |
633 | |
634 | gcc_assert (fn->eh); | |
635 | ||
412288f1 | 636 | root_region = streamer_read_hwi (ib); |
d7f09764 DN |
637 | gcc_assert (root_region == (int) root_region); |
638 | ||
639 | /* Read the EH region array. */ | |
412288f1 | 640 | len = streamer_read_hwi (ib); |
d7f09764 DN |
641 | gcc_assert (len == (int) len); |
642 | if (len > 0) | |
643 | { | |
9771b263 | 644 | vec_safe_grow_cleared (fn->eh->region_array, len); |
d7f09764 DN |
645 | for (i = 0; i < len; i++) |
646 | { | |
647 | eh_region r = input_eh_region (ib, data_in, i); | |
9771b263 | 648 | (*fn->eh->region_array)[i] = r; |
d7f09764 DN |
649 | } |
650 | } | |
651 | ||
652 | /* Read the landing pads. */ | |
412288f1 | 653 | len = streamer_read_hwi (ib); |
d7f09764 DN |
654 | gcc_assert (len == (int) len); |
655 | if (len > 0) | |
656 | { | |
9771b263 | 657 | vec_safe_grow_cleared (fn->eh->lp_array, len); |
d7f09764 DN |
658 | for (i = 0; i < len; i++) |
659 | { | |
660 | eh_landing_pad lp = input_eh_lp (ib, data_in, i); | |
9771b263 | 661 | (*fn->eh->lp_array)[i] = lp; |
d7f09764 DN |
662 | } |
663 | } | |
664 | ||
665 | /* Read the runtime type data. */ | |
412288f1 | 666 | len = streamer_read_hwi (ib); |
d7f09764 DN |
667 | gcc_assert (len == (int) len); |
668 | if (len > 0) | |
669 | { | |
9771b263 | 670 | vec_safe_grow_cleared (fn->eh->ttype_data, len); |
d7f09764 DN |
671 | for (i = 0; i < len; i++) |
672 | { | |
b9393656 | 673 | tree ttype = stream_read_tree (ib, data_in); |
9771b263 | 674 | (*fn->eh->ttype_data)[i] = ttype; |
d7f09764 DN |
675 | } |
676 | } | |
677 | ||
678 | /* Read the table of action chains. */ | |
412288f1 | 679 | len = streamer_read_hwi (ib); |
d7f09764 DN |
680 | gcc_assert (len == (int) len); |
681 | if (len > 0) | |
682 | { | |
683 | if (targetm.arm_eabi_unwinder) | |
684 | { | |
9771b263 | 685 | vec_safe_grow_cleared (fn->eh->ehspec_data.arm_eabi, len); |
d7f09764 DN |
686 | for (i = 0; i < len; i++) |
687 | { | |
b9393656 | 688 | tree t = stream_read_tree (ib, data_in); |
9771b263 | 689 | (*fn->eh->ehspec_data.arm_eabi)[i] = t; |
d7f09764 DN |
690 | } |
691 | } | |
692 | else | |
693 | { | |
9771b263 | 694 | vec_safe_grow_cleared (fn->eh->ehspec_data.other, len); |
d7f09764 DN |
695 | for (i = 0; i < len; i++) |
696 | { | |
412288f1 | 697 | uchar c = streamer_read_uchar (ib); |
9771b263 | 698 | (*fn->eh->ehspec_data.other)[i] = c; |
d7f09764 DN |
699 | } |
700 | } | |
701 | } | |
702 | ||
703 | /* Reconstruct the EH region tree by fixing up the peer/children | |
704 | pointers. */ | |
705 | fixup_eh_region_pointers (fn, root_region); | |
706 | ||
412288f1 | 707 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
708 | lto_tag_check_range (tag, LTO_null, LTO_null); |
709 | } | |
710 | ||
711 | ||
712 | /* Make a new basic block with index INDEX in function FN. */ | |
713 | ||
714 | static basic_block | |
715 | make_new_block (struct function *fn, unsigned int index) | |
716 | { | |
717 | basic_block bb = alloc_block (); | |
718 | bb->index = index; | |
bbd79259 | 719 | SET_BASIC_BLOCK_FOR_FN (fn, index, bb); |
0cae8d31 | 720 | n_basic_blocks_for_fn (fn)++; |
d7f09764 DN |
721 | return bb; |
722 | } | |
723 | ||
724 | ||
807e902e KZ |
725 | /* Read a wide-int. */ |
726 | ||
727 | static widest_int | |
728 | streamer_read_wi (struct lto_input_block *ib) | |
729 | { | |
730 | HOST_WIDE_INT a[WIDE_INT_MAX_ELTS]; | |
731 | int i; | |
732 | int prec ATTRIBUTE_UNUSED = streamer_read_uhwi (ib); | |
733 | int len = streamer_read_uhwi (ib); | |
734 | for (i = 0; i < len; i++) | |
735 | a[i] = streamer_read_hwi (ib); | |
736 | return widest_int::from_array (a, len); | |
737 | } | |
738 | ||
739 | ||
d7f09764 DN |
740 | /* Read the CFG for function FN from input block IB. */ |
741 | ||
b8698a0f | 742 | static void |
e9287a41 RB |
743 | input_cfg (struct lto_input_block *ib, struct data_in *data_in, |
744 | struct function *fn, | |
db0bf14f | 745 | int count_materialization_scale) |
d7f09764 DN |
746 | { |
747 | unsigned int bb_count; | |
748 | basic_block p_bb; | |
749 | unsigned int i; | |
750 | int index; | |
751 | ||
752 | init_empty_tree_cfg_for_function (fn); | |
3828719a | 753 | init_ssa_operands (fn); |
d7f09764 | 754 | |
ea19eb9f DM |
755 | profile_status_for_fn (fn) = streamer_read_enum (ib, profile_status_d, |
756 | PROFILE_LAST); | |
d7f09764 | 757 | |
412288f1 | 758 | bb_count = streamer_read_uhwi (ib); |
d7f09764 | 759 | |
3986e690 | 760 | last_basic_block_for_fn (fn) = bb_count; |
bbd79259 DM |
761 | if (bb_count > basic_block_info_for_fn (fn)->length ()) |
762 | vec_safe_grow_cleared (basic_block_info_for_fn (fn), bb_count); | |
d7f09764 | 763 | |
3e248e06 DM |
764 | if (bb_count > label_to_block_map_for_fn (fn)->length ()) |
765 | vec_safe_grow_cleared (label_to_block_map_for_fn (fn), bb_count); | |
d7f09764 | 766 | |
412288f1 | 767 | index = streamer_read_hwi (ib); |
d7f09764 DN |
768 | while (index != -1) |
769 | { | |
bbd79259 | 770 | basic_block bb = BASIC_BLOCK_FOR_FN (fn, index); |
d7f09764 DN |
771 | unsigned int edge_count; |
772 | ||
773 | if (bb == NULL) | |
774 | bb = make_new_block (fn, index); | |
775 | ||
412288f1 | 776 | edge_count = streamer_read_uhwi (ib); |
d7f09764 DN |
777 | |
778 | /* Connect up the CFG. */ | |
779 | for (i = 0; i < edge_count; i++) | |
780 | { | |
781 | unsigned int dest_index; | |
782 | unsigned int edge_flags; | |
783 | basic_block dest; | |
784 | int probability; | |
785 | gcov_type count; | |
786 | edge e; | |
787 | ||
412288f1 DN |
788 | dest_index = streamer_read_uhwi (ib); |
789 | probability = (int) streamer_read_hwi (ib); | |
f41f80f9 TJ |
790 | count = apply_scale ((gcov_type) streamer_read_gcov_count (ib), |
791 | count_materialization_scale); | |
412288f1 | 792 | edge_flags = streamer_read_uhwi (ib); |
d7f09764 | 793 | |
bbd79259 | 794 | dest = BASIC_BLOCK_FOR_FN (fn, dest_index); |
d7f09764 | 795 | |
b8698a0f | 796 | if (dest == NULL) |
d7f09764 DN |
797 | dest = make_new_block (fn, dest_index); |
798 | ||
799 | e = make_edge (bb, dest, edge_flags); | |
800 | e->probability = probability; | |
801 | e->count = count; | |
802 | } | |
803 | ||
412288f1 | 804 | index = streamer_read_hwi (ib); |
d7f09764 DN |
805 | } |
806 | ||
fefa31b5 | 807 | p_bb = ENTRY_BLOCK_PTR_FOR_FN (fn); |
412288f1 | 808 | index = streamer_read_hwi (ib); |
d7f09764 DN |
809 | while (index != -1) |
810 | { | |
bbd79259 | 811 | basic_block bb = BASIC_BLOCK_FOR_FN (fn, index); |
d7f09764 DN |
812 | bb->prev_bb = p_bb; |
813 | p_bb->next_bb = bb; | |
814 | p_bb = bb; | |
412288f1 | 815 | index = streamer_read_hwi (ib); |
d7f09764 | 816 | } |
dd366ec3 RB |
817 | |
818 | /* ??? The cfgloop interface is tied to cfun. */ | |
819 | gcc_assert (cfun == fn); | |
820 | ||
821 | /* Input the loop tree. */ | |
822 | unsigned n_loops = streamer_read_uhwi (ib); | |
823 | if (n_loops == 0) | |
824 | return; | |
825 | ||
766090c2 | 826 | struct loops *loops = ggc_cleared_alloc<struct loops> (); |
dd366ec3 | 827 | init_loops_structure (fn, loops, n_loops); |
0fc822d0 | 828 | set_loops_for_fn (fn, loops); |
dd366ec3 RB |
829 | |
830 | /* Input each loop and associate it with its loop header so | |
831 | flow_loops_find can rebuild the loop tree. */ | |
832 | for (unsigned i = 1; i < n_loops; ++i) | |
833 | { | |
834 | int header_index = streamer_read_hwi (ib); | |
835 | if (header_index == -1) | |
836 | { | |
837 | loops->larray->quick_push (NULL); | |
838 | continue; | |
839 | } | |
840 | ||
841 | struct loop *loop = alloc_loop (); | |
bbd79259 | 842 | loop->header = BASIC_BLOCK_FOR_FN (fn, header_index); |
dd366ec3 RB |
843 | loop->header->loop_father = loop; |
844 | ||
845 | /* Read everything copy_loop_info copies. */ | |
846 | loop->estimate_state = streamer_read_enum (ib, loop_estimation, EST_LAST); | |
847 | loop->any_upper_bound = streamer_read_hwi (ib); | |
848 | if (loop->any_upper_bound) | |
807e902e | 849 | loop->nb_iterations_upper_bound = streamer_read_wi (ib); |
dd366ec3 RB |
850 | loop->any_estimate = streamer_read_hwi (ib); |
851 | if (loop->any_estimate) | |
807e902e | 852 | loop->nb_iterations_estimate = streamer_read_wi (ib); |
dd366ec3 | 853 | |
e9287a41 RB |
854 | /* Read OMP SIMD related info. */ |
855 | loop->safelen = streamer_read_hwi (ib); | |
718c4601 | 856 | loop->dont_vectorize = streamer_read_hwi (ib); |
b15b5979 | 857 | loop->force_vectorize = streamer_read_hwi (ib); |
e9287a41 RB |
858 | loop->simduid = stream_read_tree (ib, data_in); |
859 | ||
0fc822d0 | 860 | place_new_loop (fn, loop); |
dd366ec3 RB |
861 | |
862 | /* flow_loops_find doesn't like loops not in the tree, hook them | |
863 | all as siblings of the tree root temporarily. */ | |
864 | flow_loop_tree_node_add (loops->tree_root, loop); | |
865 | } | |
866 | ||
867 | /* Rebuild the loop tree. */ | |
0fc822d0 | 868 | flow_loops_find (loops); |
d7f09764 DN |
869 | } |
870 | ||
871 | ||
d7f09764 DN |
872 | /* Read the SSA names array for function FN from DATA_IN using input |
873 | block IB. */ | |
874 | ||
875 | static void | |
876 | input_ssa_names (struct lto_input_block *ib, struct data_in *data_in, | |
877 | struct function *fn) | |
878 | { | |
879 | unsigned int i, size; | |
880 | ||
412288f1 | 881 | size = streamer_read_uhwi (ib); |
d7f09764 DN |
882 | init_ssanames (fn, size); |
883 | ||
412288f1 | 884 | i = streamer_read_uhwi (ib); |
d7f09764 DN |
885 | while (i) |
886 | { | |
887 | tree ssa_name, name; | |
888 | bool is_default_def; | |
889 | ||
890 | /* Skip over the elements that had been freed. */ | |
9771b263 DN |
891 | while (SSANAMES (fn)->length () < i) |
892 | SSANAMES (fn)->quick_push (NULL_TREE); | |
d7f09764 | 893 | |
412288f1 | 894 | is_default_def = (streamer_read_uchar (ib) != 0); |
b9393656 | 895 | name = stream_read_tree (ib, data_in); |
d7f09764 DN |
896 | ssa_name = make_ssa_name_fn (fn, name, gimple_build_nop ()); |
897 | ||
898 | if (is_default_def) | |
32244553 | 899 | set_ssa_default_def (cfun, SSA_NAME_VAR (ssa_name), ssa_name); |
d7f09764 | 900 | |
412288f1 | 901 | i = streamer_read_uhwi (ib); |
b8698a0f | 902 | } |
d7f09764 DN |
903 | } |
904 | ||
d7f09764 DN |
905 | |
906 | /* Go through all NODE edges and fixup call_stmt pointers | |
907 | so they point to STMTS. */ | |
908 | ||
909 | static void | |
042ae7d2 JH |
910 | fixup_call_stmt_edges_1 (struct cgraph_node *node, gimple *stmts, |
911 | struct function *fn) | |
d7f09764 DN |
912 | { |
913 | struct cgraph_edge *cedge; | |
d122681a | 914 | struct ipa_ref *ref = NULL; |
042ae7d2 JH |
915 | unsigned int i; |
916 | ||
d7f09764 | 917 | for (cedge = node->callees; cedge; cedge = cedge->next_callee) |
042ae7d2 JH |
918 | { |
919 | if (gimple_stmt_max_uid (fn) < cedge->lto_stmt_uid) | |
40fecdd6 JM |
920 | fatal_error (input_location, |
921 | "Cgraph edge statement index out of range"); | |
538dd0b7 | 922 | cedge->call_stmt = as_a <gcall *> (stmts[cedge->lto_stmt_uid - 1]); |
042ae7d2 | 923 | if (!cedge->call_stmt) |
40fecdd6 JM |
924 | fatal_error (input_location, |
925 | "Cgraph edge statement index not found"); | |
042ae7d2 | 926 | } |
e33c6cd6 | 927 | for (cedge = node->indirect_calls; cedge; cedge = cedge->next_callee) |
042ae7d2 JH |
928 | { |
929 | if (gimple_stmt_max_uid (fn) < cedge->lto_stmt_uid) | |
40fecdd6 JM |
930 | fatal_error (input_location, |
931 | "Cgraph edge statement index out of range"); | |
538dd0b7 | 932 | cedge->call_stmt = as_a <gcall *> (stmts[cedge->lto_stmt_uid - 1]); |
042ae7d2 | 933 | if (!cedge->call_stmt) |
40fecdd6 | 934 | fatal_error (input_location, "Cgraph edge statement index not found"); |
042ae7d2 | 935 | } |
d122681a | 936 | for (i = 0; node->iterate_reference (i, ref); i++) |
042ae7d2 JH |
937 | if (ref->lto_stmt_uid) |
938 | { | |
939 | if (gimple_stmt_max_uid (fn) < ref->lto_stmt_uid) | |
40fecdd6 JM |
940 | fatal_error (input_location, |
941 | "Reference statement index out of range"); | |
042ae7d2 JH |
942 | ref->stmt = stmts[ref->lto_stmt_uid - 1]; |
943 | if (!ref->stmt) | |
40fecdd6 | 944 | fatal_error (input_location, "Reference statement index not found"); |
042ae7d2 | 945 | } |
d7f09764 DN |
946 | } |
947 | ||
042ae7d2 | 948 | |
d7f09764 DN |
949 | /* Fixup call_stmt pointers in NODE and all clones. */ |
950 | ||
951 | static void | |
952 | fixup_call_stmt_edges (struct cgraph_node *orig, gimple *stmts) | |
953 | { | |
954 | struct cgraph_node *node; | |
042ae7d2 | 955 | struct function *fn; |
d7f09764 DN |
956 | |
957 | while (orig->clone_of) | |
958 | orig = orig->clone_of; | |
67348ccc | 959 | fn = DECL_STRUCT_FUNCTION (orig->decl); |
d7f09764 | 960 | |
042ae7d2 | 961 | fixup_call_stmt_edges_1 (orig, stmts, fn); |
d7f09764 DN |
962 | if (orig->clones) |
963 | for (node = orig->clones; node != orig;) | |
964 | { | |
042ae7d2 | 965 | fixup_call_stmt_edges_1 (node, stmts, fn); |
d7f09764 DN |
966 | if (node->clones) |
967 | node = node->clones; | |
968 | else if (node->next_sibling_clone) | |
969 | node = node->next_sibling_clone; | |
970 | else | |
971 | { | |
972 | while (node != orig && !node->next_sibling_clone) | |
973 | node = node->clone_of; | |
974 | if (node != orig) | |
975 | node = node->next_sibling_clone; | |
976 | } | |
977 | } | |
978 | } | |
979 | ||
35f5b1c1 LC |
980 | |
981 | /* Input the base body of struct function FN from DATA_IN | |
982 | using input block IB. */ | |
d7f09764 DN |
983 | |
984 | static void | |
35f5b1c1 LC |
985 | input_struct_function_base (struct function *fn, struct data_in *data_in, |
986 | struct lto_input_block *ib) | |
d7f09764 | 987 | { |
2465dcc2 | 988 | struct bitpack_d bp; |
c021f10b | 989 | int len; |
d7f09764 | 990 | |
35f5b1c1 LC |
991 | /* Read the static chain and non-local goto save area. */ |
992 | fn->static_chain_decl = stream_read_tree (ib, data_in); | |
993 | fn->nonlocal_goto_save_area = stream_read_tree (ib, data_in); | |
d7f09764 | 994 | |
35f5b1c1 LC |
995 | /* Read all the local symbols. */ |
996 | len = streamer_read_hwi (ib); | |
997 | if (len > 0) | |
998 | { | |
999 | int i; | |
9771b263 | 1000 | vec_safe_grow_cleared (fn->local_decls, len); |
35f5b1c1 LC |
1001 | for (i = 0; i < len; i++) |
1002 | { | |
1003 | tree t = stream_read_tree (ib, data_in); | |
9771b263 | 1004 | (*fn->local_decls)[i] = t; |
35f5b1c1 LC |
1005 | } |
1006 | } | |
1007 | ||
35f5b1c1 LC |
1008 | /* Input the current IL state of the function. */ |
1009 | fn->curr_properties = streamer_read_uhwi (ib); | |
d7f09764 DN |
1010 | |
1011 | /* Read all the attributes for FN. */ | |
412288f1 | 1012 | bp = streamer_read_bitpack (ib); |
2465dcc2 RG |
1013 | fn->is_thunk = bp_unpack_value (&bp, 1); |
1014 | fn->has_local_explicit_reg_vars = bp_unpack_value (&bp, 1); | |
2465dcc2 RG |
1015 | fn->returns_pcc_struct = bp_unpack_value (&bp, 1); |
1016 | fn->returns_struct = bp_unpack_value (&bp, 1); | |
1017 | fn->can_throw_non_call_exceptions = bp_unpack_value (&bp, 1); | |
2da02156 | 1018 | fn->can_delete_dead_exceptions = bp_unpack_value (&bp, 1); |
2465dcc2 RG |
1019 | fn->always_inline_functions_inlined = bp_unpack_value (&bp, 1); |
1020 | fn->after_inlining = bp_unpack_value (&bp, 1); | |
2465dcc2 RG |
1021 | fn->stdarg = bp_unpack_value (&bp, 1); |
1022 | fn->has_nonlocal_label = bp_unpack_value (&bp, 1); | |
1023 | fn->calls_alloca = bp_unpack_value (&bp, 1); | |
1024 | fn->calls_setjmp = bp_unpack_value (&bp, 1); | |
b15b5979 | 1025 | fn->has_force_vectorize_loops = bp_unpack_value (&bp, 1); |
e9287a41 | 1026 | fn->has_simduid_loops = bp_unpack_value (&bp, 1); |
2465dcc2 RG |
1027 | fn->va_list_fpr_size = bp_unpack_value (&bp, 8); |
1028 | fn->va_list_gpr_size = bp_unpack_value (&bp, 8); | |
743c1134 | 1029 | fn->last_clique = bp_unpack_value (&bp, sizeof (short) * 8); |
7cb7d208 RB |
1030 | |
1031 | /* Input the function start and end loci. */ | |
eaeec5ec JH |
1032 | fn->function_start_locus = stream_input_location_now (&bp, data_in); |
1033 | fn->function_end_locus = stream_input_location_now (&bp, data_in); | |
35f5b1c1 | 1034 | } |
d7f09764 | 1035 | |
ac364a48 | 1036 | |
35f5b1c1 | 1037 | /* Read the body of function FN_DECL from DATA_IN using input block IB. */ |
688a482d | 1038 | |
35f5b1c1 LC |
1039 | static void |
1040 | input_function (tree fn_decl, struct data_in *data_in, | |
815effe1 | 1041 | struct lto_input_block *ib, struct lto_input_block *ib_cfg) |
35f5b1c1 LC |
1042 | { |
1043 | struct function *fn; | |
1044 | enum LTO_tags tag; | |
1045 | gimple *stmts; | |
1046 | basic_block bb; | |
1047 | struct cgraph_node *node; | |
d7f09764 | 1048 | |
35f5b1c1 | 1049 | tag = streamer_read_record_start (ib); |
815effe1 JH |
1050 | lto_tag_check (tag, LTO_function); |
1051 | ||
1052 | /* Read decls for parameters and args. */ | |
1053 | DECL_RESULT (fn_decl) = stream_read_tree (ib, data_in); | |
1054 | DECL_ARGUMENTS (fn_decl) = streamer_read_chain (ib, data_in); | |
1055 | ||
1056 | /* Read the tree of lexical scopes for the function. */ | |
1057 | DECL_INITIAL (fn_decl) = stream_read_tree (ib, data_in); | |
1058 | ||
1059 | if (!streamer_read_uhwi (ib)) | |
1060 | return; | |
1061 | ||
1062 | push_struct_function (fn_decl); | |
1063 | fn = DECL_STRUCT_FUNCTION (fn_decl); | |
1064 | init_tree_ssa (fn); | |
1065 | /* We input IL in SSA form. */ | |
1066 | cfun->gimple_df->in_ssa_p = true; | |
35f5b1c1 LC |
1067 | |
1068 | gimple_register_cfg_hooks (); | |
35f5b1c1 | 1069 | |
d52f5295 | 1070 | node = cgraph_node::get (fn_decl); |
d1c369c2 | 1071 | if (!node) |
d52f5295 | 1072 | node = cgraph_node::create (fn_decl); |
35f5b1c1 | 1073 | input_struct_function_base (fn, data_in, ib); |
e9287a41 | 1074 | input_cfg (ib_cfg, data_in, fn, node->count_materialization_scale); |
d7f09764 DN |
1075 | |
1076 | /* Read all the SSA names. */ | |
1077 | input_ssa_names (ib, data_in, fn); | |
1078 | ||
1079 | /* Read the exception handling regions in the function. */ | |
1080 | input_eh_regions (ib, data_in, fn); | |
1081 | ||
d7f09764 DN |
1082 | gcc_assert (DECL_INITIAL (fn_decl)); |
1083 | DECL_SAVED_TREE (fn_decl) = NULL_TREE; | |
1084 | ||
d7f09764 | 1085 | /* Read all the basic blocks. */ |
412288f1 | 1086 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
1087 | while (tag) |
1088 | { | |
db0bf14f JH |
1089 | input_bb (ib, tag, data_in, fn, |
1090 | node->count_materialization_scale); | |
412288f1 | 1091 | tag = streamer_read_record_start (ib); |
d7f09764 DN |
1092 | } |
1093 | ||
1094 | /* Fix up the call statements that are mentioned in the callgraph | |
1095 | edges. */ | |
8f984534 | 1096 | set_gimple_stmt_max_uid (cfun, 0); |
04a90bec | 1097 | FOR_ALL_BB_FN (bb, cfun) |
8f984534 RB |
1098 | { |
1099 | gimple_stmt_iterator gsi; | |
aa1e10cc JH |
1100 | for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
1101 | { | |
1102 | gimple stmt = gsi_stmt (gsi); | |
1103 | gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun)); | |
1104 | } | |
8f984534 RB |
1105 | for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
1106 | { | |
1107 | gimple stmt = gsi_stmt (gsi); | |
1108 | gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun)); | |
1109 | } | |
1110 | } | |
d7f09764 | 1111 | stmts = (gimple *) xcalloc (gimple_stmt_max_uid (fn), sizeof (gimple)); |
04a90bec | 1112 | FOR_ALL_BB_FN (bb, cfun) |
d7f09764 | 1113 | { |
aa1e10cc JH |
1114 | gimple_stmt_iterator bsi = gsi_start_phis (bb); |
1115 | while (!gsi_end_p (bsi)) | |
1116 | { | |
1117 | gimple stmt = gsi_stmt (bsi); | |
1118 | gsi_next (&bsi); | |
1119 | stmts[gimple_uid (stmt)] = stmt; | |
1120 | } | |
1121 | bsi = gsi_start_bb (bb); | |
7254364e | 1122 | while (!gsi_end_p (bsi)) |
d7f09764 DN |
1123 | { |
1124 | gimple stmt = gsi_stmt (bsi); | |
7254364e AO |
1125 | /* If we're recompiling LTO objects with debug stmts but |
1126 | we're not supposed to have debug stmts, remove them now. | |
1127 | We can't remove them earlier because this would cause uid | |
1128 | mismatches in fixups, but we can do it at this point, as | |
1129 | long as debug stmts don't require fixups. */ | |
8c9cfbe6 | 1130 | if (!MAY_HAVE_DEBUG_STMTS && !flag_wpa && is_gimple_debug (stmt)) |
7254364e AO |
1131 | { |
1132 | gimple_stmt_iterator gsi = bsi; | |
1133 | gsi_next (&bsi); | |
1134 | gsi_remove (&gsi, true); | |
1135 | } | |
1136 | else | |
1137 | { | |
1138 | gsi_next (&bsi); | |
1139 | stmts[gimple_uid (stmt)] = stmt; | |
1140 | } | |
d7f09764 DN |
1141 | } |
1142 | } | |
1143 | ||
1144 | /* Set the gimple body to the statement sequence in the entry | |
1145 | basic block. FIXME lto, this is fairly hacky. The existence | |
1146 | of a gimple body is used by the cgraph routines, but we should | |
1147 | really use the presence of the CFG. */ | |
1148 | { | |
fefa31b5 | 1149 | edge_iterator ei = ei_start (ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs); |
d7f09764 DN |
1150 | gimple_set_body (fn_decl, bb_seq (ei_edge (ei)->dest)); |
1151 | } | |
1152 | ||
2c5721d9 MJ |
1153 | fixup_call_stmt_edges (node, stmts); |
1154 | execute_all_ipa_stmt_fixups (node, stmts); | |
d7f09764 | 1155 | |
b8698a0f | 1156 | update_ssa (TODO_update_ssa_only_virtuals); |
fb3f88cc JH |
1157 | free_dominance_info (CDI_DOMINATORS); |
1158 | free_dominance_info (CDI_POST_DOMINATORS); | |
d7f09764 | 1159 | free (stmts); |
bcb650cb | 1160 | pop_cfun (); |
d7f09764 DN |
1161 | } |
1162 | ||
0b83e688 JH |
1163 | /* Read the body of function FN_DECL from DATA_IN using input block IB. */ |
1164 | ||
1165 | static void | |
1166 | input_constructor (tree var, struct data_in *data_in, | |
1167 | struct lto_input_block *ib) | |
1168 | { | |
1169 | DECL_INITIAL (var) = stream_read_tree (ib, data_in); | |
1170 | } | |
1171 | ||
d7f09764 | 1172 | |
4843f032 | 1173 | /* Read the body from DATA for function NODE and fill it in. |
d7f09764 DN |
1174 | FILE_DATA are the global decls and types. SECTION_TYPE is either |
1175 | LTO_section_function_body or LTO_section_static_initializer. If | |
1176 | section type is LTO_section_function_body, FN must be the decl for | |
1177 | that function. */ | |
1178 | ||
b8698a0f | 1179 | static void |
0b83e688 JH |
1180 | lto_read_body_or_constructor (struct lto_file_decl_data *file_data, struct symtab_node *node, |
1181 | const char *data, enum lto_section_type section_type) | |
d7f09764 DN |
1182 | { |
1183 | const struct lto_function_header *header; | |
1184 | struct data_in *data_in; | |
4ad9a9de EB |
1185 | int cfg_offset; |
1186 | int main_offset; | |
1187 | int string_offset; | |
67348ccc | 1188 | tree fn_decl = node->decl; |
d7f09764 DN |
1189 | |
1190 | header = (const struct lto_function_header *) data; | |
0b83e688 JH |
1191 | if (TREE_CODE (node->decl) == FUNCTION_DECL) |
1192 | { | |
1193 | cfg_offset = sizeof (struct lto_function_header); | |
1194 | main_offset = cfg_offset + header->cfg_size; | |
1195 | string_offset = main_offset + header->main_size; | |
0b83e688 JH |
1196 | } |
1197 | else | |
1198 | { | |
1199 | main_offset = sizeof (struct lto_function_header); | |
1200 | string_offset = main_offset + header->main_size; | |
0b83e688 | 1201 | } |
b8698a0f | 1202 | |
d7f09764 | 1203 | data_in = lto_data_in_create (file_data, data + string_offset, |
6e1aa848 | 1204 | header->string_size, vNULL); |
d7f09764 | 1205 | |
d7f09764 DN |
1206 | if (section_type == LTO_section_function_body) |
1207 | { | |
d7f09764 | 1208 | struct lto_in_decl_state *decl_state; |
23ee14a5 | 1209 | unsigned from; |
d7f09764 | 1210 | |
fe660d7b | 1211 | gcc_checking_assert (node); |
39c58b3a | 1212 | |
d7f09764 DN |
1213 | /* Use the function's decl state. */ |
1214 | decl_state = lto_get_function_in_decl_state (file_data, fn_decl); | |
1215 | gcc_assert (decl_state); | |
1216 | file_data->current_decl_state = decl_state; | |
1217 | ||
d7f09764 DN |
1218 | |
1219 | /* Set up the struct function. */ | |
9771b263 | 1220 | from = data_in->reader_cache->nodes.length (); |
db847fa8 JJ |
1221 | lto_input_block ib_main (data + main_offset, header->main_size, |
1222 | file_data->mode_table); | |
0b83e688 | 1223 | if (TREE_CODE (node->decl) == FUNCTION_DECL) |
207c68cd | 1224 | { |
db847fa8 JJ |
1225 | lto_input_block ib_cfg (data + cfg_offset, header->cfg_size, |
1226 | file_data->mode_table); | |
207c68cd RB |
1227 | input_function (fn_decl, data_in, &ib_main, &ib_cfg); |
1228 | } | |
0b83e688 JH |
1229 | else |
1230 | input_constructor (fn_decl, data_in, &ib_main); | |
eaeec5ec | 1231 | data_in->location_cache.apply_location_cache (); |
23ee14a5 RG |
1232 | /* And fixup types we streamed locally. */ |
1233 | { | |
1234 | struct streamer_tree_cache_d *cache = data_in->reader_cache; | |
9771b263 | 1235 | unsigned len = cache->nodes.length (); |
23ee14a5 RG |
1236 | unsigned i; |
1237 | for (i = len; i-- > from;) | |
1238 | { | |
ee03e71d | 1239 | tree t = streamer_tree_cache_get_tree (cache, i); |
23ee14a5 RG |
1240 | if (t == NULL_TREE) |
1241 | continue; | |
1242 | ||
1243 | if (TYPE_P (t)) | |
1244 | { | |
1245 | gcc_assert (TYPE_CANONICAL (t) == NULL_TREE); | |
1246 | TYPE_CANONICAL (t) = TYPE_MAIN_VARIANT (t); | |
1247 | if (TYPE_MAIN_VARIANT (t) != t) | |
1248 | { | |
1249 | gcc_assert (TYPE_NEXT_VARIANT (t) == NULL_TREE); | |
1250 | TYPE_NEXT_VARIANT (t) | |
1251 | = TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (t)); | |
1252 | TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (t)) = t; | |
1253 | } | |
1254 | } | |
1255 | } | |
1256 | } | |
d7f09764 | 1257 | |
d7f09764 DN |
1258 | /* Restore decl state */ |
1259 | file_data->current_decl_state = file_data->global_decl_state; | |
d7f09764 | 1260 | } |
d7f09764 | 1261 | |
d7f09764 DN |
1262 | lto_data_in_delete (data_in); |
1263 | } | |
1264 | ||
1265 | ||
4843f032 | 1266 | /* Read the body of NODE using DATA. FILE_DATA holds the global |
d7f09764 DN |
1267 | decls and types. */ |
1268 | ||
b8698a0f | 1269 | void |
d7f09764 | 1270 | lto_input_function_body (struct lto_file_decl_data *file_data, |
4843f032 | 1271 | struct cgraph_node *node, const char *data) |
d7f09764 | 1272 | { |
0b83e688 JH |
1273 | lto_read_body_or_constructor (file_data, node, data, LTO_section_function_body); |
1274 | } | |
1275 | ||
1276 | /* Read the body of NODE using DATA. FILE_DATA holds the global | |
1277 | decls and types. */ | |
1278 | ||
1279 | void | |
1280 | lto_input_variable_constructor (struct lto_file_decl_data *file_data, | |
1281 | struct varpool_node *node, const char *data) | |
1282 | { | |
1283 | lto_read_body_or_constructor (file_data, node, data, LTO_section_function_body); | |
d7f09764 DN |
1284 | } |
1285 | ||
1286 | ||
ee03e71d RB |
1287 | /* Read the physical representation of a tree node EXPR from |
1288 | input block IB using the per-file context in DATA_IN. */ | |
1289 | ||
1290 | static void | |
1291 | lto_read_tree_1 (struct lto_input_block *ib, struct data_in *data_in, tree expr) | |
1292 | { | |
1293 | /* Read all the bitfield values in EXPR. Note that for LTO, we | |
1294 | only write language-independent bitfields, so no more unpacking is | |
1295 | needed. */ | |
1296 | streamer_read_tree_bitfields (ib, data_in, expr); | |
1297 | ||
1298 | /* Read all the pointer fields in EXPR. */ | |
1299 | streamer_read_tree_body (ib, data_in, expr); | |
1300 | ||
1301 | /* Read any LTO-specific data not read by the tree streamer. */ | |
1302 | if (DECL_P (expr) | |
1303 | && TREE_CODE (expr) != FUNCTION_DECL | |
1304 | && TREE_CODE (expr) != TRANSLATION_UNIT_DECL) | |
1305 | DECL_INITIAL (expr) = stream_read_tree (ib, data_in); | |
1306 | ||
1307 | /* We should never try to instantiate an MD or NORMAL builtin here. */ | |
1308 | if (TREE_CODE (expr) == FUNCTION_DECL) | |
1309 | gcc_assert (!streamer_handle_as_builtin_p (expr)); | |
1310 | ||
1311 | #ifdef LTO_STREAMER_DEBUG | |
1312 | /* Remove the mapping to RESULT's original address set by | |
1313 | streamer_alloc_tree. */ | |
1314 | lto_orig_address_remove (expr); | |
1315 | #endif | |
1316 | } | |
1317 | ||
b9393656 DN |
1318 | /* Read the physical representation of a tree node with tag TAG from |
1319 | input block IB using the per-file context in DATA_IN. */ | |
d7f09764 | 1320 | |
b9393656 DN |
1321 | static tree |
1322 | lto_read_tree (struct lto_input_block *ib, struct data_in *data_in, | |
ee03e71d | 1323 | enum LTO_tags tag, hashval_t hash) |
47c79d56 | 1324 | { |
b9393656 | 1325 | /* Instantiate a new tree node. */ |
412288f1 | 1326 | tree result = streamer_alloc_tree (ib, data_in, tag); |
b9393656 DN |
1327 | |
1328 | /* Enter RESULT in the reader cache. This will make RESULT | |
1329 | available so that circular references in the rest of the tree | |
1330 | structure can be resolved in subsequent calls to stream_read_tree. */ | |
ee03e71d | 1331 | streamer_tree_cache_append (data_in->reader_cache, result, hash); |
b9393656 | 1332 | |
ee03e71d | 1333 | lto_read_tree_1 (ib, data_in, result); |
b9393656 | 1334 | |
ee03e71d | 1335 | /* end_marker = */ streamer_read_uchar (ib); |
b9393656 | 1336 | |
ee03e71d RB |
1337 | return result; |
1338 | } | |
b9393656 | 1339 | |
b9393656 | 1340 | |
ee03e71d RB |
1341 | /* Populate the reader cache with trees materialized from the SCC |
1342 | following in the IB, DATA_IN stream. */ | |
b9393656 | 1343 | |
ee03e71d RB |
1344 | hashval_t |
1345 | lto_input_scc (struct lto_input_block *ib, struct data_in *data_in, | |
1346 | unsigned *len, unsigned *entry_len) | |
1347 | { | |
1348 | /* A blob of unnamed tree nodes, fill the cache from it and | |
1349 | recurse. */ | |
1350 | unsigned size = streamer_read_uhwi (ib); | |
1351 | hashval_t scc_hash = streamer_read_uhwi (ib); | |
1352 | unsigned scc_entry_len = 1; | |
b9393656 | 1353 | |
ee03e71d RB |
1354 | if (size == 1) |
1355 | { | |
1356 | enum LTO_tags tag = streamer_read_record_start (ib); | |
1357 | lto_input_tree_1 (ib, data_in, tag, scc_hash); | |
1358 | } | |
1359 | else | |
1360 | { | |
1361 | unsigned int first = data_in->reader_cache->nodes.length (); | |
1362 | tree result; | |
1363 | ||
1364 | scc_entry_len = streamer_read_uhwi (ib); | |
1365 | ||
1366 | /* Materialize size trees by reading their headers. */ | |
1367 | for (unsigned i = 0; i < size; ++i) | |
1368 | { | |
1369 | enum LTO_tags tag = streamer_read_record_start (ib); | |
1370 | if (tag == LTO_null | |
1371 | || (tag >= LTO_field_decl_ref && tag <= LTO_global_decl_ref) | |
1372 | || tag == LTO_tree_pickle_reference | |
1373 | || tag == LTO_builtin_decl | |
1374 | || tag == LTO_integer_cst | |
1375 | || tag == LTO_tree_scc) | |
1376 | gcc_unreachable (); | |
1377 | ||
1378 | result = streamer_alloc_tree (ib, data_in, tag); | |
1379 | streamer_tree_cache_append (data_in->reader_cache, result, 0); | |
1380 | } | |
1381 | ||
1382 | /* Read the tree bitpacks and references. */ | |
1383 | for (unsigned i = 0; i < size; ++i) | |
1384 | { | |
1385 | result = streamer_tree_cache_get_tree (data_in->reader_cache, | |
1386 | first + i); | |
1387 | lto_read_tree_1 (ib, data_in, result); | |
1388 | /* end_marker = */ streamer_read_uchar (ib); | |
1389 | } | |
1390 | } | |
1391 | ||
1392 | *len = size; | |
1393 | *entry_len = scc_entry_len; | |
1394 | return scc_hash; | |
b9393656 DN |
1395 | } |
1396 | ||
1397 | ||
1398 | /* Read a tree from input block IB using the per-file context in | |
1399 | DATA_IN. This context is used, for example, to resolve references | |
1400 | to previously read nodes. */ | |
1401 | ||
1402 | tree | |
ee03e71d RB |
1403 | lto_input_tree_1 (struct lto_input_block *ib, struct data_in *data_in, |
1404 | enum LTO_tags tag, hashval_t hash) | |
b9393656 | 1405 | { |
b9393656 DN |
1406 | tree result; |
1407 | ||
b9393656 DN |
1408 | gcc_assert ((unsigned) tag < (unsigned) LTO_NUM_TAGS); |
1409 | ||
1410 | if (tag == LTO_null) | |
1411 | result = NULL_TREE; | |
5f673c6a | 1412 | else if (tag >= LTO_field_decl_ref && tag <= LTO_namelist_decl_ref) |
b9393656 DN |
1413 | { |
1414 | /* If TAG is a reference to an indexable tree, the next value | |
1415 | in IB is the index into the table where we expect to find | |
1416 | that tree. */ | |
1417 | result = lto_input_tree_ref (ib, data_in, cfun, tag); | |
1418 | } | |
1419 | else if (tag == LTO_tree_pickle_reference) | |
1420 | { | |
1421 | /* If TAG is a reference to a previously read tree, look it up in | |
1422 | the reader cache. */ | |
412288f1 | 1423 | result = streamer_get_pickled_tree (ib, data_in); |
b9393656 DN |
1424 | } |
1425 | else if (tag == LTO_builtin_decl) | |
1426 | { | |
1427 | /* If we are going to read a built-in function, all we need is | |
1428 | the code and class. */ | |
412288f1 | 1429 | result = streamer_get_builtin_tree (ib, data_in); |
b9393656 | 1430 | } |
c61f8c3b | 1431 | else if (tag == LTO_integer_cst) |
b9393656 | 1432 | { |
807e902e KZ |
1433 | /* For shared integer constants in singletons we can use the |
1434 | existing tree integer constant merging code. */ | |
ee03e71d | 1435 | tree type = stream_read_tree (ib, data_in); |
807e902e KZ |
1436 | unsigned HOST_WIDE_INT len = streamer_read_uhwi (ib); |
1437 | unsigned HOST_WIDE_INT i; | |
1438 | HOST_WIDE_INT a[WIDE_INT_MAX_ELTS]; | |
1439 | ||
1440 | for (i = 0; i < len; i++) | |
1441 | a[i] = streamer_read_hwi (ib); | |
1442 | gcc_assert (TYPE_PRECISION (type) <= MAX_BITSIZE_MODE_ANY_INT); | |
1443 | result = wide_int_to_tree (type, wide_int::from_array | |
1444 | (a, len, TYPE_PRECISION (type))); | |
ee03e71d RB |
1445 | streamer_tree_cache_append (data_in->reader_cache, result, hash); |
1446 | } | |
1447 | else if (tag == LTO_tree_scc) | |
b12c44e9 | 1448 | gcc_unreachable (); |
b9393656 DN |
1449 | else |
1450 | { | |
1451 | /* Otherwise, materialize a new node from IB. */ | |
ee03e71d | 1452 | result = lto_read_tree (ib, data_in, tag, hash); |
b9393656 DN |
1453 | } |
1454 | ||
1455 | return result; | |
47c79d56 DN |
1456 | } |
1457 | ||
ee03e71d RB |
1458 | tree |
1459 | lto_input_tree (struct lto_input_block *ib, struct data_in *data_in) | |
1460 | { | |
b12c44e9 RB |
1461 | enum LTO_tags tag; |
1462 | ||
1463 | /* Input and skip SCCs. */ | |
1464 | while ((tag = streamer_read_record_start (ib)) == LTO_tree_scc) | |
1465 | { | |
1466 | unsigned len, entry_len; | |
1467 | lto_input_scc (ib, data_in, &len, &entry_len); | |
1468 | } | |
1469 | return lto_input_tree_1 (ib, data_in, tag, 0); | |
ee03e71d RB |
1470 | } |
1471 | ||
47c79d56 | 1472 | |
49f836ba JB |
1473 | /* Input toplevel asms. */ |
1474 | ||
1475 | void | |
398f05da | 1476 | lto_input_toplevel_asms (struct lto_file_decl_data *file_data, int order_base) |
49f836ba JB |
1477 | { |
1478 | size_t len; | |
1479 | const char *data = lto_get_section_data (file_data, LTO_section_asm, | |
1480 | NULL, &len); | |
207c68cd RB |
1481 | const struct lto_simple_header_with_strings *header |
1482 | = (const struct lto_simple_header_with_strings *) data; | |
4ad9a9de | 1483 | int string_offset; |
49f836ba | 1484 | struct data_in *data_in; |
49f836ba JB |
1485 | tree str; |
1486 | ||
1487 | if (! data) | |
1488 | return; | |
1489 | ||
1490 | string_offset = sizeof (*header) + header->main_size; | |
1491 | ||
db847fa8 JJ |
1492 | lto_input_block ib (data + sizeof (*header), header->main_size, |
1493 | file_data->mode_table); | |
49f836ba JB |
1494 | |
1495 | data_in = lto_data_in_create (file_data, data + string_offset, | |
6e1aa848 | 1496 | header->string_size, vNULL); |
49f836ba | 1497 | |
49f836ba | 1498 | while ((str = streamer_read_string_cst (data_in, &ib))) |
398f05da | 1499 | { |
3dafb85c | 1500 | asm_node *node = symtab->finalize_toplevel_asm (str); |
398f05da | 1501 | node->order = streamer_read_hwi (&ib) + order_base; |
3dafb85c ML |
1502 | if (node->order >= symtab->order) |
1503 | symtab->order = node->order + 1; | |
398f05da | 1504 | } |
49f836ba | 1505 | |
49f836ba JB |
1506 | lto_data_in_delete (data_in); |
1507 | ||
1508 | lto_free_section_data (file_data, LTO_section_asm, NULL, data, len); | |
1509 | } | |
1510 | ||
1511 | ||
db847fa8 JJ |
1512 | /* Input mode table. */ |
1513 | ||
1514 | void | |
1515 | lto_input_mode_table (struct lto_file_decl_data *file_data) | |
1516 | { | |
1517 | size_t len; | |
1518 | const char *data = lto_get_section_data (file_data, LTO_section_mode_table, | |
1519 | NULL, &len); | |
1520 | if (! data) | |
1521 | { | |
1522 | internal_error ("cannot read LTO mode table from %s", | |
1523 | file_data->file_name); | |
1524 | return; | |
1525 | } | |
1526 | ||
1527 | unsigned char *table = ggc_cleared_vec_alloc<unsigned char> (1 << 8); | |
1528 | file_data->mode_table = table; | |
1529 | const struct lto_simple_header_with_strings *header | |
1530 | = (const struct lto_simple_header_with_strings *) data; | |
1531 | int string_offset; | |
1532 | struct data_in *data_in; | |
1533 | string_offset = sizeof (*header) + header->main_size; | |
1534 | ||
1535 | lto_input_block ib (data + sizeof (*header), header->main_size, NULL); | |
1536 | data_in = lto_data_in_create (file_data, data + string_offset, | |
1537 | header->string_size, vNULL); | |
1538 | bitpack_d bp = streamer_read_bitpack (&ib); | |
1539 | ||
1540 | table[VOIDmode] = VOIDmode; | |
1541 | table[BLKmode] = BLKmode; | |
1542 | unsigned int m; | |
1543 | while ((m = bp_unpack_value (&bp, 8)) != VOIDmode) | |
1544 | { | |
1545 | enum mode_class mclass | |
1546 | = bp_unpack_enum (&bp, mode_class, MAX_MODE_CLASS); | |
1547 | unsigned int size = bp_unpack_value (&bp, 8); | |
1548 | unsigned int prec = bp_unpack_value (&bp, 16); | |
1549 | machine_mode inner = (machine_mode) table[bp_unpack_value (&bp, 8)]; | |
1550 | unsigned int nunits = bp_unpack_value (&bp, 8); | |
1551 | unsigned int ibit = 0, fbit = 0; | |
1552 | unsigned int real_fmt_len = 0; | |
1553 | const char *real_fmt_name = NULL; | |
1554 | switch (mclass) | |
1555 | { | |
1556 | case MODE_FRACT: | |
1557 | case MODE_UFRACT: | |
1558 | case MODE_ACCUM: | |
1559 | case MODE_UACCUM: | |
1560 | ibit = bp_unpack_value (&bp, 8); | |
1561 | fbit = bp_unpack_value (&bp, 8); | |
1562 | break; | |
1563 | case MODE_FLOAT: | |
1564 | case MODE_DECIMAL_FLOAT: | |
1565 | real_fmt_name = bp_unpack_indexed_string (data_in, &bp, | |
1566 | &real_fmt_len); | |
1567 | break; | |
1568 | default: | |
1569 | break; | |
1570 | } | |
1571 | /* First search just the GET_CLASS_NARROWEST_MODE to wider modes, | |
1572 | if not found, fallback to all modes. */ | |
1573 | int pass; | |
1574 | for (pass = 0; pass < 2; pass++) | |
1575 | for (machine_mode mr = pass ? VOIDmode | |
1576 | : GET_CLASS_NARROWEST_MODE (mclass); | |
1577 | pass ? mr < MAX_MACHINE_MODE : mr != VOIDmode; | |
1578 | pass ? mr = (machine_mode) (m + 1) | |
1579 | : mr = GET_MODE_WIDER_MODE (mr)) | |
1580 | if (GET_MODE_CLASS (mr) != mclass | |
1581 | || GET_MODE_SIZE (mr) != size | |
1582 | || GET_MODE_PRECISION (mr) != prec | |
1583 | || GET_MODE_INNER (mr) != inner | |
1584 | || GET_MODE_IBIT (mr) != ibit | |
1585 | || GET_MODE_FBIT (mr) != fbit | |
1586 | || GET_MODE_NUNITS (mr) != nunits) | |
1587 | continue; | |
1588 | else if ((mclass == MODE_FLOAT || mclass == MODE_DECIMAL_FLOAT) | |
1589 | && strcmp (REAL_MODE_FORMAT (mr)->name, real_fmt_name) != 0) | |
1590 | continue; | |
1591 | else | |
1592 | { | |
1593 | table[m] = mr; | |
1594 | pass = 2; | |
1595 | break; | |
1596 | } | |
1597 | unsigned int mname_len; | |
1598 | const char *mname = bp_unpack_indexed_string (data_in, &bp, &mname_len); | |
1599 | if (pass == 2) | |
1600 | { | |
1601 | switch (mclass) | |
1602 | { | |
1603 | case MODE_VECTOR_INT: | |
1604 | case MODE_VECTOR_FLOAT: | |
1605 | case MODE_VECTOR_FRACT: | |
1606 | case MODE_VECTOR_UFRACT: | |
1607 | case MODE_VECTOR_ACCUM: | |
1608 | case MODE_VECTOR_UACCUM: | |
1609 | /* For unsupported vector modes just use BLKmode, | |
1610 | if the scalar mode is supported. */ | |
1611 | if (inner != VOIDmode) | |
1612 | { | |
1613 | table[m] = BLKmode; | |
1614 | break; | |
1615 | } | |
1616 | /* FALLTHRU */ | |
1617 | default: | |
1618 | fatal_error (UNKNOWN_LOCATION, "unsupported mode %s\n", mname); | |
1619 | break; | |
1620 | } | |
1621 | } | |
1622 | } | |
1623 | lto_data_in_delete (data_in); | |
1624 | ||
1625 | lto_free_section_data (file_data, LTO_section_mode_table, NULL, data, len); | |
1626 | } | |
1627 | ||
1628 | ||
d7f09764 DN |
1629 | /* Initialization for the LTO reader. */ |
1630 | ||
1631 | void | |
47c79d56 | 1632 | lto_reader_init (void) |
d7f09764 DN |
1633 | { |
1634 | lto_streamer_init (); | |
c203e8a7 TS |
1635 | file_name_hash_table |
1636 | = new hash_table<freeing_string_slot_hasher> (37); | |
d7f09764 DN |
1637 | } |
1638 | ||
1639 | ||
1640 | /* Create a new data_in object for FILE_DATA. STRINGS is the string | |
1641 | table to use with LEN strings. RESOLUTIONS is the vector of linker | |
1642 | resolutions (NULL if not using a linker plugin). */ | |
1643 | ||
1644 | struct data_in * | |
1645 | lto_data_in_create (struct lto_file_decl_data *file_data, const char *strings, | |
1646 | unsigned len, | |
9771b263 | 1647 | vec<ld_plugin_symbol_resolution_t> resolutions) |
d7f09764 | 1648 | { |
eaeec5ec | 1649 | struct data_in *data_in = new (struct data_in); |
d7f09764 DN |
1650 | data_in->file_data = file_data; |
1651 | data_in->strings = strings; | |
1652 | data_in->strings_len = len; | |
1653 | data_in->globals_resolution = resolutions; | |
bdc67fd6 | 1654 | data_in->reader_cache = streamer_tree_cache_create (false, false, true); |
d7f09764 DN |
1655 | return data_in; |
1656 | } | |
1657 | ||
1658 | ||
1659 | /* Remove DATA_IN. */ | |
1660 | ||
1661 | void | |
1662 | lto_data_in_delete (struct data_in *data_in) | |
1663 | { | |
9771b263 | 1664 | data_in->globals_resolution.release (); |
412288f1 | 1665 | streamer_tree_cache_delete (data_in->reader_cache); |
eaeec5ec | 1666 | delete data_in; |
d7f09764 | 1667 | } |