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 "attr-handlers.h"
34 : #include "cgraph.h"
35 : #include "target.h"
36 : #include "diagnostics/text-sink.h"
37 : #include "print-tree.h"
38 :
39 : #include <mpfr.h>
40 : #include <unordered_map>
41 :
42 : using namespace gcc::jit;
43 :
44 : /* Attribute handling. These are the libgccjit-specific attribute handlers;
45 : the handlers shared with the C family live in gcc/attr-handlers.cc. */
46 :
47 : static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
48 : static tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
49 : static tree handle_format_attribute (tree *, tree, tree, int, bool *);
50 : static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
51 : static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
52 : static tree handle_patchable_function_entry_attribute (tree *, tree, tree,
53 : int, bool *);
54 : static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
55 : static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
56 :
57 : /* Helper to define attribute exclusions. */
58 : #define ATTR_EXCL(name, function, type, variable) \
59 : { name, function, type, variable }
60 :
61 : /* These variables act as a cache for the target builtins. This is needed in
62 : order to be able to type-check the calls since we can only get those types
63 : in the playback phase while we need them in the recording phase. */
64 : hash_map<nofree_string_hash, tree> target_builtins{};
65 : std::unordered_map<std::string, recording::function_type*> target_function_types
66 : {};
67 : recording::context target_builtins_ctxt{NULL};
68 :
69 : /* Table of machine-independent attributes supported in libgccjit. */
70 : static const attribute_spec jit_gnu_attributes[] =
71 : {
72 : /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
73 : affects_type_identity, handler, exclude } */
74 : { "alias", 1, 1, true, false, false, false,
75 : handle_alias_attribute, NULL },
76 : { "always_inline", 0, 0, true, false, false, false,
77 : handle_always_inline_attribute,
78 : attr_always_inline_exclusions },
79 : { "cold", 0, 0, true, false, false, false,
80 : handle_cold_attribute,
81 : attr_cold_hot_exclusions },
82 : /* The same comments as for noreturn attributes apply to const ones. */
83 : { "const", 0, 0, true, false, false, false,
84 : handle_const_attribute,
85 : attr_const_pure_exclusions },
86 : { "fn spec", 1, 1, false, true, true, false,
87 : handle_fnspec_attribute, NULL },
88 :
89 : { "leaf", 0, 0, true, false, false, false,
90 : handle_leaf_attribute, NULL },
91 : { "malloc", 0, 0, true, false, false, false,
92 : handle_malloc_common, attr_alloc_exclusions },
93 : { "noreturn", 0, 0, true, false, false, false,
94 : handle_noreturn_attribute,
95 : attr_noreturn_exclusions },
96 : { "no vops", 0, 0, true, false, false, false,
97 : handle_novops_attribute, NULL },
98 : { "noinline", 0, 0, true, false, false, false,
99 : handle_noinline_attribute,
100 : attr_noinline_exclusions },
101 : { "nonnull", 0, -1, false, true, true, false,
102 : handle_nonnull_attribute, NULL },
103 : { "nothrow", 0, 0, true, false, false, false,
104 : handle_nothrow_attribute, NULL },
105 : { "patchable_function_entry", 1, 2, true, false, false, false,
106 : handle_patchable_function_entry_attribute,
107 : NULL },
108 : { "pure", 0, 0, true, false, false, false,
109 : handle_pure_attribute,
110 : attr_const_pure_exclusions },
111 : { "returns_twice", 0, 0, true, false, false, false,
112 : handle_returns_twice_attribute,
113 : attr_returns_twice_exclusions },
114 : { "sentinel", 0, 1, false, true, true, false,
115 : handle_sentinel_attribute, NULL },
116 : { "target", 1, -1, true, false, false, false,
117 : handle_target_attribute, attr_target_exclusions },
118 : { "type generic", 0, 0, false, true, true, false,
119 : handle_type_generic_attribute, NULL },
120 : { "transaction_pure", 0, 0, false, true, true, false,
121 : handle_transaction_pure_attribute, NULL },
122 : { "used", 0, 0, true, false, false, false,
123 : handle_used_attribute, NULL },
124 : { "visibility", 1, 1, false, false, false, false,
125 : handle_visibility_attribute, NULL },
126 : { "weak", 0, 0, true, false, false, false,
127 : handle_weak_attribute, NULL },
128 : /* For internal use only. The leading '*' both prevents its usage in
129 : source code and signals that it may be overridden by machine tables. */
130 : { "*tm regparm", 0, 0, false, true, true, false,
131 : ignore_attribute, NULL },
132 : };
133 :
134 : static const scoped_attribute_specs jit_gnu_attribute_table =
135 : {
136 : "gnu", { jit_gnu_attributes }
137 : };
138 :
139 : /* Give the specifications for the format attributes, used by C and all
140 : descendants. */
141 :
142 : static const attribute_spec jit_format_attributes[] =
143 : {
144 : /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
145 : affects_type_identity, handler, exclude } */
146 : { "format", 3, 3, false, true, true, false,
147 : handle_format_attribute, NULL },
148 : { "format_arg", 1, 1, false, true, true, false,
149 : handle_format_arg_attribute, NULL }
150 : };
151 :
152 : static const scoped_attribute_specs jit_format_attribute_table =
153 : {
154 : "gnu", { jit_format_attributes }
155 : };
156 :
157 : static const scoped_attribute_specs *const jit_attribute_table[] =
158 : {
159 : &jit_gnu_attribute_table,
160 : &jit_format_attribute_table
161 : };
162 :
163 : /* Attribute handlers. */
164 :
165 : /* Attribute handlers specific to libgccjit. If the attribute handler code
166 : is the same as the one in `c-family/c-attribs.cc`, please move the
167 : handler into `attr-handlers.cc`. */
168 :
169 :
170 : /* Handle a "noreturn" attribute; arguments as in
171 : struct attribute_spec.handler. */
172 :
173 : static tree
174 1336 : handle_noreturn_attribute (tree *node, tree ARG_UNUSED (name),
175 : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
176 : bool * ARG_UNUSED (no_add_attrs))
177 : {
178 1336 : tree type = TREE_TYPE (*node);
179 :
180 1336 : if (TREE_CODE (*node) == FUNCTION_DECL)
181 1336 : TREE_THIS_VOLATILE (*node) = 1;
182 0 : else if (TREE_CODE (type) == POINTER_TYPE
183 0 : && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
184 0 : TREE_TYPE (*node)
185 0 : = build_pointer_type
186 0 : (build_type_variant (TREE_TYPE (type),
187 : TYPE_READONLY (TREE_TYPE (type)), 1));
188 : else
189 0 : gcc_unreachable ();
190 :
191 1336 : return NULL_TREE;
192 : }
193 :
194 : /* Helper for nonnull attribute handling; fetch the operand number
195 : from the attribute argument list. */
196 :
197 : static bool
198 5 : get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
199 : {
200 : /* Verify the arg number is a constant. */
201 5 : if (!tree_fits_uhwi_p (arg_num_expr))
202 : return false;
203 :
204 5 : *valp = TREE_INT_CST_LOW (arg_num_expr);
205 5 : return true;
206 : }
207 :
208 : /* Handle the "nonnull" attribute. */
209 :
210 : static tree
211 105 : handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
212 : tree args, int ARG_UNUSED (flags),
213 : bool * ARG_UNUSED (no_add_attrs))
214 : {
215 105 : tree type = *node;
216 :
217 : /* If no arguments are specified, all pointer arguments should be
218 : non-null. Verify a full prototype is given so that the arguments
219 : will have the correct types when we actually check them later.
220 : Avoid diagnosing type-generic built-ins since those have no
221 : prototype. */
222 105 : if (!args)
223 : {
224 100 : gcc_assert (prototype_p (type)
225 : || !TYPE_ATTRIBUTES (type)
226 : || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type)));
227 :
228 : return NULL_TREE;
229 : }
230 :
231 : /* Argument list specified. Verify that each argument number references
232 : a pointer argument. */
233 10 : for (; args; args = TREE_CHAIN (args))
234 : {
235 5 : tree argument;
236 5 : unsigned HOST_WIDE_INT arg_num = 0, ck_num;
237 :
238 5 : if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
239 0 : gcc_unreachable ();
240 :
241 5 : argument = TYPE_ARG_TYPES (type);
242 5 : if (argument)
243 : {
244 0 : for (ck_num = 1; ; ck_num++)
245 : {
246 5 : if (!argument || ck_num == arg_num)
247 : break;
248 0 : argument = TREE_CHAIN (argument);
249 : }
250 :
251 5 : gcc_assert (argument
252 : && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE);
253 : }
254 : }
255 :
256 : return NULL_TREE;
257 : }
258 :
259 : /* Handle a "sentinel" attribute. */
260 :
261 : static tree
262 0 : handle_sentinel_attribute (tree *node, tree ARG_UNUSED (name), tree args,
263 : int ARG_UNUSED (flags),
264 : bool * ARG_UNUSED (no_add_attrs))
265 : {
266 0 : gcc_assert (stdarg_p (*node));
267 :
268 0 : if (args)
269 : {
270 0 : tree position = TREE_VALUE (args);
271 0 : gcc_assert (TREE_CODE (position) == INTEGER_CST);
272 0 : if (tree_int_cst_lt (position, integer_zero_node))
273 0 : gcc_unreachable ();
274 : }
275 :
276 0 : return NULL_TREE;
277 : }
278 :
279 : /* Handle a "transaction_pure" attribute. */
280 :
281 : static tree
282 0 : handle_transaction_pure_attribute (tree *node, tree ARG_UNUSED (name),
283 : tree ARG_UNUSED (args),
284 : int ARG_UNUSED (flags),
285 : bool * ARG_UNUSED (no_add_attrs))
286 : {
287 : /* Ensure we have a function type. */
288 0 : gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
289 :
290 0 : return NULL_TREE;
291 : }
292 :
293 : /* Handle a "cold" and attribute; arguments as in
294 : struct attribute_spec.handler. */
295 :
296 : static tree
297 1341 : handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
298 : int ARG_UNUSED (flags), bool *no_add_attrs)
299 : {
300 1341 : if (TREE_CODE (*node) == FUNCTION_DECL
301 1341 : || TREE_CODE (*node) == LABEL_DECL)
302 : {
303 : /* Attribute cold processing is done later with lookup_attribute. */
304 : }
305 : else
306 : {
307 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
308 0 : *no_add_attrs = true;
309 : }
310 :
311 1341 : return NULL_TREE;
312 : }
313 :
314 : static tree
315 0 : handle_patchable_function_entry_attribute (tree *, tree, tree, int, bool *)
316 : {
317 : /* Nothing to be done here. */
318 0 : return NULL_TREE;
319 : }
320 :
321 : /* Handle a "format" attribute; arguments as in
322 : struct attribute_spec.handler. */
323 :
324 : static tree
325 0 : handle_format_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
326 : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
327 : bool *no_add_attrs)
328 : {
329 0 : *no_add_attrs = true;
330 0 : return NULL_TREE;
331 : }
332 :
333 :
334 : /* Handle a "format_arg" attribute; arguments as in
335 : struct attribute_spec.handler. */
336 :
337 : tree
338 0 : handle_format_arg_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
339 : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
340 : bool *no_add_attrs)
341 : {
342 0 : *no_add_attrs = true;
343 0 : return NULL_TREE;
344 : }
345 :
346 : /* (end of attribute-handling). */
347 :
348 : /* Language-dependent contents of a type. */
349 :
350 : struct GTY(()) lang_type
351 : {
352 : char dummy;
353 : };
354 :
355 : /* Language-dependent contents of a decl. */
356 :
357 : struct GTY((variable_size)) lang_decl
358 : {
359 : char dummy;
360 : };
361 :
362 : /* Language-dependent contents of an identifier. This must include a
363 : tree_identifier. */
364 :
365 : struct GTY(()) lang_identifier
366 : {
367 : struct tree_identifier common;
368 : };
369 :
370 : /* The resulting tree type. */
371 :
372 : /* See lang_tree_node in gcc/c/c-decl.cc. */
373 : union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
374 : chain_next ("(union lang_tree_node *) jit_tree_chain_next (&%h.generic)")))
375 : lang_tree_node
376 : {
377 : union tree_node GTY ((tag ("0"),
378 : desc ("tree_node_structure (&%h)")))
379 : generic;
380 : struct lang_identifier GTY ((tag ("1"))) identifier;
381 : };
382 :
383 : /* We don't use language_function. */
384 :
385 : struct GTY(()) language_function
386 : {
387 : int dummy;
388 : };
389 :
390 : /* GC-marking callback for use from jit_root_tab.
391 :
392 : If there's an active playback context, call its marking method
393 : so that it can mark any pointers it references. */
394 :
395 660050 : static void my_ggc_walker (void *)
396 : {
397 660050 : if (gcc::jit::active_playback_ctxt)
398 660050 : gcc::jit::active_playback_ctxt->gt_ggc_mx ();
399 660050 : }
400 :
401 : const char *dummy;
402 :
403 : struct ggc_root_tab jit_root_tab[] =
404 : {
405 : {
406 : &dummy, 1, 0, my_ggc_walker, NULL
407 : },
408 : LAST_GGC_ROOT_TAB
409 : };
410 :
411 : /* Subclass of diagnostics::text_sink for libgccjit: like text
412 : output, but capture the message and call add_diagnostic with it
413 : on the active playback context. */
414 :
415 : class jit_diagnostic_listener : public diagnostics::text_sink
416 : {
417 : public:
418 1366 : jit_diagnostic_listener (diagnostics::context &dc,
419 : gcc::jit::playback::context &playback_ctxt)
420 : : diagnostics::text_sink (dc),
421 1366 : m_playback_ctxt (playback_ctxt)
422 : {
423 : }
424 :
425 0 : void dump (FILE *out, int indent) const final override
426 : {
427 0 : fprintf (out, "%*sjit_diagnostic_listener\n", indent, "");
428 0 : fprintf (out, "%*sm_playback_context: %p\n",
429 : indent + 2, "",
430 0 : (void *)&m_playback_ctxt);
431 0 : }
432 :
433 25 : void on_report_diagnostic (const diagnostics::diagnostic_info &info,
434 : enum diagnostics::kind orig_diag_kind) final override
435 : {
436 25 : JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
437 :
438 : /* Let the text output format do most of the work. */
439 25 : diagnostics::text_sink::on_report_diagnostic (info, orig_diag_kind);
440 :
441 25 : const char *text = pp_formatted_text (get_printer ());
442 :
443 : /* Delegate to the playback context (and thence to the
444 : recording context). */
445 25 : gcc::jit::active_playback_ctxt->add_diagnostic (text, info);
446 :
447 25 : pp_clear_output_area (get_printer ());
448 25 : }
449 :
450 : private:
451 : gcc::jit::playback::context &m_playback_ctxt;
452 : };
453 :
454 : /* JIT-specific implementation of diagnostic callbacks. */
455 :
456 : /* Implementation of "begin_diagnostic". */
457 :
458 : static void
459 25 : jit_begin_diagnostic (diagnostics::text_sink &,
460 : const diagnostics::diagnostic_info */*diagnostic*/)
461 : {
462 25 : gcc_assert (gcc::jit::active_playback_ctxt);
463 25 : JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
464 :
465 : /* No-op (apart from logging); the real error-handling is done by the
466 : jit_diagnostic_listener. */
467 25 : }
468 :
469 : /* Implementation of "end_diagnostic". */
470 :
471 : static void
472 25 : jit_end_diagnostic (diagnostics::text_sink &,
473 : const diagnostics::diagnostic_info *,
474 : enum diagnostics::kind)
475 : {
476 25 : gcc_assert (gcc::jit::active_playback_ctxt);
477 25 : JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
478 :
479 : /* No-op (apart from logging); the real error-handling is done by the
480 : jit_diagnostic_listener. */
481 25 : }
482 :
483 : /* Language hooks. */
484 :
485 : static bool
486 1366 : jit_langhook_init (void)
487 : {
488 1366 : gcc_assert (gcc::jit::active_playback_ctxt);
489 1366 : JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
490 :
491 1366 : static bool registered_root_tab = false;
492 1366 : if (!registered_root_tab)
493 : {
494 131 : ggc_register_root_tab (jit_root_tab);
495 131 : registered_root_tab = true;
496 : }
497 :
498 1366 : gcc_assert (global_dc);
499 1366 : diagnostics::text_starter (global_dc) = jit_begin_diagnostic;
500 1366 : diagnostics::text_finalizer (global_dc) = jit_end_diagnostic;
501 1366 : auto sink
502 : = std::make_unique<jit_diagnostic_listener>
503 : (*global_dc,
504 1366 : *gcc::jit::active_playback_ctxt);
505 1366 : global_dc->set_sink (std::move (sink));
506 :
507 1366 : build_common_tree_nodes (flag_signed_char);
508 :
509 1366 : target_builtins.empty ();
510 1366 : build_common_builtin_nodes ();
511 :
512 : /* The default precision for floating point numbers. This is used
513 : for floating point constants with abstract type. This may
514 : eventually be controllable by a command line option. */
515 1366 : mpfr_set_default_prec (256);
516 :
517 1366 : targetm.init_builtins ();
518 :
519 2732 : return true;
520 1366 : }
521 :
522 : static void
523 1366 : jit_langhook_parse_file (void)
524 : {
525 : /* Replay the activity by the client, recorded on the context. */
526 1366 : gcc_assert (gcc::jit::active_playback_ctxt);
527 1366 : gcc::jit::active_playback_ctxt->replay ();
528 1366 : }
529 :
530 : static tree
531 13578 : jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
532 : {
533 : /* Build any vector types here (see PR 46805). */
534 13578 : if (VECTOR_MODE_P (mode))
535 : {
536 360 : tree inner;
537 :
538 720 : inner = jit_langhook_type_for_mode (GET_MODE_INNER (mode), unsignedp);
539 360 : if (inner != NULL_TREE)
540 360 : return build_vector_type_for_mode (inner, mode);
541 : return NULL_TREE;
542 : }
543 :
544 13218 : if (mode == TYPE_MODE (float_type_node))
545 170 : return float_type_node;
546 :
547 13048 : if (mode == TYPE_MODE (double_type_node))
548 494 : return double_type_node;
549 :
550 12554 : if (mode == TYPE_MODE (intQI_type_node))
551 1025 : return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
552 11529 : if (mode == TYPE_MODE (intHI_type_node))
553 80 : return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
554 11449 : if (mode == TYPE_MODE (intSI_type_node))
555 1092 : return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
556 10357 : if (mode == TYPE_MODE (intDI_type_node))
557 2161 : return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
558 8196 : if (mode == TYPE_MODE (intTI_type_node))
559 0 : return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
560 :
561 8196 : if (mode == TYPE_MODE (integer_type_node))
562 0 : return unsignedp ? unsigned_type_node : integer_type_node;
563 :
564 8196 : if (mode == TYPE_MODE (long_integer_type_node))
565 0 : return unsignedp ? long_unsigned_type_node : long_integer_type_node;
566 :
567 8196 : if (mode == TYPE_MODE (long_long_integer_type_node))
568 0 : return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
569 :
570 8196 : if (COMPLEX_MODE_P (mode))
571 : {
572 8196 : if (mode == TYPE_MODE (complex_float_type_node))
573 1366 : return complex_float_type_node;
574 6830 : if (mode == TYPE_MODE (complex_double_type_node))
575 1366 : return complex_double_type_node;
576 5464 : if (mode == TYPE_MODE (complex_long_double_type_node))
577 1366 : return complex_long_double_type_node;
578 4098 : if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp)
579 0 : return complex_integer_type_node;
580 : }
581 :
582 32784 : for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
583 28686 : if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE
584 28686 : && mode == TYPE_MODE (FLOATN_NX_TYPE_NODE (i)))
585 0 : return FLOATN_NX_TYPE_NODE (i);
586 : /* gcc_unreachable */
587 : return NULL;
588 : }
589 :
590 3465998 : recording::type* tree_type_to_jit_type (tree type)
591 : {
592 3465998 : gcc_assert (gcc::jit::active_playback_ctxt);
593 3465998 : gcc::jit::playback::context* ctxt = gcc::jit::active_playback_ctxt;
594 :
595 3465998 : if (TREE_CODE (type) == VECTOR_TYPE)
596 : {
597 1414276 : tree inner_type = TREE_TYPE (type);
598 1414276 : recording::type* element_type = tree_type_to_jit_type (inner_type);
599 1414276 : poly_uint64 size = TYPE_VECTOR_SUBPARTS (type);
600 1414276 : long constant_size = size.to_constant ();
601 1414276 : if (element_type != NULL)
602 1414276 : return element_type->get_vector (constant_size);
603 : return NULL;
604 : }
605 2051722 : if (TREE_CODE (type) == REFERENCE_TYPE)
606 : // For __builtin_ms_va_start.
607 : // FIXME: wrong type.
608 393 : return new recording::memento_of_get_type (&target_builtins_ctxt,
609 393 : GCC_JIT_TYPE_VOID);
610 2051329 : if (TREE_CODE (type) == RECORD_TYPE)
611 : // For __builtin_sysv_va_copy.
612 : // FIXME: wrong type.
613 524 : return new recording::memento_of_get_type (&target_builtins_ctxt,
614 524 : GCC_JIT_TYPE_VOID);
615 2050805 : if (type == void_type_node)
616 41003 : return new recording::memento_of_get_type (&target_builtins_ctxt,
617 41003 : GCC_JIT_TYPE_VOID);
618 2009802 : else if (type == ptr_type_node)
619 12969 : return new recording::memento_of_get_type (&target_builtins_ctxt,
620 12969 : GCC_JIT_TYPE_VOID_PTR);
621 1996833 : else if (type == const_ptr_type_node)
622 : {
623 : // Void const ptr.
624 7336 : recording::type* result =
625 : new recording::memento_of_get_type (&target_builtins_ctxt,
626 7336 : GCC_JIT_TYPE_VOID_PTR);
627 7336 : return new recording::memento_of_get_const (result);
628 : }
629 1989497 : else if (type == unsigned_type_node)
630 51221 : return new recording::memento_of_get_type (&target_builtins_ctxt,
631 51221 : GCC_JIT_TYPE_UNSIGNED_INT);
632 1938276 : else if (type == long_unsigned_type_node)
633 1703 : return new recording::memento_of_get_type (&target_builtins_ctxt,
634 1703 : GCC_JIT_TYPE_UNSIGNED_LONG);
635 1936573 : else if (type == integer_type_node)
636 431252 : return new recording::memento_of_get_type (&target_builtins_ctxt,
637 431252 : GCC_JIT_TYPE_INT);
638 1505321 : else if (type == long_integer_type_node)
639 131 : return new recording::memento_of_get_type (&target_builtins_ctxt,
640 131 : GCC_JIT_TYPE_LONG);
641 1505190 : else if (type == long_long_integer_type_node)
642 207635 : return new recording::memento_of_get_type (&target_builtins_ctxt,
643 207635 : GCC_JIT_TYPE_LONG_LONG);
644 1297555 : else if (type == signed_char_type_node)
645 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
646 0 : GCC_JIT_TYPE_SIGNED_CHAR);
647 1297555 : else if (type == char_type_node)
648 174361 : return new recording::memento_of_get_type (&target_builtins_ctxt,
649 174361 : GCC_JIT_TYPE_CHAR);
650 1123194 : else if (type == unsigned_intQI_type_node)
651 189164 : return new recording::memento_of_get_type (&target_builtins_ctxt,
652 189164 : GCC_JIT_TYPE_UINT8_T);
653 934030 : else if (type == short_integer_type_node)
654 182352 : return new recording::memento_of_get_type (&target_builtins_ctxt,
655 182352 : GCC_JIT_TYPE_SHORT);
656 751678 : else if (type == short_unsigned_type_node)
657 68251 : return new recording::memento_of_get_type (&target_builtins_ctxt,
658 68251 : GCC_JIT_TYPE_UNSIGNED_SHORT);
659 683427 : else if (type == complex_float_type_node)
660 262 : return new recording::memento_of_get_type (&target_builtins_ctxt,
661 262 : GCC_JIT_TYPE_COMPLEX_FLOAT);
662 683165 : else if (type == complex_double_type_node)
663 262 : return new recording::memento_of_get_type (&target_builtins_ctxt,
664 262 : GCC_JIT_TYPE_COMPLEX_DOUBLE);
665 682903 : else if (type == complex_long_double_type_node)
666 262 : return new recording::memento_of_get_type (&target_builtins_ctxt,
667 262 : GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE);
668 682641 : else if (type == float_type_node)
669 225713 : return new recording::memento_of_get_type (&target_builtins_ctxt,
670 225713 : GCC_JIT_TYPE_FLOAT);
671 456928 : else if (type == double_type_node)
672 190998 : return new recording::memento_of_get_type (&target_builtins_ctxt,
673 190998 : GCC_JIT_TYPE_DOUBLE);
674 265930 : else if (type == long_double_type_node)
675 1048 : return new recording::memento_of_get_type (&target_builtins_ctxt,
676 1048 : GCC_JIT_TYPE_LONG_DOUBLE);
677 264882 : else if (type == bfloat16_type_node)
678 58950 : return new recording::memento_of_get_type (&target_builtins_ctxt,
679 58950 : GCC_JIT_TYPE_BFLOAT16);
680 205932 : else if (type == float16_type_node)
681 : {
682 122354 : return new recording::memento_of_get_type (&target_builtins_ctxt,
683 122354 : GCC_JIT_TYPE_FLOAT16);
684 : }
685 83578 : else if (type == float32_type_node)
686 : {
687 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
688 0 : GCC_JIT_TYPE_FLOAT32);
689 : }
690 83578 : else if (type == float64_type_node)
691 : {
692 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
693 0 : GCC_JIT_TYPE_FLOAT64);
694 : }
695 83578 : else if (type == float128_type_node)
696 : {
697 1179 : return new recording::memento_of_get_type (&target_builtins_ctxt,
698 1179 : GCC_JIT_TYPE_FLOAT128);
699 : }
700 82399 : else if (type == dfloat128_type_node)
701 : // FIXME: wrong type.
702 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
703 0 : GCC_JIT_TYPE_VOID);
704 82399 : else if (type == long_long_unsigned_type_node)
705 25152 : return new recording::memento_of_get_type (&target_builtins_ctxt,
706 25152 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
707 57247 : else if (type == boolean_type_node)
708 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
709 0 : GCC_JIT_TYPE_BOOL);
710 57247 : else if (type == size_type_node)
711 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
712 0 : GCC_JIT_TYPE_SIZE_T);
713 57247 : else if (TREE_CODE (type) == POINTER_TYPE)
714 : {
715 47422 : tree inner_type = TREE_TYPE (type);
716 47422 : recording::type* element_type = tree_type_to_jit_type (inner_type);
717 47422 : if (!element_type)
718 : return nullptr;
719 47422 : return element_type->get_pointer ();
720 : }
721 9825 : else if (type == unsigned_intTI_type_node)
722 0 : return new recording::memento_of_get_type (&target_builtins_ctxt,
723 0 : GCC_JIT_TYPE_UINT128_T);
724 9825 : else if (INTEGRAL_TYPE_P (type))
725 : {
726 4978 : unsigned int size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
727 4978 : return target_builtins_ctxt.get_int_type (size, TYPE_UNSIGNED (type));
728 : }
729 4847 : else if (SCALAR_FLOAT_TYPE_P (type))
730 : {
731 4847 : unsigned int size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
732 4847 : enum gcc_jit_types type;
733 4847 : switch (size)
734 : {
735 : case 2:
736 : type = GCC_JIT_TYPE_BFLOAT16;
737 : break;
738 1965 : case 4:
739 1965 : type = GCC_JIT_TYPE_FLOAT;
740 1965 : break;
741 2096 : case 8:
742 2096 : type = GCC_JIT_TYPE_DOUBLE;
743 2096 : break;
744 0 : default:
745 0 : if (ctxt->get_abort_on_unsupported_target_builtin ())
746 : {
747 0 : fprintf (stderr, "Unexpected float size: %d\n", size);
748 0 : abort ();
749 : }
750 : return NULL;
751 : }
752 4847 : return new recording::memento_of_get_type (&target_builtins_ctxt, type);
753 : }
754 : else
755 : {
756 : // Attempt to find an unqualified type when the current type has qualifiers.
757 0 : tree tp = TYPE_MAIN_VARIANT (type);
758 0 : for ( ; tp != NULL ; tp = TYPE_NEXT_VARIANT (tp))
759 : {
760 0 : if (TYPE_QUALS (tp) == 0 && type != tp)
761 : {
762 0 : recording::type* result = tree_type_to_jit_type (tp);
763 0 : if (result != NULL)
764 : {
765 0 : if (TYPE_READONLY (tp))
766 0 : result = new recording::memento_of_get_const (result);
767 0 : if (TYPE_VOLATILE (tp))
768 0 : result = new recording::memento_of_get_volatile (result);
769 : return result;
770 : }
771 : }
772 : }
773 :
774 0 : if (ctxt->get_abort_on_unsupported_target_builtin ())
775 : {
776 0 : fprintf (stderr, "Unknown type:\n");
777 0 : debug_tree (type);
778 0 : abort ();
779 : }
780 : }
781 :
782 : return NULL;
783 : }
784 :
785 : /* Record a builtin function. We save their types to be able to check types
786 : in recording and for reflection. */
787 :
788 : static tree
789 5186702 : jit_langhook_builtin_function (tree decl)
790 : {
791 5186702 : if (TREE_CODE (decl) == FUNCTION_DECL)
792 : {
793 5186702 : const char* name = IDENTIFIER_POINTER (DECL_NAME (decl));
794 5186702 : target_builtins.put (name, decl);
795 :
796 5186702 : std::string string_name (name);
797 9875997 : if (target_function_types.count (string_name) == 0)
798 : {
799 497407 : tree function_type = TREE_TYPE (decl);
800 497407 : tree arg = TYPE_ARG_TYPES (function_type);
801 497407 : bool is_variadic = false;
802 :
803 497407 : auto_vec <recording::type *> param_types;
804 :
805 2004300 : while (arg != void_list_node)
806 : {
807 1507155 : if (arg == NULL)
808 : {
809 : is_variadic = true;
810 : break;
811 : }
812 1506893 : if (arg != void_list_node)
813 : {
814 1506893 : recording::type* arg_type = tree_type_to_jit_type (TREE_VALUE (arg));
815 1506893 : if (arg_type == NULL)
816 0 : return decl;
817 1506893 : param_types.safe_push (arg_type);
818 : }
819 1506893 : arg = TREE_CHAIN (arg);
820 : }
821 :
822 497407 : tree result_type = TREE_TYPE (function_type);
823 497407 : recording::type* return_type = tree_type_to_jit_type (result_type);
824 :
825 497407 : if (return_type == NULL)
826 : return decl;
827 :
828 497407 : recording::function_type* func_type =
829 : new recording::function_type (&target_builtins_ctxt, return_type,
830 497407 : param_types.length (),
831 : param_types.address (), is_variadic,
832 1479645 : false);
833 :
834 497407 : target_function_types[string_name] = func_type;
835 497407 : }
836 5186702 : }
837 : return decl;
838 : }
839 :
840 : static bool
841 80 : jit_langhook_global_bindings_p (void)
842 : {
843 80 : return true;
844 : }
845 :
846 : static tree
847 0 : jit_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED)
848 : {
849 0 : return NULL_TREE;
850 : }
851 :
852 : static tree
853 0 : jit_langhook_getdecls (void)
854 : {
855 0 : return NULL;
856 : }
857 :
858 : #undef LANG_HOOKS_NAME
859 : #define LANG_HOOKS_NAME "libgccjit"
860 :
861 : #undef LANG_HOOKS_INIT
862 : #define LANG_HOOKS_INIT jit_langhook_init
863 :
864 : #undef LANG_HOOKS_PARSE_FILE
865 : #define LANG_HOOKS_PARSE_FILE jit_langhook_parse_file
866 :
867 : #undef LANG_HOOKS_TYPE_FOR_MODE
868 : #define LANG_HOOKS_TYPE_FOR_MODE jit_langhook_type_for_mode
869 :
870 : #undef LANG_HOOKS_BUILTIN_FUNCTION
871 : #define LANG_HOOKS_BUILTIN_FUNCTION jit_langhook_builtin_function
872 :
873 : #undef LANG_HOOKS_GLOBAL_BINDINGS_P
874 : #define LANG_HOOKS_GLOBAL_BINDINGS_P jit_langhook_global_bindings_p
875 :
876 : #undef LANG_HOOKS_PUSHDECL
877 : #define LANG_HOOKS_PUSHDECL jit_langhook_pushdecl
878 :
879 : #undef LANG_HOOKS_GETDECLS
880 : #define LANG_HOOKS_GETDECLS jit_langhook_getdecls
881 :
882 : /* Attribute hooks. */
883 : #undef LANG_HOOKS_ATTRIBUTE_TABLE
884 : #define LANG_HOOKS_ATTRIBUTE_TABLE jit_attribute_table
885 :
886 : #undef LANG_HOOKS_DEEP_UNSHARING
887 : #define LANG_HOOKS_DEEP_UNSHARING true
888 :
889 : struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
890 :
891 : #include "gt-jit-dummy-frontend.h"
892 : #include "gtype-jit.h"
|