Branch data Line data Source code
1 : : /* jit.c -- Dummy "frontend" for use during JIT-compilation.
2 : : Copyright (C) 2013-2025 Free Software Foundation, Inc.
3 : :
4 : : This file is part of GCC.
5 : :
6 : : GCC is free software; you can redistribute it and/or modify it under
7 : : the terms of the GNU General Public License as published by the Free
8 : : Software Foundation; either version 3, or (at your option) any later
9 : : version.
10 : :
11 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : : for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along with GCC; see the file COPYING3. If not see
18 : : <http://www.gnu.org/licenses/>. */
19 : :
20 : : #include "config.h"
21 : : #include "system.h"
22 : : #include "coretypes.h"
23 : : #include "target.h"
24 : : #include "jit-playback.h"
25 : : #include "stor-layout.h"
26 : : #include "debug.h"
27 : : #include "langhooks.h"
28 : : #include "langhooks-def.h"
29 : : #include "diagnostic.h"
30 : : #include "options.h"
31 : : #include "stringpool.h"
32 : : #include "attribs.h"
33 : : #include "cgraph.h"
34 : : #include "target.h"
35 : : #include "diagnostic-format-text.h"
36 : : #include "print-tree.h"
37 : :
38 : : #include <mpfr.h>
39 : : #include <unordered_map>
40 : :
41 : : using namespace gcc::jit;
42 : :
43 : : /* Attribute handling. */
44 : :
45 : : static tree handle_alias_attribute (tree *, tree, tree, int, bool *);
46 : : static tree handle_always_inline_attribute (tree *, tree, tree, int,
47 : : bool *);
48 : : static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
49 : : static tree handle_const_attribute (tree *, tree, tree, int, bool *);
50 : : static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
51 : : static tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
52 : : static tree handle_format_attribute (tree *, tree, tree, int, bool *);
53 : : static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
54 : : static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
55 : : static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
56 : : static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
57 : : static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
58 : : static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
59 : : static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
60 : : static tree handle_patchable_function_entry_attribute (tree *, tree, tree,
61 : : int, bool *);
62 : : static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
63 : : static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
64 : : static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
65 : : static tree handle_target_attribute (tree *, tree, tree, int, bool *);
66 : : static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
67 : : static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
68 : : static tree handle_used_attribute (tree *, tree, tree, int, bool *);
69 : : static tree handle_visibility_attribute (tree *, tree, tree, int,
70 : : bool *);
71 : : static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
72 : :
73 : : static tree ignore_attribute (tree *, tree, tree, int, bool *);
74 : :
75 : : /* Helper to define attribute exclusions. */
76 : : #define ATTR_EXCL(name, function, type, variable) \
77 : : { name, function, type, variable }
78 : :
79 : : /* Define attributes that are mutually exclusive with one another. */
80 : : static const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
81 : : {
82 : : ATTR_EXCL ("alloc_align", true, true, true),
83 : : ATTR_EXCL ("alloc_size", true, true, true),
84 : : ATTR_EXCL ("const", true, true, true),
85 : : ATTR_EXCL ("malloc", true, true, true),
86 : : ATTR_EXCL ("pure", true, true, true),
87 : : ATTR_EXCL ("returns_twice", true, true, true),
88 : : ATTR_EXCL ("warn_unused_result", true, true, true),
89 : : ATTR_EXCL (NULL, false, false, false),
90 : : };
91 : :
92 : : static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] =
93 : : {
94 : : ATTR_EXCL ("noreturn", true, true, true),
95 : : ATTR_EXCL (NULL, false, false, false),
96 : : };
97 : :
98 : : /* Exclusions that apply to attribute alloc_align, alloc_size, and malloc. */
99 : : static const struct attribute_spec::exclusions attr_alloc_exclusions[] =
100 : : {
101 : : ATTR_EXCL ("const", true, true, true),
102 : : ATTR_EXCL ("noreturn", true, true, true),
103 : : ATTR_EXCL ("pure", true, true, true),
104 : : ATTR_EXCL (NULL, false, false, false),
105 : : };
106 : :
107 : : static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
108 : : {
109 : : ATTR_EXCL ("const", true, true, true),
110 : : ATTR_EXCL ("alloc_align", true, true, true),
111 : : ATTR_EXCL ("alloc_size", true, true, true),
112 : : ATTR_EXCL ("malloc", true, true, true),
113 : : ATTR_EXCL ("noreturn", true, true, true),
114 : : ATTR_EXCL ("pure", true, true, true),
115 : : ATTR_EXCL (NULL, false, false, false)
116 : : };
117 : :
118 : : static const struct attribute_spec::exclusions attr_always_inline_exclusions[] =
119 : : {
120 : : ATTR_EXCL ("noinline", true, true, true),
121 : : ATTR_EXCL ("target_clones", true, true, true),
122 : : ATTR_EXCL (NULL, false, false, false),
123 : : };
124 : :
125 : : extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[] =
126 : : {
127 : : ATTR_EXCL ("cold", true, true, true),
128 : : ATTR_EXCL ("hot", true, true, true),
129 : : ATTR_EXCL (NULL, false, false, false)
130 : : };
131 : :
132 : : static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
133 : : {
134 : : ATTR_EXCL ("always_inline", true, true, true),
135 : : ATTR_EXCL ("gnu_inline", true, true, true),
136 : : ATTR_EXCL (NULL, false, false, false),
137 : : };
138 : :
139 : : static const struct attribute_spec::exclusions attr_target_exclusions[] =
140 : : {
141 : : ATTR_EXCL ("target_clones", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
142 : : TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE),
143 : : ATTR_EXCL (NULL, false, false, false),
144 : : };
145 : :
146 : : /* These variables act as a cache for the target builtins. This is needed in
147 : : order to be able to type-check the calls since we can only get those types
148 : : in the playback phase while we need them in the recording phase. */
149 : : hash_map<nofree_string_hash, tree> target_builtins{};
150 : : std::unordered_map<std::string, recording::function_type*> target_function_types
151 : : {};
152 : : recording::context target_builtins_ctxt{NULL};
153 : :
154 : : /* Table of machine-independent attributes supported in libgccjit. */
155 : : static const attribute_spec jit_gnu_attributes[] =
156 : : {
157 : : /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
158 : : affects_type_identity, handler, exclude } */
159 : : { "alias", 1, 1, true, false, false, false,
160 : : handle_alias_attribute, NULL },
161 : : { "always_inline", 0, 0, true, false, false, false,
162 : : handle_always_inline_attribute,
163 : : attr_always_inline_exclusions },
164 : : { "cold", 0, 0, true, false, false, false,
165 : : handle_cold_attribute,
166 : : attr_cold_hot_exclusions },
167 : : /* The same comments as for noreturn attributes apply to const ones. */
168 : : { "const", 0, 0, true, false, false, false,
169 : : handle_const_attribute,
170 : : attr_const_pure_exclusions },
171 : : { "fn spec", 1, 1, false, true, true, false,
172 : : handle_fnspec_attribute, NULL },
173 : :
174 : : { "leaf", 0, 0, true, false, false, false,
175 : : handle_leaf_attribute, NULL },
176 : : { "malloc", 0, 0, true, false, false, false,
177 : : handle_malloc_attribute, attr_alloc_exclusions },
178 : : { "noreturn", 0, 0, true, false, false, false,
179 : : handle_noreturn_attribute,
180 : : attr_noreturn_exclusions },
181 : : { "no vops", 0, 0, true, false, false, false,
182 : : handle_novops_attribute, NULL },
183 : : { "noinline", 0, 0, true, false, false, false,
184 : : handle_noinline_attribute,
185 : : attr_noinline_exclusions },
186 : : { "nonnull", 0, -1, false, true, true, false,
187 : : handle_nonnull_attribute, NULL },
188 : : { "nothrow", 0, 0, true, false, false, false,
189 : : handle_nothrow_attribute, NULL },
190 : : { "patchable_function_entry", 1, 2, true, false, false, false,
191 : : handle_patchable_function_entry_attribute,
192 : : NULL },
193 : : { "pure", 0, 0, true, false, false, false,
194 : : handle_pure_attribute,
195 : : attr_const_pure_exclusions },
196 : : { "returns_twice", 0, 0, true, false, false, false,
197 : : handle_returns_twice_attribute,
198 : : attr_returns_twice_exclusions },
199 : : { "sentinel", 0, 1, false, true, true, false,
200 : : handle_sentinel_attribute, NULL },
201 : : { "target", 1, -1, true, false, false, false,
202 : : handle_target_attribute, attr_target_exclusions },
203 : : { "type generic", 0, 0, false, true, true, false,
204 : : handle_type_generic_attribute, NULL },
205 : : { "transaction_pure", 0, 0, false, true, true, false,
206 : : handle_transaction_pure_attribute, NULL },
207 : : { "used", 0, 0, true, false, false, false,
208 : : handle_used_attribute, NULL },
209 : : { "visibility", 1, 1, false, false, false, false,
210 : : handle_visibility_attribute, NULL },
211 : : { "weak", 0, 0, true, false, false, false,
212 : : handle_weak_attribute, NULL },
213 : : /* For internal use only. The leading '*' both prevents its usage in
214 : : source code and signals that it may be overridden by machine tables. */
215 : : { "*tm regparm", 0, 0, false, true, true, false,
216 : : ignore_attribute, NULL },
217 : : };
218 : :
219 : : static const scoped_attribute_specs jit_gnu_attribute_table =
220 : : {
221 : : "gnu", { jit_gnu_attributes }
222 : : };
223 : :
224 : : /* Give the specifications for the format attributes, used by C and all
225 : : descendants. */
226 : :
227 : : static const attribute_spec jit_format_attributes[] =
228 : : {
229 : : /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
230 : : affects_type_identity, handler, exclude } */
231 : : { "format", 3, 3, false, true, true, false,
232 : : handle_format_attribute, NULL },
233 : : { "format_arg", 1, 1, false, true, true, false,
234 : : handle_format_arg_attribute, NULL }
235 : : };
236 : :
237 : : static const scoped_attribute_specs jit_format_attribute_table =
238 : : {
239 : : "gnu", { jit_format_attributes }
240 : : };
241 : :
242 : : static const scoped_attribute_specs *const jit_attribute_table[] =
243 : : {
244 : : &jit_gnu_attribute_table,
245 : : &jit_format_attribute_table
246 : : };
247 : :
248 : : /* Attribute handlers. */
249 : :
250 : : /* Handle a "noreturn" attribute; arguments as in
251 : : struct attribute_spec.handler. */
252 : :
253 : : static tree
254 : 1219 : handle_noreturn_attribute (tree *node, tree ARG_UNUSED (name),
255 : : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
256 : : bool * ARG_UNUSED (no_add_attrs))
257 : : {
258 : 1219 : tree type = TREE_TYPE (*node);
259 : :
260 : 1219 : if (TREE_CODE (*node) == FUNCTION_DECL)
261 : 1219 : TREE_THIS_VOLATILE (*node) = 1;
262 : 0 : else if (TREE_CODE (type) == POINTER_TYPE
263 : 0 : && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
264 : 0 : TREE_TYPE (*node)
265 : 0 : = build_pointer_type
266 : 0 : (build_type_variant (TREE_TYPE (type),
267 : : TYPE_READONLY (TREE_TYPE (type)), 1));
268 : : else
269 : 0 : gcc_unreachable ();
270 : :
271 : 1219 : return NULL_TREE;
272 : : }
273 : :
274 : : /* Handle a "leaf" attribute; arguments as in
275 : : struct attribute_spec.handler. */
276 : :
277 : : static tree
278 : 12365 : handle_leaf_attribute (tree *node, tree name,
279 : : tree ARG_UNUSED (args),
280 : : int ARG_UNUSED (flags), bool *no_add_attrs)
281 : : {
282 : 12365 : if (TREE_CODE (*node) != FUNCTION_DECL)
283 : : {
284 : 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
285 : 0 : *no_add_attrs = true;
286 : : }
287 : 12365 : if (!TREE_PUBLIC (*node))
288 : : {
289 : 0 : warning (OPT_Wattributes, "%qE attribute has no effect on unit local functions", name);
290 : 0 : *no_add_attrs = true;
291 : : }
292 : :
293 : 12365 : return NULL_TREE;
294 : : }
295 : :
296 : : /* Handle a "const" attribute; arguments as in
297 : : struct attribute_spec.handler. */
298 : :
299 : : static tree
300 : 10981 : handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
301 : : int ARG_UNUSED (flags), bool *no_add_attrs)
302 : : {
303 : 10981 : tree type = TREE_TYPE (*node);
304 : :
305 : : /* See FIXME comment on noreturn in c_common_attribute_table. */
306 : 10981 : if (TREE_CODE (*node) == FUNCTION_DECL)
307 : 10981 : TREE_READONLY (*node) = 1;
308 : 0 : else if (TREE_CODE (type) == POINTER_TYPE
309 : 0 : && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
310 : 0 : TREE_TYPE (*node)
311 : 0 : = (build_qualified_type
312 : 0 : (build_pointer_type
313 : 0 : (build_type_variant (TREE_TYPE (type), 1,
314 : : TREE_THIS_VOLATILE (TREE_TYPE (type)))),
315 : 0 : TYPE_QUALS (type)));
316 : : else
317 : : {
318 : 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
319 : 0 : *no_add_attrs = true;
320 : : }
321 : :
322 : 10981 : return NULL_TREE;
323 : : }
324 : :
325 : :
326 : : /* Handle a "malloc" attribute; arguments as in
327 : : struct attribute_spec.handler. */
328 : :
329 : : static tree
330 : 0 : handle_malloc_attribute (tree *node, tree ARG_UNUSED (name),
331 : : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
332 : : bool * ARG_UNUSED (no_add_attrs))
333 : : {
334 : 0 : if (TREE_CODE (*node) == FUNCTION_DECL
335 : 0 : && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
336 : 0 : DECL_IS_MALLOC (*node) = 1;
337 : : else
338 : 0 : gcc_unreachable ();
339 : :
340 : 0 : return NULL_TREE;
341 : : }
342 : :
343 : :
344 : : /* Handle a "pure" attribute; arguments as in
345 : : struct attribute_spec.handler. */
346 : :
347 : : static tree
348 : 20 : handle_pure_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 : 20 : if (TREE_CODE (*node) == FUNCTION_DECL)
353 : 20 : DECL_PURE_P (*node) = 1;
354 : : else
355 : 0 : gcc_unreachable ();
356 : :
357 : 20 : return NULL_TREE;
358 : : }
359 : :
360 : :
361 : : /* Handle a "no vops" attribute; arguments as in
362 : : struct attribute_spec.handler. */
363 : :
364 : : static tree
365 : 0 : handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
366 : : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
367 : : bool *ARG_UNUSED (no_add_attrs))
368 : : {
369 : 0 : gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
370 : 0 : DECL_IS_NOVOPS (*node) = 1;
371 : 0 : return NULL_TREE;
372 : : }
373 : :
374 : :
375 : : /* Helper for nonnull attribute handling; fetch the operand number
376 : : from the attribute argument list. */
377 : :
378 : : static bool
379 : 5 : get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
380 : : {
381 : : /* Verify the arg number is a constant. */
382 : 5 : if (!tree_fits_uhwi_p (arg_num_expr))
383 : : return false;
384 : :
385 : 5 : *valp = TREE_INT_CST_LOW (arg_num_expr);
386 : 5 : return true;
387 : : }
388 : :
389 : : /* Handle the "nonnull" attribute. */
390 : :
391 : : static tree
392 : 80 : handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
393 : : tree args, int ARG_UNUSED (flags),
394 : : bool * ARG_UNUSED (no_add_attrs))
395 : : {
396 : 80 : tree type = *node;
397 : :
398 : : /* If no arguments are specified, all pointer arguments should be
399 : : non-null. Verify a full prototype is given so that the arguments
400 : : will have the correct types when we actually check them later.
401 : : Avoid diagnosing type-generic built-ins since those have no
402 : : prototype. */
403 : 80 : if (!args)
404 : : {
405 : 75 : gcc_assert (prototype_p (type)
406 : : || !TYPE_ATTRIBUTES (type)
407 : : || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type)));
408 : :
409 : 75 : return NULL_TREE;
410 : : }
411 : :
412 : : /* Argument list specified. Verify that each argument number references
413 : : a pointer argument. */
414 : 10 : for (; args; args = TREE_CHAIN (args))
415 : : {
416 : 5 : tree argument;
417 : 5 : unsigned HOST_WIDE_INT arg_num = 0, ck_num;
418 : :
419 : 5 : if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
420 : 0 : gcc_unreachable ();
421 : :
422 : 5 : argument = TYPE_ARG_TYPES (type);
423 : 5 : if (argument)
424 : : {
425 : 0 : for (ck_num = 1; ; ck_num++)
426 : : {
427 : 5 : if (!argument || ck_num == arg_num)
428 : : break;
429 : 0 : argument = TREE_CHAIN (argument);
430 : : }
431 : :
432 : 5 : gcc_assert (argument
433 : : && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE);
434 : : }
435 : : }
436 : :
437 : : return NULL_TREE;
438 : : }
439 : :
440 : :
441 : : /* Handle a "nothrow" attribute; arguments as in
442 : : struct attribute_spec.handler. */
443 : :
444 : : static tree
445 : 12350 : handle_nothrow_attribute (tree *node, tree ARG_UNUSED (name),
446 : : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
447 : : bool * ARG_UNUSED (no_add_attrs))
448 : : {
449 : 12350 : if (TREE_CODE (*node) == FUNCTION_DECL)
450 : 12350 : TREE_NOTHROW (*node) = 1;
451 : : else
452 : 0 : gcc_unreachable ();
453 : :
454 : 12350 : return NULL_TREE;
455 : : }
456 : :
457 : :
458 : : /* Handle a "sentinel" attribute. */
459 : :
460 : : static tree
461 : 0 : handle_sentinel_attribute (tree *node, tree ARG_UNUSED (name), tree args,
462 : : int ARG_UNUSED (flags),
463 : : bool * ARG_UNUSED (no_add_attrs))
464 : : {
465 : 0 : gcc_assert (stdarg_p (*node));
466 : :
467 : 0 : if (args)
468 : : {
469 : 0 : tree position = TREE_VALUE (args);
470 : 0 : gcc_assert (TREE_CODE (position) == INTEGER_CST);
471 : 0 : if (tree_int_cst_lt (position, integer_zero_node))
472 : 0 : gcc_unreachable ();
473 : : }
474 : :
475 : 0 : return NULL_TREE;
476 : : }
477 : :
478 : : /* Handle a "type_generic" attribute. */
479 : :
480 : : static tree
481 : 45 : handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
482 : : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
483 : : bool * ARG_UNUSED (no_add_attrs))
484 : : {
485 : : /* Ensure we have a function type. */
486 : 45 : gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
487 : :
488 : : /* Ensure we have a variadic function. */
489 : 45 : gcc_assert (!prototype_p (*node) || stdarg_p (*node));
490 : :
491 : 45 : return NULL_TREE;
492 : : }
493 : :
494 : : /* Handle a "transaction_pure" attribute. */
495 : :
496 : : static tree
497 : 0 : handle_transaction_pure_attribute (tree *node, tree ARG_UNUSED (name),
498 : : tree ARG_UNUSED (args),
499 : : int ARG_UNUSED (flags),
500 : : bool * ARG_UNUSED (no_add_attrs))
501 : : {
502 : : /* Ensure we have a function type. */
503 : 0 : gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
504 : :
505 : 0 : return NULL_TREE;
506 : : }
507 : :
508 : : /* Handle a "returns_twice" attribute. */
509 : :
510 : : static tree
511 : 0 : handle_returns_twice_attribute (tree *node, tree ARG_UNUSED (name),
512 : : tree ARG_UNUSED (args),
513 : : int ARG_UNUSED (flags),
514 : : bool * ARG_UNUSED (no_add_attrs))
515 : : {
516 : 0 : gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
517 : :
518 : 0 : DECL_IS_RETURNS_TWICE (*node) = 1;
519 : :
520 : 0 : return NULL_TREE;
521 : : }
522 : :
523 : : static tree
524 : 0 : handle_patchable_function_entry_attribute (tree *, tree, tree, int, bool *)
525 : : {
526 : : /* Nothing to be done here. */
527 : 0 : return NULL_TREE;
528 : : }
529 : :
530 : : /* Ignore the given attribute. Used when this attribute may be usefully
531 : : overridden by the target, but is not used generically. */
532 : :
533 : : static tree
534 : 0 : ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
535 : : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
536 : : bool *no_add_attrs)
537 : : {
538 : 0 : *no_add_attrs = true;
539 : 0 : return NULL_TREE;
540 : : }
541 : :
542 : : /* Handle a "format" attribute; arguments as in
543 : : struct attribute_spec.handler. */
544 : :
545 : : static tree
546 : 0 : handle_format_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
547 : : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
548 : : bool *no_add_attrs)
549 : : {
550 : 0 : *no_add_attrs = true;
551 : 0 : return NULL_TREE;
552 : : }
553 : :
554 : :
555 : : /* Handle a "format_arg" attribute; arguments as in
556 : : struct attribute_spec.handler. */
557 : :
558 : : tree
559 : 0 : handle_format_arg_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
560 : : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
561 : : bool *no_add_attrs)
562 : : {
563 : 0 : *no_add_attrs = true;
564 : 0 : return NULL_TREE;
565 : : }
566 : :
567 : :
568 : : /* Handle a "fn spec" attribute; arguments as in
569 : : struct attribute_spec.handler. */
570 : :
571 : : static tree
572 : 0 : handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name),
573 : : tree args, int ARG_UNUSED (flags),
574 : : bool *no_add_attrs ATTRIBUTE_UNUSED)
575 : : {
576 : 0 : gcc_assert (args
577 : : && TREE_CODE (TREE_VALUE (args)) == STRING_CST
578 : : && !TREE_CHAIN (args));
579 : 0 : return NULL_TREE;
580 : : }
581 : :
582 : : /* Handle an "visibility" attribute; arguments as in
583 : : struct attribute_spec.handler. */
584 : :
585 : : static tree
586 : 5 : handle_visibility_attribute (tree *node, tree name, tree args,
587 : : int ARG_UNUSED (flags),
588 : : bool *ARG_UNUSED (no_add_attrs))
589 : : {
590 : 5 : tree decl = *node;
591 : 5 : tree id = TREE_VALUE (args);
592 : 5 : enum symbol_visibility vis;
593 : :
594 : 5 : if (TYPE_P (*node))
595 : : {
596 : 0 : if (TREE_CODE (*node) == ENUMERAL_TYPE)
597 : : /* OK. */;
598 : 0 : else if (!RECORD_OR_UNION_TYPE_P (*node))
599 : : {
600 : 0 : warning (OPT_Wattributes, "%qE attribute ignored on non-class types",
601 : : name);
602 : 0 : return NULL_TREE;
603 : : }
604 : 0 : else if (TYPE_FIELDS (*node))
605 : : {
606 : 0 : error ("%qE attribute ignored because %qT is already defined",
607 : : name, *node);
608 : 0 : return NULL_TREE;
609 : : }
610 : : }
611 : 5 : else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl))
612 : : {
613 : 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
614 : 0 : return NULL_TREE;
615 : : }
616 : :
617 : 5 : if (TREE_CODE (id) != STRING_CST)
618 : : {
619 : 0 : error ("visibility argument not a string");
620 : 0 : return NULL_TREE;
621 : : }
622 : :
623 : : /* If this is a type, set the visibility on the type decl. */
624 : 5 : if (TYPE_P (decl))
625 : : {
626 : 0 : decl = TYPE_NAME (decl);
627 : 0 : if (!decl)
628 : : return NULL_TREE;
629 : 0 : if (TREE_CODE (decl) == IDENTIFIER_NODE)
630 : : {
631 : 0 : warning (OPT_Wattributes, "%qE attribute ignored on types",
632 : : name);
633 : 0 : return NULL_TREE;
634 : : }
635 : : }
636 : :
637 : 5 : if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
638 : : vis = VISIBILITY_DEFAULT;
639 : 5 : else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0)
640 : : vis = VISIBILITY_INTERNAL;
641 : 5 : else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0)
642 : : vis = VISIBILITY_HIDDEN;
643 : 0 : else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0)
644 : : vis = VISIBILITY_PROTECTED;
645 : : else
646 : : {
647 : 0 : error ("attribute %qE argument must be one of %qs, %qs, %qs, or %qs",
648 : : name, "default", "hidden", "protected", "internal");
649 : 0 : vis = VISIBILITY_DEFAULT;
650 : : }
651 : :
652 : 5 : if (DECL_VISIBILITY_SPECIFIED (decl)
653 : 5 : && vis != DECL_VISIBILITY (decl))
654 : : {
655 : 0 : tree attributes = (TYPE_P (*node)
656 : 0 : ? TYPE_ATTRIBUTES (*node)
657 : 0 : : DECL_ATTRIBUTES (decl));
658 : 0 : if (lookup_attribute ("visibility", attributes))
659 : 0 : error ("%qD redeclared with different visibility", decl);
660 : : else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
661 : : && lookup_attribute ("dllimport", attributes))
662 : : error ("%qD was declared %qs which implies default visibility",
663 : : decl, "dllimport");
664 : : else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
665 : : && lookup_attribute ("dllexport", attributes))
666 : : error ("%qD was declared %qs which implies default visibility",
667 : : decl, "dllexport");
668 : : }
669 : :
670 : 5 : DECL_VISIBILITY (decl) = vis;
671 : 5 : DECL_VISIBILITY_SPECIFIED (decl) = 1;
672 : :
673 : : /* Go ahead and attach the attribute to the node as well. This is needed
674 : : so we can determine whether we have VISIBILITY_DEFAULT because the
675 : : visibility was not specified, or because it was explicitly overridden
676 : : from the containing scope. */
677 : :
678 : 5 : return NULL_TREE;
679 : : }
680 : :
681 : : /* Handle a "always_inline" attribute; arguments as in
682 : : struct attribute_spec.handler. */
683 : :
684 : : static tree
685 : 20 : handle_always_inline_attribute (tree *node, tree name,
686 : : tree ARG_UNUSED (args),
687 : : int ARG_UNUSED (flags),
688 : : bool *no_add_attrs)
689 : : {
690 : 20 : if (TREE_CODE (*node) == FUNCTION_DECL)
691 : : {
692 : : /* Set the attribute and mark it for disregarding inline
693 : : limits. */
694 : 20 : DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
695 : : }
696 : : else
697 : : {
698 : 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
699 : 0 : *no_add_attrs = true;
700 : : }
701 : :
702 : 20 : return NULL_TREE;
703 : : }
704 : :
705 : : /* Handle a "cold" and attribute; arguments as in
706 : : struct attribute_spec.handler. */
707 : :
708 : : static tree
709 : 1224 : handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
710 : : int ARG_UNUSED (flags), bool *no_add_attrs)
711 : : {
712 : 1224 : if (TREE_CODE (*node) == FUNCTION_DECL
713 : 1224 : || TREE_CODE (*node) == LABEL_DECL)
714 : : {
715 : : /* Attribute cold processing is done later with lookup_attribute. */
716 : : }
717 : : else
718 : : {
719 : 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
720 : 0 : *no_add_attrs = true;
721 : : }
722 : :
723 : 1224 : return NULL_TREE;
724 : : }
725 : :
726 : : /* Handle a "noinline" attribute; arguments as in
727 : : struct attribute_spec.handler. */
728 : :
729 : : static tree
730 : 5 : handle_noinline_attribute (tree *node, tree name,
731 : : tree ARG_UNUSED (args),
732 : : int ARG_UNUSED (flags), bool *no_add_attrs)
733 : : {
734 : 5 : if (TREE_CODE (*node) == FUNCTION_DECL)
735 : 5 : DECL_UNINLINABLE (*node) = 1;
736 : : else
737 : : {
738 : 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
739 : 0 : *no_add_attrs = true;
740 : : }
741 : :
742 : 5 : return NULL_TREE;
743 : : }
744 : :
745 : : /* Handle a "weak" attribute; arguments as in
746 : : struct attribute_spec.handler. */
747 : :
748 : : static tree
749 : 5 : handle_weak_attribute (tree *node, tree name,
750 : : tree ARG_UNUSED (args),
751 : : int ARG_UNUSED (flags),
752 : : bool * ARG_UNUSED (no_add_attrs))
753 : : {
754 : 5 : if (TREE_CODE (*node) == FUNCTION_DECL
755 : 5 : && DECL_DECLARED_INLINE_P (*node))
756 : : {
757 : 0 : warning (OPT_Wattributes, "inline function %q+D declared weak", *node);
758 : 0 : *no_add_attrs = true;
759 : : }
760 : 5 : else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (*node)))
761 : : {
762 : 0 : error ("indirect function %q+D cannot be declared weak", *node);
763 : 0 : *no_add_attrs = true;
764 : 0 : return NULL_TREE;
765 : : }
766 : 5 : else if (VAR_OR_FUNCTION_DECL_P (*node))
767 : 5 : declare_weak (*node);
768 : : else
769 : 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
770 : :
771 : : return NULL_TREE;
772 : : }
773 : :
774 : : /* Handle a "target" attribute. */
775 : :
776 : : static tree
777 : 0 : handle_target_attribute (tree *node, tree name, tree args, int flags,
778 : : bool *no_add_attrs)
779 : : {
780 : : /* Ensure we have a function declaration. */
781 : 0 : if (TREE_CODE (*node) != FUNCTION_DECL)
782 : : {
783 : 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
784 : 0 : *no_add_attrs = true;
785 : : }
786 : 0 : else if (! targetm.target_option.valid_attribute_p (*node, name, args,
787 : : flags))
788 : 0 : *no_add_attrs = true;
789 : :
790 : : /* Check that there's no empty string in values of the attribute. */
791 : 0 : for (tree t = args; t != NULL_TREE; t = TREE_CHAIN (t))
792 : : {
793 : 0 : tree value = TREE_VALUE (t);
794 : 0 : if (TREE_CODE (value) == STRING_CST
795 : 0 : && TREE_STRING_LENGTH (value) == 1
796 : 0 : && TREE_STRING_POINTER (value)[0] == '\0')
797 : : {
798 : 0 : warning (OPT_Wattributes, "empty string in attribute %<target%>");
799 : 0 : *no_add_attrs = true;
800 : : }
801 : : }
802 : :
803 : 0 : return NULL_TREE;
804 : : }
805 : :
806 : : /* Handle a "used" attribute; arguments as in
807 : : struct attribute_spec.handler. */
808 : :
809 : : static tree
810 : 5 : handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
811 : : int ARG_UNUSED (flags), bool *no_add_attrs)
812 : : {
813 : 5 : tree node = *pnode;
814 : :
815 : 5 : if (TREE_CODE (node) == FUNCTION_DECL
816 : 0 : || (VAR_P (node) && TREE_STATIC (node))
817 : 0 : || (TREE_CODE (node) == TYPE_DECL))
818 : : {
819 : 5 : TREE_USED (node) = 1;
820 : 5 : DECL_PRESERVE_P (node) = 1;
821 : 5 : if (VAR_P (node))
822 : 0 : DECL_READ_P (node) = 1;
823 : : }
824 : : else
825 : : {
826 : 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
827 : 0 : *no_add_attrs = true;
828 : : }
829 : :
830 : 5 : return NULL_TREE;
831 : : }
832 : :
833 : : /* Handle an "alias" or "ifunc" attribute; arguments as in
834 : : struct attribute_spec.handler, except that IS_ALIAS tells us
835 : : whether this is an alias as opposed to ifunc attribute. */
836 : :
837 : : static tree
838 : 5 : handle_alias_ifunc_attribute (bool is_alias, tree *node, tree name, tree args,
839 : : bool *no_add_attrs)
840 : : {
841 : 5 : tree decl = *node;
842 : :
843 : 5 : if (TREE_CODE (decl) != FUNCTION_DECL
844 : 0 : && (!is_alias || !VAR_P (decl)))
845 : : {
846 : 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
847 : 0 : *no_add_attrs = true;
848 : : }
849 : 5 : else if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
850 : 5 : || (TREE_CODE (decl) != FUNCTION_DECL
851 : 0 : && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
852 : : /* A static variable declaration is always a tentative definition,
853 : : but the alias is a non-tentative definition which overrides. */
854 : 10 : || (TREE_CODE (decl) != FUNCTION_DECL
855 : 0 : && ! TREE_PUBLIC (decl) && DECL_INITIAL (decl)))
856 : : {
857 : 0 : error ("%q+D defined both normally and as %qE attribute", decl, name);
858 : 0 : *no_add_attrs = true;
859 : 0 : return NULL_TREE;
860 : : }
861 : 5 : else if (!is_alias
862 : 5 : && (lookup_attribute ("weak", DECL_ATTRIBUTES (decl))
863 : 0 : || lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))))
864 : : {
865 : 0 : error ("weak %q+D cannot be defined %qE", decl, name);
866 : 0 : *no_add_attrs = true;
867 : 0 : return NULL_TREE;
868 : : }
869 : :
870 : : /* Note that the very first time we process a nested declaration,
871 : : decl_function_context will not be set. Indeed, *would* never
872 : : be set except for the DECL_INITIAL/DECL_EXTERNAL frobbery that
873 : : we do below. After such frobbery, pushdecl would set the context.
874 : : In any case, this is never what we want. */
875 : 5 : else if (decl_function_context (decl) == 0 && current_function_decl == NULL)
876 : : {
877 : 5 : tree id;
878 : :
879 : 5 : id = TREE_VALUE (args);
880 : 5 : if (TREE_CODE (id) != STRING_CST)
881 : : {
882 : 0 : error ("attribute %qE argument not a string", name);
883 : 0 : *no_add_attrs = true;
884 : 0 : return NULL_TREE;
885 : : }
886 : 5 : id = get_identifier (TREE_STRING_POINTER (id));
887 : : /* This counts as a use of the object pointed to. */
888 : 5 : TREE_USED (id) = 1;
889 : :
890 : 5 : if (TREE_CODE (decl) == FUNCTION_DECL)
891 : 5 : DECL_INITIAL (decl) = error_mark_node;
892 : : else
893 : 0 : TREE_STATIC (decl) = 1;
894 : :
895 : 5 : if (!is_alias)
896 : : {
897 : : /* ifuncs are also aliases, so set that attribute too. */
898 : 0 : DECL_ATTRIBUTES (decl)
899 : 0 : = tree_cons (get_identifier ("alias"), args,
900 : 0 : DECL_ATTRIBUTES (decl));
901 : 0 : DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("ifunc"),
902 : 0 : NULL, DECL_ATTRIBUTES (decl));
903 : : }
904 : : }
905 : : else
906 : : {
907 : 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
908 : 0 : *no_add_attrs = true;
909 : : }
910 : :
911 : 5 : if (decl_in_symtab_p (*node))
912 : : {
913 : 5 : struct symtab_node *n = symtab_node::get (decl);
914 : 5 : if (n && n->refuse_visibility_changes)
915 : 0 : error ("%+qD declared %qs after being used",
916 : : decl, is_alias ? "alias" : "ifunc");
917 : : }
918 : :
919 : :
920 : : return NULL_TREE;
921 : : }
922 : :
923 : : /* Handle an "alias" or "ifunc" attribute; arguments as in
924 : : struct attribute_spec.handler. */
925 : :
926 : : static tree
927 : 5 : handle_alias_attribute (tree *node, tree name, tree args,
928 : : int ARG_UNUSED (flags), bool *no_add_attrs)
929 : : {
930 : 5 : return handle_alias_ifunc_attribute (true, node, name, args, no_add_attrs);
931 : : }
932 : :
933 : : /* (end of attribute-handling). */
934 : :
935 : : /* Language-dependent contents of a type. */
936 : :
937 : : struct GTY(()) lang_type
938 : : {
939 : : char dummy;
940 : : };
941 : :
942 : : /* Language-dependent contents of a decl. */
943 : :
944 : : struct GTY((variable_size)) lang_decl
945 : : {
946 : : char dummy;
947 : : };
948 : :
949 : : /* Language-dependent contents of an identifier. This must include a
950 : : tree_identifier. */
951 : :
952 : : struct GTY(()) lang_identifier
953 : : {
954 : : struct tree_identifier common;
955 : : };
956 : :
957 : : /* The resulting tree type. */
958 : :
959 : : union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
960 : : chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL")))
961 : : lang_tree_node
962 : : {
963 : : union tree_node GTY((tag ("0"),
964 : : desc ("tree_node_structure (&%h)"))) generic;
965 : : struct lang_identifier GTY((tag ("1"))) identifier;
966 : : };
967 : :
968 : : /* We don't use language_function. */
969 : :
970 : : struct GTY(()) language_function
971 : : {
972 : : int dummy;
973 : : };
974 : :
975 : : /* GC-marking callback for use from jit_root_tab.
976 : :
977 : : If there's an active playback context, call its marking method
978 : : so that it can mark any pointers it references. */
979 : :
980 : 498519 : static void my_ggc_walker (void *)
981 : : {
982 : 498519 : if (gcc::jit::active_playback_ctxt)
983 : 498519 : gcc::jit::active_playback_ctxt->gt_ggc_mx ();
984 : 498519 : }
985 : :
986 : : const char *dummy;
987 : :
988 : : struct ggc_root_tab jit_root_tab[] =
989 : : {
990 : : {
991 : : &dummy, 1, 0, my_ggc_walker, NULL
992 : : },
993 : : LAST_GGC_ROOT_TAB
994 : : };
995 : :
996 : : /* Subclass of diagnostic_output_format for libgccjit: like text
997 : : output, but capture the message and call add_diagnostic with it
998 : : on the active playback context. */
999 : :
1000 : : class jit_diagnostic_listener : public diagnostic_text_output_format
1001 : : {
1002 : : public:
1003 : 1249 : jit_diagnostic_listener (diagnostic_context &dc,
1004 : : gcc::jit::playback::context &playback_ctxt)
1005 : 1249 : : diagnostic_text_output_format (dc),
1006 : 1249 : m_playback_ctxt (playback_ctxt)
1007 : : {
1008 : : }
1009 : :
1010 : 0 : void dump (FILE *out, int indent) const final override
1011 : : {
1012 : 0 : fprintf (out, "%*sjit_diagnostic_listener\n", indent, "");
1013 : 0 : fprintf (out, "%*sm_playback_context: %p\n",
1014 : : indent + 2, "",
1015 : 0 : (void *)&m_playback_ctxt);
1016 : 0 : }
1017 : :
1018 : 20 : void on_report_diagnostic (const diagnostic_info &info,
1019 : : diagnostic_t orig_diag_kind) final override
1020 : : {
1021 : 20 : JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
1022 : :
1023 : : /* Let the text output format do most of the work. */
1024 : 20 : diagnostic_text_output_format::on_report_diagnostic (info, orig_diag_kind);
1025 : :
1026 : 20 : const char *text = pp_formatted_text (get_printer ());
1027 : :
1028 : : /* Delegate to the playback context (and thence to the
1029 : : recording context). */
1030 : 20 : gcc::jit::active_playback_ctxt->add_diagnostic (text, info);
1031 : :
1032 : 20 : pp_clear_output_area (get_printer ());
1033 : 20 : }
1034 : :
1035 : : private:
1036 : : gcc::jit::playback::context &m_playback_ctxt;
1037 : : };
1038 : :
1039 : : /* JIT-specific implementation of diagnostic callbacks. */
1040 : :
1041 : : /* Implementation of "begin_diagnostic". */
1042 : :
1043 : : static void
1044 : 20 : jit_begin_diagnostic (diagnostic_text_output_format &,
1045 : : const diagnostic_info */*diagnostic*/)
1046 : : {
1047 : 20 : gcc_assert (gcc::jit::active_playback_ctxt);
1048 : 20 : JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
1049 : :
1050 : : /* No-op (apart from logging); the real error-handling is done by the
1051 : : jit_diagnostic_listener. */
1052 : 20 : }
1053 : :
1054 : : /* Implementation of "end_diagnostic". */
1055 : :
1056 : : static void
1057 : 20 : jit_end_diagnostic (diagnostic_text_output_format &,
1058 : : const diagnostic_info *,
1059 : : diagnostic_t)
1060 : : {
1061 : 20 : gcc_assert (gcc::jit::active_playback_ctxt);
1062 : 20 : JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
1063 : :
1064 : : /* No-op (apart from logging); the real error-handling is done by the
1065 : : jit_diagnostic_listener. */
1066 : 20 : }
1067 : :
1068 : : /* Language hooks. */
1069 : :
1070 : : static bool
1071 : 1249 : jit_langhook_init (void)
1072 : : {
1073 : 1249 : gcc_assert (gcc::jit::active_playback_ctxt);
1074 : 1249 : JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
1075 : :
1076 : 1249 : static bool registered_root_tab = false;
1077 : 1249 : if (!registered_root_tab)
1078 : : {
1079 : 123 : ggc_register_root_tab (jit_root_tab);
1080 : 123 : registered_root_tab = true;
1081 : : }
1082 : :
1083 : 1249 : gcc_assert (global_dc);
1084 : 1249 : diagnostic_text_starter (global_dc) = jit_begin_diagnostic;
1085 : 1249 : diagnostic_text_finalizer (global_dc) = jit_end_diagnostic;
1086 : 1249 : auto sink
1087 : : = std::make_unique<jit_diagnostic_listener>
1088 : : (*global_dc,
1089 : 1249 : *gcc::jit::active_playback_ctxt);
1090 : 1249 : global_dc->set_output_format (std::move (sink));
1091 : :
1092 : 1249 : build_common_tree_nodes (flag_signed_char);
1093 : :
1094 : 1249 : target_builtins.empty ();
1095 : 1249 : build_common_builtin_nodes ();
1096 : :
1097 : : /* The default precision for floating point numbers. This is used
1098 : : for floating point constants with abstract type. This may
1099 : : eventually be controllable by a command line option. */
1100 : 1249 : mpfr_set_default_prec (256);
1101 : :
1102 : 1249 : targetm.init_builtins ();
1103 : :
1104 : 2498 : return true;
1105 : 1249 : }
1106 : :
1107 : : static void
1108 : 1249 : jit_langhook_parse_file (void)
1109 : : {
1110 : : /* Replay the activity by the client, recorded on the context. */
1111 : 1249 : gcc_assert (gcc::jit::active_playback_ctxt);
1112 : 1249 : gcc::jit::active_playback_ctxt->replay ();
1113 : 1249 : }
1114 : :
1115 : : static tree
1116 : 12721 : jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
1117 : : {
1118 : : /* Build any vector types here (see PR 46805). */
1119 : 12721 : if (VECTOR_MODE_P (mode))
1120 : : {
1121 : 270 : tree inner;
1122 : :
1123 : 540 : inner = jit_langhook_type_for_mode (GET_MODE_INNER (mode), unsignedp);
1124 : 270 : if (inner != NULL_TREE)
1125 : 270 : return build_vector_type_for_mode (inner, mode);
1126 : : return NULL_TREE;
1127 : : }
1128 : :
1129 : 12451 : if (mode == TYPE_MODE (float_type_node))
1130 : 140 : return float_type_node;
1131 : :
1132 : 12311 : if (mode == TYPE_MODE (double_type_node))
1133 : 369 : return double_type_node;
1134 : :
1135 : 11942 : if (mode == TYPE_MODE (intQI_type_node))
1136 : 805 : return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
1137 : 11137 : if (mode == TYPE_MODE (intHI_type_node))
1138 : 60 : return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
1139 : 11077 : if (mode == TYPE_MODE (intSI_type_node))
1140 : 1449 : return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
1141 : 9628 : if (mode == TYPE_MODE (intDI_type_node))
1142 : 2134 : return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
1143 : 7494 : if (mode == TYPE_MODE (intTI_type_node))
1144 : 0 : return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
1145 : :
1146 : 7494 : if (mode == TYPE_MODE (integer_type_node))
1147 : 0 : return unsignedp ? unsigned_type_node : integer_type_node;
1148 : :
1149 : 7494 : if (mode == TYPE_MODE (long_integer_type_node))
1150 : 0 : return unsignedp ? long_unsigned_type_node : long_integer_type_node;
1151 : :
1152 : 7494 : if (mode == TYPE_MODE (long_long_integer_type_node))
1153 : 0 : return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
1154 : :
1155 : 7494 : if (COMPLEX_MODE_P (mode))
1156 : : {
1157 : 7494 : if (mode == TYPE_MODE (complex_float_type_node))
1158 : 1249 : return complex_float_type_node;
1159 : 6245 : if (mode == TYPE_MODE (complex_double_type_node))
1160 : 1249 : return complex_double_type_node;
1161 : 4996 : if (mode == TYPE_MODE (complex_long_double_type_node))
1162 : 1249 : return complex_long_double_type_node;
1163 : 3747 : if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp)
1164 : 0 : return complex_integer_type_node;
1165 : : }
1166 : :
1167 : : /* gcc_unreachable */
1168 : : return NULL;
1169 : : }
1170 : :
1171 : 3187053 : recording::type* tree_type_to_jit_type (tree type)
1172 : : {
1173 : 3187053 : if (TREE_CODE (type) == VECTOR_TYPE)
1174 : : {
1175 : 1296912 : tree inner_type = TREE_TYPE (type);
1176 : 1296912 : recording::type* element_type = tree_type_to_jit_type (inner_type);
1177 : 1296912 : poly_uint64 size = TYPE_VECTOR_SUBPARTS (type);
1178 : 1296912 : long constant_size = size.to_constant ();
1179 : 1296912 : if (element_type != NULL)
1180 : 1296912 : return element_type->get_vector (constant_size);
1181 : : return NULL;
1182 : : }
1183 : 1890141 : if (TREE_CODE (type) == REFERENCE_TYPE)
1184 : : // For __builtin_ms_va_start.
1185 : : // FIXME: wrong type.
1186 : 369 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1187 : 369 : GCC_JIT_TYPE_VOID);
1188 : 1889772 : if (TREE_CODE (type) == RECORD_TYPE)
1189 : : // For __builtin_sysv_va_copy.
1190 : : // FIXME: wrong type.
1191 : 492 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1192 : 492 : GCC_JIT_TYPE_VOID);
1193 : : /* TODO: Remove when we add support for sized floating-point types. */
1194 : 14303916 : for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
1195 : 12530871 : if (type == FLOATN_NX_TYPE_NODE (i))
1196 : : // FIXME: wrong type.
1197 : 116235 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1198 : 116235 : GCC_JIT_TYPE_VOID);
1199 : 1773045 : if (type == void_type_node)
1200 : 35916 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1201 : 35916 : GCC_JIT_TYPE_VOID);
1202 : 1737129 : else if (type == ptr_type_node)
1203 : 12177 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1204 : 12177 : GCC_JIT_TYPE_VOID_PTR);
1205 : 1724952 : else if (type == const_ptr_type_node)
1206 : : {
1207 : : // Void const ptr.
1208 : 6888 : recording::type* result =
1209 : : new recording::memento_of_get_type (&target_builtins_ctxt,
1210 : 6888 : GCC_JIT_TYPE_VOID_PTR);
1211 : 6888 : return new recording::memento_of_get_const (result);
1212 : : }
1213 : 1718064 : else if (type == unsigned_type_node)
1214 : 47355 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1215 : 47355 : GCC_JIT_TYPE_UNSIGNED_INT);
1216 : 1670709 : else if (type == long_unsigned_type_node)
1217 : 1599 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1218 : 1599 : GCC_JIT_TYPE_UNSIGNED_LONG);
1219 : 1669110 : else if (type == integer_type_node)
1220 : 400980 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1221 : 400980 : GCC_JIT_TYPE_INT);
1222 : 1268130 : else if (type == long_integer_type_node)
1223 : 123 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1224 : 123 : GCC_JIT_TYPE_LONG);
1225 : 1268007 : else if (type == long_long_integer_type_node)
1226 : 196308 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1227 : 196308 : GCC_JIT_TYPE_LONG_LONG);
1228 : 1071699 : else if (type == signed_char_type_node)
1229 : 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1230 : 0 : GCC_JIT_TYPE_SIGNED_CHAR);
1231 : 1071699 : else if (type == char_type_node)
1232 : 145509 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1233 : 145509 : GCC_JIT_TYPE_CHAR);
1234 : 926190 : else if (type == unsigned_intQI_type_node)
1235 : 171831 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1236 : 171831 : GCC_JIT_TYPE_UINT8_T);
1237 : 754359 : else if (type == short_integer_type_node)
1238 : 169740 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1239 : 169740 : GCC_JIT_TYPE_SHORT);
1240 : 584619 : else if (type == short_unsigned_type_node)
1241 : 61746 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1242 : 61746 : GCC_JIT_TYPE_UNSIGNED_SHORT);
1243 : 522873 : else if (type == complex_float_type_node)
1244 : 246 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1245 : 246 : GCC_JIT_TYPE_COMPLEX_FLOAT);
1246 : 522627 : else if (type == complex_double_type_node)
1247 : 246 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1248 : 246 : GCC_JIT_TYPE_COMPLEX_DOUBLE);
1249 : 522381 : else if (type == complex_long_double_type_node)
1250 : 246 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1251 : 246 : GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE);
1252 : 522135 : else if (type == float_type_node)
1253 : 208485 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1254 : 208485 : GCC_JIT_TYPE_FLOAT);
1255 : 313650 : else if (type == double_type_node)
1256 : 181302 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1257 : 181302 : GCC_JIT_TYPE_DOUBLE);
1258 : 132348 : else if (type == long_double_type_node)
1259 : 984 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1260 : 984 : GCC_JIT_TYPE_LONG_DOUBLE);
1261 : 131364 : else if (type == bfloat16_type_node)
1262 : 55104 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1263 : 55104 : GCC_JIT_TYPE_BFLOAT16);
1264 : 76260 : else if (type == dfloat128_type_node)
1265 : : // FIXME: wrong type.
1266 : 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1267 : 0 : GCC_JIT_TYPE_VOID);
1268 : 76260 : else if (type == long_long_unsigned_type_node)
1269 : 22878 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1270 : 22878 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
1271 : 53382 : else if (type == boolean_type_node)
1272 : 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1273 : 0 : GCC_JIT_TYPE_BOOL);
1274 : 53382 : else if (type == size_type_node)
1275 : 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1276 : 0 : GCC_JIT_TYPE_SIZE_T);
1277 : 53382 : else if (TREE_CODE (type) == POINTER_TYPE)
1278 : : {
1279 : 44157 : tree inner_type = TREE_TYPE (type);
1280 : 44157 : recording::type* element_type = tree_type_to_jit_type (inner_type);
1281 : 44157 : if (!element_type)
1282 : : return nullptr;
1283 : 44157 : return element_type->get_pointer ();
1284 : : }
1285 : : else
1286 : : {
1287 : : // Attempt to find an unqualified type when the current type has qualifiers.
1288 : 9225 : tree tp = TYPE_MAIN_VARIANT (type);
1289 : 9225 : for ( ; tp != NULL ; tp = TYPE_NEXT_VARIANT (tp))
1290 : : {
1291 : 9225 : if (TYPE_QUALS (tp) == 0 && type != tp)
1292 : : {
1293 : 9225 : recording::type* result = tree_type_to_jit_type (tp);
1294 : 9225 : if (result != NULL)
1295 : : {
1296 : 9225 : if (TYPE_READONLY (tp))
1297 : 0 : result = new recording::memento_of_get_const (result);
1298 : 9225 : if (TYPE_VOLATILE (tp))
1299 : 0 : result = new recording::memento_of_get_volatile (result);
1300 : 9225 : return result;
1301 : : }
1302 : : }
1303 : : }
1304 : : }
1305 : :
1306 : : return NULL;
1307 : : }
1308 : :
1309 : : /* Record a builtin function. We save their types to be able to check types
1310 : : in recording and for reflection. */
1311 : :
1312 : : static tree
1313 : 4618802 : jit_langhook_builtin_function (tree decl)
1314 : : {
1315 : 4618802 : if (TREE_CODE (decl) == FUNCTION_DECL)
1316 : : {
1317 : 4618802 : const char* name = IDENTIFIER_POINTER (DECL_NAME (decl));
1318 : 4618802 : target_builtins.put (name, decl);
1319 : :
1320 : 4618802 : std::string string_name (name);
1321 : 8782750 : if (target_function_types.count (string_name) == 0)
1322 : : {
1323 : 454854 : tree function_type = TREE_TYPE (decl);
1324 : 454854 : tree arg = TYPE_ARG_TYPES (function_type);
1325 : 454854 : bool is_variadic = false;
1326 : :
1327 : 454854 : auto_vec <recording::type *> param_types;
1328 : :
1329 : 1836759 : while (arg != void_list_node)
1330 : : {
1331 : 1382151 : if (arg == NULL)
1332 : : {
1333 : : is_variadic = true;
1334 : : break;
1335 : : }
1336 : 1381905 : if (arg != void_list_node)
1337 : : {
1338 : 1381905 : recording::type* arg_type = tree_type_to_jit_type (TREE_VALUE (arg));
1339 : 1381905 : if (arg_type == NULL)
1340 : 0 : return decl;
1341 : 1381905 : param_types.safe_push (arg_type);
1342 : : }
1343 : 1381905 : arg = TREE_CHAIN (arg);
1344 : : }
1345 : :
1346 : 454854 : tree result_type = TREE_TYPE (function_type);
1347 : 454854 : recording::type* return_type = tree_type_to_jit_type (result_type);
1348 : :
1349 : 454854 : if (return_type == NULL)
1350 : : return decl;
1351 : :
1352 : 454854 : recording::function_type* func_type =
1353 : : new recording::function_type (&target_builtins_ctxt, return_type,
1354 : 454854 : param_types.length (),
1355 : : param_types.address (), is_variadic,
1356 : 1353738 : false);
1357 : :
1358 : 454854 : target_function_types[string_name] = func_type;
1359 : 454854 : }
1360 : 4618802 : }
1361 : : return decl;
1362 : : }
1363 : :
1364 : : static bool
1365 : 60 : jit_langhook_global_bindings_p (void)
1366 : : {
1367 : 60 : return true;
1368 : : }
1369 : :
1370 : : static tree
1371 : 0 : jit_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED)
1372 : : {
1373 : 0 : return NULL_TREE;
1374 : : }
1375 : :
1376 : : static tree
1377 : 0 : jit_langhook_getdecls (void)
1378 : : {
1379 : 0 : return NULL;
1380 : : }
1381 : :
1382 : : #undef LANG_HOOKS_NAME
1383 : : #define LANG_HOOKS_NAME "libgccjit"
1384 : :
1385 : : #undef LANG_HOOKS_INIT
1386 : : #define LANG_HOOKS_INIT jit_langhook_init
1387 : :
1388 : : #undef LANG_HOOKS_PARSE_FILE
1389 : : #define LANG_HOOKS_PARSE_FILE jit_langhook_parse_file
1390 : :
1391 : : #undef LANG_HOOKS_TYPE_FOR_MODE
1392 : : #define LANG_HOOKS_TYPE_FOR_MODE jit_langhook_type_for_mode
1393 : :
1394 : : #undef LANG_HOOKS_BUILTIN_FUNCTION
1395 : : #define LANG_HOOKS_BUILTIN_FUNCTION jit_langhook_builtin_function
1396 : :
1397 : : #undef LANG_HOOKS_GLOBAL_BINDINGS_P
1398 : : #define LANG_HOOKS_GLOBAL_BINDINGS_P jit_langhook_global_bindings_p
1399 : :
1400 : : #undef LANG_HOOKS_PUSHDECL
1401 : : #define LANG_HOOKS_PUSHDECL jit_langhook_pushdecl
1402 : :
1403 : : #undef LANG_HOOKS_GETDECLS
1404 : : #define LANG_HOOKS_GETDECLS jit_langhook_getdecls
1405 : :
1406 : : /* Attribute hooks. */
1407 : : #undef LANG_HOOKS_ATTRIBUTE_TABLE
1408 : : #define LANG_HOOKS_ATTRIBUTE_TABLE jit_attribute_table
1409 : :
1410 : : #undef LANG_HOOKS_DEEP_UNSHARING
1411 : : #define LANG_HOOKS_DEEP_UNSHARING true
1412 : :
1413 : : struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
1414 : :
1415 : : #include "gt-jit-dummy-frontend.h"
1416 : : #include "gtype-jit.h"
|