]>
Commit | Line | Data |
---|---|---|
d7f09764 | 1 | /* Top-level LTO routines. |
d7fb0a6d | 2 | Copyright 2009, 2010 Free Software Foundation, Inc. |
d7f09764 DN |
3 | Contributed by CodeSourcery, Inc. |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify it under | |
8 | the terms of the GNU General Public License as published by the Free | |
9 | Software Foundation; either version 3, or (at your option) any later | |
10 | version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GCC; see the file COPYING3. If not see | |
19 | <http://www.gnu.org/licenses/>. */ | |
20 | ||
21 | #include "config.h" | |
22 | #include "system.h" | |
23 | #include "coretypes.h" | |
24 | #include "opts.h" | |
25 | #include "toplev.h" | |
26 | #include "tree.h" | |
1da2ed5f | 27 | #include "diagnostic-core.h" |
d7f09764 DN |
28 | #include "tm.h" |
29 | #include "libiberty.h" | |
30 | #include "cgraph.h" | |
31 | #include "ggc.h" | |
32 | #include "tree-ssa-operands.h" | |
33 | #include "tree-pass.h" | |
34 | #include "langhooks.h" | |
35 | #include "vec.h" | |
36 | #include "bitmap.h" | |
37 | #include "pointer-set.h" | |
38 | #include "ipa-prop.h" | |
39 | #include "common.h" | |
7951d88a | 40 | #include "debug.h" |
d7f09764 DN |
41 | #include "timevar.h" |
42 | #include "gimple.h" | |
43 | #include "lto.h" | |
44 | #include "lto-tree.h" | |
45 | #include "lto-streamer.h" | |
46 | ||
47 | /* This needs to be included after config.h. Otherwise, _GNU_SOURCE will not | |
48 | be defined in time to set __USE_GNU in the system headers, and strsignal | |
49 | will not be declared. */ | |
4bedf19a | 50 | #if HAVE_MMAP_FILE |
d7f09764 | 51 | #include <sys/mman.h> |
4bedf19a | 52 | #endif |
d7f09764 | 53 | |
3cdea2b4 AH |
54 | /* Handle opening elf files on hosts, such as Windows, that may use |
55 | text file handling that will break binary access. */ | |
56 | ||
57 | #ifndef O_BINARY | |
58 | # define O_BINARY 0 | |
59 | #endif | |
60 | ||
7951d88a EB |
61 | static GTY(()) tree first_personality_decl; |
62 | ||
63 | ||
d7f09764 DN |
64 | /* Read the constructors and inits. */ |
65 | ||
66 | static void | |
67 | lto_materialize_constructors_and_inits (struct lto_file_decl_data * file_data) | |
68 | { | |
69 | size_t len; | |
70 | const char *data = lto_get_section_data (file_data, | |
71 | LTO_section_static_initializer, | |
72 | NULL, &len); | |
73 | lto_input_constructors_and_inits (file_data, data); | |
74 | lto_free_section_data (file_data, LTO_section_static_initializer, NULL, | |
75 | data, len); | |
76 | } | |
77 | ||
7951d88a | 78 | /* Read the function body for the function associated with NODE. */ |
d7f09764 DN |
79 | |
80 | static void | |
81 | lto_materialize_function (struct cgraph_node *node) | |
82 | { | |
83 | tree decl; | |
84 | struct lto_file_decl_data *file_data; | |
85 | const char *data, *name; | |
86 | size_t len; | |
d7f09764 DN |
87 | |
88 | /* Ignore clone nodes. Read the body only from the original one. | |
89 | We may find clone nodes during LTRANS after WPA has made inlining | |
90 | decisions. */ | |
91 | if (node->clone_of) | |
92 | return; | |
93 | ||
94 | decl = node->decl; | |
95 | file_data = node->local.lto_file_data; | |
96 | name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); | |
97 | ||
98 | /* We may have renamed the declaration, e.g., a static function. */ | |
99 | name = lto_get_decl_name_mapping (file_data, name); | |
100 | ||
101 | data = lto_get_section_data (file_data, LTO_section_function_body, | |
102 | name, &len); | |
103 | if (data) | |
104 | { | |
d7f09764 DN |
105 | gcc_assert (!DECL_IS_BUILTIN (decl)); |
106 | ||
107 | /* This function has a definition. */ | |
108 | TREE_STATIC (decl) = 1; | |
109 | ||
110 | gcc_assert (DECL_STRUCT_FUNCTION (decl) == NULL); | |
d7f09764 DN |
111 | |
112 | /* Load the function body only if not operating in WPA mode. In | |
113 | WPA mode, the body of the function is not needed. */ | |
114 | if (!flag_wpa) | |
115 | { | |
7951d88a EB |
116 | allocate_struct_function (decl, false); |
117 | announce_function (decl); | |
d7f09764 | 118 | lto_input_function_body (file_data, decl, data); |
7951d88a EB |
119 | if (DECL_FUNCTION_PERSONALITY (decl) && !first_personality_decl) |
120 | first_personality_decl = DECL_FUNCTION_PERSONALITY (decl); | |
d7f09764 DN |
121 | lto_stats.num_function_bodies++; |
122 | } | |
123 | ||
d7f09764 DN |
124 | lto_free_section_data (file_data, LTO_section_function_body, name, |
125 | data, len); | |
28632d63 JH |
126 | if (!flag_wpa) |
127 | ggc_collect (); | |
d7f09764 DN |
128 | } |
129 | else | |
130 | DECL_EXTERNAL (decl) = 1; | |
131 | ||
132 | /* Let the middle end know about the function. */ | |
133 | rest_of_decl_compilation (decl, 1, 0); | |
d7f09764 DN |
134 | } |
135 | ||
136 | ||
137 | /* Decode the content of memory pointed to by DATA in the the | |
138 | in decl state object STATE. DATA_IN points to a data_in structure for | |
139 | decoding. Return the address after the decoded object in the input. */ | |
140 | ||
141 | static const uint32_t * | |
142 | lto_read_in_decl_state (struct data_in *data_in, const uint32_t *data, | |
143 | struct lto_in_decl_state *state) | |
144 | { | |
145 | uint32_t ix; | |
146 | tree decl; | |
147 | uint32_t i, j; | |
148 | ||
149 | ix = *data++; | |
150 | decl = lto_streamer_cache_get (data_in->reader_cache, (int) ix); | |
151 | if (TREE_CODE (decl) != FUNCTION_DECL) | |
152 | { | |
153 | gcc_assert (decl == void_type_node); | |
154 | decl = NULL_TREE; | |
155 | } | |
156 | state->fn_decl = decl; | |
157 | ||
158 | for (i = 0; i < LTO_N_DECL_STREAMS; i++) | |
159 | { | |
160 | uint32_t size = *data++; | |
a9429e29 | 161 | tree *decls = ggc_alloc_vec_tree (size); |
d7f09764 DN |
162 | |
163 | for (j = 0; j < size; j++) | |
164 | { | |
165 | decls[j] = lto_streamer_cache_get (data_in->reader_cache, data[j]); | |
166 | ||
167 | /* Register every type in the global type table. If the | |
168 | type existed already, use the existing type. */ | |
169 | if (TYPE_P (decls[j])) | |
170 | decls[j] = gimple_register_type (decls[j]); | |
171 | } | |
172 | ||
173 | state->streams[i].size = size; | |
174 | state->streams[i].trees = decls; | |
175 | data += size; | |
176 | } | |
177 | ||
178 | return data; | |
179 | } | |
180 | ||
181 | ||
182 | /* Read all the symbols from buffer DATA, using descriptors in DECL_DATA. | |
183 | RESOLUTIONS is the set of symbols picked by the linker (read from the | |
184 | resolution file when the linker plugin is being used). */ | |
185 | ||
186 | static void | |
187 | lto_read_decls (struct lto_file_decl_data *decl_data, const void *data, | |
188 | VEC(ld_plugin_symbol_resolution_t,heap) *resolutions) | |
189 | { | |
190 | const struct lto_decl_header *header = (const struct lto_decl_header *) data; | |
191 | const int32_t decl_offset = sizeof (struct lto_decl_header); | |
192 | const int32_t main_offset = decl_offset + header->decl_state_size; | |
193 | const int32_t string_offset = main_offset + header->main_size; | |
194 | struct lto_input_block ib_main; | |
195 | struct data_in *data_in; | |
196 | unsigned int i; | |
197 | const uint32_t *data_ptr, *data_end; | |
198 | uint32_t num_decl_states; | |
199 | ||
200 | LTO_INIT_INPUT_BLOCK (ib_main, (const char *) data + main_offset, 0, | |
201 | header->main_size); | |
202 | ||
203 | data_in = lto_data_in_create (decl_data, (const char *) data + string_offset, | |
204 | header->string_size, resolutions); | |
205 | ||
206 | /* Read the global declarations and types. */ | |
207 | while (ib_main.p < ib_main.len) | |
208 | { | |
209 | tree t = lto_input_tree (&ib_main, data_in); | |
210 | gcc_assert (t && ib_main.p <= ib_main.len); | |
211 | } | |
212 | ||
213 | /* Read in lto_in_decl_state objects. */ | |
214 | data_ptr = (const uint32_t *) ((const char*) data + decl_offset); | |
215 | data_end = | |
216 | (const uint32_t *) ((const char*) data_ptr + header->decl_state_size); | |
217 | num_decl_states = *data_ptr++; | |
218 | ||
219 | gcc_assert (num_decl_states > 0); | |
220 | decl_data->global_decl_state = lto_new_in_decl_state (); | |
221 | data_ptr = lto_read_in_decl_state (data_in, data_ptr, | |
222 | decl_data->global_decl_state); | |
223 | ||
224 | /* Read in per-function decl states and enter them in hash table. */ | |
225 | decl_data->function_decl_states = | |
49ba8180 | 226 | htab_create_ggc (37, lto_hash_in_decl_state, lto_eq_in_decl_state, NULL); |
d7f09764 DN |
227 | |
228 | for (i = 1; i < num_decl_states; i++) | |
229 | { | |
230 | struct lto_in_decl_state *state = lto_new_in_decl_state (); | |
231 | void **slot; | |
232 | ||
233 | data_ptr = lto_read_in_decl_state (data_in, data_ptr, state); | |
234 | slot = htab_find_slot (decl_data->function_decl_states, state, INSERT); | |
235 | gcc_assert (*slot == NULL); | |
236 | *slot = state; | |
237 | } | |
238 | ||
239 | if (data_ptr != data_end) | |
240 | internal_error ("bytecode stream: garbage at the end of symbols section"); | |
241 | ||
242 | /* Set the current decl state to be the global state. */ | |
243 | decl_data->current_decl_state = decl_data->global_decl_state; | |
244 | ||
d7f09764 DN |
245 | lto_data_in_delete (data_in); |
246 | } | |
247 | ||
92fa7608 RAE |
248 | /* strtoll is not portable. */ |
249 | int64_t | |
250 | lto_parse_hex (const char *p) { | |
251 | uint64_t ret = 0; | |
252 | for (; *p != '\0'; ++p) | |
253 | { | |
254 | char c = *p; | |
255 | unsigned char part; | |
256 | ret <<= 4; | |
257 | if (c >= '0' && c <= '9') | |
258 | part = c - '0'; | |
259 | else if (c >= 'a' && c <= 'f') | |
260 | part = c - 'a' + 10; | |
261 | else if (c >= 'A' && c <= 'F') | |
262 | part = c - 'A' + 10; | |
263 | else | |
264 | internal_error ("could not parse hex number"); | |
265 | ret |= part; | |
266 | } | |
267 | return ret; | |
268 | } | |
269 | ||
d7f09764 DN |
270 | /* Read resolution for file named FILE_NAME. The resolution is read from |
271 | RESOLUTION. An array with the symbol resolution is returned. The array | |
272 | size is written to SIZE. */ | |
273 | ||
274 | static VEC(ld_plugin_symbol_resolution_t,heap) * | |
9870fe4f | 275 | lto_resolution_read (FILE *resolution, lto_file *file) |
d7f09764 DN |
276 | { |
277 | /* We require that objects in the resolution file are in the same | |
278 | order as the lto1 command line. */ | |
279 | unsigned int name_len; | |
280 | char *obj_name; | |
281 | unsigned int num_symbols; | |
282 | unsigned int i; | |
283 | VEC(ld_plugin_symbol_resolution_t,heap) *ret = NULL; | |
284 | unsigned max_index = 0; | |
285 | ||
286 | if (!resolution) | |
287 | return NULL; | |
288 | ||
9870fe4f | 289 | name_len = strlen (file->filename); |
d7f09764 DN |
290 | obj_name = XNEWVEC (char, name_len + 1); |
291 | fscanf (resolution, " "); /* Read white space. */ | |
292 | ||
293 | fread (obj_name, sizeof (char), name_len, resolution); | |
294 | obj_name[name_len] = '\0'; | |
9870fe4f | 295 | if (strcmp (obj_name, file->filename) != 0) |
d7f09764 | 296 | internal_error ("unexpected file name %s in linker resolution file. " |
9870fe4f RAE |
297 | "Expected %s", obj_name, file->filename); |
298 | if (file->offset != 0) | |
299 | { | |
300 | int t; | |
92fa7608 RAE |
301 | char offset_p[17]; |
302 | int64_t offset; | |
303 | t = fscanf (resolution, "@0x%16s", offset_p); | |
9870fe4f RAE |
304 | if (t != 1) |
305 | internal_error ("could not parse file offset"); | |
92fa7608 | 306 | offset = lto_parse_hex (offset_p); |
9870fe4f RAE |
307 | if (offset != file->offset) |
308 | internal_error ("unexpected offset"); | |
309 | } | |
d7f09764 DN |
310 | |
311 | free (obj_name); | |
312 | ||
313 | fscanf (resolution, "%u", &num_symbols); | |
314 | ||
315 | for (i = 0; i < num_symbols; i++) | |
316 | { | |
06bd7f56 | 317 | int t; |
d7f09764 DN |
318 | unsigned index; |
319 | char r_str[27]; | |
320 | enum ld_plugin_symbol_resolution r; | |
321 | unsigned int j; | |
322 | unsigned int lto_resolution_str_len = | |
323 | sizeof (lto_resolution_str) / sizeof (char *); | |
324 | ||
06bd7f56 RAE |
325 | t = fscanf (resolution, "%u %26s %*[^\n]\n", &index, r_str); |
326 | if (t != 2) | |
327 | internal_error ("Invalid line in the resolution file."); | |
d7f09764 DN |
328 | if (index > max_index) |
329 | max_index = index; | |
330 | ||
331 | for (j = 0; j < lto_resolution_str_len; j++) | |
332 | { | |
333 | if (strcmp (lto_resolution_str[j], r_str) == 0) | |
334 | { | |
335 | r = (enum ld_plugin_symbol_resolution) j; | |
336 | break; | |
337 | } | |
338 | } | |
06bd7f56 RAE |
339 | if (j == lto_resolution_str_len) |
340 | internal_error ("Invalid resolution in the resolution file."); | |
d7f09764 DN |
341 | |
342 | VEC_safe_grow_cleared (ld_plugin_symbol_resolution_t, heap, ret, | |
e7d00517 | 343 | max_index + 1); |
d7f09764 DN |
344 | VEC_replace (ld_plugin_symbol_resolution_t, ret, index, r); |
345 | } | |
346 | ||
347 | return ret; | |
348 | } | |
349 | ||
350 | /* Generate a TREE representation for all types and external decls | |
351 | entities in FILE. | |
352 | ||
353 | Read all of the globals out of the file. Then read the cgraph | |
354 | and process the .o index into the cgraph nodes so that it can open | |
355 | the .o file to load the functions and ipa information. */ | |
356 | ||
357 | static struct lto_file_decl_data * | |
358 | lto_file_read (lto_file *file, FILE *resolution_file) | |
359 | { | |
360 | struct lto_file_decl_data *file_data; | |
361 | const char *data; | |
362 | size_t len; | |
363 | VEC(ld_plugin_symbol_resolution_t,heap) *resolutions; | |
364 | ||
9870fe4f | 365 | resolutions = lto_resolution_read (resolution_file, file); |
d7f09764 | 366 | |
a9429e29 | 367 | file_data = ggc_alloc_lto_file_decl_data (); |
d7f09764 | 368 | file_data->file_name = file->filename; |
2cee0101 | 369 | file_data->section_hash_table = lto_obj_build_section_table (file); |
d7f09764 DN |
370 | file_data->renaming_hash_table = lto_create_renaming_table (); |
371 | ||
372 | data = lto_get_section_data (file_data, LTO_section_decls, NULL, &len); | |
373 | lto_read_decls (file_data, data, resolutions); | |
374 | lto_free_section_data (file_data, LTO_section_decls, NULL, data, len); | |
375 | ||
376 | return file_data; | |
377 | } | |
378 | ||
379 | #if HAVE_MMAP_FILE && HAVE_SYSCONF && defined _SC_PAGE_SIZE | |
380 | #define LTO_MMAP_IO 1 | |
381 | #endif | |
382 | ||
383 | #if LTO_MMAP_IO | |
384 | /* Page size of machine is used for mmap and munmap calls. */ | |
385 | static size_t page_mask; | |
386 | #endif | |
387 | ||
388 | /* Get the section data of length LEN from FILENAME starting at | |
389 | OFFSET. The data segment must be freed by the caller when the | |
390 | caller is finished. Returns NULL if all was not well. */ | |
391 | ||
392 | static char * | |
393 | lto_read_section_data (struct lto_file_decl_data *file_data, | |
394 | intptr_t offset, size_t len) | |
395 | { | |
396 | char *result; | |
b207f900 RG |
397 | static int fd = -1; |
398 | static char *fd_name; | |
d7f09764 DN |
399 | #if LTO_MMAP_IO |
400 | intptr_t computed_len; | |
401 | intptr_t computed_offset; | |
402 | intptr_t diff; | |
403 | #endif | |
404 | ||
b207f900 RG |
405 | /* Keep a single-entry file-descriptor cache. The last file we |
406 | touched will get closed at exit. | |
407 | ??? Eventually we want to add a more sophisticated larger cache | |
408 | or rather fix function body streaming to not stream them in | |
409 | practically random order. */ | |
410 | if (fd != -1 | |
411 | && strcmp (fd_name, file_data->file_name) != 0) | |
412 | { | |
413 | free (fd_name); | |
414 | close (fd); | |
415 | fd = -1; | |
416 | } | |
417 | if (fd == -1) | |
418 | { | |
419 | fd_name = xstrdup (file_data->file_name); | |
3cdea2b4 | 420 | fd = open (file_data->file_name, O_RDONLY|O_BINARY); |
b207f900 RG |
421 | if (fd == -1) |
422 | return NULL; | |
423 | } | |
d7f09764 DN |
424 | |
425 | #if LTO_MMAP_IO | |
426 | if (!page_mask) | |
427 | { | |
428 | size_t page_size = sysconf (_SC_PAGE_SIZE); | |
429 | page_mask = ~(page_size - 1); | |
430 | } | |
431 | ||
432 | computed_offset = offset & page_mask; | |
433 | diff = offset - computed_offset; | |
434 | computed_len = len + diff; | |
435 | ||
436 | result = (char *) mmap (NULL, computed_len, PROT_READ, MAP_PRIVATE, | |
b207f900 | 437 | fd, computed_offset); |
d7f09764 | 438 | if (result == MAP_FAILED) |
b207f900 | 439 | return NULL; |
d7f09764 DN |
440 | |
441 | return result + diff; | |
442 | #else | |
443 | result = (char *) xmalloc (len); | |
b207f900 RG |
444 | if (lseek (fd, offset, SEEK_SET) != offset |
445 | || read (fd, result, len) != (ssize_t) len) | |
d7f09764 DN |
446 | { |
447 | free (result); | |
d7f09764 DN |
448 | return NULL; |
449 | } | |
450 | ||
451 | return result; | |
452 | #endif | |
453 | } | |
454 | ||
455 | ||
456 | /* Get the section data from FILE_DATA of SECTION_TYPE with NAME. | |
457 | NAME will be NULL unless the section type is for a function | |
458 | body. */ | |
459 | ||
460 | static const char * | |
461 | get_section_data (struct lto_file_decl_data *file_data, | |
462 | enum lto_section_type section_type, | |
463 | const char *name, | |
464 | size_t *len) | |
465 | { | |
466 | htab_t section_hash_table = file_data->section_hash_table; | |
467 | struct lto_section_slot *f_slot; | |
468 | struct lto_section_slot s_slot; | |
469 | const char *section_name = lto_get_section_name (section_type, name); | |
470 | char *data = NULL; | |
471 | ||
472 | *len = 0; | |
473 | s_slot.name = section_name; | |
474 | f_slot = (struct lto_section_slot *) htab_find (section_hash_table, &s_slot); | |
475 | if (f_slot) | |
476 | { | |
477 | data = lto_read_section_data (file_data, f_slot->start, f_slot->len); | |
478 | *len = f_slot->len; | |
479 | } | |
480 | ||
481 | free (CONST_CAST (char *, section_name)); | |
482 | return data; | |
483 | } | |
484 | ||
485 | ||
486 | /* Free the section data from FILE_DATA of SECTION_TYPE with NAME that | |
487 | starts at OFFSET and has LEN bytes. */ | |
488 | ||
489 | static void | |
b207f900 | 490 | free_section_data (struct lto_file_decl_data *file_data ATTRIBUTE_UNUSED, |
d7f09764 DN |
491 | enum lto_section_type section_type ATTRIBUTE_UNUSED, |
492 | const char *name ATTRIBUTE_UNUSED, | |
493 | const char *offset, size_t len ATTRIBUTE_UNUSED) | |
494 | { | |
495 | #if LTO_MMAP_IO | |
496 | intptr_t computed_len; | |
497 | intptr_t computed_offset; | |
498 | intptr_t diff; | |
499 | #endif | |
500 | ||
d7f09764 DN |
501 | #if LTO_MMAP_IO |
502 | computed_offset = ((intptr_t) offset) & page_mask; | |
503 | diff = (intptr_t) offset - computed_offset; | |
504 | computed_len = len + diff; | |
505 | ||
506 | munmap ((caddr_t) computed_offset, computed_len); | |
507 | #else | |
508 | free (CONST_CAST(char *, offset)); | |
509 | #endif | |
510 | } | |
511 | ||
9eec9488 JH |
512 | /* Structure describing ltrans partitions. */ |
513 | ||
514 | struct GTY (()) ltrans_partition_def | |
515 | { | |
516 | cgraph_node_set cgraph_set; | |
517 | varpool_node_set varpool_set; | |
518 | const char * GTY ((skip)) name; | |
519 | int insns; | |
520 | }; | |
521 | ||
522 | typedef struct ltrans_partition_def *ltrans_partition; | |
523 | DEF_VEC_P(ltrans_partition); | |
524 | DEF_VEC_ALLOC_P(ltrans_partition,gc); | |
525 | ||
526 | static GTY (()) VEC(ltrans_partition, gc) *ltrans_partitions; | |
d7f09764 | 527 | |
9eec9488 JH |
528 | /* Create new partition with name NAME. */ |
529 | static ltrans_partition | |
530 | new_partition (const char *name) | |
531 | { | |
a9429e29 | 532 | ltrans_partition part = ggc_alloc_ltrans_partition_def (); |
9eec9488 JH |
533 | part->cgraph_set = cgraph_node_set_new (); |
534 | part->varpool_set = varpool_node_set_new (); | |
535 | part->name = name; | |
536 | part->insns = 0; | |
537 | VEC_safe_push (ltrans_partition, gc, ltrans_partitions, part); | |
538 | return part; | |
539 | } | |
540 | ||
541 | /* Add NODE to partition as well as the inline callees into partition PART. */ | |
542 | ||
543 | static void | |
544 | add_cgraph_node_to_partition (ltrans_partition part, struct cgraph_node *node) | |
545 | { | |
546 | struct cgraph_edge *e; | |
547 | part->insns += node->local.inline_summary.self_size; | |
548 | cgraph_node_set_add (part->cgraph_set, node); | |
549 | for (e = node->callees; e; e = e->next_callee) | |
550 | if (!e->inline_failed) | |
551 | add_cgraph_node_to_partition (part, e->callee); | |
552 | } | |
d7f09764 DN |
553 | |
554 | /* Group cgrah nodes by input files. This is used mainly for testing | |
555 | right now. */ | |
556 | ||
557 | static void | |
558 | lto_1_to_1_map (void) | |
559 | { | |
560 | struct cgraph_node *node; | |
2942c502 | 561 | struct varpool_node *vnode; |
d7f09764 DN |
562 | struct lto_file_decl_data *file_data; |
563 | struct pointer_map_t *pmap; | |
9eec9488 | 564 | ltrans_partition partition; |
d7f09764 | 565 | void **slot; |
9eec9488 | 566 | int npartitions = 0; |
d7f09764 DN |
567 | |
568 | timevar_push (TV_WHOPR_WPA); | |
569 | ||
d7f09764 DN |
570 | pmap = pointer_map_create (); |
571 | ||
572 | for (node = cgraph_nodes; node; node = node->next) | |
573 | { | |
36576655 JH |
574 | /* We will get proper partition based on function they are inlined to. */ |
575 | if (node->global.inlined_to) | |
3ee2243c | 576 | continue; |
2942c502 | 577 | /* Nodes without a body do not need partitioning. */ |
9a809897 | 578 | if (!node->analyzed) |
2942c502 | 579 | continue; |
9a809897 | 580 | |
d7f09764 | 581 | file_data = node->local.lto_file_data; |
9a809897 | 582 | gcc_assert (!node->same_body_alias && file_data); |
d7f09764 DN |
583 | |
584 | slot = pointer_map_contains (pmap, file_data); | |
585 | if (slot) | |
9eec9488 | 586 | partition = (ltrans_partition) *slot; |
d7f09764 DN |
587 | else |
588 | { | |
9eec9488 | 589 | partition = new_partition (file_data->file_name); |
d7f09764 | 590 | slot = pointer_map_insert (pmap, file_data); |
9eec9488 JH |
591 | *slot = partition; |
592 | npartitions++; | |
d7f09764 DN |
593 | } |
594 | ||
9eec9488 | 595 | add_cgraph_node_to_partition (partition, node); |
d7f09764 DN |
596 | } |
597 | ||
2942c502 JH |
598 | for (vnode = varpool_nodes; vnode; vnode = vnode->next) |
599 | { | |
2f41ecf5 | 600 | if (vnode->alias || !vnode->needed) |
2942c502 | 601 | continue; |
d4c0c9f6 | 602 | file_data = vnode->lto_file_data; |
9eec9488 | 603 | slot = pointer_map_contains (pmap, file_data); |
2942c502 | 604 | if (slot) |
9eec9488 | 605 | partition = (ltrans_partition) *slot; |
2942c502 JH |
606 | else |
607 | { | |
9eec9488 | 608 | partition = new_partition (file_data->file_name); |
2942c502 | 609 | slot = pointer_map_insert (pmap, file_data); |
9eec9488 JH |
610 | *slot = partition; |
611 | npartitions++; | |
2942c502 JH |
612 | } |
613 | ||
9eec9488 | 614 | varpool_node_set_add (partition->varpool_set, vnode); |
2942c502 JH |
615 | } |
616 | ||
617 | /* If the cgraph is empty, create one cgraph node set so that there is still | |
618 | an output file for any variables that need to be exported in a DSO. */ | |
9eec9488 JH |
619 | if (!npartitions) |
620 | new_partition ("empty"); | |
2942c502 | 621 | |
d7f09764 DN |
622 | pointer_map_destroy (pmap); |
623 | ||
d7f09764 DN |
624 | timevar_pop (TV_WHOPR_WPA); |
625 | ||
9eec9488 JH |
626 | lto_stats.num_cgraph_partitions += VEC_length (ltrans_partition, |
627 | ltrans_partitions); | |
d7f09764 DN |
628 | } |
629 | ||
66576e1b JH |
630 | /* Promote variable VNODE to be static. */ |
631 | ||
632 | static bool | |
633 | promote_var (struct varpool_node *vnode) | |
634 | { | |
635 | if (TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl)) | |
636 | return false; | |
637 | gcc_assert (flag_wpa); | |
638 | TREE_PUBLIC (vnode->decl) = 1; | |
639 | DECL_VISIBILITY (vnode->decl) = VISIBILITY_HIDDEN; | |
0a5fa5a1 JH |
640 | if (cgraph_dump_file) |
641 | fprintf (cgraph_dump_file, | |
642 | "Promoting var as hidden: %s\n", varpool_node_name (vnode)); | |
66576e1b JH |
643 | return true; |
644 | } | |
645 | ||
646 | /* Promote function NODE to be static. */ | |
647 | ||
648 | static bool | |
649 | promote_fn (struct cgraph_node *node) | |
650 | { | |
651 | gcc_assert (flag_wpa); | |
652 | if (TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)) | |
653 | return false; | |
654 | TREE_PUBLIC (node->decl) = 1; | |
655 | DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN; | |
656 | if (node->same_body) | |
657 | { | |
658 | struct cgraph_node *alias; | |
659 | for (alias = node->same_body; | |
660 | alias; alias = alias->next) | |
661 | { | |
662 | TREE_PUBLIC (alias->decl) = 1; | |
663 | DECL_VISIBILITY (alias->decl) = VISIBILITY_HIDDEN; | |
664 | } | |
665 | } | |
0a5fa5a1 JH |
666 | if (cgraph_dump_file) |
667 | fprintf (cgraph_dump_file, | |
668 | "Promoting function as hidden: %s/%i\n", | |
669 | cgraph_node_name (node), node->uid); | |
66576e1b JH |
670 | return true; |
671 | } | |
672 | ||
d7f09764 DN |
673 | /* Find out all static decls that need to be promoted to global because |
674 | of cross file sharing. This function must be run in the WPA mode after | |
675 | all inlinees are added. */ | |
676 | ||
677 | static void | |
678 | lto_promote_cross_file_statics (void) | |
679 | { | |
2942c502 | 680 | struct varpool_node *vnode; |
d7f09764 DN |
681 | unsigned i, n_sets; |
682 | cgraph_node_set set; | |
369451ec | 683 | varpool_node_set vset; |
d7f09764 | 684 | cgraph_node_set_iterator csi; |
369451ec | 685 | varpool_node_set_iterator vsi; |
66576e1b JH |
686 | VEC(varpool_node_ptr, heap) *promoted_initializers = NULL; |
687 | struct pointer_set_t *inserted = pointer_set_create (); | |
d7f09764 | 688 | |
2942c502 | 689 | gcc_assert (flag_wpa); |
d7f09764 | 690 | |
9eec9488 | 691 | n_sets = VEC_length (ltrans_partition, ltrans_partitions); |
d7f09764 DN |
692 | for (i = 0; i < n_sets; i++) |
693 | { | |
9eec9488 JH |
694 | ltrans_partition part = VEC_index (ltrans_partition, ltrans_partitions, i); |
695 | set = part->cgraph_set; | |
696 | vset = part->varpool_set; | |
d7f09764 | 697 | |
2942c502 JH |
698 | /* If node has either address taken (and we have no clue from where) |
699 | or it is called from other partition, it needs to be globalized. */ | |
d7f09764 | 700 | for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) |
2942c502 JH |
701 | { |
702 | struct cgraph_node *node = csi_node (csi); | |
2942c502 JH |
703 | if (node->local.externally_visible) |
704 | continue; | |
36576655 | 705 | if (node->global.inlined_to) |
9a809897 JH |
706 | continue; |
707 | if (!DECL_EXTERNAL (node->decl) | |
708 | && (referenced_from_other_partition_p (&node->ref_list, set, vset) | |
709 | || reachable_from_other_partition_p (node, set))) | |
66576e1b | 710 | promote_fn (node); |
2942c502 | 711 | } |
369451ec JH |
712 | for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi)) |
713 | { | |
714 | vnode = vsi_node (vsi); | |
715 | /* Constant pool references use internal labels and thus can not | |
716 | be made global. It is sensible to keep those ltrans local to | |
717 | allow better optimization. */ | |
718 | if (!DECL_IN_CONSTANT_POOL (vnode->decl) | |
66576e1b JH |
719 | && !vnode->externally_visible && vnode->analyzed |
720 | && referenced_from_other_partition_p (&vnode->ref_list, | |
721 | set, vset)) | |
722 | promote_var (vnode); | |
723 | } | |
724 | ||
725 | /* We export initializers of read-only var into each partition | |
726 | referencing it. Folding might take declarations from the | |
727 | initializers and use it; so everything referenced from the | |
728 | initializers needs can be accessed from this partition after | |
729 | folding. | |
730 | ||
731 | This means that we need to promote all variables and functions | |
732 | referenced from all initializers from readonly vars referenced | |
733 | from this partition that are not in this partition. | |
734 | This needs to be done recursively. */ | |
735 | for (vnode = varpool_nodes; vnode; vnode = vnode->next) | |
736 | if ((TREE_READONLY (vnode->decl) || DECL_IN_CONSTANT_POOL (vnode->decl)) | |
737 | && DECL_INITIAL (vnode->decl) | |
738 | && !varpool_node_in_set_p (vnode, vset) | |
739 | && referenced_from_this_partition_p (&vnode->ref_list, set, vset) | |
740 | && !pointer_set_insert (inserted, vnode)) | |
741 | VEC_safe_push (varpool_node_ptr, heap, promoted_initializers, vnode); | |
742 | while (!VEC_empty (varpool_node_ptr, promoted_initializers)) | |
743 | { | |
744 | int i; | |
745 | struct ipa_ref *ref; | |
746 | ||
747 | vnode = VEC_pop (varpool_node_ptr, promoted_initializers); | |
748 | for (i = 0; ipa_ref_list_reference_iterate (&vnode->ref_list, i, ref); i++) | |
369451ec | 749 | { |
66576e1b JH |
750 | if (ref->refered_type == IPA_REF_CGRAPH) |
751 | { | |
752 | struct cgraph_node *n = ipa_ref_node (ref); | |
753 | gcc_assert (!n->global.inlined_to); | |
754 | if (!n->local.externally_visible | |
755 | && !cgraph_node_in_set_p (n, set)) | |
756 | promote_fn (n); | |
757 | } | |
758 | else | |
759 | { | |
760 | struct varpool_node *v = ipa_ref_varpool_node (ref); | |
761 | if (varpool_node_in_set_p (v, vset)) | |
762 | continue; | |
763 | /* Constant pool references use internal labels and thus can not | |
764 | be made global. It is sensible to keep those ltrans local to | |
765 | allow better optimization. */ | |
766 | if (DECL_IN_CONSTANT_POOL (v->decl)) | |
767 | { | |
768 | if (!pointer_set_insert (inserted, vnode)) | |
769 | VEC_safe_push (varpool_node_ptr, heap, | |
770 | promoted_initializers, v); | |
771 | } | |
772 | else if (!DECL_IN_CONSTANT_POOL (v->decl) | |
773 | && !v->externally_visible && v->analyzed) | |
774 | { | |
775 | if (promote_var (v) | |
776 | && DECL_INITIAL (v->decl) && TREE_READONLY (v->decl) | |
777 | && !pointer_set_insert (inserted, vnode)) | |
778 | VEC_safe_push (varpool_node_ptr, heap, | |
779 | promoted_initializers, v); | |
780 | } | |
781 | } | |
369451ec JH |
782 | } |
783 | } | |
d7f09764 | 784 | } |
66576e1b | 785 | pointer_set_destroy (inserted); |
d7f09764 DN |
786 | } |
787 | ||
d7f09764 DN |
788 | static lto_file *current_lto_file; |
789 | ||
9eec9488 JH |
790 | /* Helper for qsort; compare partitions and return one with smaller size. |
791 | We sort from greatest to smallest so parallel build doesn't stale on the | |
792 | longest compilation being executed too late. */ | |
793 | ||
794 | static int | |
795 | cmp_partitions (const void *a, const void *b) | |
796 | { | |
797 | const struct ltrans_partition_def *pa | |
798 | = *(struct ltrans_partition_def *const *)a; | |
799 | const struct ltrans_partition_def *pb | |
800 | = *(struct ltrans_partition_def *const *)b; | |
801 | return pb->insns - pa->insns; | |
802 | } | |
d7f09764 | 803 | |
b5611987 RG |
804 | /* Write all output files in WPA mode and the file with the list of |
805 | LTRANS units. */ | |
d7f09764 | 806 | |
b5611987 | 807 | static void |
d7f09764 DN |
808 | lto_wpa_write_files (void) |
809 | { | |
b5611987 | 810 | unsigned i, n_sets; |
d7f09764 DN |
811 | lto_file *file; |
812 | cgraph_node_set set; | |
2942c502 | 813 | varpool_node_set vset; |
9eec9488 | 814 | ltrans_partition part; |
b5611987 RG |
815 | FILE *ltrans_output_list_stream; |
816 | char *temp_filename; | |
817 | size_t blen; | |
818 | ||
819 | /* Open the LTRANS output list. */ | |
820 | if (!ltrans_output_list) | |
821 | fatal_error ("no LTRANS output list filename provided"); | |
822 | ltrans_output_list_stream = fopen (ltrans_output_list, "w"); | |
823 | if (ltrans_output_list_stream == NULL) | |
824 | fatal_error ("opening LTRANS output list %s: %m", ltrans_output_list); | |
d7f09764 DN |
825 | |
826 | timevar_push (TV_WHOPR_WPA); | |
827 | ||
828 | /* Include all inlined functions and determine what sets need to be | |
829 | compiled by LTRANS. After this loop, only those sets that | |
830 | contain callgraph nodes from more than one file will need to be | |
831 | compiled by LTRANS. */ | |
9eec9488 JH |
832 | for (i = 0; VEC_iterate (ltrans_partition, ltrans_partitions, i, part); i++) |
833 | lto_stats.num_output_cgraph_nodes += VEC_length (cgraph_node_ptr, | |
834 | part->cgraph_set->nodes); | |
d7f09764 DN |
835 | |
836 | /* After adding all inlinees, find out statics that need to be promoted | |
837 | to globals because of cross-file inlining. */ | |
838 | lto_promote_cross_file_statics (); | |
839 | ||
840 | timevar_pop (TV_WHOPR_WPA); | |
841 | ||
842 | timevar_push (TV_WHOPR_WPA_IO); | |
843 | ||
b5611987 RG |
844 | /* Generate a prefix for the LTRANS unit files. */ |
845 | blen = strlen (ltrans_output_list); | |
846 | temp_filename = (char *) xmalloc (blen + sizeof ("2147483648.o")); | |
847 | strcpy (temp_filename, ltrans_output_list); | |
848 | if (blen > sizeof (".out") | |
849 | && strcmp (temp_filename + blen - sizeof (".out") + 1, | |
850 | ".out") == 0) | |
851 | temp_filename[blen - sizeof (".out") + 1] = '\0'; | |
852 | blen = strlen (temp_filename); | |
d7f09764 | 853 | |
9eec9488 JH |
854 | n_sets = VEC_length (ltrans_partition, ltrans_partitions); |
855 | qsort (VEC_address (ltrans_partition, ltrans_partitions), n_sets, | |
856 | sizeof (ltrans_partition), cmp_partitions); | |
d7f09764 DN |
857 | for (i = 0; i < n_sets; i++) |
858 | { | |
b5611987 | 859 | size_t len; |
9eec9488 | 860 | ltrans_partition part = VEC_index (ltrans_partition, ltrans_partitions, i); |
d7f09764 | 861 | |
9eec9488 JH |
862 | set = part->cgraph_set; |
863 | vset = part->varpool_set; | |
d7f09764 | 864 | |
b5611987 RG |
865 | /* Write all the nodes in SET. */ |
866 | sprintf (temp_filename + blen, "%u.o", i); | |
867 | file = lto_obj_file_open (temp_filename, true); | |
868 | if (!file) | |
869 | fatal_error ("lto_obj_file_open() failed"); | |
d7f09764 | 870 | |
b5611987 | 871 | if (!quiet_flag) |
9eec9488 | 872 | fprintf (stderr, " %s (%s %i insns)", temp_filename, part->name, part->insns); |
0a5fa5a1 JH |
873 | if (cgraph_dump_file) |
874 | { | |
875 | fprintf (cgraph_dump_file, "Writting partition %s to file %s, %i insns\n", | |
876 | part->name, temp_filename, part->insns); | |
877 | fprintf (cgraph_dump_file, "cgraph nodes:"); | |
878 | dump_cgraph_node_set (cgraph_dump_file, set); | |
879 | fprintf (cgraph_dump_file, "varpool nodes:"); | |
880 | dump_varpool_node_set (cgraph_dump_file, vset); | |
881 | } | |
9eec9488 JH |
882 | gcc_assert (cgraph_node_set_nonempty_p (set) |
883 | || varpool_node_set_nonempty_p (vset) || !i); | |
d7f09764 | 884 | |
b5611987 | 885 | lto_set_current_out_file (file); |
48cf395b | 886 | |
b5611987 | 887 | ipa_write_optimization_summaries (set, vset); |
d7f09764 | 888 | |
b5611987 RG |
889 | lto_set_current_out_file (NULL); |
890 | lto_obj_file_close (file); | |
d7f09764 | 891 | |
b5611987 RG |
892 | len = strlen (temp_filename); |
893 | if (fwrite (temp_filename, 1, len, ltrans_output_list_stream) < len | |
48cf395b | 894 | || fwrite ("\n", 1, 1, ltrans_output_list_stream) < 1) |
b5611987 RG |
895 | fatal_error ("writing to LTRANS output list %s: %m", |
896 | ltrans_output_list); | |
d7f09764 DN |
897 | } |
898 | ||
b5611987 RG |
899 | lto_stats.num_output_files += n_sets; |
900 | ||
d7f09764 | 901 | /* Close the LTRANS output list. */ |
48cf395b | 902 | if (fclose (ltrans_output_list_stream)) |
b5611987 RG |
903 | fatal_error ("closing LTRANS output list %s: %m", ltrans_output_list); |
904 | ||
905 | timevar_pop (TV_WHOPR_WPA_IO); | |
d7f09764 DN |
906 | } |
907 | ||
908 | ||
909 | typedef struct { | |
d7f09764 DN |
910 | struct pointer_set_t *seen; |
911 | } lto_fixup_data_t; | |
912 | ||
913 | #define LTO_FIXUP_SUBTREE(t) \ | |
914 | do \ | |
915 | walk_tree (&(t), lto_fixup_tree, data, NULL); \ | |
916 | while (0) | |
917 | ||
918 | #define LTO_REGISTER_TYPE_AND_FIXUP_SUBTREE(t) \ | |
919 | do \ | |
920 | { \ | |
921 | if (t) \ | |
922 | (t) = gimple_register_type (t); \ | |
923 | walk_tree (&(t), lto_fixup_tree, data, NULL); \ | |
924 | } \ | |
925 | while (0) | |
926 | ||
927 | static tree lto_fixup_tree (tree *, int *, void *); | |
928 | ||
929 | /* Return true if T does not need to be fixed up recursively. */ | |
930 | ||
931 | static inline bool | |
932 | no_fixup_p (tree t) | |
933 | { | |
934 | return (t == NULL | |
935 | || CONSTANT_CLASS_P (t) | |
936 | || TREE_CODE (t) == IDENTIFIER_NODE); | |
937 | } | |
938 | ||
939 | /* Fix up fields of a tree_common T. DATA points to fix-up states. */ | |
940 | ||
941 | static void | |
942 | lto_fixup_common (tree t, void *data) | |
943 | { | |
944 | /* The following re-creates the TYPE_REFERENCE_TO and TYPE_POINTER_TO | |
945 | lists. We do not stream TYPE_REFERENCE_TO, TYPE_POINTER_TO or | |
946 | TYPE_NEXT_PTR_TO and TYPE_NEXT_REF_TO. | |
947 | First remove us from any pointer list we are on. */ | |
948 | if (TREE_CODE (t) == POINTER_TYPE) | |
949 | { | |
950 | if (TYPE_POINTER_TO (TREE_TYPE (t)) == t) | |
951 | TYPE_POINTER_TO (TREE_TYPE (t)) = TYPE_NEXT_PTR_TO (t); | |
952 | else | |
953 | { | |
954 | tree tem = TYPE_POINTER_TO (TREE_TYPE (t)); | |
955 | while (tem && TYPE_NEXT_PTR_TO (tem) != t) | |
956 | tem = TYPE_NEXT_PTR_TO (tem); | |
957 | if (tem) | |
958 | TYPE_NEXT_PTR_TO (tem) = TYPE_NEXT_PTR_TO (t); | |
959 | } | |
960 | TYPE_NEXT_PTR_TO (t) = NULL_TREE; | |
961 | } | |
962 | else if (TREE_CODE (t) == REFERENCE_TYPE) | |
963 | { | |
964 | if (TYPE_REFERENCE_TO (TREE_TYPE (t)) == t) | |
965 | TYPE_REFERENCE_TO (TREE_TYPE (t)) = TYPE_NEXT_REF_TO (t); | |
966 | else | |
967 | { | |
968 | tree tem = TYPE_REFERENCE_TO (TREE_TYPE (t)); | |
969 | while (tem && TYPE_NEXT_REF_TO (tem) != t) | |
970 | tem = TYPE_NEXT_REF_TO (tem); | |
971 | if (tem) | |
972 | TYPE_NEXT_REF_TO (tem) = TYPE_NEXT_REF_TO (t); | |
973 | } | |
974 | TYPE_NEXT_REF_TO (t) = NULL_TREE; | |
975 | } | |
976 | ||
977 | /* Fixup our type. */ | |
978 | LTO_REGISTER_TYPE_AND_FIXUP_SUBTREE (TREE_TYPE (t)); | |
979 | ||
980 | /* Second put us on the list of pointers of the new pointed-to type | |
981 | if we are a main variant. This is done in lto_fixup_type after | |
982 | fixing up our main variant. */ | |
983 | ||
984 | /* This is not very efficient because we cannot do tail-recursion with | |
985 | a long chain of trees. */ | |
986 | LTO_FIXUP_SUBTREE (TREE_CHAIN (t)); | |
987 | } | |
988 | ||
989 | /* Fix up fields of a decl_minimal T. DATA points to fix-up states. */ | |
990 | ||
991 | static void | |
992 | lto_fixup_decl_minimal (tree t, void *data) | |
993 | { | |
994 | lto_fixup_common (t, data); | |
995 | LTO_FIXUP_SUBTREE (DECL_NAME (t)); | |
996 | LTO_FIXUP_SUBTREE (DECL_CONTEXT (t)); | |
997 | } | |
998 | ||
999 | /* Fix up fields of a decl_common T. DATA points to fix-up states. */ | |
1000 | ||
1001 | static void | |
1002 | lto_fixup_decl_common (tree t, void *data) | |
1003 | { | |
1004 | lto_fixup_decl_minimal (t, data); | |
1005 | LTO_FIXUP_SUBTREE (DECL_SIZE (t)); | |
1006 | LTO_FIXUP_SUBTREE (DECL_SIZE_UNIT (t)); | |
1007 | LTO_FIXUP_SUBTREE (DECL_INITIAL (t)); | |
1008 | LTO_FIXUP_SUBTREE (DECL_ATTRIBUTES (t)); | |
1009 | LTO_FIXUP_SUBTREE (DECL_ABSTRACT_ORIGIN (t)); | |
1010 | } | |
1011 | ||
1012 | /* Fix up fields of a decl_with_vis T. DATA points to fix-up states. */ | |
1013 | ||
1014 | static void | |
1015 | lto_fixup_decl_with_vis (tree t, void *data) | |
1016 | { | |
1017 | lto_fixup_decl_common (t, data); | |
1018 | ||
1019 | /* Accessor macro has side-effects, use field-name here. */ | |
1020 | LTO_FIXUP_SUBTREE (t->decl_with_vis.assembler_name); | |
1021 | ||
1022 | gcc_assert (no_fixup_p (DECL_SECTION_NAME (t))); | |
1023 | } | |
1024 | ||
1025 | /* Fix up fields of a decl_non_common T. DATA points to fix-up states. */ | |
1026 | ||
1027 | static void | |
1028 | lto_fixup_decl_non_common (tree t, void *data) | |
1029 | { | |
1030 | lto_fixup_decl_with_vis (t, data); | |
1031 | LTO_FIXUP_SUBTREE (DECL_ARGUMENT_FLD (t)); | |
1032 | LTO_FIXUP_SUBTREE (DECL_RESULT_FLD (t)); | |
1033 | LTO_FIXUP_SUBTREE (DECL_VINDEX (t)); | |
1034 | ||
1035 | /* SAVED_TREE should not cleared by now. Also no accessor for base type. */ | |
1036 | gcc_assert (no_fixup_p (t->decl_non_common.saved_tree)); | |
1037 | } | |
1038 | ||
1039 | /* Fix up fields of a decl_non_common T. DATA points to fix-up states. */ | |
1040 | ||
1041 | static void | |
1042 | lto_fixup_function (tree t, void *data) | |
1043 | { | |
1044 | lto_fixup_decl_non_common (t, data); | |
1045 | LTO_FIXUP_SUBTREE (DECL_FUNCTION_PERSONALITY (t)); | |
1046 | } | |
1047 | ||
1048 | /* Fix up fields of a field_decl T. DATA points to fix-up states. */ | |
1049 | ||
1050 | static void | |
1051 | lto_fixup_field_decl (tree t, void *data) | |
1052 | { | |
1053 | lto_fixup_decl_common (t, data); | |
2a71eb48 | 1054 | LTO_FIXUP_SUBTREE (DECL_FIELD_OFFSET (t)); |
d7f09764 DN |
1055 | LTO_FIXUP_SUBTREE (DECL_BIT_FIELD_TYPE (t)); |
1056 | LTO_FIXUP_SUBTREE (DECL_QUALIFIER (t)); | |
1057 | gcc_assert (no_fixup_p (DECL_FIELD_BIT_OFFSET (t))); | |
1058 | LTO_FIXUP_SUBTREE (DECL_FCONTEXT (t)); | |
1059 | } | |
1060 | ||
1061 | /* Fix up fields of a type T. DATA points to fix-up states. */ | |
1062 | ||
1063 | static void | |
1064 | lto_fixup_type (tree t, void *data) | |
1065 | { | |
1066 | tree tem, mv; | |
1067 | ||
1068 | lto_fixup_common (t, data); | |
1069 | LTO_FIXUP_SUBTREE (TYPE_CACHED_VALUES (t)); | |
1070 | LTO_FIXUP_SUBTREE (TYPE_SIZE (t)); | |
1071 | LTO_FIXUP_SUBTREE (TYPE_SIZE_UNIT (t)); | |
1072 | LTO_FIXUP_SUBTREE (TYPE_ATTRIBUTES (t)); | |
1073 | LTO_FIXUP_SUBTREE (TYPE_NAME (t)); | |
1074 | ||
1075 | /* Accessors are for derived node types only. */ | |
1076 | if (!POINTER_TYPE_P (t)) | |
1077 | LTO_FIXUP_SUBTREE (t->type.minval); | |
1078 | LTO_FIXUP_SUBTREE (t->type.maxval); | |
1079 | ||
1080 | /* Accessor is for derived node types only. */ | |
1081 | LTO_FIXUP_SUBTREE (t->type.binfo); | |
1082 | ||
21aac880 RG |
1083 | if (TYPE_CONTEXT (t)) |
1084 | { | |
1085 | if (TYPE_P (TYPE_CONTEXT (t))) | |
1086 | LTO_REGISTER_TYPE_AND_FIXUP_SUBTREE (TYPE_CONTEXT (t)); | |
1087 | else | |
1088 | LTO_FIXUP_SUBTREE (TYPE_CONTEXT (t)); | |
1089 | } | |
d7f09764 DN |
1090 | LTO_REGISTER_TYPE_AND_FIXUP_SUBTREE (TYPE_CANONICAL (t)); |
1091 | ||
1092 | /* The following re-creates proper variant lists while fixing up | |
1093 | the variant leaders. We do not stream TYPE_NEXT_VARIANT so the | |
1094 | variant list state before fixup is broken. */ | |
1095 | ||
1096 | /* Remove us from our main variant list if we are not the variant leader. */ | |
1097 | if (TYPE_MAIN_VARIANT (t) != t) | |
1098 | { | |
1099 | tem = TYPE_MAIN_VARIANT (t); | |
1100 | while (tem && TYPE_NEXT_VARIANT (tem) != t) | |
1101 | tem = TYPE_NEXT_VARIANT (tem); | |
1102 | if (tem) | |
1103 | TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t); | |
1104 | TYPE_NEXT_VARIANT (t) = NULL_TREE; | |
1105 | } | |
1106 | ||
1107 | /* Query our new main variant. */ | |
1108 | mv = gimple_register_type (TYPE_MAIN_VARIANT (t)); | |
1109 | ||
1110 | /* If we were the variant leader and we get replaced ourselves drop | |
1111 | all variants from our list. */ | |
1112 | if (TYPE_MAIN_VARIANT (t) == t | |
1113 | && mv != t) | |
1114 | { | |
1115 | tem = t; | |
1116 | while (tem) | |
1117 | { | |
1118 | tree tem2 = TYPE_NEXT_VARIANT (tem); | |
1119 | TYPE_NEXT_VARIANT (tem) = NULL_TREE; | |
1120 | tem = tem2; | |
1121 | } | |
1122 | } | |
1123 | ||
1124 | /* If we are not our own variant leader link us into our new leaders | |
1125 | variant list. */ | |
1126 | if (mv != t) | |
1127 | { | |
1128 | TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (mv); | |
1129 | TYPE_NEXT_VARIANT (mv) = t; | |
1130 | } | |
1131 | ||
1132 | /* Finally adjust our main variant and fix it up. */ | |
1133 | TYPE_MAIN_VARIANT (t) = mv; | |
1134 | LTO_FIXUP_SUBTREE (TYPE_MAIN_VARIANT (t)); | |
1135 | ||
1136 | /* As the second step of reconstructing the pointer chains put us | |
1137 | on the list of pointers of the new pointed-to type | |
1138 | if we are a main variant. See lto_fixup_common for the first step. */ | |
1139 | if (TREE_CODE (t) == POINTER_TYPE | |
1140 | && TYPE_MAIN_VARIANT (t) == t) | |
1141 | { | |
1142 | TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (TREE_TYPE (t)); | |
1143 | TYPE_POINTER_TO (TREE_TYPE (t)) = t; | |
1144 | } | |
1145 | else if (TREE_CODE (t) == REFERENCE_TYPE | |
1146 | && TYPE_MAIN_VARIANT (t) == t) | |
1147 | { | |
1148 | TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (TREE_TYPE (t)); | |
1149 | TYPE_REFERENCE_TO (TREE_TYPE (t)) = t; | |
1150 | } | |
1151 | } | |
1152 | ||
1153 | /* Fix up fields of a BINFO T. DATA points to fix-up states. */ | |
1154 | ||
1155 | static void | |
1156 | lto_fixup_binfo (tree t, void *data) | |
1157 | { | |
1158 | unsigned HOST_WIDE_INT i, n; | |
1159 | tree base, saved_base; | |
1160 | ||
1161 | lto_fixup_common (t, data); | |
1162 | gcc_assert (no_fixup_p (BINFO_OFFSET (t))); | |
1163 | LTO_FIXUP_SUBTREE (BINFO_VTABLE (t)); | |
1164 | LTO_FIXUP_SUBTREE (BINFO_VIRTUALS (t)); | |
1165 | LTO_FIXUP_SUBTREE (BINFO_VPTR_FIELD (t)); | |
1166 | n = VEC_length (tree, BINFO_BASE_ACCESSES (t)); | |
1167 | for (i = 0; i < n; i++) | |
1168 | { | |
1169 | saved_base = base = BINFO_BASE_ACCESS (t, i); | |
1170 | LTO_FIXUP_SUBTREE (base); | |
1171 | if (base != saved_base) | |
1172 | VEC_replace (tree, BINFO_BASE_ACCESSES (t), i, base); | |
1173 | } | |
1174 | LTO_FIXUP_SUBTREE (BINFO_INHERITANCE_CHAIN (t)); | |
1175 | LTO_FIXUP_SUBTREE (BINFO_SUBVTT_INDEX (t)); | |
1176 | LTO_FIXUP_SUBTREE (BINFO_VPTR_INDEX (t)); | |
1177 | n = BINFO_N_BASE_BINFOS (t); | |
1178 | for (i = 0; i < n; i++) | |
1179 | { | |
1180 | saved_base = base = BINFO_BASE_BINFO (t, i); | |
1181 | LTO_FIXUP_SUBTREE (base); | |
1182 | if (base != saved_base) | |
1183 | VEC_replace (tree, BINFO_BASE_BINFOS (t), i, base); | |
1184 | } | |
1185 | } | |
1186 | ||
1187 | /* Fix up fields of a CONSTRUCTOR T. DATA points to fix-up states. */ | |
1188 | ||
1189 | static void | |
1190 | lto_fixup_constructor (tree t, void *data) | |
1191 | { | |
1192 | unsigned HOST_WIDE_INT idx; | |
1193 | constructor_elt *ce; | |
1194 | ||
1195 | LTO_REGISTER_TYPE_AND_FIXUP_SUBTREE (TREE_TYPE (t)); | |
1196 | ||
1197 | for (idx = 0; | |
1198 | VEC_iterate(constructor_elt, CONSTRUCTOR_ELTS (t), idx, ce); | |
1199 | idx++) | |
1200 | { | |
1201 | LTO_FIXUP_SUBTREE (ce->index); | |
1202 | LTO_FIXUP_SUBTREE (ce->value); | |
1203 | } | |
1204 | } | |
1205 | ||
1206 | /* A walk_tree callback used by lto_fixup_state. TP is the pointer to the | |
1207 | current tree. WALK_SUBTREES indicates if the subtrees will be walked. | |
1208 | DATA is a pointer set to record visited nodes. */ | |
1209 | ||
1210 | static tree | |
1211 | lto_fixup_tree (tree *tp, int *walk_subtrees, void *data) | |
1212 | { | |
1213 | tree t; | |
1214 | lto_fixup_data_t *fixup_data = (lto_fixup_data_t *) data; | |
1215 | tree prevailing; | |
1216 | ||
1217 | t = *tp; | |
1218 | *walk_subtrees = 0; | |
369451ec | 1219 | if (!t || pointer_set_contains (fixup_data->seen, t)) |
d7f09764 DN |
1220 | return NULL; |
1221 | ||
1222 | if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL) | |
1223 | { | |
1224 | prevailing = lto_symtab_prevailing_decl (t); | |
1225 | ||
1226 | if (t != prevailing) | |
1227 | { | |
d7f09764 DN |
1228 | /* Also replace t with prevailing defintion. We don't want to |
1229 | insert the other defintion in the seen set as we want to | |
1230 | replace all instances of it. */ | |
35f1e9f4 | 1231 | *tp = prevailing; |
d7f09764 DN |
1232 | t = prevailing; |
1233 | } | |
1234 | } | |
1235 | else if (TYPE_P (t)) | |
1236 | { | |
1237 | /* Replace t with the prevailing type. We don't want to insert the | |
1238 | other type in the seen set as we want to replace all instances of it. */ | |
1239 | t = gimple_register_type (t); | |
1240 | *tp = t; | |
1241 | } | |
1242 | ||
1243 | if (pointer_set_insert (fixup_data->seen, t)) | |
1244 | return NULL; | |
1245 | ||
1246 | /* walk_tree does not visit all reachable nodes that need to be fixed up. | |
1247 | Hence we do special processing here for those kind of nodes. */ | |
1248 | switch (TREE_CODE (t)) | |
1249 | { | |
1250 | case FIELD_DECL: | |
1251 | lto_fixup_field_decl (t, data); | |
1252 | break; | |
1253 | ||
1254 | case LABEL_DECL: | |
1255 | case CONST_DECL: | |
1256 | case PARM_DECL: | |
1257 | case RESULT_DECL: | |
1258 | case IMPORTED_DECL: | |
1259 | lto_fixup_decl_common (t, data); | |
1260 | break; | |
1261 | ||
1262 | case VAR_DECL: | |
1263 | lto_fixup_decl_with_vis (t, data); | |
1264 | break; | |
1265 | ||
1266 | case TYPE_DECL: | |
1267 | lto_fixup_decl_non_common (t, data); | |
1268 | break; | |
1269 | ||
1270 | case FUNCTION_DECL: | |
1271 | lto_fixup_function (t, data); | |
1272 | break; | |
1273 | ||
1274 | case TREE_BINFO: | |
1275 | lto_fixup_binfo (t, data); | |
1276 | break; | |
1277 | ||
1278 | default: | |
1279 | if (TYPE_P (t)) | |
1280 | lto_fixup_type (t, data); | |
1281 | else if (TREE_CODE (t) == CONSTRUCTOR) | |
1282 | lto_fixup_constructor (t, data); | |
1283 | else if (CONSTANT_CLASS_P (t)) | |
1284 | LTO_REGISTER_TYPE_AND_FIXUP_SUBTREE (TREE_TYPE (t)); | |
1285 | else if (EXPR_P (t)) | |
1286 | { | |
1287 | /* walk_tree only handles TREE_OPERANDs. Do the rest here. */ | |
1288 | lto_fixup_common (t, data); | |
1289 | LTO_FIXUP_SUBTREE (t->exp.block); | |
1290 | *walk_subtrees = 1; | |
1291 | } | |
1292 | else | |
1293 | { | |
1294 | /* Let walk_tree handle sub-trees. */ | |
1295 | *walk_subtrees = 1; | |
1296 | } | |
1297 | } | |
1298 | ||
1299 | return NULL; | |
1300 | } | |
1301 | ||
1302 | /* Helper function of lto_fixup_decls. Walks the var and fn streams in STATE, | |
1303 | replaces var and function decls with the corresponding prevailing def and | |
1304 | records the old decl in the free-list in DATA. We also record visted nodes | |
1305 | in the seen-set in DATA to avoid multiple visit for nodes that need not | |
1306 | to be replaced. */ | |
1307 | ||
1308 | static void | |
1309 | lto_fixup_state (struct lto_in_decl_state *state, lto_fixup_data_t *data) | |
1310 | { | |
1311 | unsigned i, si; | |
1312 | struct lto_tree_ref_table *table; | |
1313 | ||
1314 | /* Although we only want to replace FUNCTION_DECLs and VAR_DECLs, | |
1315 | we still need to walk from all DECLs to find the reachable | |
1316 | FUNCTION_DECLs and VAR_DECLs. */ | |
1317 | for (si = 0; si < LTO_N_DECL_STREAMS; si++) | |
1318 | { | |
1319 | table = &state->streams[si]; | |
1320 | for (i = 0; i < table->size; i++) | |
1321 | walk_tree (table->trees + i, lto_fixup_tree, data, NULL); | |
1322 | } | |
1323 | } | |
1324 | ||
1325 | /* A callback of htab_traverse. Just extract a state from SLOT and the | |
1326 | lto_fixup_data_t object from AUX and calls lto_fixup_state. */ | |
1327 | ||
1328 | static int | |
1329 | lto_fixup_state_aux (void **slot, void *aux) | |
1330 | { | |
1331 | struct lto_in_decl_state *state = (struct lto_in_decl_state *) *slot; | |
1332 | lto_fixup_state (state, (lto_fixup_data_t *) aux); | |
1333 | return 1; | |
1334 | } | |
1335 | ||
d7f09764 DN |
1336 | /* Fix the decls from all FILES. Replaces each decl with the corresponding |
1337 | prevailing one. */ | |
1338 | ||
1339 | static void | |
1340 | lto_fixup_decls (struct lto_file_decl_data **files) | |
1341 | { | |
1342 | unsigned int i; | |
1343 | tree decl; | |
d7f09764 DN |
1344 | struct pointer_set_t *seen = pointer_set_create (); |
1345 | lto_fixup_data_t data; | |
1346 | ||
d7f09764 DN |
1347 | data.seen = seen; |
1348 | for (i = 0; files[i]; i++) | |
1349 | { | |
1350 | struct lto_file_decl_data *file = files[i]; | |
1351 | struct lto_in_decl_state *state = file->global_decl_state; | |
1352 | lto_fixup_state (state, &data); | |
1353 | ||
1354 | htab_traverse (file->function_decl_states, lto_fixup_state_aux, &data); | |
1355 | } | |
1356 | ||
1357 | for (i = 0; VEC_iterate (tree, lto_global_var_decls, i, decl); i++) | |
1358 | { | |
1359 | tree saved_decl = decl; | |
1360 | walk_tree (&decl, lto_fixup_tree, &data, NULL); | |
1361 | if (decl != saved_decl) | |
1362 | VEC_replace (tree, lto_global_var_decls, i, decl); | |
1363 | } | |
1364 | ||
d7f09764 DN |
1365 | pointer_set_destroy (seen); |
1366 | } | |
1367 | ||
d7f09764 DN |
1368 | /* Read the options saved from each file in the command line. Called |
1369 | from lang_hooks.post_options which is called by process_options | |
1370 | right before all the options are used to initialize the compiler. | |
1371 | This assumes that decode_options has already run, so the | |
1372 | num_in_fnames and in_fnames are properly set. | |
1373 | ||
1374 | Note that this assumes that all the files had been compiled with | |
1375 | the same options, which is not a good assumption. In general, | |
1376 | options ought to be read from all the files in the set and merged. | |
1377 | However, it is still unclear what the merge rules should be. */ | |
1378 | ||
1379 | void | |
1380 | lto_read_all_file_options (void) | |
1381 | { | |
1382 | size_t i; | |
1383 | ||
1384 | /* Clear any file options currently saved. */ | |
1385 | lto_clear_file_options (); | |
1386 | ||
1387 | /* Set the hooks to read ELF sections. */ | |
1388 | lto_set_in_hooks (NULL, get_section_data, free_section_data); | |
9eec9488 JH |
1389 | if (!quiet_flag) |
1390 | fprintf (stderr, "Reading command line options:"); | |
d7f09764 DN |
1391 | |
1392 | for (i = 0; i < num_in_fnames; i++) | |
1393 | { | |
1394 | struct lto_file_decl_data *file_data; | |
2cee0101 | 1395 | lto_file *file = lto_obj_file_open (in_fnames[i], false); |
d7f09764 DN |
1396 | if (!file) |
1397 | break; | |
9eec9488 JH |
1398 | if (!quiet_flag) |
1399 | { | |
1400 | fprintf (stderr, " %s", in_fnames[i]); | |
1401 | fflush (stderr); | |
1402 | } | |
d7f09764 DN |
1403 | |
1404 | file_data = XCNEW (struct lto_file_decl_data); | |
1405 | file_data->file_name = file->filename; | |
2cee0101 | 1406 | file_data->section_hash_table = lto_obj_build_section_table (file); |
d7f09764 DN |
1407 | |
1408 | lto_read_file_options (file_data); | |
1409 | ||
2cee0101 | 1410 | lto_obj_file_close (file); |
d7f09764 | 1411 | htab_delete (file_data->section_hash_table); |
d7f09764 DN |
1412 | free (file_data); |
1413 | } | |
1414 | ||
1415 | /* Apply globally the options read from all the files. */ | |
1416 | lto_reissue_options (); | |
1417 | } | |
1418 | ||
49ba8180 | 1419 | static GTY((length ("lto_stats.num_input_files + 1"))) struct lto_file_decl_data **all_file_decl_data; |
d7f09764 DN |
1420 | |
1421 | /* Read all the symbols from the input files FNAMES. NFILES is the | |
1422 | number of files requested in the command line. Instantiate a | |
1423 | global call graph by aggregating all the sub-graphs found in each | |
1424 | file. */ | |
1425 | ||
1426 | static void | |
1427 | read_cgraph_and_symbols (unsigned nfiles, const char **fnames) | |
1428 | { | |
1429 | unsigned int i, last_file_ix; | |
d7f09764 | 1430 | FILE *resolution; |
1a735925 | 1431 | struct cgraph_node *node; |
d7f09764 DN |
1432 | |
1433 | lto_stats.num_input_files = nfiles; | |
1434 | ||
1435 | timevar_push (TV_IPA_LTO_DECL_IO); | |
1436 | ||
1437 | /* Set the hooks so that all of the ipa passes can read in their data. */ | |
a9429e29 LB |
1438 | all_file_decl_data |
1439 | = ggc_alloc_cleared_vec_lto_file_decl_data_ptr (nfiles + 1); | |
d7f09764 DN |
1440 | lto_set_in_hooks (all_file_decl_data, get_section_data, free_section_data); |
1441 | ||
1442 | /* Read the resolution file. */ | |
1443 | resolution = NULL; | |
1444 | if (resolution_file_name) | |
1445 | { | |
1446 | int t; | |
1447 | unsigned num_objects; | |
1448 | ||
1449 | resolution = fopen (resolution_file_name, "r"); | |
b1b07c92 | 1450 | if (resolution == NULL) |
7ca92787 | 1451 | fatal_error ("could not open symbol resolution file: %m"); |
b1b07c92 | 1452 | |
d7f09764 DN |
1453 | t = fscanf (resolution, "%u", &num_objects); |
1454 | gcc_assert (t == 1); | |
1455 | ||
1456 | /* True, since the plugin splits the archives. */ | |
1457 | gcc_assert (num_objects == nfiles); | |
1458 | } | |
1459 | ||
e792884f JH |
1460 | if (!quiet_flag) |
1461 | fprintf (stderr, "Reading object files:"); | |
1462 | ||
d7f09764 DN |
1463 | /* Read all of the object files specified on the command line. */ |
1464 | for (i = 0, last_file_ix = 0; i < nfiles; ++i) | |
1465 | { | |
1466 | struct lto_file_decl_data *file_data = NULL; | |
e792884f JH |
1467 | if (!quiet_flag) |
1468 | { | |
1469 | fprintf (stderr, " %s", fnames[i]); | |
1470 | fflush (stderr); | |
1471 | } | |
d7f09764 | 1472 | |
2cee0101 | 1473 | current_lto_file = lto_obj_file_open (fnames[i], false); |
d7f09764 DN |
1474 | if (!current_lto_file) |
1475 | break; | |
1476 | ||
1477 | file_data = lto_file_read (current_lto_file, resolution); | |
1478 | if (!file_data) | |
1479 | break; | |
1480 | ||
1481 | all_file_decl_data[last_file_ix++] = file_data; | |
1482 | ||
2cee0101 | 1483 | lto_obj_file_close (current_lto_file); |
d7f09764 | 1484 | current_lto_file = NULL; |
bd9eb5da RG |
1485 | /* ??? We'd want but can't ggc_collect () here as the type merging |
1486 | code in gimple.c uses hashtables that are not ggc aware. */ | |
d7f09764 DN |
1487 | } |
1488 | ||
1489 | if (resolution_file_name) | |
1490 | fclose (resolution); | |
1491 | ||
1492 | all_file_decl_data[last_file_ix] = NULL; | |
1493 | ||
1494 | /* Set the hooks so that all of the ipa passes can read in their data. */ | |
1495 | lto_set_in_hooks (all_file_decl_data, get_section_data, free_section_data); | |
1496 | ||
d7f09764 DN |
1497 | timevar_pop (TV_IPA_LTO_DECL_IO); |
1498 | ||
e792884f JH |
1499 | if (!quiet_flag) |
1500 | fprintf (stderr, "\nReading the callgraph\n"); | |
1501 | ||
49ba8180 | 1502 | timevar_push (TV_IPA_LTO_CGRAPH_IO); |
d7f09764 DN |
1503 | /* Read the callgraph. */ |
1504 | input_cgraph (); | |
49ba8180 | 1505 | timevar_pop (TV_IPA_LTO_CGRAPH_IO); |
d7f09764 | 1506 | |
e792884f JH |
1507 | if (!quiet_flag) |
1508 | fprintf (stderr, "Merging declarations\n"); | |
1509 | ||
49ba8180 | 1510 | timevar_push (TV_IPA_LTO_DECL_MERGE); |
2c928155 RG |
1511 | /* Merge global decls. */ |
1512 | lto_symtab_merge_decls (); | |
1513 | ||
1514 | /* Fixup all decls and types and free the type hash tables. */ | |
1515 | lto_fixup_decls (all_file_decl_data); | |
1516 | free_gimple_type_tables (); | |
49ba8180 JH |
1517 | ggc_collect (); |
1518 | ||
1519 | timevar_pop (TV_IPA_LTO_DECL_MERGE); | |
1520 | /* Each pass will set the appropriate timer. */ | |
2c928155 | 1521 | |
e792884f JH |
1522 | if (!quiet_flag) |
1523 | fprintf (stderr, "Reading summaries\n"); | |
1524 | ||
1a735925 | 1525 | /* Read the IPA summary data. */ |
e792884f JH |
1526 | if (flag_ltrans) |
1527 | ipa_read_optimization_summaries (); | |
1528 | else | |
1529 | ipa_read_summaries (); | |
d7f09764 | 1530 | |
2c928155 | 1531 | /* Finally merge the cgraph according to the decl merging decisions. */ |
49ba8180 | 1532 | timevar_push (TV_IPA_LTO_CGRAPH_MERGE); |
2c928155 | 1533 | lto_symtab_merge_cgraph_nodes (); |
49ba8180 | 1534 | ggc_collect (); |
d7f09764 | 1535 | |
b20996ff JH |
1536 | if (flag_ltrans) |
1537 | for (node = cgraph_nodes; node; node = node->next) | |
0e3776db | 1538 | { |
0e3776db JH |
1539 | /* FIXME: ipa_transforms_to_apply holds list of passes that have optimization |
1540 | summaries computed and needs to apply changes. At the moment WHOPR only | |
1541 | supports inlining, so we can push it here by hand. In future we need to stream | |
1542 | this field into ltrans compilation. */ | |
1543 | if (node->analyzed) | |
1544 | VEC_safe_push (ipa_opt_pass, heap, | |
1545 | node->ipa_transforms_to_apply, | |
1546 | (ipa_opt_pass)&pass_ipa_inline); | |
1547 | } | |
9a809897 JH |
1548 | lto_symtab_free (); |
1549 | ||
49ba8180 | 1550 | timevar_pop (TV_IPA_LTO_CGRAPH_MERGE); |
d7f09764 | 1551 | |
49ba8180 | 1552 | timevar_push (TV_IPA_LTO_DECL_INIT_IO); |
d7f09764 | 1553 | |
d7f09764 DN |
1554 | /* FIXME lto. This loop needs to be changed to use the pass manager to |
1555 | call the ipa passes directly. */ | |
1da2ed5f | 1556 | if (!seen_error ()) |
d7f09764 DN |
1557 | for (i = 0; i < last_file_ix; i++) |
1558 | { | |
1559 | struct lto_file_decl_data *file_data = all_file_decl_data [i]; | |
1560 | lto_materialize_constructors_and_inits (file_data); | |
1561 | } | |
1562 | ||
1563 | /* Indicate that the cgraph is built and ready. */ | |
1564 | cgraph_function_flags_ready = true; | |
1565 | ||
49ba8180 JH |
1566 | timevar_pop (TV_IPA_LTO_DECL_INIT_IO); |
1567 | ggc_free (all_file_decl_data); | |
1568 | all_file_decl_data = NULL; | |
d7f09764 DN |
1569 | } |
1570 | ||
1571 | ||
1572 | /* Materialize all the bodies for all the nodes in the callgraph. */ | |
1573 | ||
1574 | static void | |
1575 | materialize_cgraph (void) | |
1576 | { | |
1577 | tree decl; | |
1578 | struct cgraph_node *node; | |
1579 | unsigned i; | |
1580 | timevar_id_t lto_timer; | |
1581 | ||
e792884f JH |
1582 | if (!quiet_flag) |
1583 | fprintf (stderr, | |
1584 | flag_wpa ? "Materializing decls:" : "Reading function bodies:"); | |
1585 | ||
1586 | ||
d7f09764 DN |
1587 | /* Now that we have input the cgraph, we need to clear all of the aux |
1588 | nodes and read the functions if we are not running in WPA mode. */ | |
1589 | timevar_push (TV_IPA_LTO_GIMPLE_IO); | |
1590 | ||
1591 | for (node = cgraph_nodes; node; node = node->next) | |
1592 | { | |
1593 | /* Some cgraph nodes get created on the fly, and they don't need | |
1594 | to be materialized. For instance, nodes for nested functions | |
1595 | where the parent function was not streamed out or builtin | |
1596 | functions. Additionally, builtin functions should not be | |
1597 | materialized and may, in fact, cause confusion because there | |
1598 | may be a regular function in the file whose assembler name | |
1599 | matches that of the function. | |
1600 | See gcc.c-torture/execute/20030125-1.c and | |
1601 | gcc.c-torture/execute/921215-1.c. */ | |
1602 | if (node->local.lto_file_data | |
1603 | && !DECL_IS_BUILTIN (node->decl)) | |
1604 | { | |
1605 | lto_materialize_function (node); | |
1606 | lto_stats.num_input_cgraph_nodes++; | |
1607 | } | |
1608 | } | |
1609 | ||
1610 | timevar_pop (TV_IPA_LTO_GIMPLE_IO); | |
1611 | ||
1612 | /* Start the appropriate timer depending on the mode that we are | |
1613 | operating in. */ | |
1614 | lto_timer = (flag_wpa) ? TV_WHOPR_WPA | |
1615 | : (flag_ltrans) ? TV_WHOPR_LTRANS | |
1616 | : TV_LTO; | |
1617 | timevar_push (lto_timer); | |
1618 | ||
1619 | current_function_decl = NULL; | |
1620 | set_cfun (NULL); | |
1621 | ||
1622 | /* Inform the middle end about the global variables we have seen. */ | |
1623 | for (i = 0; VEC_iterate (tree, lto_global_var_decls, i, decl); i++) | |
1624 | rest_of_decl_compilation (decl, 1, 0); | |
1625 | ||
e792884f JH |
1626 | if (!quiet_flag) |
1627 | fprintf (stderr, "\n"); | |
d7f09764 DN |
1628 | |
1629 | timevar_pop (lto_timer); | |
1630 | } | |
1631 | ||
1632 | ||
1633 | /* Perform whole program analysis (WPA) on the callgraph and write out the | |
1634 | optimization plan. */ | |
1635 | ||
1636 | static void | |
1637 | do_whole_program_analysis (void) | |
1638 | { | |
d7f09764 DN |
1639 | /* Note that since we are in WPA mode, materialize_cgraph will not |
1640 | actually read in all the function bodies. It only materializes | |
1641 | the decls and cgraph nodes so that analysis can be performed. */ | |
1642 | materialize_cgraph (); | |
1643 | ||
1644 | /* Reading in the cgraph uses different timers, start timing WPA now. */ | |
1645 | timevar_push (TV_WHOPR_WPA); | |
1646 | ||
49ba8180 JH |
1647 | if (pre_ipa_mem_report) |
1648 | { | |
1649 | fprintf (stderr, "Memory consumption before IPA\n"); | |
1650 | dump_memory_report (false); | |
1651 | } | |
1652 | ||
0a5fa5a1 JH |
1653 | if (cgraph_dump_file) |
1654 | { | |
1655 | dump_cgraph (cgraph_dump_file); | |
1656 | dump_varpool (cgraph_dump_file); | |
1657 | } | |
1658 | ||
d7f09764 DN |
1659 | cgraph_function_flags_ready = true; |
1660 | bitmap_obstack_initialize (NULL); | |
1661 | ipa_register_cgraph_hooks (); | |
3ee2243c | 1662 | cgraph_state = CGRAPH_STATE_IPA_SSA; |
d7f09764 | 1663 | |
3ee2243c | 1664 | execute_ipa_pass_list (all_regular_ipa_passes); |
d7f09764 | 1665 | |
0a5fa5a1 JH |
1666 | if (cgraph_dump_file) |
1667 | { | |
1668 | fprintf (cgraph_dump_file, "Optimized "); | |
1669 | dump_cgraph (cgraph_dump_file); | |
1670 | dump_varpool (cgraph_dump_file); | |
1671 | } | |
d7f09764 DN |
1672 | verify_cgraph (); |
1673 | bitmap_obstack_release (NULL); | |
1674 | ||
1675 | /* We are about to launch the final LTRANS phase, stop the WPA timer. */ | |
1676 | timevar_pop (TV_WHOPR_WPA); | |
1677 | ||
3ee2243c JH |
1678 | lto_1_to_1_map (); |
1679 | ||
e792884f JH |
1680 | if (!quiet_flag) |
1681 | { | |
1682 | fprintf (stderr, "\nStreaming out"); | |
1683 | fflush (stderr); | |
1684 | } | |
b5611987 | 1685 | lto_wpa_write_files (); |
49ba8180 | 1686 | ggc_collect (); |
e792884f JH |
1687 | if (!quiet_flag) |
1688 | fprintf (stderr, "\n"); | |
d7f09764 | 1689 | |
49ba8180 JH |
1690 | if (post_ipa_mem_report) |
1691 | { | |
1692 | fprintf (stderr, "Memory consumption after IPA\n"); | |
1693 | dump_memory_report (false); | |
1694 | } | |
1695 | ||
d7f09764 DN |
1696 | /* Show the LTO report before launching LTRANS. */ |
1697 | if (flag_lto_report) | |
1698 | print_lto_report (); | |
d7f09764 DN |
1699 | } |
1700 | ||
1701 | ||
7951d88a EB |
1702 | static GTY(()) tree lto_eh_personality_decl; |
1703 | ||
1704 | /* Return the LTO personality function decl. */ | |
1705 | ||
1706 | tree | |
1707 | lto_eh_personality (void) | |
1708 | { | |
1709 | if (!lto_eh_personality_decl) | |
1710 | { | |
1711 | /* Use the first personality DECL for our personality if we don't | |
1712 | support multiple ones. This ensures that we don't artificially | |
1713 | create the need for them in a single-language program. */ | |
1714 | if (first_personality_decl && !dwarf2out_do_cfi_asm ()) | |
1715 | lto_eh_personality_decl = first_personality_decl; | |
1716 | else | |
1717 | lto_eh_personality_decl = lhd_gcc_personality (); | |
1718 | } | |
1719 | ||
1720 | return lto_eh_personality_decl; | |
1721 | } | |
1722 | ||
1723 | ||
d7f09764 DN |
1724 | /* Main entry point for the GIMPLE front end. This front end has |
1725 | three main personalities: | |
1726 | ||
1727 | - LTO (-flto). All the object files on the command line are | |
1728 | loaded in memory and processed as a single translation unit. | |
1729 | This is the traditional link-time optimization behavior. | |
1730 | ||
1731 | - WPA (-fwpa). Only the callgraph and summary information for | |
1732 | files in the command file are loaded. A single callgraph | |
1733 | (without function bodies) is instantiated for the whole set of | |
1734 | files. IPA passes are only allowed to analyze the call graph | |
1735 | and make transformation decisions. The callgraph is | |
1736 | partitioned, each partition is written to a new object file | |
1737 | together with the transformation decisions. | |
1738 | ||
1739 | - LTRANS (-fltrans). Similar to -flto but it prevents the IPA | |
1740 | summary files from running again. Since WPA computed summary | |
1741 | information and decided what transformations to apply, LTRANS | |
1742 | simply applies them. */ | |
1743 | ||
1744 | void | |
1745 | lto_main (int debug_p ATTRIBUTE_UNUSED) | |
1746 | { | |
1747 | lto_init_reader (); | |
1748 | ||
1749 | /* Read all the symbols and call graph from all the files in the | |
1750 | command line. */ | |
1751 | read_cgraph_and_symbols (num_in_fnames, in_fnames); | |
1752 | ||
1da2ed5f | 1753 | if (!seen_error ()) |
d7f09764 DN |
1754 | { |
1755 | /* If WPA is enabled analyze the whole call graph and create an | |
1756 | optimization plan. Otherwise, read in all the function | |
1757 | bodies and continue with optimization. */ | |
1758 | if (flag_wpa) | |
1759 | do_whole_program_analysis (); | |
1760 | else | |
1761 | { | |
1762 | materialize_cgraph (); | |
1763 | ||
1764 | /* Let the middle end know that we have read and merged all of | |
1765 | the input files. */ | |
1766 | cgraph_optimize (); | |
1767 | ||
1768 | /* FIXME lto, if the processes spawned by WPA fail, we miss | |
1769 | the chance to print WPA's report, so WPA will call | |
1770 | print_lto_report before launching LTRANS. If LTRANS was | |
1771 | launched directly by the driver we would not need to do | |
1772 | this. */ | |
1773 | if (flag_lto_report) | |
1774 | print_lto_report (); | |
1775 | } | |
1776 | } | |
1777 | } | |
1778 | ||
1779 | #include "gt-lto-lto.h" |