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-02-28 14:20:25 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              : 
      24              : namespace Rust {
      25              : namespace Compile {
      26              : 
      27              : BuiltinsContext &
      28         5829 : BuiltinsContext::get ()
      29              : {
      30         5829 :   static BuiltinsContext instance;
      31         5829 :   return instance;
      32              : }
      33              : 
      34              : bool
      35         8561 : BuiltinsContext::lookup_simple_builtin (const std::string &name, tree *builtin)
      36              : {
      37         8561 :   auto *to_search = &name;
      38              : 
      39         8561 :   auto it = rust_intrinsic_to_gcc_builtin.find (name);
      40         8561 :   if (it != rust_intrinsic_to_gcc_builtin.end ())
      41          308 :     to_search = &it->second;
      42              : 
      43         8561 :   return lookup_gcc_builtin (*to_search, builtin);
      44              : }
      45              : 
      46         1364 : BuiltinsContext::BuiltinsContext () { setup (); }
      47              : 
      48              : /**
      49              :  * Define a function type according to `builtin-types.def`
      50              :  *
      51              :  * *Heavily* inspired by the D frontend's `def_fn_type` function
      52              :  */
      53              : void
      54       687456 : BuiltinsContext::define_function_type (Type def_idx, Type ret_idx,
      55              :                                        bool is_variadic, size_t n, ...)
      56              : {
      57       687456 :   va_list list;
      58       687456 :   va_start (list, n);
      59              : 
      60       687456 :   auto args = std::vector<tree> ();
      61              : 
      62      2211044 :   for (size_t i = 0; i < n; i++)
      63              :     {
      64              :       // The argument is an enum Type, but it's promoted to int when passed
      65              :       // though '...'.
      66      1523588 :       auto arg_idx = va_arg (list, int);
      67      1523588 :       auto arg_type = builtin_types[arg_idx];
      68              : 
      69      1523588 :       args.emplace_back (arg_type);
      70              :     }
      71              : 
      72       687456 :   auto return_type = builtin_types[ret_idx];
      73       687456 :   if (return_type == error_mark_node)
      74              :     {
      75              :       // Mark the builtin as not available.
      76        17732 :       builtin_types[def_idx] = error_mark_node;
      77        17732 :       va_end (list);
      78        17732 :       return;
      79              :     }
      80              : 
      81       669724 :   auto fn_type = NULL_TREE;
      82       669724 :   if (is_variadic)
      83        40920 :     fn_type = build_varargs_function_type_array (return_type, n, args.data ());
      84              :   else
      85       628804 :     fn_type = build_function_type_array (return_type, n, args.data ());
      86              : 
      87       669724 :   builtin_types[def_idx] = fn_type;
      88       669724 :   va_end (list);
      89       687456 : }
      90              : 
      91              : // Taken directly from the D frontend
      92              : static void
      93         1364 : build_c_type_nodes (void)
      94              : {
      95         1364 :   string_type_node = build_pointer_type (char_type_node);
      96         1364 :   const_string_type_node = build_pointer_type (
      97              :     build_qualified_type (char_type_node, TYPE_QUAL_CONST));
      98              : 
      99         1364 :   if (strcmp (UINTMAX_TYPE, "unsigned int") == 0)
     100              :     {
     101            0 :       intmax_type_node = integer_type_node;
     102            0 :       uintmax_type_node = unsigned_type_node;
     103              :     }
     104         1364 :   else if (strcmp (UINTMAX_TYPE, "long unsigned int") == 0)
     105              :     {
     106         1364 :       intmax_type_node = long_integer_type_node;
     107         1364 :       uintmax_type_node = long_unsigned_type_node;
     108              :     }
     109            0 :   else if (strcmp (UINTMAX_TYPE, "long long unsigned int") == 0)
     110              :     {
     111            0 :       intmax_type_node = long_long_integer_type_node;
     112            0 :       uintmax_type_node = long_long_unsigned_type_node;
     113              :     }
     114              :   else
     115            0 :     gcc_unreachable ();
     116              : 
     117         1364 :   signed_size_type_node = signed_type_for (size_type_node);
     118         1364 :   wint_type_node = unsigned_type_node;
     119         1364 :   pid_type_node = integer_type_node;
     120         1364 : }
     121              : 
     122              : /**
     123              :  * Define all builtin types in the `builtin_types` array
     124              :  */
     125              : void
     126         1364 : BuiltinsContext::define_builtin_types ()
     127              : {
     128              :   // This is taken directly from the D frontend's handling of builtins
     129         1364 :   auto va_list_ref_type_node = build_reference_type (va_list_type_node);
     130         1364 :   auto va_list_arg_type_node = va_list_type_node;
     131              : 
     132         1364 :   build_c_type_nodes ();
     133              : 
     134         1364 :   auto builtin_type_for_size = [] (int size, bool unsignedp) {
     135         6820 :     tree type = lang_hooks.types.type_for_size (size, unsignedp);
     136         6820 :     return type ? type : error_mark_node;
     137              :   };
     138              : 
     139              : #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) builtin_types[ENUM] = VALUE;
     140              : #define DEF_FUNCTION_TYPE_0(ENUM, RETURN)                                      \
     141              :   define_function_type (ENUM, RETURN, 0, 0);
     142              : #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, A1)                                  \
     143              :   define_function_type (ENUM, RETURN, 0, 1, A1);
     144              : #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, A1, A2)                              \
     145              :   define_function_type (ENUM, RETURN, 0, 2, A1, A2);
     146              : #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, A1, A2, A3)                          \
     147              :   define_function_type (ENUM, RETURN, 0, 3, A1, A2, A3);
     148              : #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, A1, A2, A3, A4)                      \
     149              :   define_function_type (ENUM, RETURN, 0, 4, A1, A2, A3, A4);
     150              : #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, A1, A2, A3, A4, A5)                  \
     151              :   define_function_type (ENUM, RETURN, 0, 5, A1, A2, A3, A4, A5);
     152              : #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, A1, A2, A3, A4, A5, A6)              \
     153              :   define_function_type (ENUM, RETURN, 0, 6, A1, A2, A3, A4, A5, A6);
     154              : #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7)          \
     155              :   define_function_type (ENUM, RETURN, 0, 7, A1, A2, A3, A4, A5, A6, A7);
     156              : #define DEF_FUNCTION_TYPE_8(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8)      \
     157              :   define_function_type (ENUM, RETURN, 0, 8, A1, A2, A3, A4, A5, A6, A7, A8);
     158              : #define DEF_FUNCTION_TYPE_9(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9)  \
     159              :   define_function_type (ENUM, RETURN, 0, 9, A1, A2, A3, A4, A5, A6, A7, A8, A9);
     160              : #define DEF_FUNCTION_TYPE_10(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9, \
     161              :                              A10)                                              \
     162              :   define_function_type (ENUM, RETURN, 0, 10, A1, A2, A3, A4, A5, A6, A7, A8,   \
     163              :                         A9, A10);
     164              : #define DEF_FUNCTION_TYPE_11(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9, \
     165              :                              A10, A11)                                         \
     166              :   define_function_type (ENUM, RETURN, 0, 11, A1, A2, A3, A4, A5, A6, A7, A8,   \
     167              :                         A9, A10, A11);
     168              : #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN)                                  \
     169              :   define_function_type (ENUM, RETURN, 1, 0);
     170              : #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, A1)                              \
     171              :   define_function_type (ENUM, RETURN, 1, 1, A1);
     172              : #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, A1, A2)                          \
     173              :   define_function_type (ENUM, RETURN, 1, 2, A1, A2);
     174              : #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, A1, A2, A3)                      \
     175              :   define_function_type (ENUM, RETURN, 1, 3, A1, A2, A3);
     176              : #define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, A1, A2, A3, A4)                  \
     177              :   define_function_type (ENUM, RETURN, 1, 4, A1, A2, A3, A4);
     178              : #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, A1, A2, A3, A4, A5)              \
     179              :   define_function_type (ENUM, RETURN, 1, 5, A1, A2, A3, A4, A5);
     180              : #define DEF_FUNCTION_TYPE_VAR_6(ENUM, RETURN, A1, A2, A3, A4, A5, A6)          \
     181              :   define_function_type (ENUM, RETURN, 1, 6, A1, A2, A3, A4, A5, A6);
     182              : #define DEF_FUNCTION_TYPE_VAR_7(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7)      \
     183              :   define_function_type (ENUM, RETURN, 1, 7, A1, A2, A3, A4, A5, A6, A7);
     184              : #define DEF_FUNCTION_TYPE_VAR_11(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, \
     185              :                                  A9, A10, A11)                                 \
     186              :   define_function_type (ENUM, RETURN, 1, 11, A1, A2, A3, A4, A5, A6, A7, A8,   \
     187              :                         A9, A10, A11);
     188              : #define DEF_POINTER_TYPE(ENUM, TYPE)                                           \
     189              :   builtin_types[ENUM] = build_pointer_type (builtin_types[TYPE]);
     190              : 
     191              : #include "builtin-types.def"
     192              : 
     193              : #undef DEF_PRIMITIVE_TYPE
     194              : #undef DEF_FUNCTION_TYPE_1
     195              : #undef DEF_FUNCTION_TYPE_2
     196              : #undef DEF_FUNCTION_TYPE_3
     197              : #undef DEF_FUNCTION_TYPE_4
     198              : #undef DEF_FUNCTION_TYPE_5
     199              : #undef DEF_FUNCTION_TYPE_6
     200              : #undef DEF_FUNCTION_TYPE_7
     201              : #undef DEF_FUNCTION_TYPE_8
     202              : #undef DEF_FUNCTION_TYPE_9
     203              : #undef DEF_FUNCTION_TYPE_10
     204              : #undef DEF_FUNCTION_TYPE_11
     205              : #undef DEF_FUNCTION_TYPE_VAR_0
     206              : #undef DEF_FUNCTION_TYPE_VAR_1
     207              : #undef DEF_FUNCTION_TYPE_VAR_2
     208              : #undef DEF_FUNCTION_TYPE_VAR_3
     209              : #undef DEF_FUNCTION_TYPE_VAR_4
     210              : #undef DEF_FUNCTION_TYPE_VAR_5
     211              : #undef DEF_FUNCTION_TYPE_VAR_6
     212              : #undef DEF_FUNCTION_TYPE_VAR_7
     213              : #undef DEF_FUNCTION_TYPE_VAR_11
     214              : #undef DEF_POINTER_TYPE
     215              : 
     216         1364 :   builtin_types[Type::BT_LAST] = NULL_TREE;
     217         1364 : }
     218              : 
     219              : /**
     220              :  * Define all builtin attributes in the `builtin_types` array
     221              :  */
     222              : void
     223         1364 : BuiltinsContext::define_builtin_attributes ()
     224              : 
     225              : {
     226         1364 :   auto *built_in_attributes = builtin_attributes;
     227              : 
     228              : #define DEF_ATTR_NULL_TREE(ENUM) built_in_attributes[(int) ENUM] = NULL_TREE;
     229              : #define DEF_ATTR_INT(ENUM, VALUE)                                              \
     230              :   built_in_attributes[ENUM] = build_int_cst (NULL_TREE, VALUE);
     231              : #define DEF_ATTR_STRING(ENUM, VALUE)                                           \
     232              :   built_in_attributes[ENUM] = build_string (strlen (VALUE), VALUE);
     233              : #define DEF_ATTR_IDENT(ENUM, STRING)                                           \
     234              :   built_in_attributes[ENUM] = get_identifier (STRING);
     235              : #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN)                        \
     236              :   built_in_attributes[ENUM]                                                    \
     237              :     = tree_cons (built_in_attributes[PURPOSE], built_in_attributes[VALUE],     \
     238              :                  built_in_attributes[CHAIN]);
     239              : #include "builtin-attrs.def"
     240              : #undef DEF_ATTR_NULL_TREE
     241              : #undef DEF_ATTR_INT
     242              : #undef DEF_ATTR_STRING
     243              : #undef DEF_ATTR_IDENT
     244              : #undef DEF_ATTR_TREE_LIST
     245         1364 : }
     246              : 
     247              : /**
     248              :  * Define all builtin functions during the first initialization of the
     249              :  * `BuiltinsContext`.
     250              :  */
     251              : void
     252         1364 : BuiltinsContext::define_builtins ()
     253              : {
     254         1364 :   auto *built_in_attributes = builtin_attributes;
     255      2044636 :   auto build_builtin = [this] (built_in_function fn_code, const char *fn_name,
     256              :                                built_in_class fn_class, tree fn_type, bool both,
     257              :                                bool fallback, tree attributes, bool implicit) {
     258      2043272 :     if (fn_type == error_mark_node)
     259      2043272 :       return;
     260              : 
     261      1932788 :     static auto to_skip = strlen ("__builtin_");
     262              : 
     263      1932788 :     auto libname = fn_name + to_skip;
     264      2500212 :     auto decl = add_builtin_function (fn_name, fn_type, fn_code, fn_class,
     265      1932788 :                                       fallback ? libname : NULL, attributes);
     266              : 
     267      1932788 :     set_builtin_decl (fn_code, decl, implicit);
     268              : 
     269      1932788 :     builtin_functions.insert ({std::string (fn_name), decl});
     270         1364 :   };
     271              : 
     272              : #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P,      \
     273              :                     NONANSI_P, ATTRS, IMPLICIT, COND)                          \
     274              :   if (NAME && COND)                                                            \
     275              :     build_builtin (ENUM, NAME, CLASS, builtin_types[TYPE], BOTH_P, FALLBACK_P, \
     276              :                    built_in_attributes[ATTRS], IMPLICIT);
     277              : #include "builtins.def"
     278              : #undef DEF_BUILTIN
     279         1364 : }
     280              : 
     281              : /**
     282              :  * Register direct mappings between Rust functions and GCC builtins
     283              :  */
     284              : void
     285         1364 : BuiltinsContext::register_rust_mappings ()
     286              : {
     287         1364 :   rust_intrinsic_to_gcc_builtin = {
     288              :     {"unreachable", "__builtin_unreachable"},
     289              :     {"abort", "__builtin_abort"},
     290              : 
     291              :     // Math intrinsics
     292              :     {"sqrtf32", "__builtin_sqrtf"},
     293              :     {"sqrtf64", "__builtin_sqrt"},
     294              : 
     295              :     {"sinf32", "__builtin_sinf"},
     296              :     {"sinf64", "__builtin_sin"},
     297              : 
     298              :     {"cosf32", "__builtin_cosf"},
     299              :     {"cosf64", "__builtin_cos"},
     300              : 
     301              :     {"powf32", "__builtin_powf"},
     302              :     {"powf64", "__builtin_pow"},
     303              : 
     304              :     {"powif32", "__builtin_powif"},
     305              :     {"powif64", "__builtin_powi"},
     306              : 
     307              :     {"expf32", "__builtin_expf"},
     308              :     {"expf64", "__builtin_exp"},
     309              : 
     310              :     {"exp2f32", "__builtin_exp2f"},
     311              :     {"exp2f64", "__builtin_exp2"},
     312              : 
     313              :     {"logf32", "__builtin_logf"},
     314              :     {"logf64", "__builtin_log"},
     315              : 
     316              :     {"log10f32", "__builtin_log10f"},
     317              :     {"log10f64", "__builtin_log10"},
     318              : 
     319              :     {"log2f32", "__builtin_log2f"},
     320              :     {"log2f64", "__builtin_log2"},
     321              : 
     322              :     {"fmaf32", "__builtin_fmaf"},
     323              :     {"fmaf64", "__builtin_fma"},
     324              : 
     325              :     {"fabsf32", "__builtin_fabsf"},
     326              :     {"fabsf64", "__builtin_fabs"},
     327              : 
     328              :     {"minnumf32", "__builtin_fminf"},
     329              :     {"minnumf64", "__builtin_fmin"},
     330              : 
     331              :     {"maxnumf32", "__builtin_fmaxf"},
     332              :     {"maxnumf64", "__builtin_fmax"},
     333              : 
     334              :     {"copysignf32", "__builtin_copysignf"},
     335              :     {"copysignf64", "__builtin_copysign"},
     336              : 
     337              :     {"floorf32", "__builtin_floorf"},
     338              :     {"floorf64", "__builtin_floor"},
     339              : 
     340              :     {"ceilf32", "__builtin_ceilf"},
     341              :     {"ceilf64", "__builtin_ceil"},
     342              : 
     343              :     {"truncf32", "__builtin_truncf"},
     344              :     {"truncf64", "__builtin_trunc"},
     345              : 
     346              :     {"rintf32", "__builtin_rintf"},
     347              :     {"rintf64", "__builtin_rint"},
     348              : 
     349              :     {"nearbyintf32", "__builtin_nearbyintf"},
     350              :     {"nearbyintf64", "__builtin_nearbyint"},
     351              : 
     352              :     {"roundf32", "__builtin_roundf"},
     353              :     {"roundf64", "__builtin_round"},
     354        61380 :   };
     355         1364 : }
     356              : 
     357              : void
     358         1364 : BuiltinsContext::setup ()
     359              : {
     360         1364 :   define_builtin_types ();
     361         1364 :   define_builtin_attributes ();
     362         1364 :   define_builtins ();
     363              : 
     364         1364 :   register_rust_mappings ();
     365         1364 : }
     366              : 
     367              : bool
     368         8561 : BuiltinsContext::lookup_gcc_builtin (const std::string &name, tree *builtin)
     369              : {
     370         8561 :   auto it = builtin_functions.find (name);
     371         8561 :   if (it == builtin_functions.end ())
     372              :     return false;
     373              : 
     374         6372 :   *builtin = it->second;
     375         6372 :   return true;
     376              : }
     377              : 
     378              : } // namespace Compile
     379              : } // 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.