1 | /* Language-dependent hooks for LTO. |
2 | Copyright (C) 2009-2024 Free Software Foundation, Inc. |
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 "target.h" |
25 | #include "function.h" |
26 | #include "basic-block.h" |
27 | #include "tree.h" |
28 | #include "gimple.h" |
29 | #include "stringpool.h" |
30 | #include "diagnostic-core.h" |
31 | #include "stor-layout.h" |
32 | #include "langhooks.h" |
33 | #include "langhooks-def.h" |
34 | #include "debug.h" |
35 | #include "lto-tree.h" |
36 | #include "lto.h" |
37 | #include "lto-common.h" |
38 | #include "stringpool.h" |
39 | #include "attribs.h" |
40 | |
41 | /* LTO specific dumps. */ |
42 | int lto_link_dump_id, decl_merge_dump_id, partition_dump_id; |
43 | |
44 | static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *); |
45 | static tree handle_leaf_attribute (tree *, tree, tree, int, bool *); |
46 | static tree handle_const_attribute (tree *, tree, tree, int, bool *); |
47 | static tree handle_malloc_attribute (tree *, tree, tree, int, bool *); |
48 | static tree handle_pure_attribute (tree *, tree, tree, int, bool *); |
49 | static tree handle_novops_attribute (tree *, tree, tree, int, bool *); |
50 | static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *); |
51 | static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *); |
52 | static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *); |
53 | static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *); |
54 | static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *); |
55 | static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *); |
56 | static tree handle_patchable_function_entry_attribute (tree *, tree, tree, |
57 | int, bool *); |
58 | static tree ignore_attribute (tree *, tree, tree, int, bool *); |
59 | |
60 | static tree handle_format_attribute (tree *, tree, tree, int, bool *); |
61 | static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *); |
62 | static tree handle_format_arg_attribute (tree *, tree, tree, int, bool *); |
63 | |
64 | /* Helper to define attribute exclusions. */ |
65 | #define ATTR_EXCL(name, function, type, variable) \ |
66 | { name, function, type, variable } |
67 | |
68 | /* Define attributes that are mutually exclusive with one another. */ |
69 | static const struct attribute_spec::exclusions attr_noreturn_exclusions[] = |
70 | { |
71 | ATTR_EXCL ("noreturn" , true, true, true), |
72 | ATTR_EXCL ("alloc_align" , true, true, true), |
73 | ATTR_EXCL ("alloc_size" , true, true, true), |
74 | ATTR_EXCL ("const" , true, true, true), |
75 | ATTR_EXCL ("malloc" , true, true, true), |
76 | ATTR_EXCL ("pure" , true, true, true), |
77 | ATTR_EXCL ("returns_twice" , true, true, true), |
78 | ATTR_EXCL ("warn_unused_result" , true, true, true), |
79 | ATTR_EXCL (NULL, false, false, false), |
80 | }; |
81 | |
82 | static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] = |
83 | { |
84 | ATTR_EXCL ("noreturn" , true, true, true), |
85 | ATTR_EXCL (NULL, false, false, false), |
86 | }; |
87 | |
88 | static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = |
89 | { |
90 | ATTR_EXCL ("const" , true, true, true), |
91 | ATTR_EXCL ("noreturn" , true, true, true), |
92 | ATTR_EXCL ("pure" , true, true, true), |
93 | ATTR_EXCL (NULL, false, false, false) |
94 | }; |
95 | |
96 | /* Table of machine-independent attributes supported in GIMPLE. */ |
97 | static const attribute_spec lto_gnu_attributes[] = |
98 | { |
99 | /* { name, min_len, max_len, decl_req, type_req, fn_type_req, |
100 | affects_type_identity, handler, exclude } */ |
101 | { .name: "noreturn" , .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
102 | .handler: handle_noreturn_attribute, |
103 | .exclude: attr_noreturn_exclusions }, |
104 | { .name: "leaf" , .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
105 | .handler: handle_leaf_attribute, NULL }, |
106 | /* The same comments as for noreturn attributes apply to const ones. */ |
107 | { .name: "const" , .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
108 | .handler: handle_const_attribute, |
109 | .exclude: attr_const_pure_exclusions }, |
110 | { .name: "malloc" , .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
111 | .handler: handle_malloc_attribute, NULL }, |
112 | { .name: "pure" , .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
113 | .handler: handle_pure_attribute, |
114 | .exclude: attr_const_pure_exclusions }, |
115 | { .name: "no vops" , .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
116 | .handler: handle_novops_attribute, NULL }, |
117 | { .name: "nonnull" , .min_length: 0, .max_length: -1, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false, |
118 | .handler: handle_nonnull_attribute, NULL }, |
119 | { .name: "nothrow" , .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
120 | .handler: handle_nothrow_attribute, NULL }, |
121 | { .name: "patchable_function_entry" , .min_length: 1, .max_length: 2, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
122 | .handler: handle_patchable_function_entry_attribute, |
123 | NULL }, |
124 | { .name: "returns_twice" , .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
125 | .handler: handle_returns_twice_attribute, |
126 | .exclude: attr_returns_twice_exclusions }, |
127 | { .name: "sentinel" , .min_length: 0, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false, |
128 | .handler: handle_sentinel_attribute, NULL }, |
129 | { .name: "type generic" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false, |
130 | .handler: handle_type_generic_attribute, NULL }, |
131 | { .name: "fn spec" , .min_length: 1, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false, |
132 | .handler: handle_fnspec_attribute, NULL }, |
133 | { .name: "transaction_pure" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false, |
134 | .handler: handle_transaction_pure_attribute, NULL }, |
135 | /* For internal use only. The leading '*' both prevents its usage in |
136 | source code and signals that it may be overridden by machine tables. */ |
137 | { .name: "*tm regparm" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false, |
138 | .handler: ignore_attribute, NULL } |
139 | }; |
140 | |
141 | static const scoped_attribute_specs lto_gnu_attribute_table = |
142 | { |
143 | .ns: "gnu" , .attributes: { lto_gnu_attributes } |
144 | }; |
145 | |
146 | /* Give the specifications for the format attributes, used by C and all |
147 | descendants. */ |
148 | |
149 | static const attribute_spec lto_format_attributes[] = |
150 | { |
151 | /* { name, min_len, max_len, decl_req, type_req, fn_type_req, |
152 | affects_type_identity, handler, exclude } */ |
153 | { .name: "format" , .min_length: 3, .max_length: 3, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false, |
154 | .handler: handle_format_attribute, NULL }, |
155 | { .name: "format_arg" , .min_length: 1, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false, |
156 | .handler: handle_format_arg_attribute, NULL }, |
157 | }; |
158 | |
159 | static const scoped_attribute_specs lto_format_attribute_table = |
160 | { |
161 | .ns: "gnu" , .attributes: { lto_format_attributes } |
162 | }; |
163 | |
164 | static const scoped_attribute_specs *const lto_attribute_table[] = |
165 | { |
166 | <o_gnu_attribute_table, |
167 | <o_format_attribute_table |
168 | }; |
169 | |
170 | enum built_in_attribute |
171 | { |
172 | #define DEF_ATTR_NULL_TREE(ENUM) ENUM, |
173 | #define DEF_ATTR_INT(ENUM, VALUE) ENUM, |
174 | #define DEF_ATTR_STRING(ENUM, VALUE) ENUM, |
175 | #define DEF_ATTR_IDENT(ENUM, STRING) ENUM, |
176 | #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM, |
177 | #include "builtin-attrs.def" |
178 | #undef DEF_ATTR_NULL_TREE |
179 | #undef DEF_ATTR_INT |
180 | #undef DEF_ATTR_STRING |
181 | #undef DEF_ATTR_IDENT |
182 | #undef DEF_ATTR_TREE_LIST |
183 | ATTR_LAST |
184 | }; |
185 | |
186 | static GTY(()) tree built_in_attributes[(int) ATTR_LAST]; |
187 | |
188 | /* Builtin types. */ |
189 | |
190 | enum lto_builtin_type |
191 | { |
192 | #define DEF_PRIMITIVE_TYPE(NAME, VALUE) NAME, |
193 | #define DEF_FUNCTION_TYPE_0(NAME, RETURN) NAME, |
194 | #define DEF_FUNCTION_TYPE_1(NAME, RETURN, ARG1) NAME, |
195 | #define DEF_FUNCTION_TYPE_2(NAME, RETURN, ARG1, ARG2) NAME, |
196 | #define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME, |
197 | #define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME, |
198 | #define DEF_FUNCTION_TYPE_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) NAME, |
199 | #define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
200 | ARG6) NAME, |
201 | #define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
202 | ARG6, ARG7) NAME, |
203 | #define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
204 | ARG6, ARG7, ARG8) NAME, |
205 | #define DEF_FUNCTION_TYPE_9(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
206 | ARG6, ARG7, ARG8, ARG9) NAME, |
207 | #define DEF_FUNCTION_TYPE_10(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
208 | ARG6, ARG7, ARG8, ARG9, ARG10) NAME, |
209 | #define DEF_FUNCTION_TYPE_11(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
210 | ARG6, ARG7, ARG8, ARG9, ARG10, ARG11) NAME, |
211 | #define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME, |
212 | #define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME, |
213 | #define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME, |
214 | #define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME, |
215 | #define DEF_FUNCTION_TYPE_VAR_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME, |
216 | #define DEF_FUNCTION_TYPE_VAR_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG6) \ |
217 | NAME, |
218 | #define DEF_FUNCTION_TYPE_VAR_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
219 | ARG6) NAME, |
220 | #define DEF_FUNCTION_TYPE_VAR_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
221 | ARG6, ARG7) NAME, |
222 | #define DEF_POINTER_TYPE(NAME, TYPE) NAME, |
223 | #include "builtin-types.def" |
224 | #undef DEF_PRIMITIVE_TYPE |
225 | #undef DEF_FUNCTION_TYPE_0 |
226 | #undef DEF_FUNCTION_TYPE_1 |
227 | #undef DEF_FUNCTION_TYPE_2 |
228 | #undef DEF_FUNCTION_TYPE_3 |
229 | #undef DEF_FUNCTION_TYPE_4 |
230 | #undef DEF_FUNCTION_TYPE_5 |
231 | #undef DEF_FUNCTION_TYPE_6 |
232 | #undef DEF_FUNCTION_TYPE_7 |
233 | #undef DEF_FUNCTION_TYPE_8 |
234 | #undef DEF_FUNCTION_TYPE_9 |
235 | #undef DEF_FUNCTION_TYPE_10 |
236 | #undef DEF_FUNCTION_TYPE_11 |
237 | #undef DEF_FUNCTION_TYPE_VAR_0 |
238 | #undef DEF_FUNCTION_TYPE_VAR_1 |
239 | #undef DEF_FUNCTION_TYPE_VAR_2 |
240 | #undef DEF_FUNCTION_TYPE_VAR_3 |
241 | #undef DEF_FUNCTION_TYPE_VAR_4 |
242 | #undef DEF_FUNCTION_TYPE_VAR_5 |
243 | #undef DEF_FUNCTION_TYPE_VAR_6 |
244 | #undef DEF_FUNCTION_TYPE_VAR_7 |
245 | #undef DEF_POINTER_TYPE |
246 | BT_LAST |
247 | }; |
248 | |
249 | typedef enum lto_builtin_type builtin_type; |
250 | |
251 | static GTY(()) tree builtin_types[(int) BT_LAST + 1]; |
252 | |
253 | static GTY(()) tree string_type_node; |
254 | static GTY(()) tree const_string_type_node; |
255 | static GTY(()) tree wint_type_node; |
256 | static GTY(()) tree intmax_type_node; |
257 | static GTY(()) tree uintmax_type_node; |
258 | static GTY(()) tree signed_size_type_node; |
259 | |
260 | /* Flags needed to process builtins.def. */ |
261 | int flag_isoc94; |
262 | int flag_isoc99; |
263 | int flag_isoc11; |
264 | int flag_isoc23; |
265 | |
266 | /* Attribute handlers. */ |
267 | |
268 | /* Handle a "noreturn" attribute; arguments as in |
269 | struct attribute_spec.handler. */ |
270 | |
271 | static tree |
272 | handle_noreturn_attribute (tree *node, tree ARG_UNUSED (name), |
273 | tree ARG_UNUSED (args), int ARG_UNUSED (flags), |
274 | bool * ARG_UNUSED (no_add_attrs)) |
275 | { |
276 | tree type = TREE_TYPE (*node); |
277 | |
278 | if (TREE_CODE (*node) == FUNCTION_DECL) |
279 | TREE_THIS_VOLATILE (*node) = 1; |
280 | else if (TREE_CODE (type) == POINTER_TYPE |
281 | && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) |
282 | TREE_TYPE (*node) |
283 | = build_pointer_type |
284 | (build_type_variant (TREE_TYPE (type), |
285 | TYPE_READONLY (TREE_TYPE (type)), 1)); |
286 | else |
287 | gcc_unreachable (); |
288 | |
289 | return NULL_TREE; |
290 | } |
291 | |
292 | /* Handle a "leaf" attribute; arguments as in |
293 | struct attribute_spec.handler. */ |
294 | |
295 | static tree |
296 | handle_leaf_attribute (tree *node, tree name, |
297 | tree ARG_UNUSED (args), |
298 | int ARG_UNUSED (flags), bool *no_add_attrs) |
299 | { |
300 | if (TREE_CODE (*node) != FUNCTION_DECL) |
301 | { |
302 | warning (OPT_Wattributes, "%qE attribute ignored" , name); |
303 | *no_add_attrs = true; |
304 | } |
305 | if (!TREE_PUBLIC (*node)) |
306 | { |
307 | warning (OPT_Wattributes, "%qE attribute has no effect on unit local functions" , name); |
308 | *no_add_attrs = true; |
309 | } |
310 | |
311 | return NULL_TREE; |
312 | } |
313 | |
314 | /* Handle a "const" attribute; arguments as in |
315 | struct attribute_spec.handler. */ |
316 | |
317 | static tree |
318 | handle_const_attribute (tree *node, tree ARG_UNUSED (name), |
319 | tree ARG_UNUSED (args), int ARG_UNUSED (flags), |
320 | bool * ARG_UNUSED (no_add_attrs)) |
321 | { |
322 | if (TREE_CODE (*node) != FUNCTION_DECL |
323 | || !fndecl_built_in_p (node: *node)) |
324 | inform (UNKNOWN_LOCATION, "%s:%s: %E: %E" , __FILE__, __func__, *node, name); |
325 | |
326 | tree type = TREE_TYPE (*node); |
327 | |
328 | /* See FIXME comment on noreturn in c_common_attribute_table. */ |
329 | if (TREE_CODE (*node) == FUNCTION_DECL) |
330 | TREE_READONLY (*node) = 1; |
331 | else if (TREE_CODE (type) == POINTER_TYPE |
332 | && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) |
333 | TREE_TYPE (*node) |
334 | = build_pointer_type |
335 | (build_type_variant (TREE_TYPE (type), 1, |
336 | TREE_THIS_VOLATILE (TREE_TYPE (type)))); |
337 | else |
338 | gcc_unreachable (); |
339 | |
340 | return NULL_TREE; |
341 | } |
342 | |
343 | |
344 | /* Handle a "malloc" attribute; arguments as in |
345 | struct attribute_spec.handler. */ |
346 | |
347 | static tree |
348 | handle_malloc_attribute (tree *node, tree ARG_UNUSED (name), |
349 | tree ARG_UNUSED (args), int ARG_UNUSED (flags), |
350 | bool * ARG_UNUSED (no_add_attrs)) |
351 | { |
352 | if (TREE_CODE (*node) == FUNCTION_DECL |
353 | && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node)))) |
354 | DECL_IS_MALLOC (*node) = 1; |
355 | else |
356 | gcc_unreachable (); |
357 | |
358 | return NULL_TREE; |
359 | } |
360 | |
361 | |
362 | /* Handle a "pure" attribute; arguments as in |
363 | struct attribute_spec.handler. */ |
364 | |
365 | static tree |
366 | handle_pure_attribute (tree *node, tree ARG_UNUSED (name), |
367 | tree ARG_UNUSED (args), int ARG_UNUSED (flags), |
368 | bool * ARG_UNUSED (no_add_attrs)) |
369 | { |
370 | if (TREE_CODE (*node) == FUNCTION_DECL) |
371 | DECL_PURE_P (*node) = 1; |
372 | else |
373 | gcc_unreachable (); |
374 | |
375 | return NULL_TREE; |
376 | } |
377 | |
378 | |
379 | /* Handle a "no vops" attribute; arguments as in |
380 | struct attribute_spec.handler. */ |
381 | |
382 | static tree |
383 | handle_novops_attribute (tree *node, tree ARG_UNUSED (name), |
384 | tree ARG_UNUSED (args), int ARG_UNUSED (flags), |
385 | bool *ARG_UNUSED (no_add_attrs)) |
386 | { |
387 | gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); |
388 | DECL_IS_NOVOPS (*node) = 1; |
389 | return NULL_TREE; |
390 | } |
391 | |
392 | |
393 | /* Helper for nonnull attribute handling; fetch the operand number |
394 | from the attribute argument list. */ |
395 | |
396 | static bool |
397 | get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp) |
398 | { |
399 | /* Verify the arg number is a constant. */ |
400 | if (!tree_fits_uhwi_p (arg_num_expr)) |
401 | return false; |
402 | |
403 | *valp = TREE_INT_CST_LOW (arg_num_expr); |
404 | return true; |
405 | } |
406 | |
407 | /* Handle the "nonnull" attribute. */ |
408 | |
409 | static tree |
410 | handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name), |
411 | tree args, int ARG_UNUSED (flags), |
412 | bool * ARG_UNUSED (no_add_attrs)) |
413 | { |
414 | tree type = *node; |
415 | |
416 | /* If no arguments are specified, all pointer arguments should be |
417 | non-null. Verify a full prototype is given so that the arguments |
418 | will have the correct types when we actually check them later. |
419 | Avoid diagnosing type-generic built-ins since those have no |
420 | prototype. */ |
421 | if (!args) |
422 | { |
423 | gcc_assert (prototype_p (type) |
424 | || !TYPE_ATTRIBUTES (type) |
425 | || lookup_attribute ("type generic" , TYPE_ATTRIBUTES (type))); |
426 | |
427 | return NULL_TREE; |
428 | } |
429 | |
430 | /* Argument list specified. Verify that each argument number references |
431 | a pointer argument. */ |
432 | for (; args; args = TREE_CHAIN (args)) |
433 | { |
434 | tree argument; |
435 | unsigned HOST_WIDE_INT arg_num = 0, ck_num; |
436 | |
437 | if (!get_nonnull_operand (TREE_VALUE (args), valp: &arg_num)) |
438 | gcc_unreachable (); |
439 | |
440 | argument = TYPE_ARG_TYPES (type); |
441 | if (argument) |
442 | { |
443 | for (ck_num = 1; ; ck_num++) |
444 | { |
445 | if (!argument || ck_num == arg_num) |
446 | break; |
447 | argument = TREE_CHAIN (argument); |
448 | } |
449 | |
450 | gcc_assert (argument |
451 | && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE); |
452 | } |
453 | } |
454 | |
455 | return NULL_TREE; |
456 | } |
457 | |
458 | |
459 | /* Handle a "nothrow" attribute; arguments as in |
460 | struct attribute_spec.handler. */ |
461 | |
462 | static tree |
463 | handle_nothrow_attribute (tree *node, tree ARG_UNUSED (name), |
464 | tree ARG_UNUSED (args), int ARG_UNUSED (flags), |
465 | bool * ARG_UNUSED (no_add_attrs)) |
466 | { |
467 | if (TREE_CODE (*node) == FUNCTION_DECL) |
468 | TREE_NOTHROW (*node) = 1; |
469 | else |
470 | gcc_unreachable (); |
471 | |
472 | return NULL_TREE; |
473 | } |
474 | |
475 | |
476 | /* Handle a "sentinel" attribute. */ |
477 | |
478 | static tree |
479 | handle_sentinel_attribute (tree *node, tree ARG_UNUSED (name), tree args, |
480 | int ARG_UNUSED (flags), |
481 | bool * ARG_UNUSED (no_add_attrs)) |
482 | { |
483 | gcc_assert (stdarg_p (*node)); |
484 | |
485 | if (args) |
486 | { |
487 | tree position = TREE_VALUE (args); |
488 | gcc_assert (TREE_CODE (position) == INTEGER_CST); |
489 | if (tree_int_cst_lt (t1: position, integer_zero_node)) |
490 | gcc_unreachable (); |
491 | } |
492 | |
493 | return NULL_TREE; |
494 | } |
495 | |
496 | /* Handle a "type_generic" attribute. */ |
497 | |
498 | static tree |
499 | handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name), |
500 | tree ARG_UNUSED (args), int ARG_UNUSED (flags), |
501 | bool * ARG_UNUSED (no_add_attrs)) |
502 | { |
503 | /* Ensure we have a function type. */ |
504 | gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE); |
505 | |
506 | /* Ensure we have a variadic function. */ |
507 | gcc_assert (!prototype_p (*node) || stdarg_p (*node)); |
508 | |
509 | return NULL_TREE; |
510 | } |
511 | |
512 | /* Handle a "transaction_pure" attribute. */ |
513 | |
514 | static tree |
515 | handle_transaction_pure_attribute (tree *node, tree ARG_UNUSED (name), |
516 | tree ARG_UNUSED (args), |
517 | int ARG_UNUSED (flags), |
518 | bool * ARG_UNUSED (no_add_attrs)) |
519 | { |
520 | /* Ensure we have a function type. */ |
521 | gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE); |
522 | |
523 | return NULL_TREE; |
524 | } |
525 | |
526 | /* Handle a "returns_twice" attribute. */ |
527 | |
528 | static tree |
529 | handle_returns_twice_attribute (tree *node, tree ARG_UNUSED (name), |
530 | tree ARG_UNUSED (args), |
531 | int ARG_UNUSED (flags), |
532 | bool * ARG_UNUSED (no_add_attrs)) |
533 | { |
534 | gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); |
535 | |
536 | DECL_IS_RETURNS_TWICE (*node) = 1; |
537 | |
538 | return NULL_TREE; |
539 | } |
540 | |
541 | static tree |
542 | handle_patchable_function_entry_attribute (tree *, tree, tree, int, bool *) |
543 | { |
544 | /* Nothing to be done here. */ |
545 | return NULL_TREE; |
546 | } |
547 | |
548 | /* Ignore the given attribute. Used when this attribute may be usefully |
549 | overridden by the target, but is not used generically. */ |
550 | |
551 | static tree |
552 | ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name), |
553 | tree ARG_UNUSED (args), int ARG_UNUSED (flags), |
554 | bool *no_add_attrs) |
555 | { |
556 | *no_add_attrs = true; |
557 | return NULL_TREE; |
558 | } |
559 | |
560 | /* Handle a "format" attribute; arguments as in |
561 | struct attribute_spec.handler. */ |
562 | |
563 | static tree |
564 | handle_format_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name), |
565 | tree ARG_UNUSED (args), int ARG_UNUSED (flags), |
566 | bool *no_add_attrs) |
567 | { |
568 | *no_add_attrs = true; |
569 | return NULL_TREE; |
570 | } |
571 | |
572 | |
573 | /* Handle a "format_arg" attribute; arguments as in |
574 | struct attribute_spec.handler. */ |
575 | |
576 | tree |
577 | handle_format_arg_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name), |
578 | tree ARG_UNUSED (args), int ARG_UNUSED (flags), |
579 | bool *no_add_attrs) |
580 | { |
581 | *no_add_attrs = true; |
582 | return NULL_TREE; |
583 | } |
584 | |
585 | |
586 | /* Handle a "fn spec" attribute; arguments as in |
587 | struct attribute_spec.handler. */ |
588 | |
589 | static tree |
590 | handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name), |
591 | tree args, int ARG_UNUSED (flags), |
592 | bool *no_add_attrs ATTRIBUTE_UNUSED) |
593 | { |
594 | gcc_assert (args |
595 | && TREE_CODE (TREE_VALUE (args)) == STRING_CST |
596 | && !TREE_CHAIN (args)); |
597 | return NULL_TREE; |
598 | } |
599 | |
600 | /* Cribbed from c-common.cc. */ |
601 | |
602 | static void |
603 | def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...) |
604 | { |
605 | tree t; |
606 | tree *args = XALLOCAVEC (tree, n); |
607 | va_list list; |
608 | int i; |
609 | bool err = false; |
610 | |
611 | va_start (list, n); |
612 | for (i = 0; i < n; ++i) |
613 | { |
614 | builtin_type a = (builtin_type) va_arg (list, int); |
615 | t = builtin_types[a]; |
616 | if (t == error_mark_node) |
617 | err = true; |
618 | args[i] = t; |
619 | } |
620 | va_end (list); |
621 | |
622 | t = builtin_types[ret]; |
623 | if (err) |
624 | t = error_mark_node; |
625 | if (t == error_mark_node) |
626 | ; |
627 | else if (var) |
628 | t = build_varargs_function_type_array (t, n, args); |
629 | else |
630 | t = build_function_type_array (t, n, args); |
631 | |
632 | builtin_types[def] = t; |
633 | } |
634 | |
635 | /* Used to help initialize the builtin-types.def table. When a type of |
636 | the correct size doesn't exist, use error_mark_node instead of NULL. |
637 | The later results in segfaults even when a decl using the type doesn't |
638 | get invoked. */ |
639 | |
640 | static tree |
641 | builtin_type_for_size (int size, bool unsignedp) |
642 | { |
643 | tree type = lang_hooks.types.type_for_size (size, unsignedp); |
644 | return type ? type : error_mark_node; |
645 | } |
646 | |
647 | /* Support for DEF_BUILTIN. */ |
648 | |
649 | static void |
650 | def_builtin_1 (enum built_in_function fncode, const char *name, |
651 | enum built_in_class fnclass, tree fntype, tree libtype, |
652 | bool both_p, bool fallback_p, bool nonansi_p, |
653 | tree fnattrs, bool implicit_p) |
654 | { |
655 | tree decl; |
656 | const char *libname; |
657 | |
658 | if (fntype == error_mark_node) |
659 | return; |
660 | |
661 | libname = name + strlen (s: "__builtin_" ); |
662 | decl = add_builtin_function (name, type: fntype, function_code: fncode, cl: fnclass, |
663 | library_name: (fallback_p ? libname : NULL), |
664 | attrs: fnattrs); |
665 | |
666 | if (both_p |
667 | && !flag_no_builtin |
668 | && !(nonansi_p && flag_no_nonansi_builtin)) |
669 | add_builtin_function (name: libname, type: libtype, function_code: fncode, cl: fnclass, |
670 | NULL, attrs: fnattrs); |
671 | |
672 | set_builtin_decl (fncode, decl, implicit_p); |
673 | } |
674 | |
675 | |
676 | /* Initialize the attribute table for all the supported builtins. */ |
677 | |
678 | static void |
679 | lto_init_attributes (void) |
680 | { |
681 | /* Fill in the built_in_attributes array. */ |
682 | #define DEF_ATTR_NULL_TREE(ENUM) \ |
683 | built_in_attributes[(int) ENUM] = NULL_TREE; |
684 | #define DEF_ATTR_INT(ENUM, VALUE) \ |
685 | built_in_attributes[(int) ENUM] = build_int_cst (NULL_TREE, VALUE); |
686 | #define DEF_ATTR_STRING(ENUM, VALUE) \ |
687 | built_in_attributes[(int) ENUM] = build_string (strlen (VALUE), VALUE); |
688 | #define DEF_ATTR_IDENT(ENUM, STRING) \ |
689 | built_in_attributes[(int) ENUM] = get_identifier (STRING); |
690 | #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) \ |
691 | built_in_attributes[(int) ENUM] \ |
692 | = tree_cons (built_in_attributes[(int) PURPOSE], \ |
693 | built_in_attributes[(int) VALUE], \ |
694 | built_in_attributes[(int) CHAIN]); |
695 | #include "builtin-attrs.def" |
696 | #undef DEF_ATTR_NULL_TREE |
697 | #undef DEF_ATTR_INT |
698 | #undef DEF_ATTR_STRING |
699 | #undef DEF_ATTR_IDENT |
700 | #undef DEF_ATTR_TREE_LIST |
701 | } |
702 | |
703 | /* Create builtin types and functions. VA_LIST_REF_TYPE_NODE and |
704 | VA_LIST_ARG_TYPE_NODE are used in builtin-types.def. */ |
705 | |
706 | static void |
707 | lto_define_builtins (tree va_list_ref_type_node ATTRIBUTE_UNUSED, |
708 | tree va_list_arg_type_node ATTRIBUTE_UNUSED) |
709 | { |
710 | #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \ |
711 | builtin_types[ENUM] = VALUE; |
712 | #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \ |
713 | def_fn_type (ENUM, RETURN, 0, 0); |
714 | #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \ |
715 | def_fn_type (ENUM, RETURN, 0, 1, ARG1); |
716 | #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \ |
717 | def_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2); |
718 | #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \ |
719 | def_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3); |
720 | #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \ |
721 | def_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, ARG4); |
722 | #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ |
723 | def_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, ARG4, ARG5); |
724 | #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
725 | ARG6) \ |
726 | def_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6); |
727 | #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
728 | ARG6, ARG7) \ |
729 | def_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7); |
730 | #define DEF_FUNCTION_TYPE_8(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
731 | ARG6, ARG7, ARG8) \ |
732 | def_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \ |
733 | ARG7, ARG8); |
734 | #define DEF_FUNCTION_TYPE_9(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
735 | ARG6, ARG7, ARG8, ARG9) \ |
736 | def_fn_type (ENUM, RETURN, 0, 9, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \ |
737 | ARG7, ARG8, ARG9); |
738 | #define DEF_FUNCTION_TYPE_10(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
739 | ARG6, ARG7, ARG8, ARG9, ARG10) \ |
740 | def_fn_type (ENUM, RETURN, 0, 10, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \ |
741 | ARG7, ARG8, ARG9, ARG10); |
742 | #define DEF_FUNCTION_TYPE_11(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
743 | ARG6, ARG7, ARG8, ARG9, ARG10, ARG11) \ |
744 | def_fn_type (ENUM, RETURN, 0, 11, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \ |
745 | ARG7, ARG8, ARG9, ARG10, ARG11); |
746 | #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \ |
747 | def_fn_type (ENUM, RETURN, 1, 0); |
748 | #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \ |
749 | def_fn_type (ENUM, RETURN, 1, 1, ARG1); |
750 | #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \ |
751 | def_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2); |
752 | #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \ |
753 | def_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3); |
754 | #define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \ |
755 | def_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, ARG4); |
756 | #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ |
757 | def_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, ARG4, ARG5); |
758 | #define DEF_FUNCTION_TYPE_VAR_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
759 | ARG6) \ |
760 | def_fn_type (ENUM, RETURN, 1, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6); |
761 | #define DEF_FUNCTION_TYPE_VAR_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
762 | ARG6, ARG7) \ |
763 | def_fn_type (ENUM, RETURN, 1, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7); |
764 | #define DEF_POINTER_TYPE(ENUM, TYPE) \ |
765 | builtin_types[(int) ENUM] = build_pointer_type (builtin_types[(int) TYPE]); |
766 | |
767 | #include "builtin-types.def" |
768 | |
769 | #undef DEF_PRIMITIVE_TYPE |
770 | #undef DEF_FUNCTION_TYPE_0 |
771 | #undef DEF_FUNCTION_TYPE_1 |
772 | #undef DEF_FUNCTION_TYPE_2 |
773 | #undef DEF_FUNCTION_TYPE_3 |
774 | #undef DEF_FUNCTION_TYPE_4 |
775 | #undef DEF_FUNCTION_TYPE_5 |
776 | #undef DEF_FUNCTION_TYPE_6 |
777 | #undef DEF_FUNCTION_TYPE_7 |
778 | #undef DEF_FUNCTION_TYPE_8 |
779 | #undef DEF_FUNCTION_TYPE_9 |
780 | #undef DEF_FUNCTION_TYPE_10 |
781 | #undef DEF_FUNCTION_TYPE_11 |
782 | #undef DEF_FUNCTION_TYPE_VAR_0 |
783 | #undef DEF_FUNCTION_TYPE_VAR_1 |
784 | #undef DEF_FUNCTION_TYPE_VAR_2 |
785 | #undef DEF_FUNCTION_TYPE_VAR_3 |
786 | #undef DEF_FUNCTION_TYPE_VAR_4 |
787 | #undef DEF_FUNCTION_TYPE_VAR_5 |
788 | #undef DEF_FUNCTION_TYPE_VAR_6 |
789 | #undef DEF_FUNCTION_TYPE_VAR_7 |
790 | #undef DEF_POINTER_TYPE |
791 | builtin_types[(int) BT_LAST] = NULL_TREE; |
792 | |
793 | lto_init_attributes (); |
794 | |
795 | #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P,\ |
796 | NONANSI_P, ATTRS, IMPLICIT, COND) \ |
797 | if (NAME && COND) \ |
798 | def_builtin_1 (ENUM, NAME, CLASS, builtin_types[(int) TYPE], \ |
799 | builtin_types[(int) LIBTYPE], BOTH_P, FALLBACK_P, \ |
800 | NONANSI_P, built_in_attributes[(int) ATTRS], IMPLICIT); |
801 | #include "builtins.def" |
802 | } |
803 | |
804 | static GTY(()) tree registered_builtin_types; |
805 | |
806 | /* Language hooks. */ |
807 | |
808 | static bool |
809 | lto_complain_wrong_lang_p (const struct cl_option *option ATTRIBUTE_UNUSED) |
810 | { |
811 | /* The LTO front end inherits all the options from the first front |
812 | end that was used. However, not all the original front end |
813 | options make sense in LTO. |
814 | |
815 | A real solution would be to filter this in collect2, but collect2 |
816 | does not have access to all the option attributes to know what to |
817 | filter. So, in lto1 we silently accept inherited flags and do |
818 | nothing about it. */ |
819 | return false; |
820 | } |
821 | |
822 | static void |
823 | lto_init_options_struct (struct gcc_options *opts) |
824 | { |
825 | /* By default, C99-like requirements for complex multiply and divide. |
826 | ??? Until the complex method is encoded in the IL this is the only |
827 | safe choice. This will pessimize Fortran code with LTO unless |
828 | people specify a complex method manually or use -ffast-math. */ |
829 | opts->x_flag_complex_method = 2; |
830 | opts->x_flag_default_complex_method = opts->x_flag_complex_method; |
831 | } |
832 | |
833 | /* Handle command-line option SCODE. If the option takes an argument, it is |
834 | stored in ARG, which is otherwise NULL. VALUE holds either a numerical |
835 | argument or a binary value indicating whether the positive or negative form |
836 | of the option was supplied. */ |
837 | |
838 | const char *resolution_file_name; |
839 | static bool |
840 | lto_handle_option (size_t scode, const char *arg, |
841 | HOST_WIDE_INT value ATTRIBUTE_UNUSED, |
842 | int kind ATTRIBUTE_UNUSED, |
843 | location_t loc ATTRIBUTE_UNUSED, |
844 | const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED) |
845 | { |
846 | enum opt_code code = (enum opt_code) scode; |
847 | bool result = true; |
848 | |
849 | switch (code) |
850 | { |
851 | case OPT_fresolution_: |
852 | resolution_file_name = arg; |
853 | break; |
854 | |
855 | case OPT_Wabi: |
856 | warn_psabi = value; |
857 | break; |
858 | |
859 | case OPT_fwpa: |
860 | flag_wpa = value ? "" : NULL; |
861 | break; |
862 | |
863 | default: |
864 | break; |
865 | } |
866 | |
867 | return result; |
868 | } |
869 | |
870 | /* Perform post-option processing. Does additional initialization based on |
871 | command-line options. PFILENAME is the main input filename. Returns false |
872 | to enable subsequent back-end initialization. */ |
873 | |
874 | static bool |
875 | lto_post_options (const char **pfilename ATTRIBUTE_UNUSED) |
876 | { |
877 | /* -fltrans and -fwpa are mutually exclusive. Check for that here. */ |
878 | if (flag_wpa && flag_ltrans) |
879 | error ("%<-fwpa%> and %<-fltrans%> are mutually exclusive" ); |
880 | |
881 | if (flag_ltrans) |
882 | { |
883 | flag_generate_lto = 0; |
884 | |
885 | /* During LTRANS, we are not looking at the whole program, only |
886 | a subset of the whole callgraph. */ |
887 | flag_whole_program = 0; |
888 | } |
889 | |
890 | if (flag_wpa) |
891 | flag_generate_lto = 1; |
892 | |
893 | /* Initialize the codegen flags according to the output type. */ |
894 | switch (flag_lto_linker_output) |
895 | { |
896 | case LTO_LINKER_OUTPUT_REL: /* .o: incremental link producing LTO IL */ |
897 | /* Configure compiler same way as normal frontend would do with -flto: |
898 | this way we read the trees (declarations & types), symbol table, |
899 | optimization summaries and link them. Subsequently we output new LTO |
900 | file. */ |
901 | flag_lto = "" ; |
902 | flag_incremental_link = INCREMENTAL_LINK_LTO; |
903 | flag_whole_program = 0; |
904 | flag_wpa = 0; |
905 | flag_generate_lto = 1; |
906 | /* It would be cool to produce .o file directly, but our current |
907 | simple objects does not contain the lto symbol markers. Go the slow |
908 | way through the asm file. */ |
909 | lang_hooks.lto.begin_section = lhd_begin_section; |
910 | lang_hooks.lto.append_data = lhd_append_data; |
911 | lang_hooks.lto.end_section = lhd_end_section; |
912 | if (flag_ltrans) |
913 | error ("%<-flinker-output=rel%> and %<-fltrans%> are mutually " |
914 | "exclusive" ); |
915 | break; |
916 | |
917 | case LTO_LINKER_OUTPUT_NOLTOREL: /* .o: incremental link producing asm */ |
918 | flag_incremental_link = INCREMENTAL_LINK_NOLTO; |
919 | break; |
920 | |
921 | case LTO_LINKER_OUTPUT_DYN: /* .so: PID library */ |
922 | /* On some targets, like i386 it makes sense to build PIC library wihout |
923 | -fpic for performance reasons. So no need to adjust flags. */ |
924 | break; |
925 | |
926 | case LTO_LINKER_OUTPUT_PIE: /* PIE binary */ |
927 | /* If -fPIC or -fPIE was used at compile time, be sure that |
928 | flag_pie is 2. */ |
929 | flag_pie = MAX (flag_pie, flag_pic); |
930 | flag_pic = flag_pie; |
931 | flag_shlib = 0; |
932 | break; |
933 | |
934 | case LTO_LINKER_OUTPUT_EXEC: /* Normal executable */ |
935 | flag_pic = 0; |
936 | flag_pie = 0; |
937 | flag_shlib = 0; |
938 | break; |
939 | |
940 | case LTO_LINKER_OUTPUT_UNKNOWN: |
941 | break; |
942 | } |
943 | |
944 | /* Excess precision other than "fast" requires front-end |
945 | support. */ |
946 | if (flag_excess_precision == EXCESS_PRECISION_DEFAULT) |
947 | flag_excess_precision = EXCESS_PRECISION_FAST; |
948 | |
949 | /* When partitioning, we can tear appart STRING_CSTs uses from the same |
950 | TU into multiple partitions. Without constant merging the constants |
951 | might not be equal at runtime. See PR50199. */ |
952 | if (!flag_merge_constants) |
953 | flag_merge_constants = 1; |
954 | |
955 | /* Initialize the compiler back end. */ |
956 | return false; |
957 | } |
958 | |
959 | /* Return a data type that has machine mode MODE. |
960 | If the mode is an integer, |
961 | then UNSIGNEDP selects between signed and unsigned types. |
962 | If the mode is a fixed-point mode, |
963 | then UNSIGNEDP selects between saturating and nonsaturating types. */ |
964 | |
965 | static tree |
966 | lto_type_for_mode (machine_mode mode, int unsigned_p) |
967 | { |
968 | tree t; |
969 | int i; |
970 | |
971 | if (mode == TYPE_MODE (integer_type_node)) |
972 | return unsigned_p ? unsigned_type_node : integer_type_node; |
973 | |
974 | if (mode == TYPE_MODE (signed_char_type_node)) |
975 | return unsigned_p ? unsigned_char_type_node : signed_char_type_node; |
976 | |
977 | if (mode == TYPE_MODE (short_integer_type_node)) |
978 | return unsigned_p ? short_unsigned_type_node : short_integer_type_node; |
979 | |
980 | if (mode == TYPE_MODE (long_integer_type_node)) |
981 | return unsigned_p ? long_unsigned_type_node : long_integer_type_node; |
982 | |
983 | if (mode == TYPE_MODE (long_long_integer_type_node)) |
984 | return unsigned_p ? long_long_unsigned_type_node : long_long_integer_type_node; |
985 | |
986 | for (i = 0; i < NUM_INT_N_ENTS; i ++) |
987 | if (int_n_enabled_p[i] |
988 | && mode == int_n_data[i].m) |
989 | return (unsigned_p ? int_n_trees[i].unsigned_type |
990 | : int_n_trees[i].signed_type); |
991 | |
992 | if (mode == QImode) |
993 | return unsigned_p ? unsigned_intQI_type_node : intQI_type_node; |
994 | |
995 | if (mode == HImode) |
996 | return unsigned_p ? unsigned_intHI_type_node : intHI_type_node; |
997 | |
998 | if (mode == SImode) |
999 | return unsigned_p ? unsigned_intSI_type_node : intSI_type_node; |
1000 | |
1001 | if (mode == DImode) |
1002 | return unsigned_p ? unsigned_intDI_type_node : intDI_type_node; |
1003 | |
1004 | #if HOST_BITS_PER_WIDE_INT >= 64 |
1005 | if (mode == TYPE_MODE (intTI_type_node)) |
1006 | return unsigned_p ? unsigned_intTI_type_node : intTI_type_node; |
1007 | #endif |
1008 | |
1009 | if (float16_type_node && mode == TYPE_MODE (float16_type_node)) |
1010 | return float16_type_node; |
1011 | |
1012 | if (mode == TYPE_MODE (float_type_node)) |
1013 | return float_type_node; |
1014 | |
1015 | if (mode == TYPE_MODE (double_type_node)) |
1016 | return double_type_node; |
1017 | |
1018 | if (mode == TYPE_MODE (long_double_type_node)) |
1019 | return long_double_type_node; |
1020 | |
1021 | for (i = 0; i < NUM_FLOATN_NX_TYPES; i++) |
1022 | if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE |
1023 | && mode == TYPE_MODE (FLOATN_NX_TYPE_NODE (i))) |
1024 | return FLOATN_NX_TYPE_NODE (i); |
1025 | |
1026 | if (mode == TYPE_MODE (void_type_node)) |
1027 | return void_type_node; |
1028 | |
1029 | if (mode == TYPE_MODE (build_pointer_type (char_type_node)) |
1030 | || mode == TYPE_MODE (build_pointer_type (integer_type_node))) |
1031 | { |
1032 | unsigned int precision |
1033 | = GET_MODE_PRECISION (mode: as_a <scalar_int_mode> (m: mode)); |
1034 | return (unsigned_p |
1035 | ? make_unsigned_type (precision) |
1036 | : make_signed_type (precision)); |
1037 | } |
1038 | |
1039 | if (COMPLEX_MODE_P (mode)) |
1040 | { |
1041 | machine_mode inner_mode; |
1042 | tree inner_type; |
1043 | |
1044 | if (mode == TYPE_MODE (complex_float_type_node)) |
1045 | return complex_float_type_node; |
1046 | if (mode == TYPE_MODE (complex_double_type_node)) |
1047 | return complex_double_type_node; |
1048 | if (mode == TYPE_MODE (complex_long_double_type_node)) |
1049 | return complex_long_double_type_node; |
1050 | |
1051 | for (i = 0; i < NUM_FLOATN_NX_TYPES; i++) |
1052 | if (COMPLEX_FLOATN_NX_TYPE_NODE (i) != NULL_TREE |
1053 | && mode == TYPE_MODE (COMPLEX_FLOATN_NX_TYPE_NODE (i))) |
1054 | return COMPLEX_FLOATN_NX_TYPE_NODE (i); |
1055 | |
1056 | if (mode == TYPE_MODE (complex_integer_type_node) && !unsigned_p) |
1057 | return complex_integer_type_node; |
1058 | |
1059 | inner_mode = GET_MODE_INNER (mode); |
1060 | inner_type = lto_type_for_mode (mode: inner_mode, unsigned_p); |
1061 | if (inner_type != NULL_TREE) |
1062 | return build_complex_type (inner_type); |
1063 | } |
1064 | else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL |
1065 | && valid_vector_subparts_p (subparts: GET_MODE_NUNITS (mode))) |
1066 | { |
1067 | unsigned int elem_bits = vector_element_size (GET_MODE_PRECISION (mode), |
1068 | GET_MODE_NUNITS (mode)); |
1069 | tree bool_type = build_nonstandard_boolean_type (elem_bits); |
1070 | return build_vector_type_for_mode (bool_type, mode); |
1071 | } |
1072 | else if (VECTOR_MODE_P (mode) |
1073 | && valid_vector_subparts_p (subparts: GET_MODE_NUNITS (mode))) |
1074 | { |
1075 | machine_mode inner_mode = GET_MODE_INNER (mode); |
1076 | tree inner_type = lto_type_for_mode (mode: inner_mode, unsigned_p); |
1077 | if (inner_type != NULL_TREE) |
1078 | return build_vector_type_for_mode (inner_type, mode); |
1079 | } |
1080 | |
1081 | if (dfloat32_type_node != NULL_TREE |
1082 | && mode == TYPE_MODE (dfloat32_type_node)) |
1083 | return dfloat32_type_node; |
1084 | if (dfloat64_type_node != NULL_TREE |
1085 | && mode == TYPE_MODE (dfloat64_type_node)) |
1086 | return dfloat64_type_node; |
1087 | if (dfloat128_type_node != NULL_TREE |
1088 | && mode == TYPE_MODE (dfloat128_type_node)) |
1089 | return dfloat128_type_node; |
1090 | |
1091 | if (ALL_SCALAR_FIXED_POINT_MODE_P (mode)) |
1092 | { |
1093 | if (mode == TYPE_MODE (short_fract_type_node)) |
1094 | return unsigned_p ? sat_short_fract_type_node : short_fract_type_node; |
1095 | if (mode == TYPE_MODE (fract_type_node)) |
1096 | return unsigned_p ? sat_fract_type_node : fract_type_node; |
1097 | if (mode == TYPE_MODE (long_fract_type_node)) |
1098 | return unsigned_p ? sat_long_fract_type_node : long_fract_type_node; |
1099 | if (mode == TYPE_MODE (long_long_fract_type_node)) |
1100 | return unsigned_p ? sat_long_long_fract_type_node |
1101 | : long_long_fract_type_node; |
1102 | |
1103 | if (mode == TYPE_MODE (unsigned_short_fract_type_node)) |
1104 | return unsigned_p ? sat_unsigned_short_fract_type_node |
1105 | : unsigned_short_fract_type_node; |
1106 | if (mode == TYPE_MODE (unsigned_fract_type_node)) |
1107 | return unsigned_p ? sat_unsigned_fract_type_node |
1108 | : unsigned_fract_type_node; |
1109 | if (mode == TYPE_MODE (unsigned_long_fract_type_node)) |
1110 | return unsigned_p ? sat_unsigned_long_fract_type_node |
1111 | : unsigned_long_fract_type_node; |
1112 | if (mode == TYPE_MODE (unsigned_long_long_fract_type_node)) |
1113 | return unsigned_p ? sat_unsigned_long_long_fract_type_node |
1114 | : unsigned_long_long_fract_type_node; |
1115 | |
1116 | if (mode == TYPE_MODE (short_accum_type_node)) |
1117 | return unsigned_p ? sat_short_accum_type_node : short_accum_type_node; |
1118 | if (mode == TYPE_MODE (accum_type_node)) |
1119 | return unsigned_p ? sat_accum_type_node : accum_type_node; |
1120 | if (mode == TYPE_MODE (long_accum_type_node)) |
1121 | return unsigned_p ? sat_long_accum_type_node : long_accum_type_node; |
1122 | if (mode == TYPE_MODE (long_long_accum_type_node)) |
1123 | return unsigned_p ? sat_long_long_accum_type_node |
1124 | : long_long_accum_type_node; |
1125 | |
1126 | if (mode == TYPE_MODE (unsigned_short_accum_type_node)) |
1127 | return unsigned_p ? sat_unsigned_short_accum_type_node |
1128 | : unsigned_short_accum_type_node; |
1129 | if (mode == TYPE_MODE (unsigned_accum_type_node)) |
1130 | return unsigned_p ? sat_unsigned_accum_type_node |
1131 | : unsigned_accum_type_node; |
1132 | if (mode == TYPE_MODE (unsigned_long_accum_type_node)) |
1133 | return unsigned_p ? sat_unsigned_long_accum_type_node |
1134 | : unsigned_long_accum_type_node; |
1135 | if (mode == TYPE_MODE (unsigned_long_long_accum_type_node)) |
1136 | return unsigned_p ? sat_unsigned_long_long_accum_type_node |
1137 | : unsigned_long_long_accum_type_node; |
1138 | |
1139 | if (mode == QQmode) |
1140 | return unsigned_p ? sat_qq_type_node : qq_type_node; |
1141 | if (mode == HQmode) |
1142 | return unsigned_p ? sat_hq_type_node : hq_type_node; |
1143 | if (mode == SQmode) |
1144 | return unsigned_p ? sat_sq_type_node : sq_type_node; |
1145 | if (mode == DQmode) |
1146 | return unsigned_p ? sat_dq_type_node : dq_type_node; |
1147 | if (mode == TQmode) |
1148 | return unsigned_p ? sat_tq_type_node : tq_type_node; |
1149 | |
1150 | if (mode == UQQmode) |
1151 | return unsigned_p ? sat_uqq_type_node : uqq_type_node; |
1152 | if (mode == UHQmode) |
1153 | return unsigned_p ? sat_uhq_type_node : uhq_type_node; |
1154 | if (mode == USQmode) |
1155 | return unsigned_p ? sat_usq_type_node : usq_type_node; |
1156 | if (mode == UDQmode) |
1157 | return unsigned_p ? sat_udq_type_node : udq_type_node; |
1158 | if (mode == UTQmode) |
1159 | return unsigned_p ? sat_utq_type_node : utq_type_node; |
1160 | |
1161 | if (mode == HAmode) |
1162 | return unsigned_p ? sat_ha_type_node : ha_type_node; |
1163 | if (mode == SAmode) |
1164 | return unsigned_p ? sat_sa_type_node : sa_type_node; |
1165 | if (mode == DAmode) |
1166 | return unsigned_p ? sat_da_type_node : da_type_node; |
1167 | if (mode == TAmode) |
1168 | return unsigned_p ? sat_ta_type_node : ta_type_node; |
1169 | |
1170 | if (mode == UHAmode) |
1171 | return unsigned_p ? sat_uha_type_node : uha_type_node; |
1172 | if (mode == USAmode) |
1173 | return unsigned_p ? sat_usa_type_node : usa_type_node; |
1174 | if (mode == UDAmode) |
1175 | return unsigned_p ? sat_uda_type_node : uda_type_node; |
1176 | if (mode == UTAmode) |
1177 | return unsigned_p ? sat_uta_type_node : uta_type_node; |
1178 | } |
1179 | |
1180 | for (t = registered_builtin_types; t; t = TREE_CHAIN (t)) |
1181 | { |
1182 | tree type = TREE_VALUE (t); |
1183 | if (TYPE_MODE (type) == mode |
1184 | && VECTOR_TYPE_P (type) == VECTOR_MODE_P (mode) |
1185 | && !!unsigned_p == !!TYPE_UNSIGNED (type)) |
1186 | return type; |
1187 | } |
1188 | return NULL_TREE; |
1189 | } |
1190 | |
1191 | /* Return true if we are in the global binding level. */ |
1192 | |
1193 | static bool |
1194 | lto_global_bindings_p (void) |
1195 | { |
1196 | return cfun == NULL; |
1197 | } |
1198 | |
1199 | static void |
1200 | lto_set_decl_assembler_name (tree decl) |
1201 | { |
1202 | /* This is almost the same as lhd_set_decl_assembler_name, except that |
1203 | we need to uniquify file-scope names, even if they are not |
1204 | TREE_PUBLIC, to avoid conflicts between individual files. */ |
1205 | tree id; |
1206 | |
1207 | if (TREE_PUBLIC (decl)) |
1208 | id = targetm.mangle_decl_assembler_name (decl, DECL_NAME (decl)); |
1209 | else |
1210 | { |
1211 | const char *name = IDENTIFIER_POINTER (DECL_NAME (decl)); |
1212 | char *label; |
1213 | static unsigned long num; |
1214 | |
1215 | ASM_FORMAT_PRIVATE_NAME (label, name, num++); |
1216 | id = get_identifier (label); |
1217 | } |
1218 | |
1219 | SET_DECL_ASSEMBLER_NAME (decl, id); |
1220 | } |
1221 | |
1222 | static tree |
1223 | lto_pushdecl (tree t ATTRIBUTE_UNUSED) |
1224 | { |
1225 | /* Do nothing, since we get all information from DWARF and LTO |
1226 | sections. */ |
1227 | return NULL_TREE; |
1228 | } |
1229 | |
1230 | static tree |
1231 | lto_getdecls (void) |
1232 | { |
1233 | /* We have our own write_globals langhook, hence the getdecls |
1234 | langhook shouldn't be used, except by dbxout.cc, so we can't |
1235 | just abort here. */ |
1236 | return NULL_TREE; |
1237 | } |
1238 | |
1239 | static tree |
1240 | lto_builtin_function (tree decl) |
1241 | { |
1242 | return decl; |
1243 | } |
1244 | |
1245 | static void |
1246 | lto_register_builtin_type (tree type, const char *name) |
1247 | { |
1248 | tree decl; |
1249 | |
1250 | if (!TYPE_NAME (type)) |
1251 | { |
1252 | decl = build_decl (UNKNOWN_LOCATION, TYPE_DECL, |
1253 | get_identifier (name), type); |
1254 | DECL_ARTIFICIAL (decl) = 1; |
1255 | TYPE_NAME (type) = decl; |
1256 | } |
1257 | |
1258 | registered_builtin_types = tree_cons (0, type, registered_builtin_types); |
1259 | } |
1260 | |
1261 | /* Build nodes that would have be created by the C front-end; necessary |
1262 | for including builtin-types.def and ultimately builtins.def. */ |
1263 | |
1264 | static void |
1265 | lto_build_c_type_nodes (void) |
1266 | { |
1267 | gcc_assert (void_type_node); |
1268 | |
1269 | string_type_node = build_pointer_type (char_type_node); |
1270 | const_string_type_node |
1271 | = build_pointer_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST)); |
1272 | |
1273 | if (strcmp (SIZE_TYPE, s2: "unsigned int" ) == 0) |
1274 | { |
1275 | intmax_type_node = integer_type_node; |
1276 | uintmax_type_node = unsigned_type_node; |
1277 | signed_size_type_node = integer_type_node; |
1278 | } |
1279 | else if (strcmp (SIZE_TYPE, s2: "long unsigned int" ) == 0) |
1280 | { |
1281 | intmax_type_node = long_integer_type_node; |
1282 | uintmax_type_node = long_unsigned_type_node; |
1283 | signed_size_type_node = long_integer_type_node; |
1284 | } |
1285 | else if (strcmp (SIZE_TYPE, s2: "long long unsigned int" ) == 0) |
1286 | { |
1287 | intmax_type_node = long_long_integer_type_node; |
1288 | uintmax_type_node = long_long_unsigned_type_node; |
1289 | signed_size_type_node = long_long_integer_type_node; |
1290 | } |
1291 | else |
1292 | { |
1293 | int i; |
1294 | |
1295 | signed_size_type_node = NULL_TREE; |
1296 | for (i = 0; i < NUM_INT_N_ENTS; i++) |
1297 | if (int_n_enabled_p[i]) |
1298 | { |
1299 | char name[50], altname[50]; |
1300 | sprintf (s: name, format: "__int%d unsigned" , int_n_data[i].bitsize); |
1301 | sprintf (s: altname, format: "__int%d__ unsigned" , int_n_data[i].bitsize); |
1302 | |
1303 | if (strcmp (s1: name, SIZE_TYPE) == 0 |
1304 | || strcmp (s1: altname, SIZE_TYPE) == 0) |
1305 | { |
1306 | intmax_type_node = int_n_trees[i].signed_type; |
1307 | uintmax_type_node = int_n_trees[i].unsigned_type; |
1308 | signed_size_type_node = int_n_trees[i].signed_type; |
1309 | } |
1310 | } |
1311 | if (signed_size_type_node == NULL_TREE) |
1312 | gcc_unreachable (); |
1313 | } |
1314 | |
1315 | wint_type_node = unsigned_type_node; |
1316 | pid_type_node = integer_type_node; |
1317 | } |
1318 | |
1319 | /* Perform LTO-specific initialization. */ |
1320 | |
1321 | static bool |
1322 | lto_init (void) |
1323 | { |
1324 | int i; |
1325 | |
1326 | /* Initialize LTO-specific data structures. */ |
1327 | in_lto_p = true; |
1328 | |
1329 | /* We need to generate LTO if running in WPA mode. */ |
1330 | flag_generate_lto = (flag_incremental_link == INCREMENTAL_LINK_LTO |
1331 | || flag_wpa != NULL); |
1332 | |
1333 | /* Create the basic integer types. */ |
1334 | build_common_tree_nodes (flag_signed_char); |
1335 | |
1336 | /* The global tree for the main identifier is filled in by |
1337 | language-specific front-end initialization that is not run in the |
1338 | LTO back-end. It appears that all languages that perform such |
1339 | initialization currently do so in the same way, so we do it here. */ |
1340 | if (main_identifier_node == NULL_TREE) |
1341 | main_identifier_node = get_identifier ("main" ); |
1342 | |
1343 | /* In the C++ front-end, fileptr_type_node is defined as a variant |
1344 | copy of ptr_type_node, rather than ptr_node itself. The |
1345 | distinction should only be relevant to the front-end, so we |
1346 | always use the C definition here in lto1. |
1347 | Likewise for const struct tm*. */ |
1348 | for (unsigned i = 0; i < ARRAY_SIZE (builtin_structptr_types); ++i) |
1349 | { |
1350 | gcc_assert (builtin_structptr_types[i].node |
1351 | == builtin_structptr_types[i].base); |
1352 | gcc_assert (TYPE_MAIN_VARIANT (builtin_structptr_types[i].node) |
1353 | == builtin_structptr_types[i].base); |
1354 | } |
1355 | |
1356 | lto_build_c_type_nodes (); |
1357 | gcc_assert (va_list_type_node); |
1358 | |
1359 | if (TREE_CODE (va_list_type_node) == ARRAY_TYPE) |
1360 | { |
1361 | tree x = build_pointer_type (TREE_TYPE (va_list_type_node)); |
1362 | lto_define_builtins (va_list_ref_type_node: x, va_list_arg_type_node: x); |
1363 | } |
1364 | else |
1365 | { |
1366 | lto_define_builtins (va_list_ref_type_node: build_reference_type (va_list_type_node), |
1367 | va_list_type_node); |
1368 | } |
1369 | |
1370 | targetm.init_builtins (); |
1371 | build_common_builtin_nodes (); |
1372 | |
1373 | /* Assign names to the builtin types, otherwise they'll end up |
1374 | as __unknown__ in debug info. |
1375 | ??? We simply need to stop pre-seeding the streamer cache. |
1376 | Below is modeled after from c-common.cc:c_common_nodes_and_builtins */ |
1377 | #define NAME_TYPE(t,n) \ |
1378 | if (t) \ |
1379 | TYPE_NAME (t) = build_decl (UNKNOWN_LOCATION, TYPE_DECL, \ |
1380 | get_identifier (n), t) |
1381 | NAME_TYPE (integer_type_node, "int" ); |
1382 | NAME_TYPE (char_type_node, "char" ); |
1383 | NAME_TYPE (long_integer_type_node, "long int" ); |
1384 | NAME_TYPE (unsigned_type_node, "unsigned int" ); |
1385 | NAME_TYPE (long_unsigned_type_node, "long unsigned int" ); |
1386 | NAME_TYPE (long_long_integer_type_node, "long long int" ); |
1387 | NAME_TYPE (long_long_unsigned_type_node, "long long unsigned int" ); |
1388 | NAME_TYPE (short_integer_type_node, "short int" ); |
1389 | NAME_TYPE (short_unsigned_type_node, "short unsigned int" ); |
1390 | if (signed_char_type_node != char_type_node) |
1391 | NAME_TYPE (signed_char_type_node, "signed char" ); |
1392 | if (unsigned_char_type_node != char_type_node) |
1393 | NAME_TYPE (unsigned_char_type_node, "unsigned char" ); |
1394 | NAME_TYPE (float_type_node, "float" ); |
1395 | NAME_TYPE (double_type_node, "double" ); |
1396 | NAME_TYPE (long_double_type_node, "long double" ); |
1397 | NAME_TYPE (void_type_node, "void" ); |
1398 | NAME_TYPE (boolean_type_node, "bool" ); |
1399 | NAME_TYPE (complex_float_type_node, "complex float" ); |
1400 | NAME_TYPE (complex_double_type_node, "complex double" ); |
1401 | NAME_TYPE (complex_long_double_type_node, "complex long double" ); |
1402 | for (i = 0; i < NUM_INT_N_ENTS; i++) |
1403 | if (int_n_enabled_p[i]) |
1404 | { |
1405 | char name[50]; |
1406 | sprintf (s: name, format: "__int%d" , int_n_data[i].bitsize); |
1407 | NAME_TYPE (int_n_trees[i].signed_type, name); |
1408 | } |
1409 | #undef NAME_TYPE |
1410 | |
1411 | return true; |
1412 | } |
1413 | |
1414 | /* Register c++-specific dumps. */ |
1415 | |
1416 | void |
1417 | lto_register_dumps (gcc::dump_manager *dumps) |
1418 | { |
1419 | lto_link_dump_id = dumps->dump_register |
1420 | (suffix: ".lto-link" , swtch: "ipa-lto-link" , glob: "ipa-lto-link" , |
1421 | dkind: DK_ipa, optgroup_flags: OPTGROUP_NONE, take_ownership: false); |
1422 | decl_merge_dump_id = dumps->dump_register |
1423 | (suffix: ".lto-decl-merge" , swtch: "ipa-lto-decl-merge" , glob: "ipa-lto-decl-merge" , |
1424 | dkind: DK_ipa, optgroup_flags: OPTGROUP_NONE, take_ownership: false); |
1425 | partition_dump_id = dumps->dump_register |
1426 | (suffix: ".lto-partition" , swtch: "ipa-lto-partition" , glob: "ipa-lto-partition" , |
1427 | dkind: DK_ipa, optgroup_flags: OPTGROUP_NONE, take_ownership: false); |
1428 | } |
1429 | |
1430 | |
1431 | /* Initialize tree structures required by the LTO front end. */ |
1432 | |
1433 | static void lto_init_ts (void) |
1434 | { |
1435 | tree_contains_struct[NAMESPACE_DECL][TS_DECL_MINIMAL] = 1; |
1436 | } |
1437 | |
1438 | #undef LANG_HOOKS_NAME |
1439 | #define LANG_HOOKS_NAME "GNU GIMPLE" |
1440 | #undef LANG_HOOKS_OPTION_LANG_MASK |
1441 | #define LANG_HOOKS_OPTION_LANG_MASK lto_option_lang_mask |
1442 | #undef LANG_HOOKS_COMPLAIN_WRONG_LANG_P |
1443 | #define LANG_HOOKS_COMPLAIN_WRONG_LANG_P lto_complain_wrong_lang_p |
1444 | #undef LANG_HOOKS_INIT_OPTIONS_STRUCT |
1445 | #define LANG_HOOKS_INIT_OPTIONS_STRUCT lto_init_options_struct |
1446 | #undef LANG_HOOKS_REGISTER_DUMPS |
1447 | #define LANG_HOOKS_REGISTER_DUMPS lto_register_dumps |
1448 | #undef LANG_HOOKS_HANDLE_OPTION |
1449 | #define LANG_HOOKS_HANDLE_OPTION lto_handle_option |
1450 | #undef LANG_HOOKS_POST_OPTIONS |
1451 | #define LANG_HOOKS_POST_OPTIONS lto_post_options |
1452 | #undef LANG_HOOKS_GET_ALIAS_SET |
1453 | #define LANG_HOOKS_GET_ALIAS_SET gimple_get_alias_set |
1454 | #undef LANG_HOOKS_TYPE_FOR_MODE |
1455 | #define LANG_HOOKS_TYPE_FOR_MODE lto_type_for_mode |
1456 | #undef LANG_HOOKS_SET_DECL_ASSEMBLER_NAME |
1457 | #define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME lto_set_decl_assembler_name |
1458 | #undef LANG_HOOKS_GLOBAL_BINDINGS_P |
1459 | #define LANG_HOOKS_GLOBAL_BINDINGS_P lto_global_bindings_p |
1460 | #undef LANG_HOOKS_PUSHDECL |
1461 | #define LANG_HOOKS_PUSHDECL lto_pushdecl |
1462 | #undef LANG_HOOKS_GETDECLS |
1463 | #define LANG_HOOKS_GETDECLS lto_getdecls |
1464 | #undef LANG_HOOKS_REGISTER_BUILTIN_TYPE |
1465 | #define LANG_HOOKS_REGISTER_BUILTIN_TYPE lto_register_builtin_type |
1466 | #undef LANG_HOOKS_BUILTIN_FUNCTION |
1467 | #define LANG_HOOKS_BUILTIN_FUNCTION lto_builtin_function |
1468 | #undef LANG_HOOKS_INIT |
1469 | #define LANG_HOOKS_INIT lto_init |
1470 | #undef LANG_HOOKS_PARSE_FILE |
1471 | #define LANG_HOOKS_PARSE_FILE lto_main |
1472 | #undef LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS |
1473 | #define LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS true |
1474 | #undef LANG_HOOKS_TYPES_COMPATIBLE_P |
1475 | #define LANG_HOOKS_TYPES_COMPATIBLE_P NULL |
1476 | #undef LANG_HOOKS_EH_PERSONALITY |
1477 | #define LANG_HOOKS_EH_PERSONALITY lto_eh_personality |
1478 | |
1479 | /* Attribute hooks. */ |
1480 | #undef LANG_HOOKS_ATTRIBUTE_TABLE |
1481 | #define LANG_HOOKS_ATTRIBUTE_TABLE lto_attribute_table |
1482 | |
1483 | #undef LANG_HOOKS_BEGIN_SECTION |
1484 | #define LANG_HOOKS_BEGIN_SECTION lto_obj_begin_section |
1485 | #undef LANG_HOOKS_APPEND_DATA |
1486 | #define LANG_HOOKS_APPEND_DATA lto_obj_append_data |
1487 | #undef LANG_HOOKS_END_SECTION |
1488 | #define LANG_HOOKS_END_SECTION lto_obj_end_section |
1489 | |
1490 | #undef LANG_HOOKS_INIT_TS |
1491 | #define LANG_HOOKS_INIT_TS lto_init_ts |
1492 | |
1493 | struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; |
1494 | |
1495 | /* Language hooks that are not part of lang_hooks. */ |
1496 | |
1497 | tree |
1498 | convert (tree type ATTRIBUTE_UNUSED, tree expr ATTRIBUTE_UNUSED) |
1499 | { |
1500 | gcc_unreachable (); |
1501 | } |
1502 | |
1503 | /* Tree walking support. */ |
1504 | |
1505 | static enum lto_tree_node_structure_enum |
1506 | lto_tree_node_structure (union lang_tree_node *t ATTRIBUTE_UNUSED) |
1507 | { |
1508 | return TS_LTO_GENERIC; |
1509 | } |
1510 | |
1511 | #include "gtype-lto.h" |
1512 | #include "gt-lto-lto-lang.h" |
1513 | |