Branch data Line data Source code
1 : : /* jit.c -- Dummy "frontend" for use during JIT-compilation.
2 : : Copyright (C) 2013-2025 Free Software Foundation, Inc.
3 : :
4 : : This file is part of GCC.
5 : :
6 : : GCC is free software; you can redistribute it and/or modify it under
7 : : the terms of the GNU General Public License as published by the Free
8 : : Software Foundation; either version 3, or (at your option) any later
9 : : version.
10 : :
11 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : : for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along with GCC; see the file COPYING3. If not see
18 : : <http://www.gnu.org/licenses/>. */
19 : :
20 : : #include "config.h"
21 : : #include "system.h"
22 : : #include "coretypes.h"
23 : : #include "target.h"
24 : : #include "jit-playback.h"
25 : : #include "stor-layout.h"
26 : : #include "debug.h"
27 : : #include "langhooks.h"
28 : : #include "langhooks-def.h"
29 : : #include "diagnostic.h"
30 : : #include "options.h"
31 : : #include "stringpool.h"
32 : : #include "attribs.h"
33 : : #include "cgraph.h"
34 : : #include "target.h"
35 : : #include "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 : 514814 : static void my_ggc_walker (void *)
983 : : {
984 : 514814 : if (gcc::jit::active_playback_ctxt)
985 : 514814 : gcc::jit::active_playback_ctxt->gt_ggc_mx ();
986 : 514814 : }
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 : 13260 : jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
1119 : : {
1120 : : /* Build any vector types here (see PR 46805). */
1121 : 13260 : 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 : 12990 : if (mode == TYPE_MODE (float_type_node))
1132 : 140 : return float_type_node;
1133 : :
1134 : 12850 : if (mode == TYPE_MODE (double_type_node))
1135 : 369 : return double_type_node;
1136 : :
1137 : 12481 : if (mode == TYPE_MODE (intQI_type_node))
1138 : 805 : return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
1139 : 11676 : if (mode == TYPE_MODE (intHI_type_node))
1140 : 60 : return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
1141 : 11616 : if (mode == TYPE_MODE (intSI_type_node))
1142 : 1449 : return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
1143 : 10167 : if (mode == TYPE_MODE (intDI_type_node))
1144 : 2211 : 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 : 3358810 : recording::type* tree_type_to_jit_type (tree type)
1174 : : {
1175 : 3358810 : gcc_assert (gcc::jit::active_playback_ctxt);
1176 : 3358810 : gcc::jit::playback::context* ctxt = gcc::jit::active_playback_ctxt;
1177 : :
1178 : 3358810 : if (TREE_CODE (type) == VECTOR_TYPE)
1179 : : {
1180 : 1370720 : tree inner_type = TREE_TYPE (type);
1181 : 1370720 : recording::type* element_type = tree_type_to_jit_type (inner_type);
1182 : 1370720 : poly_uint64 size = TYPE_VECTOR_SUBPARTS (type);
1183 : 1370720 : long constant_size = size.to_constant ();
1184 : 1370720 : if (element_type != NULL)
1185 : 1370720 : return element_type->get_vector (constant_size);
1186 : : return NULL;
1187 : : }
1188 : 1988090 : 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 : 1987700 : 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 : 1987180 : if (type == void_type_node)
1199 : 38090 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1200 : 38090 : GCC_JIT_TYPE_VOID);
1201 : 1949090 : 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 : 1936220 : 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 : 1928940 : else if (type == unsigned_type_node)
1213 : 50050 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1214 : 50050 : GCC_JIT_TYPE_UNSIGNED_INT);
1215 : 1878890 : 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 : 1877200 : 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 : 1454830 : 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 : 1454700 : 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 : 1248650 : 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 : 1248650 : else if (type == char_type_node)
1231 : 152230 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1232 : 152230 : GCC_JIT_TYPE_CHAR);
1233 : 1096420 : 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 : 914810 : else if (type == short_integer_type_node)
1237 : 178880 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1238 : 178880 : GCC_JIT_TYPE_SHORT);
1239 : 735930 : else if (type == short_unsigned_type_node)
1240 : 65260 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1241 : 65260 : GCC_JIT_TYPE_UNSIGNED_SHORT);
1242 : 670670 : 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 : 670410 : 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 : 670150 : 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 : 669890 : 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 : 451490 : 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 : 261950 : 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 : 260910 : 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 : 202930 : 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 : 81770 : 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 : 81770 : 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 : 81770 : 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 : 80600 : 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 : 80600 : else if (type == long_long_unsigned_type_node)
1288 : 24180 : return new recording::memento_of_get_type (&target_builtins_ctxt,
1289 : 24180 : 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 : 4904874 : jit_langhook_builtin_function (tree decl)
1373 : : {
1374 : 4904874 : if (TREE_CODE (decl) == FUNCTION_DECL)
1375 : : {
1376 : 4904874 : const char* name = IDENTIFIER_POINTER (DECL_NAME (decl));
1377 : 4904874 : target_builtins.put (name, decl);
1378 : :
1379 : 4904874 : std::string string_name (name);
1380 : 9328878 : if (target_function_types.count (string_name) == 0)
1381 : : {
1382 : 480870 : tree function_type = TREE_TYPE (decl);
1383 : 480870 : tree arg = TYPE_ARG_TYPES (function_type);
1384 : 480870 : bool is_variadic = false;
1385 : :
1386 : 480870 : auto_vec <recording::type *> param_types;
1387 : :
1388 : 1941420 : while (arg != void_list_node)
1389 : : {
1390 : 1460810 : if (arg == NULL)
1391 : : {
1392 : : is_variadic = true;
1393 : : break;
1394 : : }
1395 : 1460550 : if (arg != void_list_node)
1396 : : {
1397 : 1460550 : recording::type* arg_type = tree_type_to_jit_type (TREE_VALUE (arg));
1398 : 1460550 : if (arg_type == NULL)
1399 : 0 : return decl;
1400 : 1460550 : param_types.safe_push (arg_type);
1401 : : }
1402 : 1460550 : arg = TREE_CHAIN (arg);
1403 : : }
1404 : :
1405 : 480870 : tree result_type = TREE_TYPE (function_type);
1406 : 480870 : recording::type* return_type = tree_type_to_jit_type (result_type);
1407 : :
1408 : 480870 : if (return_type == NULL)
1409 : : return decl;
1410 : :
1411 : 480870 : recording::function_type* func_type =
1412 : : new recording::function_type (&target_builtins_ctxt, return_type,
1413 : 480870 : param_types.length (),
1414 : : param_types.address (), is_variadic,
1415 : 1430910 : false);
1416 : :
1417 : 480870 : target_function_types[string_name] = func_type;
1418 : 480870 : }
1419 : 4904874 : }
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"
|