LCOV - code coverage report
Current view: top level - gcc/jit - dummy-frontend.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 75.7 % 317 240
Test Date: 2026-10-17 16:30:31 Functions: 63.6 % 22 14
Legend: Lines:     hit not hit

            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"
        

Generated by: LCOV version 2.5.0-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.