LCOV - code coverage report
Current view: top level - gcc/jit - dummy-frontend.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 62.8 % 508 319
Test Date: 2026-02-28 14:20:25 Functions: 65.0 % 40 26
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 "cgraph.h"
      34              : #include "target.h"
      35              : #include "diagnostics/text-sink.h"
      36              : #include "print-tree.h"
      37              : 
      38              : #include <mpfr.h>
      39              : #include <unordered_map>
      40              : 
      41              : using namespace gcc::jit;
      42              : 
      43              : /* Attribute handling.  */
      44              : 
      45              : static tree handle_alias_attribute (tree *, tree, tree, int, bool *);
      46              : static tree handle_always_inline_attribute (tree *, tree, tree, int,
      47              :                                             bool *);
      48              : static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
      49              : static tree handle_const_attribute (tree *, tree, tree, int, bool *);
      50              : static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
      51              : static tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
      52              : static tree handle_format_attribute (tree *, tree, tree, int, bool *);
      53              : static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
      54              : static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
      55              : static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
      56              : static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
      57              : static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
      58              : static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
      59              : static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
      60              : static tree handle_patchable_function_entry_attribute (tree *, tree, tree,
      61              :                                                        int, bool *);
      62              : static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
      63              : static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
      64              : static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
      65              : static tree handle_target_attribute (tree *, tree, tree, int, bool *);
      66              : static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
      67              : static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
      68              : static tree handle_used_attribute (tree *, tree, tree, int, bool *);
      69              : static tree handle_visibility_attribute (tree *, tree, tree, int,
      70              :                                          bool *);
      71              : static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
      72              : 
      73              : static tree ignore_attribute (tree *, tree, tree, int, bool *);
      74              : 
      75              : /* Helper to define attribute exclusions.  */
      76              : #define ATTR_EXCL(name, function, type, variable)       \
      77              :   { name, function, type, variable }
      78              : 
      79              : /* Define attributes that are mutually exclusive with one another.  */
      80              : static const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
      81              : {
      82              :   ATTR_EXCL ("alloc_align", true, true, true),
      83              :   ATTR_EXCL ("alloc_size", true, true, true),
      84              :   ATTR_EXCL ("const", true, true, true),
      85              :   ATTR_EXCL ("malloc", true, true, true),
      86              :   ATTR_EXCL ("pure", true, true, true),
      87              :   ATTR_EXCL ("returns_twice", true, true, true),
      88              :   ATTR_EXCL ("warn_unused_result", true, true, true),
      89              :   ATTR_EXCL (NULL, false, false, false),
      90              : };
      91              : 
      92              : static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] =
      93              : {
      94              :   ATTR_EXCL ("noreturn", true, true, true),
      95              :   ATTR_EXCL (NULL, false, false, false),
      96              : };
      97              : 
      98              : /* Exclusions that apply to attribute alloc_align, alloc_size, and malloc.  */
      99              : static const struct attribute_spec::exclusions attr_alloc_exclusions[] =
     100              : {
     101              :   ATTR_EXCL ("const", true, true, true),
     102              :   ATTR_EXCL ("noreturn", true, true, true),
     103              :   ATTR_EXCL ("pure", true, true, true),
     104              :   ATTR_EXCL (NULL, false, false, false),
     105              : };
     106              : 
     107              : static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
     108              : {
     109              :   ATTR_EXCL ("const", true, true, true),
     110              :   ATTR_EXCL ("alloc_align", true, true, true),
     111              :   ATTR_EXCL ("alloc_size", true, true, true),
     112              :   ATTR_EXCL ("malloc", true, true, true),
     113              :   ATTR_EXCL ("noreturn", true, true, true),
     114              :   ATTR_EXCL ("pure", true, true, true),
     115              :   ATTR_EXCL (NULL, false, false, false)
     116              : };
     117              : 
     118              : static const struct attribute_spec::exclusions attr_always_inline_exclusions[] =
     119              : {
     120              :   ATTR_EXCL ("noinline", true, true, true),
     121              :   ATTR_EXCL ("target_clones", true, true, true),
     122              :   ATTR_EXCL (NULL, false, false, false),
     123              : };
     124              : 
     125              : extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[] =
     126              : {
     127              :   ATTR_EXCL ("cold", true, true, true),
     128              :   ATTR_EXCL ("hot", true, true, true),
     129              :   ATTR_EXCL (NULL, false, false, false)
     130              : };
     131              : 
     132              : static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
     133              : {
     134              :   ATTR_EXCL ("always_inline", true, true, true),
     135              :   ATTR_EXCL ("gnu_inline", true, true, true),
     136              :   ATTR_EXCL (NULL, false, false, false),
     137              : };
     138              : 
     139              : static const struct attribute_spec::exclusions attr_target_exclusions[] =
     140              : {
     141              :   ATTR_EXCL ("target_clones", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
     142              :              TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE),
     143              :   ATTR_EXCL (NULL, false, false, false),
     144              : };
     145              : 
     146              : /* These variables act as a cache for the target builtins. This is needed in
     147              :    order to be able to type-check the calls since we can only get those types
     148              :    in the playback phase while we need them in the recording phase.  */
     149              : hash_map<nofree_string_hash, tree> target_builtins{};
     150              : std::unordered_map<std::string, recording::function_type*> target_function_types
     151              : {};
     152              : recording::context target_builtins_ctxt{NULL};
     153              : 
     154              : /* Table of machine-independent attributes supported in libgccjit.  */
     155              : static const attribute_spec jit_gnu_attributes[] =
     156              : {
     157              :   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
     158              :        affects_type_identity, handler, exclude } */
     159              :   { "alias",                1, 1, true,  false, false, false,
     160              :                               handle_alias_attribute, NULL },
     161              :   { "always_inline",        0, 0, true,  false, false, false,
     162              :                               handle_always_inline_attribute,
     163              :                               attr_always_inline_exclusions },
     164              :   { "cold",                 0, 0, true,  false, false, false,
     165              :                               handle_cold_attribute,
     166              :                               attr_cold_hot_exclusions },
     167              :   /* The same comments as for noreturn attributes apply to const ones.  */
     168              :   { "const",                0, 0, true,  false, false, false,
     169              :                               handle_const_attribute,
     170              :                               attr_const_pure_exclusions },
     171              :   { "fn spec",                      1, 1, false, true, true, false,
     172              :                               handle_fnspec_attribute, NULL },
     173              : 
     174              :   { "leaf",                 0, 0, true,  false, false, false,
     175              :                               handle_leaf_attribute, NULL },
     176              :   { "malloc",               0, 0, true,  false, false, false,
     177              :                               handle_malloc_attribute, attr_alloc_exclusions },
     178              :   { "noreturn",                     0, 0, true,  false, false, false,
     179              :                               handle_noreturn_attribute,
     180              :                               attr_noreturn_exclusions },
     181              :   { "no vops",                      0, 0, true,  false, false, false,
     182              :                               handle_novops_attribute, NULL },
     183              :   { "noinline",                     0, 0, true,  false, false, false,
     184              :                               handle_noinline_attribute,
     185              :                               attr_noinline_exclusions },
     186              :   { "nonnull",                      0, -1, false, true, true, false,
     187              :                               handle_nonnull_attribute, NULL },
     188              :   { "nothrow",                      0, 0, true,  false, false, false,
     189              :                               handle_nothrow_attribute, NULL },
     190              :   { "patchable_function_entry", 1, 2, true, false, false, false,
     191              :                               handle_patchable_function_entry_attribute,
     192              :                               NULL },
     193              :   { "pure",                 0, 0, true,  false, false, false,
     194              :                               handle_pure_attribute,
     195              :                               attr_const_pure_exclusions },
     196              :   { "returns_twice",        0, 0, true,  false, false, false,
     197              :                               handle_returns_twice_attribute,
     198              :                               attr_returns_twice_exclusions },
     199              :   { "sentinel",                     0, 1, false, true, true, false,
     200              :                               handle_sentinel_attribute, NULL },
     201              :   { "target",               1, -1, true, false, false, false,
     202              :                               handle_target_attribute, attr_target_exclusions },
     203              :   { "type generic",         0, 0, false, true, true, false,
     204              :                               handle_type_generic_attribute, NULL },
     205              :   { "transaction_pure",             0, 0, false, true, true, false,
     206              :                               handle_transaction_pure_attribute, NULL },
     207              :   { "used",         0, 0, true,  false, false, false,
     208              :             handle_used_attribute, NULL },
     209              :   { "visibility",       1, 1, false, false, false, false,
     210              :             handle_visibility_attribute, NULL },
     211              :   { "weak",         0, 0, true,  false, false, false,
     212              :             handle_weak_attribute, NULL },
     213              :   /* For internal use only.  The leading '*' both prevents its usage in
     214              :      source code and signals that it may be overridden by machine tables.  */
     215              :   { "*tm regparm",            0, 0, false, true, true, false,
     216              :                               ignore_attribute, NULL },
     217              : };
     218              : 
     219              : static const scoped_attribute_specs jit_gnu_attribute_table =
     220              : {
     221              :   "gnu", { jit_gnu_attributes }
     222              : };
     223              : 
     224              : /* Give the specifications for the format attributes, used by C and all
     225              :    descendants.  */
     226              : 
     227              : static const attribute_spec jit_format_attributes[] =
     228              : {
     229              :   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
     230              :        affects_type_identity, handler, exclude } */
     231              :   { "format",               3, 3, false, true,  true, false,
     232              :                               handle_format_attribute, NULL },
     233              :   { "format_arg",             1, 1, false, true,  true, false,
     234              :                               handle_format_arg_attribute, NULL }
     235              : };
     236              : 
     237              : static const scoped_attribute_specs jit_format_attribute_table =
     238              : {
     239              :   "gnu", { jit_format_attributes }
     240              : };
     241              : 
     242              : static const scoped_attribute_specs *const jit_attribute_table[] =
     243              : {
     244              :   &jit_gnu_attribute_table,
     245              :   &jit_format_attribute_table
     246              : };
     247              : 
     248              : /* Attribute handlers.  */
     249              : 
     250              : /* Handle a "noreturn" attribute; arguments as in
     251              :    struct attribute_spec.handler.  */
     252              : 
     253              : static tree
     254         1296 : handle_noreturn_attribute (tree *node, tree ARG_UNUSED (name),
     255              :                            tree ARG_UNUSED (args), int ARG_UNUSED (flags),
     256              :                            bool * ARG_UNUSED (no_add_attrs))
     257              : {
     258         1296 :   tree type = TREE_TYPE (*node);
     259              : 
     260         1296 :   if (TREE_CODE (*node) == FUNCTION_DECL)
     261         1296 :     TREE_THIS_VOLATILE (*node) = 1;
     262            0 :   else if (TREE_CODE (type) == POINTER_TYPE
     263            0 :            && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
     264            0 :     TREE_TYPE (*node)
     265            0 :       = build_pointer_type
     266            0 :         (build_type_variant (TREE_TYPE (type),
     267              :                              TYPE_READONLY (TREE_TYPE (type)), 1));
     268              :   else
     269            0 :     gcc_unreachable ();
     270              : 
     271         1296 :   return NULL_TREE;
     272              : }
     273              : 
     274              : /* Handle a "leaf" attribute; arguments as in
     275              :    struct attribute_spec.handler.  */
     276              : 
     277              : static tree
     278        13135 : handle_leaf_attribute (tree *node, tree name,
     279              :                        tree ARG_UNUSED (args),
     280              :                        int ARG_UNUSED (flags), bool *no_add_attrs)
     281              : {
     282        13135 :   if (TREE_CODE (*node) != FUNCTION_DECL)
     283              :     {
     284            0 :       warning (OPT_Wattributes, "%qE attribute ignored", name);
     285            0 :       *no_add_attrs = true;
     286              :     }
     287        13135 :   if (!TREE_PUBLIC (*node))
     288              :     {
     289            0 :       warning (OPT_Wattributes, "%qE attribute has no effect on unit local functions", name);
     290            0 :       *no_add_attrs = true;
     291              :     }
     292              : 
     293        13135 :   return NULL_TREE;
     294              : }
     295              : 
     296              : /* Handle a "const" attribute; arguments as in
     297              :    struct attribute_spec.handler.  */
     298              : 
     299              : static tree
     300        11674 : handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     301              :                         int ARG_UNUSED (flags), bool *no_add_attrs)
     302              : {
     303        11674 :   tree type = TREE_TYPE (*node);
     304              : 
     305              :   /* See FIXME comment on noreturn in c_common_attribute_table.  */
     306        11674 :   if (TREE_CODE (*node) == FUNCTION_DECL)
     307        11674 :     TREE_READONLY (*node) = 1;
     308            0 :   else if (TREE_CODE (type) == POINTER_TYPE
     309            0 :            && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
     310            0 :     TREE_TYPE (*node)
     311            0 :       = (build_qualified_type
     312            0 :          (build_pointer_type
     313            0 :           (build_type_variant (TREE_TYPE (type), 1,
     314              :                                TREE_THIS_VOLATILE (TREE_TYPE (type)))),
     315            0 :           TYPE_QUALS (type)));
     316              :   else
     317              :     {
     318            0 :       warning (OPT_Wattributes, "%qE attribute ignored", name);
     319            0 :       *no_add_attrs = true;
     320              :     }
     321              : 
     322        11674 :   return NULL_TREE;
     323              : }
     324              : 
     325              : 
     326              : /* Handle a "malloc" attribute; arguments as in
     327              :    struct attribute_spec.handler.  */
     328              : 
     329              : static tree
     330            0 : handle_malloc_attribute (tree *node, tree ARG_UNUSED (name),
     331              :                          tree ARG_UNUSED (args), int ARG_UNUSED (flags),
     332              :                          bool * ARG_UNUSED (no_add_attrs))
     333              : {
     334            0 :   if (TREE_CODE (*node) == FUNCTION_DECL
     335            0 :       && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
     336            0 :     DECL_IS_MALLOC (*node) = 1;
     337              :   else
     338            0 :     gcc_unreachable ();
     339              : 
     340            0 :   return NULL_TREE;
     341              : }
     342              : 
     343              : 
     344              : /* Handle a "pure" attribute; arguments as in
     345              :    struct attribute_spec.handler.  */
     346              : 
     347              : static tree
     348           20 : handle_pure_attribute (tree *node, tree ARG_UNUSED (name),
     349              :                        tree ARG_UNUSED (args), int ARG_UNUSED (flags),
     350              :                        bool * ARG_UNUSED (no_add_attrs))
     351              : {
     352           20 :   if (TREE_CODE (*node) == FUNCTION_DECL)
     353           20 :     DECL_PURE_P (*node) = 1;
     354              :   else
     355            0 :     gcc_unreachable ();
     356              : 
     357           20 :   return NULL_TREE;
     358              : }
     359              : 
     360              : 
     361              : /* Handle a "no vops" attribute; arguments as in
     362              :    struct attribute_spec.handler.  */
     363              : 
     364              : static tree
     365            0 : handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
     366              :                          tree ARG_UNUSED (args), int ARG_UNUSED (flags),
     367              :                          bool *ARG_UNUSED (no_add_attrs))
     368              : {
     369            0 :   gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
     370            0 :   DECL_IS_NOVOPS (*node) = 1;
     371            0 :   return NULL_TREE;
     372              : }
     373              : 
     374              : 
     375              : /* Helper for nonnull attribute handling; fetch the operand number
     376              :    from the attribute argument list.  */
     377              : 
     378              : static bool
     379            5 : get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
     380              : {
     381              :   /* Verify the arg number is a constant.  */
     382            5 :   if (!tree_fits_uhwi_p (arg_num_expr))
     383              :     return false;
     384              : 
     385            5 :   *valp = TREE_INT_CST_LOW (arg_num_expr);
     386            5 :   return true;
     387              : }
     388              : 
     389              : /* Handle the "nonnull" attribute.  */
     390              : 
     391              : static tree
     392           80 : handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
     393              :                           tree args, int ARG_UNUSED (flags),
     394              :                           bool * ARG_UNUSED (no_add_attrs))
     395              : {
     396           80 :   tree type = *node;
     397              : 
     398              :   /* If no arguments are specified, all pointer arguments should be
     399              :      non-null.  Verify a full prototype is given so that the arguments
     400              :      will have the correct types when we actually check them later.
     401              :      Avoid diagnosing type-generic built-ins since those have no
     402              :      prototype.  */
     403           80 :   if (!args)
     404              :     {
     405           75 :       gcc_assert (prototype_p (type)
     406              :                   || !TYPE_ATTRIBUTES (type)
     407              :                   || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type)));
     408              : 
     409           75 :       return NULL_TREE;
     410              :     }
     411              : 
     412              :   /* Argument list specified.  Verify that each argument number references
     413              :      a pointer argument.  */
     414           10 :   for (; args; args = TREE_CHAIN (args))
     415              :     {
     416            5 :       tree argument;
     417            5 :       unsigned HOST_WIDE_INT arg_num = 0, ck_num;
     418              : 
     419            5 :       if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
     420            0 :         gcc_unreachable ();
     421              : 
     422            5 :       argument = TYPE_ARG_TYPES (type);
     423            5 :       if (argument)
     424              :         {
     425            0 :           for (ck_num = 1; ; ck_num++)
     426              :             {
     427            5 :               if (!argument || ck_num == arg_num)
     428              :                 break;
     429            0 :               argument = TREE_CHAIN (argument);
     430              :             }
     431              : 
     432            5 :           gcc_assert (argument
     433              :                       && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE);
     434              :         }
     435              :     }
     436              : 
     437              :   return NULL_TREE;
     438              : }
     439              : 
     440              : 
     441              : /* Handle a "nothrow" attribute; arguments as in
     442              :    struct attribute_spec.handler.  */
     443              : 
     444              : static tree
     445        13120 : handle_nothrow_attribute (tree *node, tree ARG_UNUSED (name),
     446              :                           tree ARG_UNUSED (args), int ARG_UNUSED (flags),
     447              :                           bool * ARG_UNUSED (no_add_attrs))
     448              : {
     449        13120 :   if (TREE_CODE (*node) == FUNCTION_DECL)
     450        13120 :     TREE_NOTHROW (*node) = 1;
     451              :   else
     452            0 :     gcc_unreachable ();
     453              : 
     454        13120 :   return NULL_TREE;
     455              : }
     456              : 
     457              : 
     458              : /* Handle a "sentinel" attribute.  */
     459              : 
     460              : static tree
     461            0 : handle_sentinel_attribute (tree *node, tree ARG_UNUSED (name), tree args,
     462              :                            int ARG_UNUSED (flags),
     463              :                            bool * ARG_UNUSED (no_add_attrs))
     464              : {
     465            0 :   gcc_assert (stdarg_p (*node));
     466              : 
     467            0 :   if (args)
     468              :     {
     469            0 :       tree position = TREE_VALUE (args);
     470            0 :       gcc_assert (TREE_CODE (position) == INTEGER_CST);
     471            0 :       if (tree_int_cst_lt (position, integer_zero_node))
     472            0 :         gcc_unreachable ();
     473              :     }
     474              : 
     475            0 :   return NULL_TREE;
     476              : }
     477              : 
     478              : /* Handle a "type_generic" attribute.  */
     479              : 
     480              : static tree
     481           45 : handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
     482              :                                tree ARG_UNUSED (args), int ARG_UNUSED (flags),
     483              :                                bool * ARG_UNUSED (no_add_attrs))
     484              : {
     485              :   /* Ensure we have a function type.  */
     486           45 :   gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
     487              : 
     488              :   /* Ensure we have a variadic function.  */
     489           45 :   gcc_assert (!prototype_p (*node) || stdarg_p (*node));
     490              : 
     491           45 :   return NULL_TREE;
     492              : }
     493              : 
     494              : /* Handle a "transaction_pure" attribute.  */
     495              : 
     496              : static tree
     497            0 : handle_transaction_pure_attribute (tree *node, tree ARG_UNUSED (name),
     498              :                                    tree ARG_UNUSED (args),
     499              :                                    int ARG_UNUSED (flags),
     500              :                                    bool * ARG_UNUSED (no_add_attrs))
     501              : {
     502              :   /* Ensure we have a function type.  */
     503            0 :   gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
     504              : 
     505            0 :   return NULL_TREE;
     506              : }
     507              : 
     508              : /* Handle a "returns_twice" attribute.  */
     509              : 
     510              : static tree
     511            0 : handle_returns_twice_attribute (tree *node, tree ARG_UNUSED (name),
     512              :                                 tree ARG_UNUSED (args),
     513              :                                 int ARG_UNUSED (flags),
     514              :                                 bool * ARG_UNUSED (no_add_attrs))
     515              : {
     516            0 :   gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
     517              : 
     518            0 :   DECL_IS_RETURNS_TWICE (*node) = 1;
     519              : 
     520            0 :   return NULL_TREE;
     521              : }
     522              : 
     523              : static tree
     524            0 : handle_patchable_function_entry_attribute (tree *, tree, tree, int, bool *)
     525              : {
     526              :   /* Nothing to be done here.  */
     527            0 :   return NULL_TREE;
     528              : }
     529              : 
     530              : /* Ignore the given attribute.  Used when this attribute may be usefully
     531              :    overridden by the target, but is not used generically.  */
     532              : 
     533              : static tree
     534            0 : ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
     535              :                   tree ARG_UNUSED (args), int ARG_UNUSED (flags),
     536              :                   bool *no_add_attrs)
     537              : {
     538            0 :   *no_add_attrs = true;
     539            0 :   return NULL_TREE;
     540              : }
     541              : 
     542              : /* Handle a "format" attribute; arguments as in
     543              :    struct attribute_spec.handler.  */
     544              : 
     545              : static tree
     546            0 : handle_format_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
     547              :                          tree ARG_UNUSED (args), int ARG_UNUSED (flags),
     548              :                          bool *no_add_attrs)
     549              : {
     550            0 :   *no_add_attrs = true;
     551            0 :   return NULL_TREE;
     552              : }
     553              : 
     554              : 
     555              : /* Handle a "format_arg" attribute; arguments as in
     556              :    struct attribute_spec.handler.  */
     557              : 
     558              : tree
     559            0 : handle_format_arg_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
     560              :                              tree ARG_UNUSED (args), int ARG_UNUSED (flags),
     561              :                              bool *no_add_attrs)
     562              : {
     563            0 :   *no_add_attrs = true;
     564            0 :   return NULL_TREE;
     565              : }
     566              : 
     567              : 
     568              : /* Handle a "fn spec" attribute; arguments as in
     569              :    struct attribute_spec.handler.  */
     570              : 
     571              : static tree
     572            0 : handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name),
     573              :                          tree args, int ARG_UNUSED (flags),
     574              :                          bool *no_add_attrs ATTRIBUTE_UNUSED)
     575              : {
     576            0 :   gcc_assert (args
     577              :               && TREE_CODE (TREE_VALUE (args)) == STRING_CST
     578              :               && !TREE_CHAIN (args));
     579            0 :   return NULL_TREE;
     580              : }
     581              : 
     582              : /* Handle an "visibility" attribute; arguments as in
     583              :    struct attribute_spec.handler.  */
     584              : 
     585              : static tree
     586            5 : handle_visibility_attribute (tree *node, tree name, tree args,
     587              :                              int ARG_UNUSED (flags),
     588              :                              bool *ARG_UNUSED (no_add_attrs))
     589              : {
     590            5 :   tree decl = *node;
     591            5 :   tree id = TREE_VALUE (args);
     592            5 :   enum symbol_visibility vis;
     593              : 
     594            5 :   if (TYPE_P (*node))
     595              :     {
     596            0 :       if (TREE_CODE (*node) == ENUMERAL_TYPE)
     597              :         /* OK.  */;
     598            0 :       else if (!RECORD_OR_UNION_TYPE_P (*node))
     599              :         {
     600            0 :           warning (OPT_Wattributes, "%qE attribute ignored on non-class types",
     601              :                    name);
     602            0 :           return NULL_TREE;
     603              :         }
     604            0 :       else if (TYPE_FIELDS (*node))
     605              :         {
     606            0 :           error ("%qE attribute ignored because %qT is already defined",
     607              :                  name, *node);
     608            0 :           return NULL_TREE;
     609              :         }
     610              :     }
     611            5 :   else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl))
     612              :     {
     613            0 :       warning (OPT_Wattributes, "%qE attribute ignored", name);
     614            0 :       return NULL_TREE;
     615              :     }
     616              : 
     617            5 :   if (TREE_CODE (id) != STRING_CST)
     618              :     {
     619            0 :       error ("visibility argument not a string");
     620            0 :       return NULL_TREE;
     621              :     }
     622              : 
     623              :   /*  If this is a type, set the visibility on the type decl.  */
     624            5 :   if (TYPE_P (decl))
     625              :     {
     626            0 :       decl = TYPE_NAME (decl);
     627            0 :       if (!decl)
     628              :         return NULL_TREE;
     629            0 :       if (TREE_CODE (decl) == IDENTIFIER_NODE)
     630              :         {
     631            0 :            warning (OPT_Wattributes, "%qE attribute ignored on types",
     632              :                     name);
     633            0 :            return NULL_TREE;
     634              :         }
     635              :     }
     636              : 
     637            5 :   if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
     638              :     vis = VISIBILITY_DEFAULT;
     639            5 :   else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0)
     640              :     vis = VISIBILITY_INTERNAL;
     641            5 :   else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0)
     642              :     vis = VISIBILITY_HIDDEN;
     643            0 :   else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0)
     644              :     vis = VISIBILITY_PROTECTED;
     645              :   else
     646              :     {
     647            0 :       error ("attribute %qE argument must be one of %qs, %qs, %qs, or %qs",
     648              :              name, "default", "hidden", "protected", "internal");
     649            0 :       vis = VISIBILITY_DEFAULT;
     650              :     }
     651              : 
     652            5 :   if (DECL_VISIBILITY_SPECIFIED (decl)
     653            5 :       && vis != DECL_VISIBILITY (decl))
     654              :     {
     655            0 :       tree attributes = (TYPE_P (*node)
     656            0 :                          ? TYPE_ATTRIBUTES (*node)
     657            0 :                          : DECL_ATTRIBUTES (decl));
     658            0 :       if (lookup_attribute ("visibility", attributes))
     659            0 :         error ("%qD redeclared with different visibility", decl);
     660              :       else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
     661              :                && lookup_attribute ("dllimport", attributes))
     662              :         error ("%qD was declared %qs which implies default visibility",
     663              :                decl, "dllimport");
     664              :       else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
     665              :                && lookup_attribute ("dllexport", attributes))
     666              :         error ("%qD was declared %qs which implies default visibility",
     667              :                decl, "dllexport");
     668              :     }
     669              : 
     670            5 :   DECL_VISIBILITY (decl) = vis;
     671            5 :   DECL_VISIBILITY_SPECIFIED (decl) = 1;
     672              : 
     673              :   /* Go ahead and attach the attribute to the node as well.  This is needed
     674              :      so we can determine whether we have VISIBILITY_DEFAULT because the
     675              :      visibility was not specified, or because it was explicitly overridden
     676              :      from the containing scope.  */
     677              : 
     678            5 :   return NULL_TREE;
     679              : }
     680              : 
     681              : /* Handle a "always_inline" attribute; arguments as in
     682              :    struct attribute_spec.handler.  */
     683              : 
     684              : static tree
     685           20 : handle_always_inline_attribute (tree *node, tree name,
     686              :                                 tree ARG_UNUSED (args),
     687              :                                 int ARG_UNUSED (flags),
     688              :                                 bool *no_add_attrs)
     689              : {
     690           20 :   if (TREE_CODE (*node) == FUNCTION_DECL)
     691              :     {
     692              :       /* Set the attribute and mark it for disregarding inline
     693              :          limits.  */
     694           20 :       DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
     695              :     }
     696              :   else
     697              :     {
     698            0 :       warning (OPT_Wattributes, "%qE attribute ignored", name);
     699            0 :       *no_add_attrs = true;
     700              :     }
     701              : 
     702           20 :   return NULL_TREE;
     703              : }
     704              : 
     705              : /* Handle a "cold" and attribute; arguments as in
     706              :    struct attribute_spec.handler.  */
     707              : 
     708              : static tree
     709         1301 : handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     710              :                        int ARG_UNUSED (flags), bool *no_add_attrs)
     711              : {
     712         1301 :   if (TREE_CODE (*node) == FUNCTION_DECL
     713         1301 :       || TREE_CODE (*node) == LABEL_DECL)
     714              :     {
     715              :       /* Attribute cold processing is done later with lookup_attribute.  */
     716              :     }
     717              :   else
     718              :     {
     719            0 :       warning (OPT_Wattributes, "%qE attribute ignored", name);
     720            0 :       *no_add_attrs = true;
     721              :     }
     722              : 
     723         1301 :   return NULL_TREE;
     724              : }
     725              : 
     726              : /* Handle a "noinline" attribute; arguments as in
     727              :    struct attribute_spec.handler.  */
     728              : 
     729              : static tree
     730            5 : handle_noinline_attribute (tree *node, tree name,
     731              :                            tree ARG_UNUSED (args),
     732              :                            int ARG_UNUSED (flags), bool *no_add_attrs)
     733              : {
     734            5 :   if (TREE_CODE (*node) == FUNCTION_DECL)
     735            5 :     DECL_UNINLINABLE (*node) = 1;
     736              :   else
     737              :     {
     738            0 :       warning (OPT_Wattributes, "%qE attribute ignored", name);
     739            0 :       *no_add_attrs = true;
     740              :     }
     741              : 
     742            5 :   return NULL_TREE;
     743              : }
     744              : 
     745              : /* Handle a "weak" attribute; arguments as in
     746              :    struct attribute_spec.handler.  */
     747              : 
     748              : static tree
     749            5 : handle_weak_attribute (tree *node, tree name,
     750              :                        tree ARG_UNUSED (args),
     751              :                        int ARG_UNUSED (flags),
     752              :                        bool * ARG_UNUSED (no_add_attrs))
     753              : {
     754            5 :   if (TREE_CODE (*node) == FUNCTION_DECL
     755            5 :       && DECL_DECLARED_INLINE_P (*node))
     756              :     {
     757            0 :       warning (OPT_Wattributes, "inline function %q+D declared weak", *node);
     758            0 :       *no_add_attrs = true;
     759              :     }
     760            5 :   else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (*node)))
     761              :     {
     762            0 :       error ("indirect function %q+D cannot be declared weak", *node);
     763            0 :       *no_add_attrs = true;
     764            0 :       return NULL_TREE;
     765              :     }
     766            5 :   else if (VAR_OR_FUNCTION_DECL_P (*node))
     767            5 :     declare_weak (*node);
     768              :   else
     769            0 :     warning (OPT_Wattributes, "%qE attribute ignored", name);
     770              : 
     771              :   return NULL_TREE;
     772              : }
     773              : 
     774              : /* Handle a "target" attribute.  */
     775              : 
     776              : static tree
     777            0 : handle_target_attribute (tree *node, tree name, tree args, int flags,
     778              :                          bool *no_add_attrs)
     779              : {
     780              :   /* Ensure we have a function declaration.  */
     781            0 :   if (TREE_CODE (*node) != FUNCTION_DECL)
     782              :     {
     783            0 :       warning (OPT_Wattributes, "%qE attribute ignored", name);
     784            0 :       *no_add_attrs = true;
     785              :     }
     786            0 :   else if (! targetm.target_option.valid_attribute_p (*node, name, args,
     787              :                                                       flags))
     788            0 :     *no_add_attrs = true;
     789              : 
     790              :   /* Check that there's no empty string in values of the attribute.  */
     791            0 :   for (tree t = args; t != NULL_TREE; t = TREE_CHAIN (t))
     792              :     {
     793            0 :       tree value = TREE_VALUE (t);
     794            0 :       if (TREE_CODE (value) == STRING_CST
     795            0 :           && TREE_STRING_LENGTH (value) == 1
     796            0 :           && TREE_STRING_POINTER (value)[0] == '\0')
     797              :         {
     798            0 :           warning (OPT_Wattributes, "empty string in attribute %<target%>");
     799            0 :           *no_add_attrs = true;
     800              :         }
     801              :     }
     802              : 
     803            0 :   return NULL_TREE;
     804              : }
     805              : 
     806              : /* Handle a "used" attribute; arguments as in
     807              :    struct attribute_spec.handler.  */
     808              : 
     809              : static tree
     810            5 : handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
     811              :                        int ARG_UNUSED (flags), bool *no_add_attrs)
     812              : {
     813            5 :   tree node = *pnode;
     814              : 
     815            5 :   if (TREE_CODE (node) == FUNCTION_DECL
     816            0 :       || (VAR_P (node) && TREE_STATIC (node))
     817            0 :       || (TREE_CODE (node) == TYPE_DECL))
     818              :     {
     819            5 :       TREE_USED (node) = 1;
     820            5 :       DECL_PRESERVE_P (node) = 1;
     821            5 :       if (VAR_P (node))
     822            0 :         DECL_READ_P (node) = 1;
     823              :     }
     824              :   else
     825              :     {
     826            0 :       warning (OPT_Wattributes, "%qE attribute ignored", name);
     827            0 :       *no_add_attrs = true;
     828              :     }
     829              : 
     830            5 :   return NULL_TREE;
     831              : }
     832              : 
     833              : /* Handle an "alias" or "ifunc" attribute; arguments as in
     834              :    struct attribute_spec.handler, except that IS_ALIAS tells us
     835              :    whether this is an alias as opposed to ifunc attribute.  */
     836              : 
     837              : static tree
     838            5 : handle_alias_ifunc_attribute (bool is_alias, tree *node, tree name, tree args,
     839              :                               bool *no_add_attrs)
     840              : {
     841            5 :   tree decl = *node;
     842              : 
     843            5 :   if (TREE_CODE (decl) != FUNCTION_DECL
     844            0 :       && (!is_alias || !VAR_P (decl)))
     845              :     {
     846            0 :       warning (OPT_Wattributes, "%qE attribute ignored", name);
     847            0 :       *no_add_attrs = true;
     848              :     }
     849            5 :   else if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
     850            5 :       || (TREE_CODE (decl) != FUNCTION_DECL
     851            0 :           && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
     852              :       /* A static variable declaration is always a tentative definition,
     853              :          but the alias is a non-tentative definition which overrides.  */
     854           10 :       || (TREE_CODE (decl) != FUNCTION_DECL
     855            0 :           && ! TREE_PUBLIC (decl) && DECL_INITIAL (decl)))
     856              :     {
     857            0 :       error ("%q+D defined both normally and as %qE attribute", decl, name);
     858            0 :       *no_add_attrs = true;
     859            0 :       return NULL_TREE;
     860              :     }
     861            5 :   else if (!is_alias
     862            5 :            && (lookup_attribute ("weak", DECL_ATTRIBUTES (decl))
     863            0 :                || lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))))
     864              :     {
     865            0 :       error ("weak %q+D cannot be defined %qE", decl, name);
     866            0 :       *no_add_attrs = true;
     867            0 :       return NULL_TREE;
     868              :     }
     869              : 
     870              :   /* Note that the very first time we process a nested declaration,
     871              :      decl_function_context will not be set.  Indeed, *would* never
     872              :      be set except for the DECL_INITIAL/DECL_EXTERNAL frobbery that
     873              :      we do below.  After such frobbery, pushdecl would set the context.
     874              :      In any case, this is never what we want.  */
     875            5 :   else if (decl_function_context (decl) == 0 && current_function_decl == NULL)
     876              :     {
     877            5 :       tree id;
     878              : 
     879            5 :       id = TREE_VALUE (args);
     880            5 :       if (TREE_CODE (id) != STRING_CST)
     881              :         {
     882            0 :           error ("attribute %qE argument not a string", name);
     883            0 :           *no_add_attrs = true;
     884            0 :           return NULL_TREE;
     885              :         }
     886            5 :       id = get_identifier (TREE_STRING_POINTER (id));
     887              :       /* This counts as a use of the object pointed to.  */
     888            5 :       TREE_USED (id) = 1;
     889              : 
     890            5 :       if (TREE_CODE (decl) == FUNCTION_DECL)
     891            5 :         DECL_INITIAL (decl) = error_mark_node;
     892              :       else
     893            0 :         TREE_STATIC (decl) = 1;
     894              : 
     895            5 :       if (!is_alias)
     896              :         {
     897              :           /* ifuncs are also aliases, so set that attribute too.  */
     898            0 :           DECL_ATTRIBUTES (decl)
     899            0 :             = tree_cons (get_identifier ("alias"), args,
     900            0 :                          DECL_ATTRIBUTES (decl));
     901            0 :           DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("ifunc"),
     902            0 :                                               NULL, DECL_ATTRIBUTES (decl));
     903              :         }
     904              :     }
     905              :   else
     906              :     {
     907            0 :       warning (OPT_Wattributes, "%qE attribute ignored", name);
     908            0 :       *no_add_attrs = true;
     909              :     }
     910              : 
     911            5 :   if (decl_in_symtab_p (*node))
     912              :     {
     913            5 :       struct symtab_node *n = symtab_node::get (decl);
     914            5 :       if (n && n->refuse_visibility_changes)
     915            0 :         error ("%+qD declared %qs after being used",
     916              :                decl, is_alias ? "alias" : "ifunc");
     917              :     }
     918              : 
     919              : 
     920              :   return NULL_TREE;
     921              : }
     922              : 
     923              : /* Handle an "alias" or "ifunc" attribute; arguments as in
     924              :    struct attribute_spec.handler.  */
     925              : 
     926              : static tree
     927            5 : handle_alias_attribute (tree *node, tree name, tree args,
     928              :                         int ARG_UNUSED (flags), bool *no_add_attrs)
     929              : {
     930            5 :   return handle_alias_ifunc_attribute (true, node, name, args, no_add_attrs);
     931              : }
     932              : 
     933              : /* (end of attribute-handling).  */
     934              : 
     935              : /* Language-dependent contents of a type.  */
     936              : 
     937              : struct GTY(()) lang_type
     938              : {
     939              :   char dummy;
     940              : };
     941              : 
     942              : /* Language-dependent contents of a decl.  */
     943              : 
     944              : struct GTY((variable_size)) lang_decl
     945              : {
     946              :   char dummy;
     947              : };
     948              : 
     949              : /* Language-dependent contents of an identifier.  This must include a
     950              :    tree_identifier.  */
     951              : 
     952              : struct GTY(()) lang_identifier
     953              : {
     954              :   struct tree_identifier common;
     955              : };
     956              : 
     957              : /* The resulting tree type.  */
     958              : 
     959              : /* See lang_tree_node in gcc/c/c-decl.cc.  */
     960              : union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
     961              :   chain_next ("(union lang_tree_node *) jit_tree_chain_next (&%h.generic)")))
     962              :   lang_tree_node
     963              :  {
     964              :   union tree_node GTY ((tag ("0"),
     965              :                         desc ("tree_node_structure (&%h)")))
     966              :     generic;
     967              :   struct lang_identifier GTY ((tag ("1"))) identifier;
     968              : };
     969              : 
     970              : /* We don't use language_function.  */
     971              : 
     972              : struct GTY(()) language_function
     973              : {
     974              :   int dummy;
     975              : };
     976              : 
     977              : /* GC-marking callback for use from jit_root_tab.
     978              : 
     979              :    If there's an active playback context, call its marking method
     980              :    so that it can mark any pointers it references.  */
     981              : 
     982       514851 : static void my_ggc_walker (void *)
     983              : {
     984       514851 :   if (gcc::jit::active_playback_ctxt)
     985       514851 :     gcc::jit::active_playback_ctxt->gt_ggc_mx ();
     986       514851 : }
     987              : 
     988              : const char *dummy;
     989              : 
     990              : struct ggc_root_tab jit_root_tab[] =
     991              :   {
     992              :     {
     993              :       &dummy, 1, 0, my_ggc_walker, NULL
     994              :     },
     995              :     LAST_GGC_ROOT_TAB
     996              :   };
     997              : 
     998              : /* Subclass of diagnostics::text_sink for libgccjit: like text
     999              :    output, but capture the message and call add_diagnostic with it
    1000              :    on the active playback context.  */
    1001              : 
    1002              : class jit_diagnostic_listener : public diagnostics::text_sink
    1003              : {
    1004              : public:
    1005         1326 :   jit_diagnostic_listener (diagnostics::context &dc,
    1006              :                            gcc::jit::playback::context &playback_ctxt)
    1007         1326 :   : diagnostics::text_sink (dc),
    1008         1326 :     m_playback_ctxt (playback_ctxt)
    1009              :   {
    1010              :   }
    1011              : 
    1012            0 :   void dump (FILE *out, int indent) const final override
    1013              :   {
    1014            0 :     fprintf (out, "%*sjit_diagnostic_listener\n", indent, "");
    1015            0 :     fprintf (out, "%*sm_playback_context: %p\n",
    1016              :              indent + 2, "",
    1017            0 :              (void *)&m_playback_ctxt);
    1018            0 :   }
    1019              : 
    1020           25 :   void on_report_diagnostic (const diagnostics::diagnostic_info &info,
    1021              :                              enum diagnostics::kind orig_diag_kind) final override
    1022              :   {
    1023           25 :     JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
    1024              : 
    1025              :     /* Let the text output format do most of the work.  */
    1026           25 :     diagnostics::text_sink::on_report_diagnostic (info, orig_diag_kind);
    1027              : 
    1028           25 :     const char *text = pp_formatted_text (get_printer ());
    1029              : 
    1030              :     /* Delegate to the playback context (and thence to the
    1031              :        recording context).  */
    1032           25 :     gcc::jit::active_playback_ctxt->add_diagnostic (text, info);
    1033              : 
    1034           25 :     pp_clear_output_area (get_printer ());
    1035           25 :   }
    1036              : 
    1037              : private:
    1038              :   gcc::jit::playback::context &m_playback_ctxt;
    1039              : };
    1040              : 
    1041              : /* JIT-specific implementation of diagnostic callbacks.  */
    1042              : 
    1043              : /* Implementation of "begin_diagnostic".  */
    1044              : 
    1045              : static void
    1046           25 : jit_begin_diagnostic (diagnostics::text_sink &,
    1047              :                       const diagnostics::diagnostic_info */*diagnostic*/)
    1048              : {
    1049           25 :   gcc_assert (gcc::jit::active_playback_ctxt);
    1050           25 :   JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
    1051              : 
    1052              :   /* No-op (apart from logging); the real error-handling is done by the
    1053              :      jit_diagnostic_listener.  */
    1054           25 : }
    1055              : 
    1056              : /* Implementation of "end_diagnostic".  */
    1057              : 
    1058              : static void
    1059           25 : jit_end_diagnostic (diagnostics::text_sink &,
    1060              :                     const diagnostics::diagnostic_info *,
    1061              :                     enum diagnostics::kind)
    1062              : {
    1063           25 :   gcc_assert (gcc::jit::active_playback_ctxt);
    1064           25 :   JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
    1065              : 
    1066              :   /* No-op (apart from logging); the real error-handling is done by the
    1067              :      jit_diagnostic_listener.  */
    1068           25 : }
    1069              : 
    1070              : /* Language hooks.  */
    1071              : 
    1072              : static bool
    1073         1326 : jit_langhook_init (void)
    1074              : {
    1075         1326 :   gcc_assert (gcc::jit::active_playback_ctxt);
    1076         1326 :   JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
    1077              : 
    1078         1326 :   static bool registered_root_tab = false;
    1079         1326 :   if (!registered_root_tab)
    1080              :     {
    1081          130 :       ggc_register_root_tab (jit_root_tab);
    1082          130 :       registered_root_tab = true;
    1083              :     }
    1084              : 
    1085         1326 :   gcc_assert (global_dc);
    1086         1326 :   diagnostics::text_starter (global_dc) = jit_begin_diagnostic;
    1087         1326 :   diagnostics::text_finalizer (global_dc) = jit_end_diagnostic;
    1088         1326 :   auto sink
    1089              :     = std::make_unique<jit_diagnostic_listener>
    1090              :         (*global_dc,
    1091         1326 :          *gcc::jit::active_playback_ctxt);
    1092         1326 :   global_dc->set_sink (std::move (sink));
    1093              : 
    1094         1326 :   build_common_tree_nodes (flag_signed_char);
    1095              : 
    1096         1326 :   target_builtins.empty ();
    1097         1326 :   build_common_builtin_nodes ();
    1098              : 
    1099              :   /* The default precision for floating point numbers.  This is used
    1100              :      for floating point constants with abstract type.  This may
    1101              :      eventually be controllable by a command line option.  */
    1102         1326 :   mpfr_set_default_prec (256);
    1103              : 
    1104         1326 :   targetm.init_builtins ();
    1105              : 
    1106         2652 :   return true;
    1107         1326 : }
    1108              : 
    1109              : static void
    1110         1326 : jit_langhook_parse_file (void)
    1111              : {
    1112              :   /* Replay the activity by the client, recorded on the context.  */
    1113         1326 :   gcc_assert (gcc::jit::active_playback_ctxt);
    1114         1326 :   gcc::jit::active_playback_ctxt->replay ();
    1115         1326 : }
    1116              : 
    1117              : static tree
    1118        13395 : jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
    1119              : {
    1120              :   /* Build any vector types here (see PR 46805).  */
    1121        13395 :   if (VECTOR_MODE_P (mode))
    1122              :     {
    1123          270 :       tree inner;
    1124              : 
    1125          540 :       inner = jit_langhook_type_for_mode (GET_MODE_INNER (mode), unsignedp);
    1126          270 :       if (inner != NULL_TREE)
    1127          270 :         return build_vector_type_for_mode (inner, mode);
    1128              :       return NULL_TREE;
    1129              :     }
    1130              : 
    1131        13125 :   if (mode == TYPE_MODE (float_type_node))
    1132          140 :     return float_type_node;
    1133              : 
    1134        12985 :   if (mode == TYPE_MODE (double_type_node))
    1135          369 :     return double_type_node;
    1136              : 
    1137        12616 :   if (mode == TYPE_MODE (intQI_type_node))
    1138          805 :     return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
    1139        11811 :   if (mode == TYPE_MODE (intHI_type_node))
    1140           60 :     return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
    1141        11751 :   if (mode == TYPE_MODE (intSI_type_node))
    1142         1449 :     return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
    1143        10302 :   if (mode == TYPE_MODE (intDI_type_node))
    1144         2346 :     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
    1145         7956 :   if (mode == TYPE_MODE (intTI_type_node))
    1146            0 :     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
    1147              : 
    1148         7956 :   if (mode == TYPE_MODE (integer_type_node))
    1149            0 :     return unsignedp ? unsigned_type_node : integer_type_node;
    1150              : 
    1151         7956 :   if (mode == TYPE_MODE (long_integer_type_node))
    1152            0 :     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
    1153              : 
    1154         7956 :   if (mode == TYPE_MODE (long_long_integer_type_node))
    1155            0 :     return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
    1156              : 
    1157         7956 :   if (COMPLEX_MODE_P (mode))
    1158              :     {
    1159         7956 :       if (mode == TYPE_MODE (complex_float_type_node))
    1160         1326 :         return complex_float_type_node;
    1161         6630 :       if (mode == TYPE_MODE (complex_double_type_node))
    1162         1326 :         return complex_double_type_node;
    1163         5304 :       if (mode == TYPE_MODE (complex_long_double_type_node))
    1164         1326 :         return complex_long_double_type_node;
    1165         3978 :       if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp)
    1166            0 :         return complex_integer_type_node;
    1167              :     }
    1168              : 
    1169              :   /* gcc_unreachable */
    1170              :   return NULL;
    1171              : }
    1172              : 
    1173      3365700 : recording::type* tree_type_to_jit_type (tree type)
    1174              : {
    1175      3365700 :   gcc_assert (gcc::jit::active_playback_ctxt);
    1176      3365700 :   gcc::jit::playback::context* ctxt = gcc::jit::active_playback_ctxt;
    1177              : 
    1178      3365700 :   if (TREE_CODE (type) == VECTOR_TYPE)
    1179              :   {
    1180      1373970 :     tree inner_type = TREE_TYPE (type);
    1181      1373970 :     recording::type* element_type = tree_type_to_jit_type (inner_type);
    1182      1373970 :     poly_uint64 size = TYPE_VECTOR_SUBPARTS (type);
    1183      1373970 :     long constant_size = size.to_constant ();
    1184      1373970 :     if (element_type != NULL)
    1185      1373970 :       return element_type->get_vector (constant_size);
    1186              :     return NULL;
    1187              :   }
    1188      1991730 :   if (TREE_CODE (type) == REFERENCE_TYPE)
    1189              :     // For __builtin_ms_va_start.
    1190              :     // FIXME: wrong type.
    1191          390 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1192          390 :                                                GCC_JIT_TYPE_VOID);
    1193      1991340 :   if (TREE_CODE (type) == RECORD_TYPE)
    1194              :     // For __builtin_sysv_va_copy.
    1195              :     // FIXME: wrong type.
    1196          520 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1197          520 :                                                GCC_JIT_TYPE_VOID);
    1198      1990820 :   if (type == void_type_node)
    1199        38090 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1200        38090 :                                                GCC_JIT_TYPE_VOID);
    1201      1952730 :   else if (type == ptr_type_node)
    1202        12870 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1203        12870 :                                                GCC_JIT_TYPE_VOID_PTR);
    1204      1939860 :   else if (type == const_ptr_type_node)
    1205              :   {
    1206              :     // Void const ptr.
    1207         7280 :     recording::type* result =
    1208              :       new recording::memento_of_get_type (&target_builtins_ctxt,
    1209         7280 :                                           GCC_JIT_TYPE_VOID_PTR);
    1210         7280 :     return new recording::memento_of_get_const (result);
    1211              :   }
    1212      1932580 :   else if (type == unsigned_type_node)
    1213        50180 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1214        50180 :                                                GCC_JIT_TYPE_UNSIGNED_INT);
    1215      1882400 :   else if (type == long_unsigned_type_node)
    1216         1690 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1217         1690 :                                                GCC_JIT_TYPE_UNSIGNED_LONG);
    1218      1880710 :   else if (type == integer_type_node)
    1219       422370 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1220       422370 :                                                GCC_JIT_TYPE_INT);
    1221      1458340 :   else if (type == long_integer_type_node)
    1222          130 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1223          130 :                                                GCC_JIT_TYPE_LONG);
    1224      1458210 :   else if (type == long_long_integer_type_node)
    1225       206050 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1226       206050 :                                                GCC_JIT_TYPE_LONG_LONG);
    1227      1252160 :   else if (type == signed_char_type_node)
    1228            0 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1229            0 :                                                GCC_JIT_TYPE_SIGNED_CHAR);
    1230      1252160 :   else if (type == char_type_node)
    1231       153400 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1232       153400 :                                                GCC_JIT_TYPE_CHAR);
    1233      1098760 :   else if (type == unsigned_intQI_type_node)
    1234       181610 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1235       181610 :                                                GCC_JIT_TYPE_UINT8_T);
    1236       917150 :   else if (type == short_integer_type_node)
    1237       180960 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1238       180960 :                                                GCC_JIT_TYPE_SHORT);
    1239       736190 :   else if (type == short_unsigned_type_node)
    1240        65390 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1241        65390 :                                                GCC_JIT_TYPE_UNSIGNED_SHORT);
    1242       670800 :   else if (type == complex_float_type_node)
    1243          260 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1244          260 :                                                GCC_JIT_TYPE_COMPLEX_FLOAT);
    1245       670540 :   else if (type == complex_double_type_node)
    1246          260 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1247          260 :                                                GCC_JIT_TYPE_COMPLEX_DOUBLE);
    1248       670280 :   else if (type == complex_long_double_type_node)
    1249          260 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1250          260 :                                             GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE);
    1251       670020 :   else if (type == float_type_node)
    1252       218400 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1253       218400 :                                                GCC_JIT_TYPE_FLOAT);
    1254       451620 :   else if (type == double_type_node)
    1255       189540 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1256       189540 :                                                GCC_JIT_TYPE_DOUBLE);
    1257       262080 :   else if (type == long_double_type_node)
    1258         1040 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1259         1040 :                                                GCC_JIT_TYPE_LONG_DOUBLE);
    1260       261040 :   else if (type == bfloat16_type_node)
    1261        57980 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1262        57980 :                                                GCC_JIT_TYPE_BFLOAT16);
    1263       203060 :   else if (type == float16_type_node)
    1264              :   {
    1265       121160 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1266       121160 :                                               GCC_JIT_TYPE_FLOAT16);
    1267              :   }
    1268        81900 :   else if (type == float32_type_node)
    1269              :   {
    1270            0 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1271            0 :                                               GCC_JIT_TYPE_FLOAT32);
    1272              :   }
    1273        81900 :   else if (type == float64_type_node)
    1274              :   {
    1275            0 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1276            0 :                                               GCC_JIT_TYPE_FLOAT64);
    1277              :   }
    1278        81900 :   else if (type == float128_type_node)
    1279              :   {
    1280         1170 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1281         1170 :                                               GCC_JIT_TYPE_FLOAT128);
    1282              :   }
    1283        80730 :   else if (type == dfloat128_type_node)
    1284              :     // FIXME: wrong type.
    1285            0 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1286            0 :                                                GCC_JIT_TYPE_VOID);
    1287        80730 :   else if (type == long_long_unsigned_type_node)
    1288        24310 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1289        24310 :                                                GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
    1290        56420 :   else if (type == boolean_type_node)
    1291            0 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1292            0 :                                                GCC_JIT_TYPE_BOOL);
    1293        56420 :   else if (type == size_type_node)
    1294            0 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1295            0 :                                                GCC_JIT_TYPE_SIZE_T);
    1296        56420 :   else if (TREE_CODE (type) == POINTER_TYPE)
    1297              :   {
    1298        46670 :     tree inner_type = TREE_TYPE (type);
    1299        46670 :     recording::type* element_type = tree_type_to_jit_type (inner_type);
    1300        46670 :     if (!element_type)
    1301              :       return nullptr;
    1302        46670 :     return element_type->get_pointer ();
    1303              :   }
    1304         9750 :   else if (type == unsigned_intTI_type_node)
    1305            0 :     return new recording::memento_of_get_type (&target_builtins_ctxt,
    1306            0 :       GCC_JIT_TYPE_UINT128_T);
    1307         9750 :   else if (INTEGRAL_TYPE_P (type))
    1308              :   {
    1309         4940 :     unsigned int size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
    1310         4940 :     return target_builtins_ctxt.get_int_type (size, TYPE_UNSIGNED (type));
    1311              :   }
    1312         4810 :   else if (SCALAR_FLOAT_TYPE_P (type))
    1313              :   {
    1314         4810 :     unsigned int size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
    1315         4810 :     enum gcc_jit_types type;
    1316         4810 :     switch (size)
    1317              :     {
    1318              :       case 2:
    1319              :         type = GCC_JIT_TYPE_BFLOAT16;
    1320              :         break;
    1321         1950 :       case 4:
    1322         1950 :         type = GCC_JIT_TYPE_FLOAT;
    1323         1950 :         break;
    1324         2080 :       case 8:
    1325         2080 :         type = GCC_JIT_TYPE_DOUBLE;
    1326         2080 :         break;
    1327            0 :       default:
    1328            0 :         if (ctxt->get_abort_on_unsupported_target_builtin ())
    1329              :         {
    1330            0 :           fprintf (stderr, "Unexpected float size: %d\n", size);
    1331            0 :           abort ();
    1332              :         }
    1333              :         return NULL;
    1334              :     }
    1335         4810 :     return new recording::memento_of_get_type (&target_builtins_ctxt, type);
    1336              :   }
    1337              :   else
    1338              :   {
    1339              :     // Attempt to find an unqualified type when the current type has qualifiers.
    1340            0 :     tree tp = TYPE_MAIN_VARIANT (type);
    1341            0 :     for ( ; tp != NULL ; tp = TYPE_NEXT_VARIANT (tp))
    1342              :     {
    1343            0 :       if (TYPE_QUALS (tp) == 0 && type != tp)
    1344              :       {
    1345            0 :         recording::type* result = tree_type_to_jit_type (tp);
    1346            0 :         if (result != NULL)
    1347              :         {
    1348            0 :           if (TYPE_READONLY (tp))
    1349            0 :             result = new recording::memento_of_get_const (result);
    1350            0 :           if (TYPE_VOLATILE (tp))
    1351            0 :             result = new recording::memento_of_get_volatile (result);
    1352            0 :           return result;
    1353              :         }
    1354              :       }
    1355              :     }
    1356              : 
    1357            0 :     if (ctxt->get_abort_on_unsupported_target_builtin ())
    1358              :     {
    1359            0 :       fprintf (stderr, "Unknown type:\n");
    1360            0 :       debug_tree (type);
    1361            0 :       abort ();
    1362              :     }
    1363              :   }
    1364              : 
    1365              :   return NULL;
    1366              : }
    1367              : 
    1368              : /* Record a builtin function.  We save their types to be able to check types
    1369              :    in recording and for reflection.  */
    1370              : 
    1371              : static tree
    1372      4914156 : jit_langhook_builtin_function (tree decl)
    1373              : {
    1374      4914156 :   if (TREE_CODE (decl) == FUNCTION_DECL)
    1375              :   {
    1376      4914156 :     const char* name = IDENTIFIER_POINTER (DECL_NAME (decl));
    1377      4914156 :     target_builtins.put (name, decl);
    1378              : 
    1379      4914156 :     std::string string_name (name);
    1380      9346532 :     if (target_function_types.count (string_name) == 0)
    1381              :     {
    1382       481780 :       tree function_type = TREE_TYPE (decl);
    1383       481780 :       tree arg = TYPE_ARG_TYPES (function_type);
    1384       481780 :       bool is_variadic = false;
    1385              : 
    1386       481780 :       auto_vec <recording::type *> param_types;
    1387              : 
    1388      1945060 :       while (arg != void_list_node)
    1389              :       {
    1390      1463540 :         if (arg == NULL)
    1391              :         {
    1392              :           is_variadic = true;
    1393              :           break;
    1394              :         }
    1395      1463280 :         if (arg != void_list_node)
    1396              :         {
    1397      1463280 :           recording::type* arg_type = tree_type_to_jit_type (TREE_VALUE (arg));
    1398      1463280 :           if (arg_type == NULL)
    1399            0 :             return decl;
    1400      1463280 :           param_types.safe_push (arg_type);
    1401              :         }
    1402      1463280 :         arg = TREE_CHAIN (arg);
    1403              :       }
    1404              : 
    1405       481780 :       tree result_type = TREE_TYPE (function_type);
    1406       481780 :       recording::type* return_type = tree_type_to_jit_type (result_type);
    1407              : 
    1408       481780 :       if (return_type == NULL)
    1409              :         return decl;
    1410              : 
    1411       481780 :       recording::function_type* func_type =
    1412              :         new recording::function_type (&target_builtins_ctxt, return_type,
    1413       481780 :                                       param_types.length (),
    1414              :                                       param_types.address (), is_variadic,
    1415      1433640 :                                       false);
    1416              : 
    1417       481780 :       target_function_types[string_name] = func_type;
    1418       481780 :     }
    1419      4914156 :   }
    1420              :   return decl;
    1421              : }
    1422              : 
    1423              : static bool
    1424           60 : jit_langhook_global_bindings_p (void)
    1425              : {
    1426           60 :   return true;
    1427              : }
    1428              : 
    1429              : static tree
    1430            0 : jit_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED)
    1431              : {
    1432            0 :   return NULL_TREE;
    1433              : }
    1434              : 
    1435              : static tree
    1436            0 : jit_langhook_getdecls (void)
    1437              : {
    1438            0 :   return NULL;
    1439              : }
    1440              : 
    1441              : #undef LANG_HOOKS_NAME
    1442              : #define LANG_HOOKS_NAME         "libgccjit"
    1443              : 
    1444              : #undef LANG_HOOKS_INIT
    1445              : #define LANG_HOOKS_INIT         jit_langhook_init
    1446              : 
    1447              : #undef LANG_HOOKS_PARSE_FILE
    1448              : #define LANG_HOOKS_PARSE_FILE           jit_langhook_parse_file
    1449              : 
    1450              : #undef LANG_HOOKS_TYPE_FOR_MODE
    1451              : #define LANG_HOOKS_TYPE_FOR_MODE        jit_langhook_type_for_mode
    1452              : 
    1453              : #undef LANG_HOOKS_BUILTIN_FUNCTION
    1454              : #define LANG_HOOKS_BUILTIN_FUNCTION     jit_langhook_builtin_function
    1455              : 
    1456              : #undef LANG_HOOKS_GLOBAL_BINDINGS_P
    1457              : #define LANG_HOOKS_GLOBAL_BINDINGS_P    jit_langhook_global_bindings_p
    1458              : 
    1459              : #undef LANG_HOOKS_PUSHDECL
    1460              : #define LANG_HOOKS_PUSHDECL             jit_langhook_pushdecl
    1461              : 
    1462              : #undef LANG_HOOKS_GETDECLS
    1463              : #define LANG_HOOKS_GETDECLS             jit_langhook_getdecls
    1464              : 
    1465              : /* Attribute hooks.  */
    1466              : #undef LANG_HOOKS_ATTRIBUTE_TABLE
    1467              : #define LANG_HOOKS_ATTRIBUTE_TABLE jit_attribute_table
    1468              : 
    1469              : #undef  LANG_HOOKS_DEEP_UNSHARING
    1470              : #define LANG_HOOKS_DEEP_UNSHARING       true
    1471              : 
    1472              : struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
    1473              : 
    1474              : #include "gt-jit-dummy-frontend.h"
    1475              : #include "gtype-jit.h"
        

Generated by: LCOV version 2.4-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.