Line data Source code
1 : /* jit.c -- Dummy "frontend" for use during JIT-compilation.
2 : Copyright (C) 2013-2026 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 "diagnostics/text-sink.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 1296 : 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 1296 : tree type = TREE_TYPE (*node);
259 :
260 1296 : if (TREE_CODE (*node) == FUNCTION_DECL)
261 1296 : 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 1296 : return NULL_TREE;
272 : }
273 :
274 : /* Handle a "leaf" attribute; arguments as in
275 : struct attribute_spec.handler. */
276 :
277 : static tree
278 13135 : handle_leaf_attribute (tree *node, tree name,
279 : tree ARG_UNUSED (args),
280 : int ARG_UNUSED (flags), bool *no_add_attrs)
281 : {
282 13135 : if (TREE_CODE (*node) != FUNCTION_DECL)
283 : {
284 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
285 0 : *no_add_attrs = true;
286 : }
287 13135 : 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 13135 : return NULL_TREE;
294 : }
295 :
296 : /* Handle a "const" attribute; arguments as in
297 : struct attribute_spec.handler. */
298 :
299 : static tree
300 11674 : handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
301 : int ARG_UNUSED (flags), bool *no_add_attrs)
302 : {
303 11674 : tree type = TREE_TYPE (*node);
304 :
305 : /* See FIXME comment on noreturn in c_common_attribute_table. */
306 11674 : if (TREE_CODE (*node) == FUNCTION_DECL)
307 11674 : 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 11674 : 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 13120 : 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 13120 : if (TREE_CODE (*node) == FUNCTION_DECL)
450 13120 : TREE_NOTHROW (*node) = 1;
451 : else
452 0 : gcc_unreachable ();
453 :
454 13120 : 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 1301 : handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
710 : int ARG_UNUSED (flags), bool *no_add_attrs)
711 : {
712 1301 : if (TREE_CODE (*node) == FUNCTION_DECL
713 1301 : || 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 1301 : 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 : /* See lang_tree_node in gcc/c/c-decl.cc. */
960 : union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
961 : chain_next ("(union lang_tree_node *) jit_tree_chain_next (&%h.generic)")))
962 : lang_tree_node
963 : {
964 : union tree_node GTY ((tag ("0"),
965 : desc ("tree_node_structure (&%h)")))
966 : generic;
967 : struct lang_identifier GTY ((tag ("1"))) identifier;
968 : };
969 :
970 : /* We don't use language_function. */
971 :
972 : struct GTY(()) language_function
973 : {
974 : int dummy;
975 : };
976 :
977 : /* GC-marking callback for use from jit_root_tab.
978 :
979 : If there's an active playback context, call its marking method
980 : so that it can mark any pointers it references. */
981 :
982 514851 : static void my_ggc_walker (void *)
983 : {
984 514851 : if (gcc::jit::active_playback_ctxt)
985 514851 : gcc::jit::active_playback_ctxt->gt_ggc_mx ();
986 514851 : }
987 :
988 : const char *dummy;
989 :
990 : struct ggc_root_tab jit_root_tab[] =
991 : {
992 : {
993 : &dummy, 1, 0, my_ggc_walker, NULL
994 : },
995 : LAST_GGC_ROOT_TAB
996 : };
997 :
998 : /* Subclass of diagnostics::text_sink for libgccjit: like text
999 : output, but capture the message and call add_diagnostic with it
1000 : on the active playback context. */
1001 :
1002 : class jit_diagnostic_listener : public diagnostics::text_sink
1003 : {
1004 : public:
1005 1326 : jit_diagnostic_listener (diagnostics::context &dc,
1006 : gcc::jit::playback::context &playback_ctxt)
1007 1326 : : diagnostics::text_sink (dc),
1008 1326 : m_playback_ctxt (playback_ctxt)
1009 : {
1010 : }
1011 :
1012 0 : void dump (FILE *out, int indent) const final override
1013 : {
1014 0 : fprintf (out, "%*sjit_diagnostic_listener\n", indent, "");
1015 0 : fprintf (out, "%*sm_playback_context: %p\n",
1016 : indent + 2, "",
1017 0 : (void *)&m_playback_ctxt);
1018 0 : }
1019 :
1020 25 : void on_report_diagnostic (const diagnostics::diagnostic_info &info,
1021 : enum diagnostics::kind orig_diag_kind) final override
1022 : {
1023 25 : JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
1024 :
1025 : /* Let the text output format do most of the work. */
1026 25 : diagnostics::text_sink::on_report_diagnostic (info, orig_diag_kind);
1027 :
1028 25 : const char *text = pp_formatted_text (get_printer ());
1029 :
1030 : /* Delegate to the playback context (and thence to the
1031 : recording context). */
1032 25 : gcc::jit::active_playback_ctxt->add_diagnostic (text, info);
1033 :
1034 25 : pp_clear_output_area (get_printer ());
1035 25 : }
1036 :
1037 : private:
1038 : gcc::jit::playback::context &m_playback_ctxt;
1039 : };
1040 :
1041 : /* JIT-specific implementation of diagnostic callbacks. */
1042 :
1043 : /* Implementation of "begin_diagnostic". */
1044 :
1045 : static void
1046 25 : jit_begin_diagnostic (diagnostics::text_sink &,
1047 : const diagnostics::diagnostic_info */*diagnostic*/)
1048 : {
1049 25 : gcc_assert (gcc::jit::active_playback_ctxt);
1050 25 : JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
1051 :
1052 : /* No-op (apart from logging); the real error-handling is done by the
1053 : jit_diagnostic_listener. */
1054 25 : }
1055 :
1056 : /* Implementation of "end_diagnostic". */
1057 :
1058 : static void
1059 25 : jit_end_diagnostic (diagnostics::text_sink &,
1060 : const diagnostics::diagnostic_info *,
1061 : enum diagnostics::kind)
1062 : {
1063 25 : gcc_assert (gcc::jit::active_playback_ctxt);
1064 25 : JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
1065 :
1066 : /* No-op (apart from logging); the real error-handling is done by the
1067 : jit_diagnostic_listener. */
1068 25 : }
1069 :
1070 : /* Language hooks. */
1071 :
1072 : static bool
1073 1326 : jit_langhook_init (void)
1074 : {
1075 1326 : gcc_assert (gcc::jit::active_playback_ctxt);
1076 1326 : JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
1077 :
1078 1326 : static bool registered_root_tab = false;
1079 1326 : if (!registered_root_tab)
1080 : {
1081 130 : ggc_register_root_tab (jit_root_tab);
1082 130 : registered_root_tab = true;
1083 : }
1084 :
1085 1326 : gcc_assert (global_dc);
1086 1326 : diagnostics::text_starter (global_dc) = jit_begin_diagnostic;
1087 1326 : diagnostics::text_finalizer (global_dc) = jit_end_diagnostic;
1088 1326 : auto sink
1089 : = std::make_unique<jit_diagnostic_listener>
1090 : (*global_dc,
1091 1326 : *gcc::jit::active_playback_ctxt);
1092 1326 : global_dc->set_sink (std::move (sink));
1093 :
1094 1326 : build_common_tree_nodes (flag_signed_char);
1095 :
1096 1326 : target_builtins.empty ();
1097 1326 : build_common_builtin_nodes ();
1098 :
1099 : /* The default precision for floating point numbers. This is used
1100 : for floating point constants with abstract type. This may
1101 : eventually be controllable by a command line option. */
1102 1326 : mpfr_set_default_prec (256);
1103 :
1104 1326 : targetm.init_builtins ();
1105 :
1106 2652 : return true;
1107 1326 : }
1108 :
1109 : static void
1110 1326 : jit_langhook_parse_file (void)
1111 : {
1112 : /* Replay the activity by the client, recorded on the context. */
1113 1326 : gcc_assert (gcc::jit::active_playback_ctxt);
1114 1326 : gcc::jit::active_playback_ctxt->replay ();
1115 1326 : }
1116 :
1117 : static tree
1118 13395 : jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
1119 : {
1120 : /* Build any vector types here (see PR 46805). */
1121 13395 : if (VECTOR_MODE_P (mode))
1122 : {
1123 270 : tree inner;
1124 :
1125 540 : inner = jit_langhook_type_for_mode (GET_MODE_INNER (mode), unsignedp);
1126 270 : if (inner != NULL_TREE)
1127 270 : return build_vector_type_for_mode (inner, mode);
1128 : return NULL_TREE;
1129 : }
1130 :
1131 13125 : if (mode == TYPE_MODE (float_type_node))
1132 140 : return float_type_node;
1133 :
1134 12985 : if (mode == TYPE_MODE (double_type_node))
1135 369 : return double_type_node;
1136 :
1137 12616 : if (mode == TYPE_MODE (intQI_type_node))
1138 805 : return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
1139 11811 : if (mode == TYPE_MODE (intHI_type_node))
1140 60 : return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
1141 11751 : if (mode == TYPE_MODE (intSI_type_node))
1142 1449 : return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
1143 10302 : if (mode == TYPE_MODE (intDI_type_node))
1144 2346 : return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
1145 7956 : if (mode == TYPE_MODE (intTI_type_node))
1146 0 : return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
1147 :
1148 7956 : if (mode == TYPE_MODE (integer_type_node))
1149 0 : return unsignedp ? unsigned_type_node : integer_type_node;
1150 :
1151 7956 : if (mode == TYPE_MODE (long_integer_type_node))
1152 0 : return unsignedp ? long_unsigned_type_node : long_integer_type_node;
1153 :
1154 7956 : if (mode == TYPE_MODE (long_long_integer_type_node))
1155 0 : return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
1156 :
1157 7956 : if (COMPLEX_MODE_P (mode))
1158 : {
1159 7956 : if (mode == TYPE_MODE (complex_float_type_node))
1160 1326 : return complex_float_type_node;
1161 6630 : if (mode == TYPE_MODE (complex_double_type_node))
1162 1326 : return complex_double_type_node;
1163 5304 : if (mode == TYPE_MODE (complex_long_double_type_node))
1164 1326 : return complex_long_double_type_node;
1165 3978 : if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp)
1166 0 : return complex_integer_type_node;
1167 : }
1168 :
1169 : /* gcc_unreachable */
1170 : return NULL;
1171 : }
1172 :
1173 3365700 : recording::type* tree_type_to_jit_type (tree type)
1174 : {
1175 3365700 : gcc_assert (gcc::jit::active_playback_ctxt);
1176 3365700 : gcc::jit::playback::context* ctxt = gcc::jit::active_playback_ctxt;
1177 :
1178 3365700 : if (TREE_CODE (type) == VECTOR_TYPE)
1179 : {
1180 1373970 : tree inner_type = TREE_TYPE (type);
1181 1373970 : recording::type* element_type = tree_type_to_jit_type (inner_type);
1182 1373970 : poly_uint64 size = TYPE_VECTOR_SUBPARTS (type);
1183 1373970 : long constant_size = size.to_constant ();
1184 1373970 : if (element_type != NULL)
1185 1373970 : return element_type->get_vector (constant_size);
1186 : return NULL;
1187 : }
1188 1991730 : if (TREE_CODE (type) == REFERENCE_TYPE)
1189 : // For __builtin_ms_va_start.
1190 : // FIXME: wrong type.
1191 390 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1192 390 : GCC_JIT_TYPE_VOID);
1193 1991340 : if (TREE_CODE (type) == RECORD_TYPE)
1194 : // For __builtin_sysv_va_copy.
1195 : // FIXME: wrong type.
1196 520 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1197 520 : GCC_JIT_TYPE_VOID);
1198 1990820 : if (type == void_type_node)
1199 38090 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1200 38090 : GCC_JIT_TYPE_VOID);
1201 1952730 : else if (type == ptr_type_node)
1202 12870 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1203 12870 : GCC_JIT_TYPE_VOID_PTR);
1204 1939860 : else if (type == const_ptr_type_node)
1205 : {
1206 : // Void const ptr.
1207 7280 : recording::type* result =
1208 : new recording::memento_of_get_type (&target_builtins_ctxt,
1209 7280 : GCC_JIT_TYPE_VOID_PTR);
1210 7280 : return new recording::memento_of_get_const (result);
1211 : }
1212 1932580 : else if (type == unsigned_type_node)
1213 50180 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1214 50180 : GCC_JIT_TYPE_UNSIGNED_INT);
1215 1882400 : else if (type == long_unsigned_type_node)
1216 1690 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1217 1690 : GCC_JIT_TYPE_UNSIGNED_LONG);
1218 1880710 : else if (type == integer_type_node)
1219 422370 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1220 422370 : GCC_JIT_TYPE_INT);
1221 1458340 : else if (type == long_integer_type_node)
1222 130 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1223 130 : GCC_JIT_TYPE_LONG);
1224 1458210 : else if (type == long_long_integer_type_node)
1225 206050 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1226 206050 : GCC_JIT_TYPE_LONG_LONG);
1227 1252160 : else if (type == signed_char_type_node)
1228 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1229 0 : GCC_JIT_TYPE_SIGNED_CHAR);
1230 1252160 : else if (type == char_type_node)
1231 153400 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1232 153400 : GCC_JIT_TYPE_CHAR);
1233 1098760 : else if (type == unsigned_intQI_type_node)
1234 181610 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1235 181610 : GCC_JIT_TYPE_UINT8_T);
1236 917150 : else if (type == short_integer_type_node)
1237 180960 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1238 180960 : GCC_JIT_TYPE_SHORT);
1239 736190 : else if (type == short_unsigned_type_node)
1240 65390 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1241 65390 : GCC_JIT_TYPE_UNSIGNED_SHORT);
1242 670800 : else if (type == complex_float_type_node)
1243 260 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1244 260 : GCC_JIT_TYPE_COMPLEX_FLOAT);
1245 670540 : else if (type == complex_double_type_node)
1246 260 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1247 260 : GCC_JIT_TYPE_COMPLEX_DOUBLE);
1248 670280 : else if (type == complex_long_double_type_node)
1249 260 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1250 260 : GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE);
1251 670020 : else if (type == float_type_node)
1252 218400 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1253 218400 : GCC_JIT_TYPE_FLOAT);
1254 451620 : else if (type == double_type_node)
1255 189540 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1256 189540 : GCC_JIT_TYPE_DOUBLE);
1257 262080 : else if (type == long_double_type_node)
1258 1040 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1259 1040 : GCC_JIT_TYPE_LONG_DOUBLE);
1260 261040 : else if (type == bfloat16_type_node)
1261 57980 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1262 57980 : GCC_JIT_TYPE_BFLOAT16);
1263 203060 : else if (type == float16_type_node)
1264 : {
1265 121160 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1266 121160 : GCC_JIT_TYPE_FLOAT16);
1267 : }
1268 81900 : else if (type == float32_type_node)
1269 : {
1270 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1271 0 : GCC_JIT_TYPE_FLOAT32);
1272 : }
1273 81900 : else if (type == float64_type_node)
1274 : {
1275 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1276 0 : GCC_JIT_TYPE_FLOAT64);
1277 : }
1278 81900 : else if (type == float128_type_node)
1279 : {
1280 1170 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1281 1170 : GCC_JIT_TYPE_FLOAT128);
1282 : }
1283 80730 : else if (type == dfloat128_type_node)
1284 : // FIXME: wrong type.
1285 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1286 0 : GCC_JIT_TYPE_VOID);
1287 80730 : else if (type == long_long_unsigned_type_node)
1288 24310 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1289 24310 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
1290 56420 : else if (type == boolean_type_node)
1291 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1292 0 : GCC_JIT_TYPE_BOOL);
1293 56420 : else if (type == size_type_node)
1294 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1295 0 : GCC_JIT_TYPE_SIZE_T);
1296 56420 : else if (TREE_CODE (type) == POINTER_TYPE)
1297 : {
1298 46670 : tree inner_type = TREE_TYPE (type);
1299 46670 : recording::type* element_type = tree_type_to_jit_type (inner_type);
1300 46670 : if (!element_type)
1301 : return nullptr;
1302 46670 : return element_type->get_pointer ();
1303 : }
1304 9750 : else if (type == unsigned_intTI_type_node)
1305 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1306 0 : GCC_JIT_TYPE_UINT128_T);
1307 9750 : else if (INTEGRAL_TYPE_P (type))
1308 : {
1309 4940 : unsigned int size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
1310 4940 : return target_builtins_ctxt.get_int_type (size, TYPE_UNSIGNED (type));
1311 : }
1312 4810 : else if (SCALAR_FLOAT_TYPE_P (type))
1313 : {
1314 4810 : unsigned int size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
1315 4810 : enum gcc_jit_types type;
1316 4810 : switch (size)
1317 : {
1318 : case 2:
1319 : type = GCC_JIT_TYPE_BFLOAT16;
1320 : break;
1321 1950 : case 4:
1322 1950 : type = GCC_JIT_TYPE_FLOAT;
1323 1950 : break;
1324 2080 : case 8:
1325 2080 : type = GCC_JIT_TYPE_DOUBLE;
1326 2080 : break;
1327 0 : default:
1328 0 : if (ctxt->get_abort_on_unsupported_target_builtin ())
1329 : {
1330 0 : fprintf (stderr, "Unexpected float size: %d\n", size);
1331 0 : abort ();
1332 : }
1333 : return NULL;
1334 : }
1335 4810 : return new recording::memento_of_get_type (&target_builtins_ctxt, type);
1336 : }
1337 : else
1338 : {
1339 : // Attempt to find an unqualified type when the current type has qualifiers.
1340 0 : tree tp = TYPE_MAIN_VARIANT (type);
1341 0 : for ( ; tp != NULL ; tp = TYPE_NEXT_VARIANT (tp))
1342 : {
1343 0 : if (TYPE_QUALS (tp) == 0 && type != tp)
1344 : {
1345 0 : recording::type* result = tree_type_to_jit_type (tp);
1346 0 : if (result != NULL)
1347 : {
1348 0 : if (TYPE_READONLY (tp))
1349 0 : result = new recording::memento_of_get_const (result);
1350 0 : if (TYPE_VOLATILE (tp))
1351 0 : result = new recording::memento_of_get_volatile (result);
1352 0 : return result;
1353 : }
1354 : }
1355 : }
1356 :
1357 0 : if (ctxt->get_abort_on_unsupported_target_builtin ())
1358 : {
1359 0 : fprintf (stderr, "Unknown type:\n");
1360 0 : debug_tree (type);
1361 0 : abort ();
1362 : }
1363 : }
1364 :
1365 : return NULL;
1366 : }
1367 :
1368 : /* Record a builtin function. We save their types to be able to check types
1369 : in recording and for reflection. */
1370 :
1371 : static tree
1372 4914156 : jit_langhook_builtin_function (tree decl)
1373 : {
1374 4914156 : if (TREE_CODE (decl) == FUNCTION_DECL)
1375 : {
1376 4914156 : const char* name = IDENTIFIER_POINTER (DECL_NAME (decl));
1377 4914156 : target_builtins.put (name, decl);
1378 :
1379 4914156 : std::string string_name (name);
1380 9346532 : if (target_function_types.count (string_name) == 0)
1381 : {
1382 481780 : tree function_type = TREE_TYPE (decl);
1383 481780 : tree arg = TYPE_ARG_TYPES (function_type);
1384 481780 : bool is_variadic = false;
1385 :
1386 481780 : auto_vec <recording::type *> param_types;
1387 :
1388 1945060 : while (arg != void_list_node)
1389 : {
1390 1463540 : if (arg == NULL)
1391 : {
1392 : is_variadic = true;
1393 : break;
1394 : }
1395 1463280 : if (arg != void_list_node)
1396 : {
1397 1463280 : recording::type* arg_type = tree_type_to_jit_type (TREE_VALUE (arg));
1398 1463280 : if (arg_type == NULL)
1399 0 : return decl;
1400 1463280 : param_types.safe_push (arg_type);
1401 : }
1402 1463280 : arg = TREE_CHAIN (arg);
1403 : }
1404 :
1405 481780 : tree result_type = TREE_TYPE (function_type);
1406 481780 : recording::type* return_type = tree_type_to_jit_type (result_type);
1407 :
1408 481780 : if (return_type == NULL)
1409 : return decl;
1410 :
1411 481780 : recording::function_type* func_type =
1412 : new recording::function_type (&target_builtins_ctxt, return_type,
1413 481780 : param_types.length (),
1414 : param_types.address (), is_variadic,
1415 1433640 : false);
1416 :
1417 481780 : target_function_types[string_name] = func_type;
1418 481780 : }
1419 4914156 : }
1420 : return decl;
1421 : }
1422 :
1423 : static bool
1424 60 : jit_langhook_global_bindings_p (void)
1425 : {
1426 60 : return true;
1427 : }
1428 :
1429 : static tree
1430 0 : jit_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED)
1431 : {
1432 0 : return NULL_TREE;
1433 : }
1434 :
1435 : static tree
1436 0 : jit_langhook_getdecls (void)
1437 : {
1438 0 : return NULL;
1439 : }
1440 :
1441 : #undef LANG_HOOKS_NAME
1442 : #define LANG_HOOKS_NAME "libgccjit"
1443 :
1444 : #undef LANG_HOOKS_INIT
1445 : #define LANG_HOOKS_INIT jit_langhook_init
1446 :
1447 : #undef LANG_HOOKS_PARSE_FILE
1448 : #define LANG_HOOKS_PARSE_FILE jit_langhook_parse_file
1449 :
1450 : #undef LANG_HOOKS_TYPE_FOR_MODE
1451 : #define LANG_HOOKS_TYPE_FOR_MODE jit_langhook_type_for_mode
1452 :
1453 : #undef LANG_HOOKS_BUILTIN_FUNCTION
1454 : #define LANG_HOOKS_BUILTIN_FUNCTION jit_langhook_builtin_function
1455 :
1456 : #undef LANG_HOOKS_GLOBAL_BINDINGS_P
1457 : #define LANG_HOOKS_GLOBAL_BINDINGS_P jit_langhook_global_bindings_p
1458 :
1459 : #undef LANG_HOOKS_PUSHDECL
1460 : #define LANG_HOOKS_PUSHDECL jit_langhook_pushdecl
1461 :
1462 : #undef LANG_HOOKS_GETDECLS
1463 : #define LANG_HOOKS_GETDECLS jit_langhook_getdecls
1464 :
1465 : /* Attribute hooks. */
1466 : #undef LANG_HOOKS_ATTRIBUTE_TABLE
1467 : #define LANG_HOOKS_ATTRIBUTE_TABLE jit_attribute_table
1468 :
1469 : #undef LANG_HOOKS_DEEP_UNSHARING
1470 : #define LANG_HOOKS_DEEP_UNSHARING true
1471 :
1472 : struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
1473 :
1474 : #include "gt-jit-dummy-frontend.h"
1475 : #include "gtype-jit.h"
|