]>
Commit | Line | Data |
---|---|---|
e09108e1 | 1 | /* LTO routines to use object files. |
d353bf18 | 2 | Copyright (C) 2010-2015 Free Software Foundation, Inc. |
e09108e1 | 3 | Written by Ian Lance Taylor, Google. |
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" | |
b20a8bb4 | 24 | #include "alias.h" |
25 | #include "symtab.h" | |
26 | #include "options.h" | |
b20a8bb4 | 27 | #include "tree.h" |
28 | #include "fold-const.h" | |
29 | #include "predict.h" | |
94ea8568 | 30 | #include "tm.h" |
31 | #include "hard-reg-set.h" | |
94ea8568 | 32 | #include "function.h" |
bc61cadb | 33 | #include "basic-block.h" |
34 | #include "tree-ssa-alias.h" | |
35 | #include "internal-fn.h" | |
36 | #include "gimple-expr.h" | |
b23fb4cb | 37 | #include "gimple.h" |
e09108e1 | 38 | #include "diagnostic-core.h" |
e09108e1 | 39 | #include "lto.h" |
1140c305 | 40 | #include "cgraph.h" |
e09108e1 | 41 | #include "lto-streamer.h" |
47131315 | 42 | #include "lto-section-names.h" |
e09108e1 | 43 | #include "simple-object.h" |
44 | ||
e09108e1 | 45 | /* An LTO file wrapped around an simple_object. */ |
46 | ||
47 | struct lto_simple_object | |
48 | { | |
49 | /* The base information. */ | |
50 | lto_file base; | |
51 | ||
52 | /* The system file descriptor. */ | |
53 | int fd; | |
54 | ||
55 | /* The simple_object if we are reading the file. */ | |
56 | simple_object_read *sobj_r; | |
57 | ||
58 | /* The simple_object if we are writing the file. */ | |
59 | simple_object_write *sobj_w; | |
60 | ||
61 | /* The currently active section. */ | |
62 | simple_object_write_section *section; | |
63 | }; | |
64 | ||
65 | /* Saved simple_object attributes. FIXME: Once set, this is never | |
66 | cleared. */ | |
67 | ||
68 | static simple_object_attributes *saved_attributes; | |
69 | ||
70 | /* Initialize FILE, an LTO file object for FILENAME. */ | |
71 | ||
72 | static void | |
73 | lto_file_init (lto_file *file, const char *filename, off_t offset) | |
74 | { | |
75 | file->filename = filename; | |
76 | file->offset = offset; | |
77 | } | |
78 | ||
79 | /* Open the file FILENAME. It WRITABLE is true, the file is opened | |
80 | for write and, if necessary, created. Otherwise, the file is | |
81 | opened for reading. Returns the opened file. */ | |
82 | ||
83 | lto_file * | |
84 | lto_obj_file_open (const char *filename, bool writable) | |
85 | { | |
86 | const char *offset_p; | |
87 | long loffset; | |
88 | int consumed; | |
89 | char *fname; | |
90 | off_t offset; | |
91 | struct lto_simple_object *lo; | |
92 | const char *errmsg; | |
93 | int err; | |
94 | ||
95 | offset_p = strrchr (filename, '@'); | |
96 | if (offset_p != NULL | |
97 | && offset_p != filename | |
98 | && sscanf (offset_p, "@%li%n", &loffset, &consumed) >= 1 | |
99 | && strlen (offset_p) == (unsigned int) consumed) | |
100 | { | |
101 | fname = XNEWVEC (char, offset_p - filename + 1); | |
102 | memcpy (fname, filename, offset_p - filename); | |
103 | fname[offset_p - filename] = '\0'; | |
104 | offset = (off_t) loffset; | |
105 | } | |
106 | else | |
107 | { | |
108 | fname = xstrdup (filename); | |
109 | offset = 0; | |
110 | } | |
111 | ||
112 | lo = XCNEW (struct lto_simple_object); | |
113 | lto_file_init ((lto_file *) lo, fname, offset); | |
114 | ||
115 | lo->fd = open (fname, | |
116 | (writable | |
117 | ? O_WRONLY | O_CREAT | O_BINARY | |
118 | : O_RDONLY | O_BINARY), | |
119 | 0666); | |
120 | if (lo->fd == -1) | |
121 | { | |
122 | error ("open %s failed: %s", fname, xstrerror (errno)); | |
123 | goto fail; | |
124 | } | |
125 | ||
126 | if (!writable) | |
127 | { | |
128 | simple_object_attributes *attrs; | |
129 | ||
130 | lo->sobj_r = simple_object_start_read (lo->fd, offset, LTO_SEGMENT_NAME, | |
131 | &errmsg, &err); | |
132 | if (lo->sobj_r == NULL) | |
133 | goto fail_errmsg; | |
134 | ||
135 | attrs = simple_object_fetch_attributes (lo->sobj_r, &errmsg, &err); | |
136 | if (attrs == NULL) | |
137 | goto fail_errmsg; | |
138 | ||
139 | if (saved_attributes == NULL) | |
140 | saved_attributes = attrs; | |
141 | else | |
142 | { | |
2e521e13 | 143 | errmsg = simple_object_attributes_merge (saved_attributes, attrs, |
144 | &err); | |
e09108e1 | 145 | if (errmsg != NULL) |
883554eb | 146 | { |
147 | free (attrs); | |
148 | goto fail_errmsg; | |
149 | } | |
e09108e1 | 150 | } |
151 | } | |
152 | else | |
153 | { | |
154 | gcc_assert (saved_attributes != NULL); | |
155 | lo->sobj_w = simple_object_start_write (saved_attributes, | |
156 | LTO_SEGMENT_NAME, | |
157 | &errmsg, &err); | |
158 | if (lo->sobj_w == NULL) | |
159 | goto fail_errmsg; | |
160 | } | |
161 | ||
162 | return &lo->base; | |
163 | ||
164 | fail_errmsg: | |
165 | if (err == 0) | |
166 | error ("%s: %s", fname, errmsg); | |
167 | else | |
168 | error ("%s: %s: %s", fname, errmsg, xstrerror (err)); | |
169 | ||
170 | fail: | |
883554eb | 171 | if (lo->fd != -1) |
e09108e1 | 172 | lto_obj_file_close ((lto_file *) lo); |
883554eb | 173 | free (lo); |
e09108e1 | 174 | return NULL; |
175 | } | |
176 | ||
883554eb | 177 | |
e09108e1 | 178 | /* Close FILE. If FILE was opened for writing, it is written out |
179 | now. */ | |
180 | ||
181 | void | |
182 | lto_obj_file_close (lto_file *file) | |
183 | { | |
184 | struct lto_simple_object *lo = (struct lto_simple_object *) file; | |
185 | ||
186 | if (lo->sobj_r != NULL) | |
187 | simple_object_release_read (lo->sobj_r); | |
188 | else if (lo->sobj_w != NULL) | |
189 | { | |
190 | const char *errmsg; | |
191 | int err; | |
192 | ||
193 | gcc_assert (lo->base.offset == 0); | |
194 | ||
195 | errmsg = simple_object_write_to_file (lo->sobj_w, lo->fd, &err); | |
196 | if (errmsg != NULL) | |
197 | { | |
198 | if (err == 0) | |
c05be867 | 199 | fatal_error (input_location, "%s", errmsg); |
e09108e1 | 200 | else |
c05be867 | 201 | fatal_error (input_location, "%s: %s", errmsg, xstrerror (err)); |
e09108e1 | 202 | } |
203 | ||
204 | simple_object_release_write (lo->sobj_w); | |
205 | } | |
206 | ||
207 | if (lo->fd != -1) | |
208 | { | |
209 | if (close (lo->fd) < 0) | |
c05be867 | 210 | fatal_error (input_location, "close: %s", xstrerror (errno)); |
e09108e1 | 211 | } |
212 | } | |
213 | ||
214 | /* This is passed to lto_obj_add_section. */ | |
215 | ||
216 | struct lto_obj_add_section_data | |
217 | { | |
218 | /* The hash table of sections. */ | |
219 | htab_t section_hash_table; | |
220 | /* The offset of this file. */ | |
221 | off_t base_offset; | |
805389b2 | 222 | /* List in linker order */ |
223 | struct lto_section_list *list; | |
e09108e1 | 224 | }; |
225 | ||
226 | /* This is called for each section in the file. */ | |
227 | ||
228 | static int | |
229 | lto_obj_add_section (void *data, const char *name, off_t offset, | |
230 | off_t length) | |
231 | { | |
232 | struct lto_obj_add_section_data *loasd = | |
233 | (struct lto_obj_add_section_data *) data; | |
234 | htab_t section_hash_table = (htab_t) loasd->section_hash_table; | |
235 | char *new_name; | |
236 | struct lto_section_slot s_slot; | |
237 | void **slot; | |
805389b2 | 238 | struct lto_section_list *list = loasd->list; |
e09108e1 | 239 | |
b0c5e347 | 240 | if (strncmp (name, section_name_prefix, strlen (section_name_prefix))) |
e09108e1 | 241 | return 1; |
242 | ||
243 | new_name = xstrdup (name); | |
244 | s_slot.name = new_name; | |
245 | slot = htab_find_slot (section_hash_table, &s_slot, INSERT); | |
246 | if (*slot == NULL) | |
247 | { | |
805389b2 | 248 | struct lto_section_slot *new_slot = XCNEW (struct lto_section_slot); |
e09108e1 | 249 | |
250 | new_slot->name = new_name; | |
251 | new_slot->start = loasd->base_offset + offset; | |
252 | new_slot->len = length; | |
253 | *slot = new_slot; | |
805389b2 | 254 | |
255 | if (list != NULL) | |
256 | { | |
257 | if (!list->first) | |
258 | list->first = new_slot; | |
259 | if (list->last) | |
260 | list->last->next = new_slot; | |
261 | list->last = new_slot; | |
262 | } | |
e09108e1 | 263 | } |
264 | else | |
265 | { | |
266 | error ("two or more sections for %s", new_name); | |
267 | return 0; | |
268 | } | |
269 | ||
270 | return 1; | |
271 | } | |
272 | ||
273 | /* Build a hash table whose key is the section name and whose data is | |
274 | the start and size of each section in the .o file. */ | |
275 | ||
276 | htab_t | |
805389b2 | 277 | lto_obj_build_section_table (lto_file *lto_file, struct lto_section_list *list) |
e09108e1 | 278 | { |
279 | struct lto_simple_object *lo = (struct lto_simple_object *) lto_file; | |
280 | htab_t section_hash_table; | |
281 | struct lto_obj_add_section_data loasd; | |
282 | const char *errmsg; | |
283 | int err; | |
284 | ||
285 | section_hash_table = lto_obj_create_section_hash_table (); | |
286 | ||
287 | gcc_assert (lo->sobj_r != NULL && lo->sobj_w == NULL); | |
288 | loasd.section_hash_table = section_hash_table; | |
289 | loasd.base_offset = lo->base.offset; | |
805389b2 | 290 | loasd.list = list; |
e09108e1 | 291 | errmsg = simple_object_find_sections (lo->sobj_r, lto_obj_add_section, |
292 | &loasd, &err); | |
293 | if (errmsg != NULL) | |
294 | { | |
295 | if (err == 0) | |
296 | error ("%s", errmsg); | |
297 | else | |
298 | error ("%s: %s", errmsg, xstrerror (err)); | |
299 | htab_delete (section_hash_table); | |
300 | return NULL; | |
301 | } | |
302 | ||
303 | return section_hash_table; | |
304 | } | |
305 | ||
306 | /* The current output file. */ | |
307 | ||
308 | static lto_file *current_out_file; | |
309 | ||
310 | /* Set the current output file. Return the old one. */ | |
311 | ||
312 | lto_file * | |
313 | lto_set_current_out_file (lto_file *file) | |
314 | { | |
315 | lto_file *old_file; | |
316 | ||
317 | old_file = current_out_file; | |
318 | current_out_file = file; | |
319 | return old_file; | |
320 | } | |
321 | ||
322 | /* Return the current output file. */ | |
323 | ||
324 | lto_file * | |
325 | lto_get_current_out_file (void) | |
326 | { | |
327 | return current_out_file; | |
328 | } | |
329 | ||
330 | /* Begin writing a new section named NAME in the current output | |
331 | file. */ | |
332 | ||
333 | void | |
334 | lto_obj_begin_section (const char *name) | |
335 | { | |
336 | struct lto_simple_object *lo; | |
337 | int align; | |
338 | const char *errmsg; | |
339 | int err; | |
340 | ||
341 | lo = (struct lto_simple_object *) current_out_file; | |
342 | gcc_assert (lo != NULL | |
343 | && lo->sobj_r == NULL | |
344 | && lo->sobj_w != NULL | |
345 | && lo->section == NULL); | |
346 | ||
c219a638 | 347 | align = ceil_log2 (POINTER_SIZE_UNITS); |
e09108e1 | 348 | lo->section = simple_object_write_create_section (lo->sobj_w, name, align, |
349 | &errmsg, &err); | |
350 | if (lo->section == NULL) | |
351 | { | |
352 | if (err == 0) | |
c05be867 | 353 | fatal_error (input_location, "%s", errmsg); |
e09108e1 | 354 | else |
c05be867 | 355 | fatal_error (input_location, "%s: %s", errmsg, xstrerror (errno)); |
e09108e1 | 356 | } |
357 | } | |
358 | ||
359 | /* Add data to a section. BLOCK is a pointer to memory containing | |
360 | DATA. */ | |
361 | ||
362 | void | |
2d97af95 | 363 | lto_obj_append_data (const void *data, size_t len, void *) |
e09108e1 | 364 | { |
365 | struct lto_simple_object *lo; | |
366 | const char *errmsg; | |
367 | int err; | |
368 | ||
369 | lo = (struct lto_simple_object *) current_out_file; | |
370 | gcc_assert (lo != NULL && lo->section != NULL); | |
371 | ||
372 | errmsg = simple_object_write_add_data (lo->sobj_w, lo->section, data, len, | |
373 | 1, &err); | |
374 | if (errmsg != NULL) | |
375 | { | |
376 | if (err == 0) | |
c05be867 | 377 | fatal_error (input_location, "%s", errmsg); |
e09108e1 | 378 | else |
c05be867 | 379 | fatal_error (input_location, "%s: %s", errmsg, xstrerror (errno)); |
e09108e1 | 380 | } |
e09108e1 | 381 | } |
382 | ||
383 | /* Stop writing to the current output section. */ | |
384 | ||
385 | void | |
386 | lto_obj_end_section (void) | |
387 | { | |
388 | struct lto_simple_object *lo; | |
389 | ||
390 | lo = (struct lto_simple_object *) current_out_file; | |
391 | gcc_assert (lo != NULL && lo->section != NULL); | |
392 | lo->section = NULL; | |
393 | } |