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 1336 : 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 1336 : tree type = TREE_TYPE (*node);
259 :
260 1336 : if (TREE_CODE (*node) == FUNCTION_DECL)
261 1336 : 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 1336 : return NULL_TREE;
272 : }
273 :
274 : /* Handle a "leaf" attribute; arguments as in
275 : struct attribute_spec.handler. */
276 :
277 : static tree
278 21831 : handle_leaf_attribute (tree *node, tree name,
279 : tree ARG_UNUSED (args),
280 : int ARG_UNUSED (flags), bool *no_add_attrs)
281 : {
282 21831 : if (TREE_CODE (*node) != FUNCTION_DECL)
283 : {
284 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
285 0 : *no_add_attrs = true;
286 : }
287 21831 : 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 21831 : return NULL_TREE;
294 : }
295 :
296 : /* Handle a "const" attribute; arguments as in
297 : struct attribute_spec.handler. */
298 :
299 : static tree
300 12069 : handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
301 : int ARG_UNUSED (flags), bool *no_add_attrs)
302 : {
303 12069 : tree type = TREE_TYPE (*node);
304 :
305 : /* See FIXME comment on noreturn in c_common_attribute_table. */
306 12069 : if (TREE_CODE (*node) == FUNCTION_DECL)
307 12069 : 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 12069 : 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 25 : 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 25 : if (TREE_CODE (*node) == FUNCTION_DECL)
353 25 : DECL_PURE_P (*node) = 1;
354 : else
355 0 : gcc_unreachable ();
356 :
357 25 : 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 105 : 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 105 : 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 105 : if (!args)
404 : {
405 100 : gcc_assert (prototype_p (type)
406 : || !TYPE_ATTRIBUTES (type)
407 : || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type)));
408 :
409 100 : 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 21811 : 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 21811 : if (TREE_CODE (*node) == FUNCTION_DECL)
450 21811 : TREE_NOTHROW (*node) = 1;
451 : else
452 0 : gcc_unreachable ();
453 :
454 21811 : 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 60 : 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 60 : gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
487 :
488 : /* Ensure we have a variadic function. */
489 60 : gcc_assert (!prototype_p (*node) || stdarg_p (*node));
490 :
491 60 : 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 25 : 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 25 : if (TREE_CODE (*node) == FUNCTION_DECL)
691 : {
692 : /* Set the attribute and mark it for disregarding inline
693 : limits. */
694 25 : 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 25 : return NULL_TREE;
703 : }
704 :
705 : /* Handle a "cold" and attribute; arguments as in
706 : struct attribute_spec.handler. */
707 :
708 : static tree
709 1341 : handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
710 : int ARG_UNUSED (flags), bool *no_add_attrs)
711 : {
712 1341 : if (TREE_CODE (*node) == FUNCTION_DECL
713 1341 : || 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 1341 : 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 662049 : static void my_ggc_walker (void *)
983 : {
984 662049 : if (gcc::jit::active_playback_ctxt)
985 662049 : gcc::jit::active_playback_ctxt->gt_ggc_mx ();
986 662049 : }
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 1366 : jit_diagnostic_listener (diagnostics::context &dc,
1006 : gcc::jit::playback::context &playback_ctxt)
1007 1366 : : diagnostics::text_sink (dc),
1008 1366 : 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 1366 : jit_langhook_init (void)
1074 : {
1075 1366 : gcc_assert (gcc::jit::active_playback_ctxt);
1076 1366 : JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
1077 :
1078 1366 : static bool registered_root_tab = false;
1079 1366 : if (!registered_root_tab)
1080 : {
1081 131 : ggc_register_root_tab (jit_root_tab);
1082 131 : registered_root_tab = true;
1083 : }
1084 :
1085 1366 : gcc_assert (global_dc);
1086 1366 : diagnostics::text_starter (global_dc) = jit_begin_diagnostic;
1087 1366 : diagnostics::text_finalizer (global_dc) = jit_end_diagnostic;
1088 1366 : auto sink
1089 : = std::make_unique<jit_diagnostic_listener>
1090 : (*global_dc,
1091 1366 : *gcc::jit::active_playback_ctxt);
1092 1366 : global_dc->set_sink (std::move (sink));
1093 :
1094 1366 : build_common_tree_nodes (flag_signed_char);
1095 :
1096 1366 : target_builtins.empty ();
1097 1366 : 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 1366 : mpfr_set_default_prec (256);
1103 :
1104 1366 : targetm.init_builtins ();
1105 :
1106 2732 : return true;
1107 1366 : }
1108 :
1109 : static void
1110 1366 : jit_langhook_parse_file (void)
1111 : {
1112 : /* Replay the activity by the client, recorded on the context. */
1113 1366 : gcc_assert (gcc::jit::active_playback_ctxt);
1114 1366 : gcc::jit::active_playback_ctxt->replay ();
1115 1366 : }
1116 :
1117 : static tree
1118 14910 : jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
1119 : {
1120 : /* Build any vector types here (see PR 46805). */
1121 14910 : if (VECTOR_MODE_P (mode))
1122 : {
1123 360 : tree inner;
1124 :
1125 720 : inner = jit_langhook_type_for_mode (GET_MODE_INNER (mode), unsignedp);
1126 360 : if (inner != NULL_TREE)
1127 360 : return build_vector_type_for_mode (inner, mode);
1128 : return NULL_TREE;
1129 : }
1130 :
1131 14550 : if (mode == TYPE_MODE (float_type_node))
1132 170 : return float_type_node;
1133 :
1134 14380 : if (mode == TYPE_MODE (double_type_node))
1135 474 : return double_type_node;
1136 :
1137 13906 : if (mode == TYPE_MODE (intQI_type_node))
1138 1025 : return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
1139 12881 : if (mode == TYPE_MODE (intHI_type_node))
1140 80 : return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
1141 12801 : if (mode == TYPE_MODE (intSI_type_node))
1142 1884 : return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
1143 10917 : if (mode == TYPE_MODE (intDI_type_node))
1144 2721 : return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
1145 8196 : if (mode == TYPE_MODE (intTI_type_node))
1146 0 : return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
1147 :
1148 8196 : if (mode == TYPE_MODE (integer_type_node))
1149 0 : return unsignedp ? unsigned_type_node : integer_type_node;
1150 :
1151 8196 : if (mode == TYPE_MODE (long_integer_type_node))
1152 0 : return unsignedp ? long_unsigned_type_node : long_integer_type_node;
1153 :
1154 8196 : 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 8196 : if (COMPLEX_MODE_P (mode))
1158 : {
1159 8196 : if (mode == TYPE_MODE (complex_float_type_node))
1160 1366 : return complex_float_type_node;
1161 6830 : if (mode == TYPE_MODE (complex_double_type_node))
1162 1366 : return complex_double_type_node;
1163 5464 : if (mode == TYPE_MODE (complex_long_double_type_node))
1164 1366 : return complex_long_double_type_node;
1165 4098 : if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp)
1166 0 : return complex_integer_type_node;
1167 : }
1168 :
1169 32784 : for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
1170 28686 : if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE
1171 28686 : && mode == TYPE_MODE (FLOATN_NX_TYPE_NODE (i)))
1172 0 : return FLOATN_NX_TYPE_NODE (i);
1173 : /* gcc_unreachable */
1174 : return NULL;
1175 : }
1176 :
1177 3391590 : recording::type* tree_type_to_jit_type (tree type)
1178 : {
1179 3391590 : gcc_assert (gcc::jit::active_playback_ctxt);
1180 3391590 : gcc::jit::playback::context* ctxt = gcc::jit::active_playback_ctxt;
1181 :
1182 3391590 : if (TREE_CODE (type) == VECTOR_TYPE)
1183 : {
1184 1384539 : tree inner_type = TREE_TYPE (type);
1185 1384539 : recording::type* element_type = tree_type_to_jit_type (inner_type);
1186 1384539 : poly_uint64 size = TYPE_VECTOR_SUBPARTS (type);
1187 1384539 : long constant_size = size.to_constant ();
1188 1384539 : if (element_type != NULL)
1189 1384539 : return element_type->get_vector (constant_size);
1190 : return NULL;
1191 : }
1192 2007051 : if (TREE_CODE (type) == REFERENCE_TYPE)
1193 : // For __builtin_ms_va_start.
1194 : // FIXME: wrong type.
1195 393 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1196 393 : GCC_JIT_TYPE_VOID);
1197 2006658 : if (TREE_CODE (type) == RECORD_TYPE)
1198 : // For __builtin_sysv_va_copy.
1199 : // FIXME: wrong type.
1200 524 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1201 524 : GCC_JIT_TYPE_VOID);
1202 2006134 : if (type == void_type_node)
1203 38383 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1204 38383 : GCC_JIT_TYPE_VOID);
1205 1967751 : else if (type == ptr_type_node)
1206 12969 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1207 12969 : GCC_JIT_TYPE_VOID_PTR);
1208 1954782 : else if (type == const_ptr_type_node)
1209 : {
1210 : // Void const ptr.
1211 7336 : recording::type* result =
1212 : new recording::memento_of_get_type (&target_builtins_ctxt,
1213 7336 : GCC_JIT_TYPE_VOID_PTR);
1214 7336 : return new recording::memento_of_get_const (result);
1215 : }
1216 1947446 : else if (type == unsigned_type_node)
1217 50566 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1218 50566 : GCC_JIT_TYPE_UNSIGNED_INT);
1219 1896880 : else if (type == long_unsigned_type_node)
1220 1703 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1221 1703 : GCC_JIT_TYPE_UNSIGNED_LONG);
1222 1895177 : else if (type == integer_type_node)
1223 425619 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1224 425619 : GCC_JIT_TYPE_INT);
1225 1469558 : else if (type == long_integer_type_node)
1226 131 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1227 131 : GCC_JIT_TYPE_LONG);
1228 1469427 : else if (type == long_long_integer_type_node)
1229 207635 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1230 207635 : GCC_JIT_TYPE_LONG_LONG);
1231 1261792 : else if (type == signed_char_type_node)
1232 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1233 0 : GCC_JIT_TYPE_SIGNED_CHAR);
1234 1261792 : else if (type == char_type_node)
1235 154580 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1236 154580 : GCC_JIT_TYPE_CHAR);
1237 1107212 : else if (type == unsigned_intQI_type_node)
1238 183007 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1239 183007 : GCC_JIT_TYPE_UINT8_T);
1240 924205 : else if (type == short_integer_type_node)
1241 182352 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1242 182352 : GCC_JIT_TYPE_SHORT);
1243 741853 : else if (type == short_unsigned_type_node)
1244 65893 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1245 65893 : GCC_JIT_TYPE_UNSIGNED_SHORT);
1246 675960 : else if (type == complex_float_type_node)
1247 262 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1248 262 : GCC_JIT_TYPE_COMPLEX_FLOAT);
1249 675698 : else if (type == complex_double_type_node)
1250 262 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1251 262 : GCC_JIT_TYPE_COMPLEX_DOUBLE);
1252 675436 : else if (type == complex_long_double_type_node)
1253 262 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1254 262 : GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE);
1255 675174 : else if (type == float_type_node)
1256 220080 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1257 220080 : GCC_JIT_TYPE_FLOAT);
1258 455094 : else if (type == double_type_node)
1259 190998 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1260 190998 : GCC_JIT_TYPE_DOUBLE);
1261 264096 : else if (type == long_double_type_node)
1262 1048 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1263 1048 : GCC_JIT_TYPE_LONG_DOUBLE);
1264 263048 : else if (type == bfloat16_type_node)
1265 58426 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1266 58426 : GCC_JIT_TYPE_BFLOAT16);
1267 204622 : else if (type == float16_type_node)
1268 : {
1269 122092 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1270 122092 : GCC_JIT_TYPE_FLOAT16);
1271 : }
1272 82530 : else if (type == float32_type_node)
1273 : {
1274 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1275 0 : GCC_JIT_TYPE_FLOAT32);
1276 : }
1277 82530 : else if (type == float64_type_node)
1278 : {
1279 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1280 0 : GCC_JIT_TYPE_FLOAT64);
1281 : }
1282 82530 : else if (type == float128_type_node)
1283 : {
1284 1179 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1285 1179 : GCC_JIT_TYPE_FLOAT128);
1286 : }
1287 81351 : else if (type == dfloat128_type_node)
1288 : // FIXME: wrong type.
1289 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1290 0 : GCC_JIT_TYPE_VOID);
1291 81351 : else if (type == long_long_unsigned_type_node)
1292 24497 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1293 24497 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
1294 56854 : else if (type == boolean_type_node)
1295 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1296 0 : GCC_JIT_TYPE_BOOL);
1297 56854 : else if (type == size_type_node)
1298 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1299 0 : GCC_JIT_TYPE_SIZE_T);
1300 56854 : else if (TREE_CODE (type) == POINTER_TYPE)
1301 : {
1302 47029 : tree inner_type = TREE_TYPE (type);
1303 47029 : recording::type* element_type = tree_type_to_jit_type (inner_type);
1304 47029 : if (!element_type)
1305 : return nullptr;
1306 47029 : return element_type->get_pointer ();
1307 : }
1308 9825 : else if (type == unsigned_intTI_type_node)
1309 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1310 0 : GCC_JIT_TYPE_UINT128_T);
1311 9825 : else if (INTEGRAL_TYPE_P (type))
1312 : {
1313 4978 : unsigned int size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
1314 4978 : return target_builtins_ctxt.get_int_type (size, TYPE_UNSIGNED (type));
1315 : }
1316 4847 : else if (SCALAR_FLOAT_TYPE_P (type))
1317 : {
1318 4847 : unsigned int size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
1319 4847 : enum gcc_jit_types type;
1320 4847 : switch (size)
1321 : {
1322 : case 2:
1323 : type = GCC_JIT_TYPE_BFLOAT16;
1324 : break;
1325 1965 : case 4:
1326 1965 : type = GCC_JIT_TYPE_FLOAT;
1327 1965 : break;
1328 2096 : case 8:
1329 2096 : type = GCC_JIT_TYPE_DOUBLE;
1330 2096 : break;
1331 0 : default:
1332 0 : if (ctxt->get_abort_on_unsupported_target_builtin ())
1333 : {
1334 0 : fprintf (stderr, "Unexpected float size: %d\n", size);
1335 0 : abort ();
1336 : }
1337 : return NULL;
1338 : }
1339 4847 : return new recording::memento_of_get_type (&target_builtins_ctxt, type);
1340 : }
1341 : else
1342 : {
1343 : // Attempt to find an unqualified type when the current type has qualifiers.
1344 0 : tree tp = TYPE_MAIN_VARIANT (type);
1345 0 : for ( ; tp != NULL ; tp = TYPE_NEXT_VARIANT (tp))
1346 : {
1347 0 : if (TYPE_QUALS (tp) == 0 && type != tp)
1348 : {
1349 0 : recording::type* result = tree_type_to_jit_type (tp);
1350 0 : if (result != NULL)
1351 : {
1352 0 : if (TYPE_READONLY (tp))
1353 0 : result = new recording::memento_of_get_const (result);
1354 0 : if (TYPE_VOLATILE (tp))
1355 0 : result = new recording::memento_of_get_volatile (result);
1356 0 : return result;
1357 : }
1358 : }
1359 : }
1360 :
1361 0 : if (ctxt->get_abort_on_unsupported_target_builtin ())
1362 : {
1363 0 : fprintf (stderr, "Unknown type:\n");
1364 0 : debug_tree (type);
1365 0 : abort ();
1366 : }
1367 : }
1368 :
1369 : return NULL;
1370 : }
1371 :
1372 : /* Record a builtin function. We save their types to be able to check types
1373 : in recording and for reflection. */
1374 :
1375 : static tree
1376 5062396 : jit_langhook_builtin_function (tree decl)
1377 : {
1378 5062396 : if (TREE_CODE (decl) == FUNCTION_DECL)
1379 : {
1380 5062396 : const char* name = IDENTIFIER_POINTER (DECL_NAME (decl));
1381 5062396 : target_builtins.put (name, decl);
1382 :
1383 5062396 : std::string string_name (name);
1384 9639306 : if (target_function_types.count (string_name) == 0)
1385 : {
1386 485486 : tree function_type = TREE_TYPE (decl);
1387 485486 : tree arg = TYPE_ARG_TYPES (function_type);
1388 485486 : bool is_variadic = false;
1389 :
1390 485486 : auto_vec <recording::type *> param_types;
1391 :
1392 1960022 : while (arg != void_list_node)
1393 : {
1394 1474798 : if (arg == NULL)
1395 : {
1396 : is_variadic = true;
1397 : break;
1398 : }
1399 1474536 : if (arg != void_list_node)
1400 : {
1401 1474536 : recording::type* arg_type = tree_type_to_jit_type (TREE_VALUE (arg));
1402 1474536 : if (arg_type == NULL)
1403 0 : return decl;
1404 1474536 : param_types.safe_push (arg_type);
1405 : }
1406 1474536 : arg = TREE_CHAIN (arg);
1407 : }
1408 :
1409 485486 : tree result_type = TREE_TYPE (function_type);
1410 485486 : recording::type* return_type = tree_type_to_jit_type (result_type);
1411 :
1412 485486 : if (return_type == NULL)
1413 : return decl;
1414 :
1415 485486 : recording::function_type* func_type =
1416 : new recording::function_type (&target_builtins_ctxt, return_type,
1417 485486 : param_types.length (),
1418 : param_types.address (), is_variadic,
1419 1444668 : false);
1420 :
1421 485486 : target_function_types[string_name] = func_type;
1422 485486 : }
1423 5062396 : }
1424 : return decl;
1425 : }
1426 :
1427 : static bool
1428 80 : jit_langhook_global_bindings_p (void)
1429 : {
1430 80 : return true;
1431 : }
1432 :
1433 : static tree
1434 0 : jit_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED)
1435 : {
1436 0 : return NULL_TREE;
1437 : }
1438 :
1439 : static tree
1440 0 : jit_langhook_getdecls (void)
1441 : {
1442 0 : return NULL;
1443 : }
1444 :
1445 : #undef LANG_HOOKS_NAME
1446 : #define LANG_HOOKS_NAME "libgccjit"
1447 :
1448 : #undef LANG_HOOKS_INIT
1449 : #define LANG_HOOKS_INIT jit_langhook_init
1450 :
1451 : #undef LANG_HOOKS_PARSE_FILE
1452 : #define LANG_HOOKS_PARSE_FILE jit_langhook_parse_file
1453 :
1454 : #undef LANG_HOOKS_TYPE_FOR_MODE
1455 : #define LANG_HOOKS_TYPE_FOR_MODE jit_langhook_type_for_mode
1456 :
1457 : #undef LANG_HOOKS_BUILTIN_FUNCTION
1458 : #define LANG_HOOKS_BUILTIN_FUNCTION jit_langhook_builtin_function
1459 :
1460 : #undef LANG_HOOKS_GLOBAL_BINDINGS_P
1461 : #define LANG_HOOKS_GLOBAL_BINDINGS_P jit_langhook_global_bindings_p
1462 :
1463 : #undef LANG_HOOKS_PUSHDECL
1464 : #define LANG_HOOKS_PUSHDECL jit_langhook_pushdecl
1465 :
1466 : #undef LANG_HOOKS_GETDECLS
1467 : #define LANG_HOOKS_GETDECLS jit_langhook_getdecls
1468 :
1469 : /* Attribute hooks. */
1470 : #undef LANG_HOOKS_ATTRIBUTE_TABLE
1471 : #define LANG_HOOKS_ATTRIBUTE_TABLE jit_attribute_table
1472 :
1473 : #undef LANG_HOOKS_DEEP_UNSHARING
1474 : #define LANG_HOOKS_DEEP_UNSHARING true
1475 :
1476 : struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
1477 :
1478 : #include "gt-jit-dummy-frontend.h"
1479 : #include "gtype-jit.h"
|