LCOV - code coverage report
Current view: top level - gcc/rust/backend - rust-compile-type.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.0 % 448 412
Test Date: 2026-07-11 15:47:05 Functions: 77.8 % 36 28
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #include "rust-compile-type.h"
      20              : #include "rust-constexpr.h"
      21              : #include "rust-compile-base.h"
      22              : #include "rust-type-util.h"
      23              : 
      24              : #include "rust-tyty.h"
      25              : #include "tree.h"
      26              : #include "fold-const.h"
      27              : #include "stor-layout.h"
      28              : 
      29              : namespace Rust {
      30              : namespace Compile {
      31              : 
      32              : static const std::string RUST_ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR";
      33              : 
      34       316364 : TyTyResolveCompile::TyTyResolveCompile (Context *ctx, bool trait_object_mode)
      35       316364 :   : ctx (ctx), trait_object_mode (trait_object_mode),
      36       316364 :     translated (error_mark_node)
      37       316364 : {}
      38              : 
      39              : tree
      40       316364 : TyTyResolveCompile::compile (Context *ctx, const TyTy::BaseType *ty,
      41              :                              bool trait_object_mode)
      42              : {
      43       316364 :   TyTyResolveCompile compiler (ctx, trait_object_mode);
      44       316364 :   const TyTy::BaseType *destructured = ty->destructure ();
      45       316364 :   destructured->accept_vis (compiler);
      46              : 
      47       316364 :   if (compiler.translated != error_mark_node
      48       316364 :       && TYPE_NAME (compiler.translated) != NULL)
      49              :     {
      50              :       // canonicalize the type
      51       274398 :       compiler.translated = ctx->insert_compiled_type (compiler.translated);
      52              :     }
      53              : 
      54       316364 :   return compiler.translated;
      55              : }
      56              : 
      57              : // see: gcc/c/c-decl.cc:8230-8241
      58              : // https://github.com/Rust-GCC/gccrs/blob/0024bc2f028369b871a65ceb11b2fddfb0f9c3aa/gcc/c/c-decl.c#L8229-L8241
      59              : tree
      60         6388 : TyTyResolveCompile::get_implicit_enumeral_node_type (TyTy::BaseType *repr)
      61              : {
      62              :   // static tree enum_node = NULL_TREE;
      63              :   // if (enum_node == NULL_TREE)
      64              :   //   {
      65              :   //     enum_node = make_node (ENUMERAL_TYPE);
      66              :   //     SET_TYPE_MODE (enum_node, TYPE_MODE (unsigned_type_node));
      67              :   //     SET_TYPE_ALIGN (enum_node, TYPE_ALIGN (unsigned_type_node));
      68              :   //     TYPE_USER_ALIGN (enum_node) = 0;
      69              :   //     TYPE_UNSIGNED (enum_node) = 1;
      70              :   //     TYPE_PRECISION (enum_node) = TYPE_PRECISION (unsigned_type_node);
      71              :   //     TYPE_MIN_VALUE (enum_node) = TYPE_MIN_VALUE (unsigned_type_node);
      72              :   //     TYPE_MAX_VALUE (enum_node) = TYPE_MAX_VALUE (unsigned_type_node);
      73              : 
      74              :   //     // tree identifier = ctx->get_backend ()->get_identifier_node
      75              :   //     // ("enumeral"); tree enum_decl
      76              :   //     //   = build_decl (BUILTINS_LOCATION, TYPE_DECL, identifier,
      77              :   //     enum_node);
      78              :   //     // TYPE_NAME (enum_node) = enum_decl;
      79              :   //   }
      80              :   // return enum_node;
      81              : 
      82         6388 :   return compile (ctx, repr);
      83              : }
      84              : 
      85              : tree
      86        31723 : TyTyResolveCompile::get_unit_type (Context *ctx)
      87              : {
      88        31723 :   static tree unit_type;
      89        31723 :   if (unit_type == nullptr)
      90              :     {
      91         4538 :       auto cn = ctx->get_mappings ().get_current_crate ();
      92         4538 :       auto &c = ctx->get_mappings ().get_ast_crate (cn);
      93         4538 :       location_t locus = BUILTINS_LOCATION;
      94         4538 :       if (c.items.size () > 0)
      95              :         {
      96         4536 :           auto &item = c.items[0];
      97         4536 :           locus = item->get_locus ();
      98              :         }
      99              : 
     100         4538 :       auto unit_type_node = Backend::struct_type ({});
     101         4538 :       unit_type = Backend::named_type ("()", unit_type_node, locus);
     102              :     }
     103        31723 :   return unit_type;
     104              : }
     105              : 
     106              : void
     107            0 : TyTyResolveCompile::visit (const TyTy::ErrorType &)
     108              : {
     109            0 :   translated = error_mark_node;
     110            0 : }
     111              : 
     112              : void
     113          555 : TyTyResolveCompile::visit (const TyTy::InferType &type)
     114              : {
     115          555 :   const TyTy::BaseType *orig = &type;
     116          555 :   TyTy::BaseType *lookup = nullptr;
     117          555 :   bool ok = ctx->get_tyctx ()->lookup_type (type.get_ref (), &lookup);
     118          555 :   if (!ok)
     119              :     {
     120            0 :       translated = error_mark_node;
     121            7 :       return;
     122              :     }
     123              : 
     124          555 :   if (orig == lookup)
     125              :     {
     126            7 :       TyTy::BaseType *def = nullptr;
     127            7 :       if (type.default_type (&def))
     128              :         {
     129            7 :           translated = TyTyResolveCompile::compile (ctx, def);
     130            7 :           return;
     131              :         }
     132              : 
     133            0 :       translated = error_mark_node;
     134            0 :       return;
     135              :     }
     136              : 
     137          548 :   translated = TyTyResolveCompile::compile (ctx, lookup);
     138              : }
     139              : 
     140              : void
     141            0 : TyTyResolveCompile::visit (const TyTy::ParamType &type)
     142              : {
     143            0 :   translated = error_mark_node;
     144            0 : }
     145              : 
     146              : void
     147            0 : TyTyResolveCompile::visit (const TyTy::ConstParamType &type)
     148              : {
     149            0 :   translated = error_mark_node;
     150            0 : }
     151              : 
     152              : void
     153            0 : TyTyResolveCompile::visit (const TyTy::ConstValueType &type)
     154              : {
     155            0 :   translated = error_mark_node;
     156            0 : }
     157              : 
     158              : void
     159            0 : TyTyResolveCompile::visit (const TyTy::ConstInferType &type)
     160              : {
     161            0 :   translated = error_mark_node;
     162            0 : }
     163              : 
     164              : void
     165            0 : TyTyResolveCompile::visit (const TyTy::ConstErrorType &type)
     166              : {
     167            0 :   translated = error_mark_node;
     168            0 : }
     169              : 
     170              : void
     171          327 : TyTyResolveCompile::visit (const TyTy::ProjectionType &type)
     172              : {
     173              :   // workaround to get around const here
     174          327 :   TyTy::ProjectionType *projection
     175          327 :     = static_cast<TyTy::ProjectionType *> (type.clone ());
     176          327 :   auto normalized
     177          327 :     = Resolver::normalize_projection (projection, BUILTINS_LOCATION, false,
     178              :                                       false);
     179          327 :   if (normalized == projection)
     180              :     {
     181            0 :       translated = error_mark_node;
     182            0 :       return;
     183              :     }
     184              : 
     185          327 :   translated = TyTyResolveCompile::compile (ctx, normalized, false);
     186              : }
     187              : 
     188              : void
     189            0 : TyTyResolveCompile::visit (const TyTy::PlaceholderType &type)
     190              : {
     191            0 :   translated = error_mark_node;
     192            0 : }
     193              : 
     194              : void
     195          243 : TyTyResolveCompile::visit (const TyTy::ClosureType &type)
     196              : {
     197          243 :   auto &mappings = ctx->get_mappings ();
     198              : 
     199          243 :   std::vector<Backend::typed_identifier> fields;
     200              : 
     201          243 :   size_t i = 0;
     202          334 :   for (const auto &capture : type.get_captures ())
     203              :     {
     204              :       // lookup the HirId
     205           91 :       tl::optional<HirId> hid = mappings.lookup_node_to_hir (capture);
     206           91 :       rust_assert (hid.has_value ());
     207           91 :       auto ref = hid.value ();
     208              : 
     209              :       // lookup the var decl type
     210           91 :       TyTy::BaseType *lookup = nullptr;
     211           91 :       bool found = ctx->get_tyctx ()->lookup_type (ref, &lookup);
     212           91 :       rust_assert (found);
     213              : 
     214              :       // FIXME get the var pattern name
     215           91 :       std::string mappings_name = "capture_" + std::to_string (i);
     216              : 
     217              :       // FIXME
     218              :       // this should be based on the closure move-ability
     219           91 :       tree decl_type = TyTyResolveCompile::compile (ctx, lookup);
     220           91 :       tree capture_type = build_reference_type (decl_type);
     221           91 :       fields.emplace_back (mappings_name, capture_type,
     222           91 :                            type.get_ident ().locus);
     223           91 :     }
     224              : 
     225          243 :   tree type_record = Backend::struct_type (fields);
     226          243 :   RS_CLOSURE_FLAG (type_record) = 1;
     227              : 
     228          243 :   std::string named_struct_str
     229          486 :     = type.get_ident ().path.get () + "::{{closure}}";
     230          243 :   translated = Backend::named_type (named_struct_str, type_record,
     231          243 :                                     type.get_ident ().locus);
     232          243 : }
     233              : 
     234              : void
     235        17359 : TyTyResolveCompile::visit (const TyTy::FnType &type)
     236              : {
     237        17359 :   Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION);
     238        17359 :   std::vector<Backend::typed_identifier> parameters;
     239        17359 :   std::vector<Backend::typed_identifier> results;
     240              : 
     241              :   // we can only return unit-type if its not the C ABI because it will expect
     242              :   // void
     243        17359 :   auto hir_type = type.get_return_type ()->destructure ();
     244        17359 :   bool return_is_unit = hir_type->is_unit ();
     245        17359 :   bool is_c_abi = type.get_abi () == ABI::C;
     246        17359 :   bool should_be_void = is_c_abi && return_is_unit;
     247        17359 :   if (!should_be_void)
     248              :     {
     249        16304 :       auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode);
     250        16304 :       location_t return_type_locus
     251        16304 :         = ctx->get_mappings ().lookup_location (hir_type->get_ref ());
     252        16304 :       results.emplace_back ("_", ret, return_type_locus);
     253              :     }
     254              : 
     255        34474 :   for (auto &param_pair : type.get_params ())
     256              :     {
     257        17115 :       auto param_tyty = param_pair.get_type ();
     258        17115 :       auto compiled_param_type
     259        17115 :         = TyTyResolveCompile::compile (ctx, param_tyty, trait_object_mode);
     260              : 
     261        17115 :       parameters.emplace_back (param_pair.get_pattern ().to_string (),
     262              :                                compiled_param_type,
     263        34230 :                                ctx->get_mappings ().lookup_location (
     264              :                                  param_tyty->get_ref ()));
     265              :     }
     266              : 
     267        17359 :   if (!type.is_variadic ())
     268        16513 :     translated = Backend::function_type (receiver, parameters, results, NULL,
     269        16513 :                                          type.get_ident ().locus);
     270              :   else
     271          846 :     translated
     272          846 :       = Backend::function_type_variadic (receiver, parameters, results, NULL,
     273          846 :                                          type.get_ident ().locus);
     274        17359 : }
     275              : 
     276              : void
     277           94 : TyTyResolveCompile::visit (const TyTy::FnPtr &type)
     278              : {
     279           94 :   tree result_type = TyTyResolveCompile::compile (ctx, type.get_return_type ());
     280              : 
     281           94 :   std::vector<tree> parameters;
     282              : 
     283           94 :   auto &params = type.get_params ();
     284          168 :   for (auto &p : params)
     285              :     {
     286           74 :       tree pty = TyTyResolveCompile::compile (ctx, p.get_tyty ());
     287           74 :       parameters.push_back (pty);
     288              :     }
     289              : 
     290           94 :   translated = Backend::function_ptr_type (result_type, parameters,
     291           94 :                                            type.get_ident ().locus);
     292           94 : }
     293              : 
     294              : void
     295        21000 : TyTyResolveCompile::visit (const TyTy::ADTType &type)
     296              : {
     297        21000 :   tree type_record = error_mark_node;
     298        21000 :   if (!type.is_enum ())
     299              :     {
     300        14612 :       rust_assert (type.number_of_variants () == 1);
     301              : 
     302        14612 :       TyTy::VariantDef &variant = *type.get_variants ().at (0);
     303        14612 :       std::vector<Backend::typed_identifier> fields;
     304        40933 :       for (size_t i = 0; i < variant.num_fields (); i++)
     305              :         {
     306        26321 :           const TyTy::StructFieldType *field = variant.get_field_at_index (i);
     307        26321 :           tree compiled_field_ty
     308        26321 :             = TyTyResolveCompile::compile (ctx, field->get_field_type ());
     309              : 
     310        26321 :           fields.emplace_back (field->get_name (), compiled_field_ty,
     311        52642 :                                ctx->get_mappings ().lookup_location (
     312              :                                  type.get_ty_ref ()));
     313              :         }
     314              : 
     315        14612 :       type_record = type.is_union () ? Backend::union_type (fields, false)
     316        14392 :                                      : Backend::struct_type (fields, false);
     317        14612 :     }
     318              :   else
     319              :     {
     320              :       // see:
     321              :       // https://github.com/bminor/binutils-gdb/blob/527b8861cd472385fa9160a91dd6d65a25c41987/gdb/dwarf2/read.c#L9010-L9241
     322              :       //
     323              :       // enums are actually a big union so for example the rust enum:
     324              :       //
     325              :       // enum AnEnum {
     326              :       //   A,
     327              :       //   B,
     328              :       //   C (char),
     329              :       //   D { x: i64, y: i64 },
     330              :       // }
     331              :       //
     332              :       // we actually turn this into
     333              :       //
     334              :       // union {
     335              :       //   struct A { int RUST$ENUM$DISR; }; <- this is a data-less variant
     336              :       //   struct B { int RUST$ENUM$DISR; }; <- this is a data-less variant
     337              :       //   struct C { int RUST$ENUM$DISR; char __0; };
     338              :       //   struct D { int RUST$ENUM$DISR; i64 x; i64 y; };
     339              :       // }
     340              :       //
     341              :       // Ada, qual_union_types might still work for this but I am not 100% sure.
     342              :       // I ran into some issues lets reuse our normal union and ask Ada people
     343              :       // about it.
     344              :       //
     345              :       // I think the above is actually wrong and it should actually be this
     346              :       //
     347              :       // struct {
     348              :       //     int RUST$ENUM$DISR; // take into account the repr for this TODO
     349              :       //     union {
     350              :       //         // Variant A
     351              :       //         struct {
     352              :       //             // No additional fields
     353              :       //         } A;
     354              : 
     355              :       //         // Variant B
     356              :       //         struct {
     357              :       //             // No additional fields
     358              :       //         } B;
     359              : 
     360              :       //         // Variant C
     361              :       //         struct {
     362              :       //             char c;
     363              :       //         } C;
     364              : 
     365              :       //         // Variant D
     366              :       //         struct {
     367              :       //             int64_t x;
     368              :       //             int64_t y;
     369              :       //         } D;
     370              :       //     } payload; // The union of all variant data
     371              :       // };
     372              : 
     373         6388 :       std::vector<tree> variant_records;
     374        22510 :       for (auto &variant : type.get_variants ())
     375              :         {
     376        16122 :           std::vector<Backend::typed_identifier> fields;
     377        22144 :           for (size_t i = 0; i < variant->num_fields (); i++)
     378              :             {
     379         6022 :               const TyTy::StructFieldType *field
     380         6022 :                 = variant->get_field_at_index (i);
     381         6022 :               tree compiled_field_ty
     382         6022 :                 = TyTyResolveCompile::compile (ctx, field->get_field_type ());
     383              : 
     384         6022 :               std::string field_name = field->get_name ();
     385         6022 :               if (variant->get_variant_type ()
     386              :                   == TyTy::VariantDef::VariantType::TUPLE)
     387         4517 :                 field_name = "__" + field->get_name ();
     388              : 
     389        12044 :               fields.emplace_back (field_name, compiled_field_ty,
     390         6022 :                                    ctx->get_mappings ().lookup_location (
     391              :                                      type.get_ty_ref ()));
     392         6022 :             }
     393              : 
     394        16122 :           tree variant_record = Backend::struct_type (fields);
     395        16122 :           tree named_variant_record
     396        16122 :             = Backend::named_type (variant->get_ident ().path.get (),
     397        32244 :                                    variant_record, variant->get_ident ().locus);
     398              : 
     399              :           // add them to the list
     400        16122 :           variant_records.push_back (named_variant_record);
     401        16122 :         }
     402              : 
     403              :       // now we need to make the actual union, but first we need to make
     404              :       // named_type TYPE_DECL's out of the variants
     405              : 
     406         6388 :       size_t i = 0;
     407         6388 :       std::vector<Backend::typed_identifier> enum_fields;
     408        22510 :       for (auto &variant_record : variant_records)
     409              :         {
     410        16122 :           TyTy::VariantDef *variant = type.get_variants ().at (i++);
     411        16122 :           std::string implicit_variant_name = variant->get_identifier ();
     412              : 
     413        32244 :           enum_fields.emplace_back (implicit_variant_name, variant_record,
     414        16122 :                                     ctx->get_mappings ().lookup_location (
     415              :                                       type.get_ty_ref ()));
     416        16122 :         }
     417              : 
     418              :       //
     419         6388 :       location_t locus = ctx->get_mappings ().lookup_location (type.get_ref ());
     420              : 
     421              :       // finally make the union or the enum
     422         6388 :       tree variants_union = Backend::union_type (enum_fields, false);
     423         6388 :       layout_type (variants_union);
     424         6388 :       tree named_union_record
     425         6388 :         = Backend::named_type ("payload", variants_union, locus);
     426              : 
     427              :       // create the overall struct
     428         6388 :       tree enumeral_type = TyTyResolveCompile::get_implicit_enumeral_node_type (
     429         6388 :         type.get_repr_options ().repr);
     430         6388 :       Backend::typed_identifier discrim (RUST_ENUM_DISR_FIELD_NAME,
     431         6388 :                                          enumeral_type, locus);
     432         6388 :       Backend::typed_identifier variants_union_field ("payload",
     433              :                                                       named_union_record,
     434         6388 :                                                       locus);
     435              : 
     436         6388 :       std::vector<Backend::typed_identifier> fields
     437         6388 :         = {discrim, variants_union_field};
     438         6388 :       type_record = Backend::struct_type (fields, false);
     439         6388 :     }
     440              : 
     441              :   // Handle repr options
     442              :   // TODO: "packed" should only narrow type alignment and "align" should only
     443              :   // widen it. Do we need to check and enforce this here, or is it taken care of
     444              :   // later on in the gcc middle-end?
     445        21000 :   TyTy::ADTType::ReprOptions repr = type.get_repr_options ();
     446        21000 :   if (repr.pack)
     447              :     {
     448           10 :       TYPE_PACKED (type_record) = 1;
     449           10 :       if (repr.pack > 1)
     450              :         {
     451            5 :           SET_TYPE_ALIGN (type_record, repr.pack * 8);
     452            5 :           TYPE_USER_ALIGN (type_record) = 1;
     453              :         }
     454              :     }
     455        20990 :   else if (repr.align)
     456              :     {
     457           10 :       SET_TYPE_ALIGN (type_record, repr.align * 8);
     458           10 :       TYPE_USER_ALIGN (type_record) = 1;
     459              :     }
     460        21000 :   layout_type (type_record);
     461              : 
     462        21000 :   std::string named_struct_str
     463        21000 :     = type.get_ident ().path.get () + type.subst_as_string ();
     464        21000 :   translated = Backend::named_type (named_struct_str, type_record,
     465        21000 :                                     type.get_ident ().locus);
     466        21000 : }
     467              : 
     468              : void
     469        17504 : TyTyResolveCompile::visit (const TyTy::TupleType &type)
     470              : {
     471        17504 :   if (type.num_fields () == 0)
     472              :     {
     473        15674 :       translated = get_unit_type (ctx);
     474        15674 :       return;
     475              :     }
     476              : 
     477              :   // create implicit struct
     478         1830 :   std::vector<Backend::typed_identifier> fields;
     479         5669 :   for (size_t i = 0; i < type.num_fields (); i++)
     480              :     {
     481         3839 :       TyTy::BaseType *field = type.get_field (i);
     482         3839 :       tree compiled_field_ty = TyTyResolveCompile::compile (ctx, field);
     483              : 
     484              :       // rustc uses the convention __N, where N is an integer, to
     485              :       // name the fields of a tuple.  We follow this as well,
     486              :       // because this is used by GDB.  One further reason to prefer
     487              :       // this, rather than simply emitting the integer, is that this
     488              :       // approach makes it simpler to use a C-only debugger, or
     489              :       // GDB's C mode, when debugging Rust.
     490         3839 :       fields.emplace_back ("__" + std::to_string (i), compiled_field_ty,
     491         7678 :                            ctx->get_mappings ().lookup_location (
     492              :                              type.get_ty_ref ()));
     493              :     }
     494              : 
     495         1830 :   tree struct_type_record = Backend::struct_type (fields);
     496         1830 :   translated = Backend::named_type (type.get_name (), struct_type_record,
     497         1830 :                                     type.get_ident ().locus);
     498         1830 : }
     499              : 
     500              : void
     501         4136 : TyTyResolveCompile::visit (const TyTy::ArrayType &type)
     502              : {
     503         4136 :   tree element_type
     504         4136 :     = TyTyResolveCompile::compile (ctx, type.get_element_type ());
     505         4136 :   auto const_capacity = type.get_capacity ();
     506              : 
     507              :   // Check if capacity is a const type
     508         4136 :   if (const_capacity->get_kind () != TyTy::TypeKind::CONST)
     509              :     {
     510            0 :       rust_error_at (type.get_locus (), "array capacity is not a const type");
     511            0 :       translated = error_mark_node;
     512            0 :       return;
     513              :     }
     514              : 
     515         4136 :   auto *capacity_const = const_capacity->as_const_type ();
     516              : 
     517         4136 :   rust_assert (capacity_const->const_kind ()
     518              :                == TyTy::BaseConstType::ConstKind::Value);
     519         4136 :   auto &capacity_value = *static_cast<TyTy::ConstValueType *> (capacity_const);
     520         4136 :   auto folded_capacity_expr = capacity_value.get_value ();
     521              : 
     522              :   // build_index_type takes the maximum index, which is one less than
     523              :   // the length.
     524         4136 :   tree index_type_tree = build_index_type (
     525              :     fold_build2 (MINUS_EXPR, sizetype, folded_capacity_expr, size_one_node));
     526              : 
     527         4136 :   translated = build_array_type (element_type, index_type_tree, false);
     528              : }
     529              : 
     530              : void
     531          135 : TyTyResolveCompile::visit (const TyTy::SliceType &type)
     532              : {
     533          135 :   tree type_record = create_slice_type_record (type);
     534              : 
     535          135 :   std::string named_struct_str
     536          270 :     = std::string ("[") + type.get_element_type ()->get_name () + "]";
     537          135 :   translated = Backend::named_type (named_struct_str, type_record,
     538          135 :                                     type.get_ident ().locus);
     539          135 : }
     540              : 
     541              : void
     542        10311 : TyTyResolveCompile::visit (const TyTy::BoolType &)
     543              : {
     544        10311 :   translated
     545        10311 :     = Backend::named_type ("bool", boolean_type_node, BUILTINS_LOCATION);
     546        10311 : }
     547              : 
     548              : void
     549        76419 : TyTyResolveCompile::visit (const TyTy::IntType &type)
     550              : {
     551        76419 :   switch (type.get_int_kind ())
     552              :     {
     553         9552 :     case TyTy::IntType::I8:
     554         9552 :       translated = Backend::named_type ("i8", Backend::integer_type (false, 8),
     555              :                                         BUILTINS_LOCATION);
     556         9552 :       return;
     557              : 
     558         5571 :     case TyTy::IntType::I16:
     559         5571 :       translated
     560         5571 :         = Backend::named_type ("i16", Backend::integer_type (false, 16),
     561              :                                BUILTINS_LOCATION);
     562         5571 :       return;
     563              : 
     564        50308 :     case TyTy::IntType::I32:
     565        50308 :       translated
     566        50308 :         = Backend::named_type ("i32", Backend::integer_type (false, 32),
     567              :                                BUILTINS_LOCATION);
     568        50308 :       return;
     569              : 
     570         5745 :     case TyTy::IntType::I64:
     571         5745 :       translated
     572         5745 :         = Backend::named_type ("i64", Backend::integer_type (false, 64),
     573              :                                BUILTINS_LOCATION);
     574         5745 :       return;
     575              : 
     576         5243 :     case TyTy::IntType::I128:
     577         5243 :       translated
     578         5243 :         = Backend::named_type ("i128", Backend::integer_type (false, 128),
     579              :                                BUILTINS_LOCATION);
     580         5243 :       return;
     581              :     }
     582              : }
     583              : 
     584              : void
     585        56138 : TyTyResolveCompile::visit (const TyTy::UintType &type)
     586              : {
     587        56138 :   switch (type.get_uint_kind ())
     588              :     {
     589        14959 :     case TyTy::UintType::U8:
     590        14959 :       translated = Backend::named_type ("u8", Backend::integer_type (true, 8),
     591              :                                         BUILTINS_LOCATION);
     592        14959 :       return;
     593              : 
     594         8891 :     case TyTy::UintType::U16:
     595         8891 :       translated = Backend::named_type ("u16", Backend::integer_type (true, 16),
     596              :                                         BUILTINS_LOCATION);
     597         8891 :       return;
     598              : 
     599        13614 :     case TyTy::UintType::U32:
     600        13614 :       translated = Backend::named_type ("u32", Backend::integer_type (true, 32),
     601              :                                         BUILTINS_LOCATION);
     602        13614 :       return;
     603              : 
     604        13689 :     case TyTy::UintType::U64:
     605        13689 :       translated = Backend::named_type ("u64", Backend::integer_type (true, 64),
     606              :                                         BUILTINS_LOCATION);
     607        13689 :       return;
     608              : 
     609         4985 :     case TyTy::UintType::U128:
     610         4985 :       translated
     611         4985 :         = Backend::named_type ("u128", Backend::integer_type (true, 128),
     612              :                                BUILTINS_LOCATION);
     613         4985 :       return;
     614              :     }
     615              : }
     616              : 
     617              : void
     618        14943 : TyTyResolveCompile::visit (const TyTy::FloatType &type)
     619              : {
     620        14943 :   switch (type.get_float_kind ())
     621              :     {
     622         7259 :     case TyTy::FloatType::F32:
     623         7259 :       translated = Backend::named_type ("f32", Backend::float_type (32),
     624              :                                         BUILTINS_LOCATION);
     625         7259 :       return;
     626              : 
     627         7684 :     case TyTy::FloatType::F64:
     628         7684 :       translated = Backend::named_type ("f64", Backend::float_type (64),
     629              :                                         BUILTINS_LOCATION);
     630         7684 :       return;
     631              :     }
     632              : }
     633              : 
     634              : void
     635        34816 : TyTyResolveCompile::visit (const TyTy::USizeType &)
     636              : {
     637        34816 :   translated
     638        34816 :     = Backend::named_type ("usize",
     639              :                            Backend::integer_type (true,
     640              :                                                   Backend::get_pointer_size ()),
     641              :                            BUILTINS_LOCATION);
     642        34816 : }
     643              : 
     644              : void
     645        18601 : TyTyResolveCompile::visit (const TyTy::ISizeType &)
     646              : {
     647        18601 :   translated
     648        18601 :     = Backend::named_type ("isize",
     649              :                            Backend::integer_type (false,
     650              :                                                   Backend::get_pointer_size ()),
     651              :                            BUILTINS_LOCATION);
     652        18601 : }
     653              : 
     654              : void
     655         5465 : TyTyResolveCompile::visit (const TyTy::CharType &)
     656              : {
     657         5465 :   translated
     658         5465 :     = Backend::named_type ("char", Backend::wchar_type (), BUILTINS_LOCATION);
     659         5465 : }
     660              : 
     661              : void
     662        18490 : TyTyResolveCompile::visit (const TyTy::ReferenceType &type)
     663              : {
     664        18490 :   const TyTy::SliceType *slice = nullptr;
     665        18490 :   const TyTy::StrType *str = nullptr;
     666        18490 :   const TyTy::DynamicObjectType *dyn = nullptr;
     667        18490 :   const TyTy::ADTType *adt = nullptr;
     668        18490 :   if (type.is_dyn_slice_type (&slice))
     669              :     {
     670          612 :       tree type_record = create_slice_type_record (*slice);
     671          612 :       std::string dyn_slice_type_str
     672         1836 :         = std::string (type.is_mutable () ? "&mut " : "&") + "["
     673         1836 :           + slice->get_element_type ()->get_name () + "]";
     674              : 
     675          612 :       translated = Backend::named_type (dyn_slice_type_str, type_record,
     676              :                                         slice->get_locus ());
     677              : 
     678          612 :       return;
     679          612 :     }
     680        17878 :   else if (type.is_dyn_str_type (&str))
     681              :     {
     682         4070 :       tree type_record = create_str_type_record (*str);
     683         4070 :       std::string dyn_str_type_str
     684        12210 :         = std::string (type.is_mutable () ? "&mut " : "&") + "str";
     685              : 
     686         4070 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     687              :                                         str->get_locus ());
     688              : 
     689         4070 :       return;
     690         4070 :     }
     691        13808 :   else if (type.is_dyn_obj_type (&dyn))
     692              :     {
     693          683 :       tree type_record = create_dyn_obj_record (*dyn);
     694          683 :       std::string dyn_str_type_str
     695         1366 :         = std::string (type.is_mutable () ? "&mut " : "& ") + dyn->get_name ();
     696              : 
     697          683 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     698              :                                         dyn->get_locus ());
     699              : 
     700          683 :       return;
     701          683 :     }
     702              :   // Check for CStr, create a specific record for it
     703        13125 :   else if (type.is_dyn_cstr_type (&adt))
     704              :     {
     705              :       // CStr in core crate is defined as the following:
     706              :       //
     707              :       // #[repr(transparent)]
     708              :       // pub struct CStr {
     709              :       //    inner: [u8]
     710              :       // }
     711              :       //
     712              :       // Reuse the c_char (u8) slice fat-pointer layout
     713           56 :       TyTy::BaseType *u8 = nullptr;
     714           56 :       ctx->get_tyctx ()->lookup_builtin ("u8", &u8);
     715              :       // Create a synthetic SliceType over u8 and use that record layout
     716           56 :       TyTy::SliceType synthetic_slice (adt->get_ref (), adt->get_ident ().locus,
     717          112 :                                        TyTy::TyVar (u8->get_ref ()));
     718           56 :       tree type_record = create_slice_type_record (synthetic_slice);
     719           56 :       translated
     720           56 :         = Backend::named_type ("&CStr", type_record, adt->get_ident ().locus);
     721              : 
     722           56 :       return;
     723           56 :     }
     724              : 
     725        13069 :   tree base_compiled_type
     726        13069 :     = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
     727        13069 :   if (type.is_mutable ())
     728              :     {
     729         1133 :       translated = Backend::reference_type (base_compiled_type);
     730              :     }
     731              :   else
     732              :     {
     733        11936 :       auto base = Backend::immutable_type (base_compiled_type);
     734        11936 :       translated = Backend::reference_type (base);
     735              :     }
     736              : }
     737              : 
     738              : void
     739        10486 : TyTyResolveCompile::visit (const TyTy::PointerType &type)
     740              : {
     741        10486 :   const TyTy::SliceType *slice = nullptr;
     742        10486 :   const TyTy::StrType *str = nullptr;
     743        10486 :   const TyTy::DynamicObjectType *dyn = nullptr;
     744        10486 :   if (type.is_dyn_slice_type (&slice))
     745              :     {
     746          564 :       tree type_record = create_slice_type_record (*slice);
     747          564 :       std::string dyn_slice_type_str
     748         1636 :         = std::string (type.is_mutable () ? "*mut " : "*const ") + "["
     749         1692 :           + slice->get_element_type ()->get_name () + "]";
     750              : 
     751          564 :       translated = Backend::named_type (dyn_slice_type_str, type_record,
     752              :                                         slice->get_locus ());
     753              : 
     754          564 :       return;
     755          564 :     }
     756         9922 :   else if (type.is_dyn_str_type (&str))
     757              :     {
     758         2602 :       tree type_record = create_str_type_record (*str);
     759         2602 :       std::string dyn_str_type_str
     760         7806 :         = std::string (type.is_mutable () ? "*mut " : "*const ") + "str";
     761              : 
     762         2602 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     763              :                                         str->get_locus ());
     764              : 
     765         2602 :       return;
     766         2602 :     }
     767         7320 :   else if (type.is_dyn_obj_type (&dyn))
     768              :     {
     769           12 :       tree type_record = create_dyn_obj_record (*dyn);
     770           12 :       std::string dyn_str_type_str
     771           36 :         = std::string (type.is_mutable () ? "*mut " : "*const ")
     772           24 :           + dyn->get_name ();
     773              : 
     774           12 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     775              :                                         dyn->get_locus ());
     776              : 
     777           12 :       return;
     778           12 :     }
     779              : 
     780         7308 :   tree base_compiled_type
     781         7308 :     = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
     782         7308 :   if (type.is_mutable ())
     783              :     {
     784         1697 :       translated = Backend::pointer_type (base_compiled_type);
     785              :     }
     786              :   else
     787              :     {
     788         5611 :       auto base = Backend::immutable_type (base_compiled_type);
     789         5611 :       translated = Backend::pointer_type (base);
     790              :     }
     791              : }
     792              : 
     793              : void
     794         4540 : TyTyResolveCompile::visit (const TyTy::StrType &type)
     795              : {
     796         4540 :   tree raw_str = create_str_type_record (type);
     797         4540 :   translated = Backend::named_type ("str", raw_str, BUILTINS_LOCATION);
     798         4540 : }
     799              : 
     800              : void
     801         4798 : TyTyResolveCompile::visit (const TyTy::NeverType &)
     802              : {
     803         4798 :   translated = get_unit_type (ctx);
     804         4798 : }
     805              : 
     806              : void
     807            4 : TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type)
     808              : {
     809            4 :   if (trait_object_mode)
     810              :     {
     811            0 :       translated = Backend::integer_type (true, Backend::get_pointer_size ());
     812            0 :       return;
     813              :     }
     814              : 
     815            4 :   tree type_record = create_dyn_obj_record (type);
     816            4 :   translated = Backend::named_type (type.get_name (), type_record,
     817            4 :                                     type.get_ident ().locus);
     818              : }
     819              : 
     820              : void
     821            0 : TyTyResolveCompile::visit (const TyTy::OpaqueType &type)
     822              : {
     823            0 :   rust_assert (type.can_resolve ());
     824            0 :   auto underlying = type.resolve ();
     825            0 :   translated = TyTyResolveCompile::compile (ctx, underlying, trait_object_mode);
     826            0 : }
     827              : 
     828              : tree
     829          699 : TyTyResolveCompile::create_dyn_obj_record (const TyTy::DynamicObjectType &type)
     830              : {
     831          699 :   location_t locus = ctx->get_mappings ().lookup_location (type.get_ty_ref ());
     832              :   // create implicit struct
     833          699 :   std::vector<Backend::typed_identifier> fields;
     834              : 
     835          699 :   tree voidptr_ty = build_pointer_type (void_type_node);
     836              : 
     837          699 :   fields.emplace_back ("data", voidptr_ty, locus);
     838              : 
     839          699 :   std::vector<Backend::typed_identifier> vtable_fields;
     840              : 
     841              :   // drop_in_place is not implemented yet!
     842          699 :   vtable_fields.emplace_back ("__drop_in_place", voidptr_ty, locus);
     843          699 :   vtable_fields.emplace_back ("__size", size_type_node, locus);
     844          699 :   vtable_fields.emplace_back ("__align", size_type_node, locus);
     845              : 
     846          699 :   size_t items_size = type.get_object_items ().size ();
     847         1659 :   for (size_t method_idx = 0; method_idx < items_size; method_idx++)
     848          960 :     vtable_fields.emplace_back ("__method_" + std::to_string (method_idx),
     849              :                                 voidptr_ty, locus);
     850              : 
     851          699 :   tree vtable_record = Backend::struct_type (vtable_fields);
     852          699 :   tree vtable_ptr_ty = build_pointer_type (vtable_record);
     853              : 
     854          699 :   fields.emplace_back ("vtable", vtable_ptr_ty, locus);
     855              : 
     856          699 :   tree record = Backend::struct_type (fields);
     857          699 :   RS_DST_FLAG (record) = 1;
     858          699 :   TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
     859              : 
     860          699 :   return record;
     861          699 : }
     862              : 
     863              : tree
     864         1367 : TyTyResolveCompile::create_slice_type_record (const TyTy::SliceType &type)
     865              : {
     866              :   // lookup usize
     867         1367 :   TyTy::BaseType *usize = nullptr;
     868         1367 :   bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
     869         1367 :   rust_assert (ok);
     870              : 
     871         1367 :   tree element_type
     872         1367 :     = TyTyResolveCompile::compile (ctx, type.get_element_type ());
     873         1367 :   tree data_field_ty = build_pointer_type (element_type);
     874         1367 :   Backend::typed_identifier data_field ("data", data_field_ty,
     875         1367 :                                         type.get_locus ());
     876              : 
     877         1367 :   tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
     878         1367 :   Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
     879              : 
     880         1367 :   tree record = Backend::struct_type ({data_field, len_field});
     881         1367 :   RS_DST_FLAG (record) = 1;
     882         1367 :   TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
     883              : 
     884         1367 :   return record;
     885              : }
     886              : 
     887              : tree
     888        11212 : TyTyResolveCompile::create_str_type_record (const TyTy::StrType &type)
     889              : {
     890              :   // lookup usize
     891        11212 :   TyTy::BaseType *usize = nullptr;
     892        11212 :   bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
     893        11212 :   rust_assert (ok);
     894              : 
     895        11212 :   tree char_ptr = build_pointer_type (char_type_node);
     896        11212 :   tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
     897              : 
     898        11212 :   tree element_type = const_char_type;
     899        11212 :   tree data_field_ty = build_pointer_type (element_type);
     900        11212 :   Backend::typed_identifier data_field ("data", data_field_ty,
     901        11212 :                                         type.get_locus ());
     902              : 
     903        11212 :   tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
     904        11212 :   Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
     905              : 
     906        11212 :   tree record = Backend::struct_type ({data_field, len_field});
     907        11212 :   RS_DST_FLAG (record) = 1;
     908        11212 :   TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
     909              : 
     910        11212 :   return record;
     911              : }
     912              : 
     913              : } // namespace Compile
     914              : } // 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.