LCOV - code coverage report
Current view: top level - gcc/rust/backend - rust-builtins.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.1 % 87 81
Test Date: 2026-07-11 15:47:05 Functions: 100.0 % 12 12
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // This file is part of GCC.
       2              : 
       3              : // GCC is free software; you can redistribute it and/or modify it under
       4              : // the terms of the GNU General Public License as published by the Free
       5              : // Software Foundation; either version 3, or (at your option) any later
       6              : // version.
       7              : 
       8              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
       9              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      10              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      11              : // for more details.
      12              : 
      13              : // You should have received a copy of the GNU General Public License
      14              : // along with GCC; see the file COPYING3.  If not see
      15              : // <http://www.gnu.org/licenses/>.
      16              : 
      17              : #include "rust-diagnostics.h"
      18              : #include "rust-system.h"
      19              : #include "rust-builtins.h"
      20              : 
      21              : #include "target.h"
      22              : #include "stringpool.h"
      23              : #include "rust-intrinsic-values.h"
      24              : 
      25              : namespace Rust {
      26              : namespace Compile {
      27              : 
      28              : BuiltinsContext &
      29         7434 : BuiltinsContext::get ()
      30              : {
      31         7434 :   static BuiltinsContext instance;
      32         7434 :   return instance;
      33              : }
      34              : 
      35              : bool
      36        10189 : BuiltinsContext::lookup_simple_builtin (const std::string &name, tree *builtin)
      37              : {
      38        10189 :   auto *to_search = &name;
      39              : 
      40        10189 :   auto it = rust_intrinsic_to_gcc_builtin.find (name);
      41        10189 :   if (it != rust_intrinsic_to_gcc_builtin.end ())
      42          449 :     to_search = &it->second;
      43              : 
      44        10189 :   return lookup_gcc_builtin (*to_search, builtin);
      45              : }
      46              : 
      47         1527 : BuiltinsContext::BuiltinsContext () { setup (); }
      48              : 
      49              : /**
      50              :  * Define a function type according to `builtin-types.def`
      51              :  *
      52              :  * *Heavily* inspired by the D frontend's `def_fn_type` function
      53              :  */
      54              : void
      55       774189 : BuiltinsContext::define_function_type (Type def_idx, Type ret_idx,
      56              :                                        bool is_variadic, size_t n, ...)
      57              : {
      58       774189 :   va_list list;
      59       774189 :   va_start (list, n);
      60              : 
      61       774189 :   auto args = std::vector<tree> ();
      62              : 
      63      2482902 :   for (size_t i = 0; i < n; i++)
      64              :     {
      65              :       // The argument is an enum Type, but it's promoted to int when passed
      66              :       // though '...'.
      67      1708713 :       auto arg_idx = va_arg (list, int);
      68      1708713 :       auto arg_type = builtin_types[arg_idx];
      69              : 
      70      1708713 :       args.emplace_back (arg_type);
      71              :     }
      72              : 
      73       774189 :   auto return_type = builtin_types[ret_idx];
      74       774189 :   if (return_type == error_mark_node)
      75              :     {
      76              :       // Mark the builtin as not available.
      77        19851 :       builtin_types[def_idx] = error_mark_node;
      78        19851 :       va_end (list);
      79        19851 :       return;
      80              :     }
      81              : 
      82       754338 :   auto fn_type = NULL_TREE;
      83       754338 :   if (is_variadic)
      84        45810 :     fn_type = build_varargs_function_type_array (return_type, n, args.data ());
      85              :   else
      86       708528 :     fn_type = build_function_type_array (return_type, n, args.data ());
      87              : 
      88       754338 :   builtin_types[def_idx] = fn_type;
      89       754338 :   va_end (list);
      90       774189 : }
      91              : 
      92              : // Taken directly from the D frontend
      93              : static void
      94         1527 : build_c_type_nodes (void)
      95              : {
      96         1527 :   string_type_node = build_pointer_type (char_type_node);
      97         1527 :   const_string_type_node = build_pointer_type (
      98              :     build_qualified_type (char_type_node, TYPE_QUAL_CONST));
      99              : 
     100         1527 :   if (strcmp (UINTMAX_TYPE, "unsigned int") == 0)
     101              :     {
     102            0 :       intmax_type_node = integer_type_node;
     103            0 :       uintmax_type_node = unsigned_type_node;
     104              :     }
     105         1527 :   else if (strcmp (UINTMAX_TYPE, "long unsigned int") == 0)
     106              :     {
     107         1527 :       intmax_type_node = long_integer_type_node;
     108         1527 :       uintmax_type_node = long_unsigned_type_node;
     109              :     }
     110            0 :   else if (strcmp (UINTMAX_TYPE, "long long unsigned int") == 0)
     111              :     {
     112            0 :       intmax_type_node = long_long_integer_type_node;
     113            0 :       uintmax_type_node = long_long_unsigned_type_node;
     114              :     }
     115              :   else
     116            0 :     gcc_unreachable ();
     117              : 
     118         1527 :   signed_size_type_node = signed_type_for (size_type_node);
     119         1527 :   wint_type_node = unsigned_type_node;
     120         1527 :   pid_type_node = integer_type_node;
     121         1527 : }
     122              : 
     123              : /**
     124              :  * Define all builtin types in the `builtin_types` array
     125              :  */
     126              : void
     127         1527 : BuiltinsContext::define_builtin_types ()
     128              : {
     129              :   // This is taken directly from the D frontend's handling of builtins
     130         1527 :   auto va_list_ref_type_node = build_reference_type (va_list_type_node);
     131         1527 :   auto va_list_arg_type_node = va_list_type_node;
     132              : 
     133         1527 :   build_c_type_nodes ();
     134              : 
     135         1527 :   auto builtin_type_for_size = [] (int size, bool unsignedp) {
     136         7635 :     tree type = lang_hooks.types.type_for_size (size, unsignedp);
     137         7635 :     return type ? type : error_mark_node;
     138              :   };
     139              : 
     140              : #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) builtin_types[ENUM] = VALUE;
     141              : #define DEF_FUNCTION_TYPE_0(ENUM, RETURN)                                      \
     142              :   define_function_type (ENUM, RETURN, 0, 0);
     143              : #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, A1)                                  \
     144              :   define_function_type (ENUM, RETURN, 0, 1, A1);
     145              : #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, A1, A2)                              \
     146              :   define_function_type (ENUM, RETURN, 0, 2, A1, A2);
     147              : #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, A1, A2, A3)                          \
     148              :   define_function_type (ENUM, RETURN, 0, 3, A1, A2, A3);
     149              : #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, A1, A2, A3, A4)                      \
     150              :   define_function_type (ENUM, RETURN, 0, 4, A1, A2, A3, A4);
     151              : #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, A1, A2, A3, A4, A5)                  \
     152              :   define_function_type (ENUM, RETURN, 0, 5, A1, A2, A3, A4, A5);
     153              : #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, A1, A2, A3, A4, A5, A6)              \
     154              :   define_function_type (ENUM, RETURN, 0, 6, A1, A2, A3, A4, A5, A6);
     155              : #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7)          \
     156              :   define_function_type (ENUM, RETURN, 0, 7, A1, A2, A3, A4, A5, A6, A7);
     157              : #define DEF_FUNCTION_TYPE_8(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8)      \
     158              :   define_function_type (ENUM, RETURN, 0, 8, A1, A2, A3, A4, A5, A6, A7, A8);
     159              : #define DEF_FUNCTION_TYPE_9(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9)  \
     160              :   define_function_type (ENUM, RETURN, 0, 9, A1, A2, A3, A4, A5, A6, A7, A8, A9);
     161              : #define DEF_FUNCTION_TYPE_10(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9, \
     162              :                              A10)                                              \
     163              :   define_function_type (ENUM, RETURN, 0, 10, A1, A2, A3, A4, A5, A6, A7, A8,   \
     164              :                         A9, A10);
     165              : #define DEF_FUNCTION_TYPE_11(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9, \
     166              :                              A10, A11)                                         \
     167              :   define_function_type (ENUM, RETURN, 0, 11, A1, A2, A3, A4, A5, A6, A7, A8,   \
     168              :                         A9, A10, A11);
     169              : #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN)                                  \
     170              :   define_function_type (ENUM, RETURN, 1, 0);
     171              : #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, A1)                              \
     172              :   define_function_type (ENUM, RETURN, 1, 1, A1);
     173              : #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, A1, A2)                          \
     174              :   define_function_type (ENUM, RETURN, 1, 2, A1, A2);
     175              : #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, A1, A2, A3)                      \
     176              :   define_function_type (ENUM, RETURN, 1, 3, A1, A2, A3);
     177              : #define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, A1, A2, A3, A4)                  \
     178              :   define_function_type (ENUM, RETURN, 1, 4, A1, A2, A3, A4);
     179              : #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, A1, A2, A3, A4, A5)              \
     180              :   define_function_type (ENUM, RETURN, 1, 5, A1, A2, A3, A4, A5);
     181              : #define DEF_FUNCTION_TYPE_VAR_6(ENUM, RETURN, A1, A2, A3, A4, A5, A6)          \
     182              :   define_function_type (ENUM, RETURN, 1, 6, A1, A2, A3, A4, A5, A6);
     183              : #define DEF_FUNCTION_TYPE_VAR_7(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7)      \
     184              :   define_function_type (ENUM, RETURN, 1, 7, A1, A2, A3, A4, A5, A6, A7);
     185              : #define DEF_FUNCTION_TYPE_VAR_11(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, \
     186              :                                  A9, A10, A11)                                 \
     187              :   define_function_type (ENUM, RETURN, 1, 11, A1, A2, A3, A4, A5, A6, A7, A8,   \
     188              :                         A9, A10, A11);
     189              : #define DEF_POINTER_TYPE(ENUM, TYPE)                                           \
     190              :   builtin_types[ENUM] = build_pointer_type (builtin_types[TYPE]);
     191              : 
     192              : #include "builtin-types.def"
     193              : 
     194              : #undef DEF_PRIMITIVE_TYPE
     195              : #undef DEF_FUNCTION_TYPE_1
     196              : #undef DEF_FUNCTION_TYPE_2
     197              : #undef DEF_FUNCTION_TYPE_3
     198              : #undef DEF_FUNCTION_TYPE_4
     199              : #undef DEF_FUNCTION_TYPE_5
     200              : #undef DEF_FUNCTION_TYPE_6
     201              : #undef DEF_FUNCTION_TYPE_7
     202              : #undef DEF_FUNCTION_TYPE_8
     203              : #undef DEF_FUNCTION_TYPE_9
     204              : #undef DEF_FUNCTION_TYPE_10
     205              : #undef DEF_FUNCTION_TYPE_11
     206              : #undef DEF_FUNCTION_TYPE_VAR_0
     207              : #undef DEF_FUNCTION_TYPE_VAR_1
     208              : #undef DEF_FUNCTION_TYPE_VAR_2
     209              : #undef DEF_FUNCTION_TYPE_VAR_3
     210              : #undef DEF_FUNCTION_TYPE_VAR_4
     211              : #undef DEF_FUNCTION_TYPE_VAR_5
     212              : #undef DEF_FUNCTION_TYPE_VAR_6
     213              : #undef DEF_FUNCTION_TYPE_VAR_7
     214              : #undef DEF_FUNCTION_TYPE_VAR_11
     215              : #undef DEF_POINTER_TYPE
     216              : 
     217         1527 :   builtin_types[Type::BT_LAST] = NULL_TREE;
     218         1527 : }
     219              : 
     220              : /**
     221              :  * Define all builtin attributes in the `builtin_types` array
     222              :  */
     223              : void
     224         1527 : BuiltinsContext::define_builtin_attributes ()
     225              : 
     226              : {
     227         1527 :   auto *built_in_attributes = builtin_attributes;
     228              : 
     229              : #define DEF_ATTR_NULL_TREE(ENUM) built_in_attributes[(int) ENUM] = NULL_TREE;
     230              : #define DEF_ATTR_INT(ENUM, VALUE)                                              \
     231              :   built_in_attributes[ENUM] = build_int_cst (NULL_TREE, VALUE);
     232              : #define DEF_ATTR_STRING(ENUM, VALUE)                                           \
     233              :   built_in_attributes[ENUM] = build_string (strlen (VALUE), VALUE);
     234              : #define DEF_ATTR_IDENT(ENUM, STRING)                                           \
     235              :   built_in_attributes[ENUM] = get_identifier (STRING);
     236              : #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN)                        \
     237              :   built_in_attributes[ENUM]                                                    \
     238              :     = tree_cons (built_in_attributes[PURPOSE], built_in_attributes[VALUE],     \
     239              :                  built_in_attributes[CHAIN]);
     240              : #include "builtin-attrs.def"
     241              : #undef DEF_ATTR_NULL_TREE
     242              : #undef DEF_ATTR_INT
     243              : #undef DEF_ATTR_STRING
     244              : #undef DEF_ATTR_IDENT
     245              : #undef DEF_ATTR_TREE_LIST
     246         1527 : }
     247              : 
     248              : /**
     249              :  * Define all builtin functions during the first initialization of the
     250              :  * `BuiltinsContext`.
     251              :  */
     252              : void
     253         1527 : BuiltinsContext::define_builtins ()
     254              : {
     255         1527 :   auto *built_in_attributes = builtin_attributes;
     256      2299662 :   auto build_builtin = [this] (built_in_function fn_code, const char *fn_name,
     257              :                                built_in_class fn_class, tree fn_type, bool both,
     258              :                                bool fallback, tree attributes, bool implicit) {
     259      2298135 :     if (fn_type == error_mark_node)
     260      2298135 :       return;
     261              : 
     262      2174448 :     static auto to_skip = strlen ("__builtin_");
     263              : 
     264      2174448 :     auto libname = fn_name + to_skip;
     265      2820369 :     auto decl = add_builtin_function (fn_name, fn_type, fn_code, fn_class,
     266      2174448 :                                       fallback ? libname : NULL, attributes);
     267              : 
     268      2174448 :     set_builtin_decl (fn_code, decl, implicit);
     269              : 
     270      2174448 :     builtin_functions.insert ({std::string (fn_name), decl});
     271         1527 :   };
     272              : 
     273              : #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P,      \
     274              :                     NONANSI_P, ATTRS, IMPLICIT, COND)                          \
     275              :   if (NAME && COND)                                                            \
     276              :     build_builtin (ENUM, NAME, CLASS, builtin_types[TYPE], BOTH_P, FALLBACK_P, \
     277              :                    built_in_attributes[ATTRS], IMPLICIT);
     278              : #include "builtins.def"
     279              : #undef DEF_BUILTIN
     280         1527 : }
     281              : 
     282              : /**
     283              :  * Register direct mappings between Rust functions and GCC builtins
     284              :  */
     285              : void
     286         1527 : BuiltinsContext::register_rust_mappings ()
     287              : {
     288         1527 :   rust_intrinsic_to_gcc_builtin = {
     289              :     {Values::Intrinsics::UNREACHABLE, "__builtin_unreachable"},
     290              :     {Values::Intrinsics::ABORT, "__builtin_abort"},
     291              : 
     292              :     // Math intrinsics
     293              :     {Values::Intrinsics::SQRTF32, "__builtin_sqrtf"},
     294              :     {Values::Intrinsics::SQRTF64, "__builtin_sqrt"},
     295              : 
     296              :     {Values::Intrinsics::SINF32, "__builtin_sinf"},
     297              :     {Values::Intrinsics::SINF64, "__builtin_sin"},
     298              : 
     299              :     {Values::Intrinsics::COSF32, "__builtin_cosf"},
     300              :     {Values::Intrinsics::COSF64, "__builtin_cos"},
     301              : 
     302              :     {Values::Intrinsics::POWF32, "__builtin_powf"},
     303              :     {Values::Intrinsics::POWF64, "__builtin_pow"},
     304              : 
     305              :     {Values::Intrinsics::POWIF32, "__builtin_powif"},
     306              :     {Values::Intrinsics::POWIF64, "__builtin_powi"},
     307              : 
     308              :     {Values::Intrinsics::EXPF32, "__builtin_expf"},
     309              :     {Values::Intrinsics::EXPF64, "__builtin_exp"},
     310              : 
     311              :     {Values::Intrinsics::EXP2F32, "__builtin_exp2f"},
     312              :     {Values::Intrinsics::EXP2F64, "__builtin_exp2"},
     313              : 
     314              :     {Values::Intrinsics::LOGF32, "__builtin_logf"},
     315              :     {Values::Intrinsics::LOGF64, "__builtin_log"},
     316              : 
     317              :     {Values::Intrinsics::LOG10F32, "__builtin_log10f"},
     318              :     {Values::Intrinsics::LOG10F64, "__builtin_log10"},
     319              : 
     320              :     {Values::Intrinsics::LOG2F32, "__builtin_log2f"},
     321              :     {Values::Intrinsics::LOG2F64, "__builtin_log2"},
     322              : 
     323              :     {Values::Intrinsics::FMAF32, "__builtin_fmaf"},
     324              :     {Values::Intrinsics::FMAF64, "__builtin_fma"},
     325              : 
     326              :     {Values::Intrinsics::FABSF32, "__builtin_fabsf"},
     327              :     {Values::Intrinsics::FABSF64, "__builtin_fabs"},
     328              : 
     329              :     {Values::Intrinsics::MINNUMF32, "__builtin_fminf"},
     330              :     {Values::Intrinsics::MINNUMF64, "__builtin_fmin"},
     331              : 
     332              :     {Values::Intrinsics::MAXNUMF32, "__builtin_fmaxf"},
     333              :     {Values::Intrinsics::MAXNUMF64, "__builtin_fmax"},
     334              : 
     335              :     {Values::Intrinsics::COPYSIGNF32, "__builtin_copysignf"},
     336              :     {Values::Intrinsics::COPYSIGNF64, "__builtin_copysign"},
     337              : 
     338              :     {Values::Intrinsics::FLOORF32, "__builtin_floorf"},
     339              :     {Values::Intrinsics::FLOORF64, "__builtin_floor"},
     340              : 
     341              :     {Values::Intrinsics::CEILF32, "__builtin_ceilf"},
     342              :     {Values::Intrinsics::CEILF64, "__builtin_ceil"},
     343              : 
     344              :     {Values::Intrinsics::TRUNCF32, "__builtin_truncf"},
     345              :     {Values::Intrinsics::TRUNCF64, "__builtin_trunc"},
     346              : 
     347              :     {Values::Intrinsics::RINTF32, "__builtin_rintf"},
     348              :     {Values::Intrinsics::RINTF64, "__builtin_rint"},
     349              : 
     350              :     {Values::Intrinsics::NEARBYINTF32, "__builtin_nearbyintf"},
     351              :     {Values::Intrinsics::NEARBYINTF64, "__builtin_nearbyint"},
     352              : 
     353              :     {Values::Intrinsics::ROUNDF32, "__builtin_roundf"},
     354              :     {Values::Intrinsics::ROUNDF64, "__builtin_round"},
     355        68715 :   };
     356         1527 : }
     357              : 
     358              : void
     359         1527 : BuiltinsContext::setup ()
     360              : {
     361         1527 :   define_builtin_types ();
     362         1527 :   define_builtin_attributes ();
     363         1527 :   define_builtins ();
     364              : 
     365         1527 :   register_rust_mappings ();
     366         1527 : }
     367              : 
     368              : bool
     369        10189 : BuiltinsContext::lookup_gcc_builtin (const std::string &name, tree *builtin)
     370              : {
     371        10189 :   auto it = builtin_functions.find (name);
     372        10189 :   if (it == builtin_functions.end ())
     373              :     return false;
     374              : 
     375         7268 :   *builtin = it->second;
     376         7268 :   return true;
     377              : }
     378              : 
     379              : } // namespace Compile
     380              : } // namespace Rust
        

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.