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 % 614 565
Test Date: 2026-10-17 16:30:31 Functions: 82.1 % 39 32
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-type-util.h"
      21              : 
      22              : #include "rust-tyty.h"
      23              : #include "tree.h"
      24              : #include "fold-const.h"
      25              : #include "stor-layout.h"
      26              : 
      27              : namespace Rust {
      28              : namespace Compile {
      29              : 
      30              : static const std::string RUST_ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR";
      31              : 
      32              : static bool
      33        61999 : type_reaches_adt (TyTy::BaseType *type, DefId target, bool indirect,
      34              :                   std::set<std::pair<DefId, bool>> &visited)
      35              : {
      36        63165 :   type = type->destructure ();
      37        63165 :   switch (type->get_kind ())
      38              :     {
      39          405 :     case TyTy::TypeKind::POINTER:
      40          405 :       return type_reaches_adt (
      41              :         static_cast<TyTy::PointerType *> (type)->get_base (), target, true,
      42          405 :         visited);
      43              : 
      44          231 :     case TyTy::TypeKind::REF:
      45          231 :       return type_reaches_adt (
      46              :         static_cast<TyTy::ReferenceType *> (type)->get_base (), target, true,
      47          231 :         visited);
      48              : 
      49              :     case TyTy::TypeKind::TUPLE:
      50              :       {
      51              :         auto *tuple = static_cast<TyTy::TupleType *> (type);
      52          240 :         for (size_t i = 0; i < tuple->num_fields (); i++)
      53              :           {
      54           95 :             if (type_reaches_adt (tuple->get_field (i), target, indirect,
      55              :                                   visited))
      56              :               return true;
      57              :           }
      58              :         return false;
      59              :       }
      60              : 
      61          484 :     case TyTy::TypeKind::ARRAY:
      62          484 :       return type_reaches_adt (
      63              :         static_cast<TyTy::ArrayType *> (type)->get_element_type (), target,
      64          484 :         indirect, visited);
      65              : 
      66           47 :     case TyTy::TypeKind::FNPTR:
      67           47 :       {
      68           47 :         auto *fn = static_cast<TyTy::FnPtr *> (type);
      69           79 :         for (const auto &param : fn->get_params ())
      70              :           {
      71           33 :             if (type_reaches_adt (param.get_tyty (), target, true, visited))
      72        61999 :               return true;
      73              :           }
      74              : 
      75           46 :         return type_reaches_adt (fn->get_return_type (), target, true, visited);
      76              :       }
      77              : 
      78        26452 :     case TyTy::TypeKind::ADT:
      79        26452 :       break;
      80              : 
      81              :     default:
      82              :       return false;
      83              :     }
      84              : 
      85        26452 :   auto *adt = static_cast<TyTy::ADTType *> (type);
      86        48968 :   if (adt->get_id () == target && indirect)
      87           19 :     return true;
      88              : 
      89        26433 :   auto key = std::make_pair (adt->get_id (), indirect);
      90        26433 :   bool found = visited.find (key) != visited.end ();
      91        26433 :   if (found)
      92              :     return false;
      93        26199 :   visited.insert (key);
      94              : 
      95        64754 :   for (auto *variant : adt->get_variants ())
      96              :     {
      97        77939 :       for (auto *field : variant->get_fields ())
      98              :         {
      99        39384 :           if (type_reaches_adt (field->get_field_type (), target, indirect,
     100              :                                 visited))
     101        61999 :             return true;
     102              :         }
     103              :     }
     104              : 
     105              :   return false;
     106              : }
     107              : 
     108              : static bool
     109        22487 : is_recursive_adt (const TyTy::ADTType &type)
     110              : {
     111        22487 :   std::set<std::pair<DefId, bool>> visited;
     112        22487 :   return type_reaches_adt (const_cast<TyTy::ADTType *> (&type), type.get_id (),
     113        22487 :                            false, visited);
     114        22487 : }
     115              : 
     116       339975 : TyTyResolveCompile::TyTyResolveCompile (Context *ctx, bool trait_object_mode)
     117       339975 :   : ctx (ctx), trait_object_mode (trait_object_mode),
     118       339975 :     translated (error_mark_node)
     119       339975 : {}
     120              : 
     121              : tree
     122       339975 : TyTyResolveCompile::compile (Context *ctx, const TyTy::BaseType *ty,
     123              :                              bool trait_object_mode)
     124              : {
     125       339975 :   TyTyResolveCompile compiler (ctx, trait_object_mode);
     126       339975 :   const TyTy::BaseType *destructured = ty->destructure ();
     127              : 
     128       339975 :   if (const auto *adt = destructured->try_as<const TyTy::ADTType> ())
     129              :     {
     130        22525 :       tree compiled_adt = NULL_TREE;
     131        22525 :       if (ctx->lookup_compiled_adt (*adt, &compiled_adt))
     132           38 :         return compiled_adt;
     133              :     }
     134              : 
     135       339937 :   destructured->accept_vis (compiler);
     136              : 
     137       339937 :   if (compiler.translated != error_mark_node
     138       339937 :       && TYPE_NAME (compiler.translated) != NULL)
     139              :     {
     140              :       // canonicalize the type
     141       294014 :       compiler.translated = ctx->insert_compiled_type (compiler.translated);
     142              :     }
     143              : 
     144       339937 :   return compiler.translated;
     145              : }
     146              : 
     147              : // see: gcc/c/c-decl.cc:8230-8241
     148              : // https://github.com/Rust-GCC/gccrs/blob/0024bc2f028369b871a65ceb11b2fddfb0f9c3aa/gcc/c/c-decl.c#L8229-L8241
     149              : tree
     150         6752 : TyTyResolveCompile::get_implicit_enumeral_node_type (TyTy::BaseType *repr)
     151              : {
     152              :   // static tree enum_node = NULL_TREE;
     153              :   // if (enum_node == NULL_TREE)
     154              :   //   {
     155              :   //     enum_node = make_node (ENUMERAL_TYPE);
     156              :   //     SET_TYPE_MODE (enum_node, TYPE_MODE (unsigned_type_node));
     157              :   //     SET_TYPE_ALIGN (enum_node, TYPE_ALIGN (unsigned_type_node));
     158              :   //     TYPE_USER_ALIGN (enum_node) = 0;
     159              :   //     TYPE_UNSIGNED (enum_node) = 1;
     160              :   //     TYPE_PRECISION (enum_node) = TYPE_PRECISION (unsigned_type_node);
     161              :   //     TYPE_MIN_VALUE (enum_node) = TYPE_MIN_VALUE (unsigned_type_node);
     162              :   //     TYPE_MAX_VALUE (enum_node) = TYPE_MAX_VALUE (unsigned_type_node);
     163              : 
     164              :   //     // tree identifier = ctx->get_backend ()->get_identifier_node
     165              :   //     // ("enumeral"); tree enum_decl
     166              :   //     //   = build_decl (BUILTINS_LOCATION, TYPE_DECL, identifier,
     167              :   //     enum_node);
     168              :   //     // TYPE_NAME (enum_node) = enum_decl;
     169              :   //   }
     170              :   // return enum_node;
     171              : 
     172         6752 :   return compile (ctx, repr);
     173              : }
     174              : 
     175              : tree
     176        33141 : TyTyResolveCompile::get_unit_type (Context *ctx)
     177              : {
     178        33141 :   static tree unit_type;
     179        33141 :   if (unit_type == nullptr)
     180              :     {
     181         4742 :       auto cn = ctx->get_mappings ().crate.get_current_crate ();
     182         4742 :       auto &c = ctx->get_mappings ().crate.get_ast_crate (cn);
     183         4742 :       location_t locus = BUILTINS_LOCATION;
     184         4742 :       if (c.items.size () > 0)
     185              :         {
     186         4736 :           auto &item = c.items[0];
     187         4736 :           locus = item->get_locus ();
     188              :         }
     189              : 
     190         4742 :       auto unit_type_node = Backend::struct_type ({});
     191         4742 :       unit_type = Backend::named_type ("()", unit_type_node, locus);
     192              :     }
     193        33141 :   return unit_type;
     194              : }
     195              : 
     196              : void
     197            0 : TyTyResolveCompile::visit (const TyTy::ErrorType &)
     198              : {
     199            0 :   translated = error_mark_node;
     200            0 : }
     201              : 
     202              : void
     203          617 : TyTyResolveCompile::visit (const TyTy::InferType &type)
     204              : {
     205          617 :   const TyTy::BaseType *orig = &type;
     206          617 :   TyTy::BaseType *lookup = nullptr;
     207          617 :   bool ok = ctx->get_tyctx ()->lookup_type (type.get_ref (), &lookup);
     208          617 :   if (!ok)
     209              :     {
     210            0 :       translated = error_mark_node;
     211            7 :       return;
     212              :     }
     213              : 
     214          617 :   if (orig == lookup)
     215              :     {
     216            7 :       TyTy::BaseType *def = nullptr;
     217            7 :       if (type.default_type (&def))
     218              :         {
     219            7 :           translated = TyTyResolveCompile::compile (ctx, def);
     220            7 :           return;
     221              :         }
     222              : 
     223            0 :       translated = error_mark_node;
     224            0 :       return;
     225              :     }
     226              : 
     227          610 :   translated = TyTyResolveCompile::compile (ctx, lookup);
     228              : }
     229              : 
     230              : void
     231            1 : TyTyResolveCompile::visit (const TyTy::ParamType &type)
     232              : {
     233            1 :   translated = error_mark_node;
     234            1 : }
     235              : 
     236              : void
     237            0 : TyTyResolveCompile::visit (const TyTy::ConstParamType &type)
     238              : {
     239            0 :   translated = error_mark_node;
     240            0 : }
     241              : 
     242              : void
     243            0 : TyTyResolveCompile::visit (const TyTy::ConstValueType &type)
     244              : {
     245            0 :   translated = error_mark_node;
     246            0 : }
     247              : 
     248              : void
     249            0 : TyTyResolveCompile::visit (const TyTy::ConstInferType &type)
     250              : {
     251            0 :   translated = error_mark_node;
     252            0 : }
     253              : 
     254              : void
     255            0 : TyTyResolveCompile::visit (const TyTy::ConstErrorType &type)
     256              : {
     257            0 :   translated = error_mark_node;
     258            0 : }
     259              : 
     260              : void
     261          378 : TyTyResolveCompile::visit (const TyTy::ProjectionType &type)
     262              : {
     263              :   // workaround to get around const here
     264          378 :   TyTy::ProjectionType *projection
     265          378 :     = static_cast<TyTy::ProjectionType *> (type.clone ());
     266          378 :   auto normalized
     267          378 :     = Resolver::normalize_projection (projection, BUILTINS_LOCATION, false,
     268              :                                       false);
     269          378 :   if (normalized == projection)
     270              :     {
     271            0 :       translated = error_mark_node;
     272            0 :       return;
     273              :     }
     274              : 
     275          378 :   translated = TyTyResolveCompile::compile (ctx, normalized, false);
     276              : }
     277              : 
     278              : void
     279            0 : TyTyResolveCompile::visit (const TyTy::PlaceholderType &type)
     280              : {
     281            0 :   translated = error_mark_node;
     282            0 : }
     283              : 
     284              : void
     285          243 : TyTyResolveCompile::visit (const TyTy::ClosureType &type)
     286              : {
     287          243 :   auto &mappings = ctx->get_mappings ();
     288              : 
     289          243 :   std::vector<Backend::typed_identifier> fields;
     290              : 
     291          243 :   size_t i = 0;
     292          334 :   for (const auto &capture : type.get_captures ())
     293              :     {
     294              :       // lookup the HirId
     295           91 :       tl::optional<HirId> hid = mappings.lookup_node_to_hir (capture);
     296           91 :       rust_assert (hid.has_value ());
     297           91 :       auto ref = hid.value ();
     298              : 
     299              :       // lookup the var decl type
     300           91 :       TyTy::BaseType *lookup = nullptr;
     301           91 :       bool found = ctx->get_tyctx ()->lookup_type (ref, &lookup);
     302           91 :       rust_assert (found);
     303              : 
     304              :       // FIXME get the var pattern name
     305           91 :       std::string mappings_name = "capture_" + std::to_string (i);
     306              : 
     307              :       // FIXME
     308              :       // this should be based on the closure move-ability
     309           91 :       tree decl_type = TyTyResolveCompile::compile (ctx, lookup);
     310           91 :       tree capture_type = build_reference_type (decl_type);
     311           91 :       fields.emplace_back (mappings_name, capture_type,
     312           91 :                            type.get_ident ().locus);
     313           91 :     }
     314              : 
     315          243 :   tree type_record = Backend::struct_type (fields);
     316          243 :   RS_CLOSURE_FLAG (type_record) = 1;
     317              : 
     318          243 :   std::string named_struct_str
     319          486 :     = type.get_ident ().path.get () + "::{{closure}}";
     320          243 :   translated = Backend::named_type (named_struct_str, type_record,
     321          243 :                                     type.get_ident ().locus);
     322          243 : }
     323              : 
     324              : void
     325        19026 : TyTyResolveCompile::visit (const TyTy::FnType &type)
     326              : {
     327        19026 :   Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION);
     328        19026 :   std::vector<Backend::typed_identifier> parameters;
     329        19026 :   std::vector<Backend::typed_identifier> results;
     330              : 
     331              :   // we can only return unit-type if its not the C ABI because it will expect
     332              :   // void
     333        19026 :   auto hir_type = type.get_return_type ()->destructure ();
     334        19026 :   bool return_is_unit = hir_type->is_unit ();
     335        19026 :   bool is_c_abi = type.get_abi () == ABI::C;
     336        19026 :   bool should_be_void = is_c_abi && return_is_unit;
     337        19026 :   if (!should_be_void)
     338              :     {
     339        17925 :       auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode);
     340        17925 :       location_t return_type_locus
     341        17925 :         = ctx->get_mappings ().lookup_location (hir_type->get_ref ());
     342        17925 :       results.emplace_back ("_", ret, return_type_locus);
     343              :     }
     344              : 
     345        38391 :   for (auto &param_pair : type.get_params ())
     346              :     {
     347        19365 :       auto param_tyty = param_pair.get_type ();
     348        19365 :       auto compiled_param_type
     349        19365 :         = TyTyResolveCompile::compile (ctx, param_tyty, trait_object_mode);
     350              : 
     351        19365 :       parameters.emplace_back (param_pair.get_pattern ().to_string (),
     352              :                                compiled_param_type,
     353        38730 :                                ctx->get_mappings ().lookup_location (
     354              :                                  param_tyty->get_ref ()));
     355              :     }
     356              : 
     357        19026 :   if (!type.is_variadic ())
     358        36286 :     translated = Backend::function_type (receiver, parameters, results, NULL,
     359        18143 :                                          type.get_ident ().locus);
     360              :   else
     361          883 :     translated
     362          883 :       = Backend::function_type_variadic (receiver, parameters, results, NULL,
     363          883 :                                          type.get_ident ().locus);
     364        19026 : }
     365              : 
     366              : void
     367          112 : TyTyResolveCompile::visit (const TyTy::FnPtr &type)
     368              : {
     369          112 :   tree result_type = TyTyResolveCompile::compile (ctx, type.get_return_type ());
     370              : 
     371          112 :   std::vector<tree> parameters;
     372              : 
     373          112 :   auto &params = type.get_params ();
     374          204 :   for (auto &p : params)
     375              :     {
     376           92 :       tree pty = TyTyResolveCompile::compile (ctx, p.get_tyty ());
     377           92 :       parameters.push_back (pty);
     378              :     }
     379              : 
     380          112 :   translated = Backend::function_ptr_type (result_type, parameters,
     381          112 :                                            type.get_ident ().locus);
     382          112 : }
     383              : 
     384              : void
     385        22487 : TyTyResolveCompile::visit (const TyTy::ADTType &type)
     386              : {
     387        22487 :   tree type_record = error_mark_node;
     388              : 
     389        22487 :   TyTy::ADTType::ReprOptions repr = type.get_repr_options ();
     390        22487 :   bool cached_incomplete_record = false;
     391              : 
     392        22487 :   if (is_recursive_adt (type)
     393           19 :       && repr.repr_kind != TyTy::ADTType::ReprKind::TRANSPARENT
     394        22506 :       && repr.repr_kind != TyTy::ADTType::ReprKind::SIMD)
     395              :     {
     396           38 :       tree aggregate = make_node (type.is_union () ? UNION_TYPE : RECORD_TYPE);
     397           19 :       std::string name
     398           19 :         = type.get_ident ().path.get () + type.subst_as_string ();
     399              : 
     400           19 :       tree decl = build_decl (type.get_ident ().locus, TYPE_DECL,
     401              :                               Backend::get_identifier_node (name), aggregate);
     402           19 :       TYPE_NAME (aggregate) = decl;
     403           19 :       type_record = aggregate;
     404           19 :       ctx->insert_compiled_adt (type, type_record);
     405           19 :       cached_incomplete_record = true;
     406           19 :     }
     407              : 
     408        22487 :   if (repr.repr_kind == TyTy::ADTType::ReprKind::TRANSPARENT)
     409              :     {
     410           90 :       rust_assert (type.number_of_variants () == 1);
     411           90 :       TyTy::VariantDef &variant = *type.get_variants ().at (0);
     412              : 
     413           90 :       if (variant.num_fields () == 0)
     414              :         {
     415              :           // 0-field transparent repr
     416              :           // Rustonomicon states that transparent structs should have a single
     417              :           // non-zero-sized field, but rustc compiles one with 0 fields happily
     418              :           // without errors, so not sure what's the correct treatment.
     419              :           //
     420              :           // For now, treat it as a unit struct
     421            0 :           type_record = Backend::struct_type ({});
     422              :         }
     423           90 :       else if (variant.num_fields () == 1)
     424              :         {
     425              :           // single field transparent repr
     426           90 :           const TyTy::StructFieldType *field = variant.get_field_at_index (0);
     427           90 :           type_record
     428           90 :             = TyTyResolveCompile::compile (ctx, field->get_field_type ());
     429              :         }
     430              :       else
     431              :         {
     432              :           // more than one field - typechecking already ensures there's only one
     433              :           // non-zero-sized field, just compile accessor for that
     434              :           // non-zero-sized.
     435            0 :           for (size_t i = 0; i < variant.num_fields (); i++)
     436              :             {
     437            0 :               auto field_ty = variant.get_field_at_index (i)->get_field_type ();
     438            0 :               if (!field_ty->is_zero_sized ())
     439              :                 {
     440            0 :                   type_record = TyTyResolveCompile::compile (ctx, field_ty);
     441              :                 }
     442              :             }
     443              :         }
     444              :     }
     445        22397 :   else if (repr.repr_kind == TyTy::ADTType::ReprKind::SIMD)
     446              :     {
     447           16 :       TyTy::VariantDef &variant = *type.get_variants ().at (0);
     448           16 :       auto element = variant.get_fields ().at (0)->get_field_type ();
     449           16 :       auto inner_type = compile (ctx, element);
     450              : 
     451           16 :       type_record = build_vector_type (inner_type, variant.num_fields ());
     452              :     }
     453        22381 :   else if (type.get_adt_kind () == TyTy::ADTType::ADTKind::EXTERN)
     454              :     {
     455              :       // Extern types are codegen'd as C's void type. They can only be used
     456              :       // through indirection, so they're effectively always codegen'd as
     457              :       // `void *` types.
     458            6 :       type_record = void_type_node;
     459              :     }
     460        22375 :   else if (!type.is_enum ())
     461              :     {
     462        15623 :       rust_assert (type.number_of_variants () == 1);
     463              : 
     464        15623 :       TyTy::VariantDef &variant = *type.get_variants ().at (0);
     465        15623 :       std::vector<Backend::typed_identifier> fields;
     466        43192 :       for (size_t i = 0; i < variant.num_fields (); i++)
     467              :         {
     468        27569 :           const TyTy::StructFieldType *field = variant.get_field_at_index (i);
     469        27569 :           tree compiled_field_ty
     470        27569 :             = TyTyResolveCompile::compile (ctx, field->get_field_type ());
     471              : 
     472        27569 :           fields.emplace_back (field->get_name (), compiled_field_ty,
     473        55138 :                                ctx->get_mappings ().lookup_location (
     474              :                                  type.get_ty_ref ()));
     475              :         }
     476              : 
     477        15623 :       if (!type.is_union () && variant.num_fields () > 0)
     478              :         {
     479        13242 :           const TyTy::StructFieldType *tail_field
     480        13242 :             = variant.get_field_at_index (variant.num_fields () - 1);
     481        13242 :           TyTy::BaseType *tail_ty = tail_field->get_field_type ();
     482              : 
     483        13242 :           if (tail_ty->is_unsized ())
     484              :             {
     485           57 :               tree raw_dst_type = error_mark_node;
     486              : 
     487           57 :               if (tail_ty->get_kind () == TyTy::TypeKind::SLICE)
     488              :                 {
     489           40 :                   auto slice = static_cast<TyTy::SliceType *> (tail_ty);
     490           40 :                   tree elem_type
     491           40 :                     = TyTyResolveCompile::compile (ctx,
     492           40 :                                                    slice->get_element_type ());
     493           40 :                   raw_dst_type = build_array_type (elem_type, NULL_TREE);
     494              :                 }
     495           17 :               else if (tail_ty->get_kind () == TyTy::TypeKind::DYNAMIC)
     496              :                 {
     497           10 :                   raw_dst_type = make_node (RECORD_TYPE);
     498           10 :                   TYPE_SIZE (raw_dst_type) = bitsize_zero_node;
     499           10 :                   TYPE_SIZE_UNIT (raw_dst_type) = size_zero_node;
     500           10 :                   layout_type (raw_dst_type);
     501              :                 }
     502              :               else
     503              :                 {
     504            7 :                   raw_dst_type = fields.back ().type;
     505              :                 }
     506           57 :               fields.pop_back ();
     507           57 :               fields.emplace_back (tail_field->get_name (), raw_dst_type,
     508          114 :                                    type.get_locus ());
     509              :             }
     510              :         }
     511        15623 :       if (cached_incomplete_record)
     512           19 :         type_record = Backend::fill_in_fields (type_record, fields, false);
     513              :       else
     514        15604 :         type_record = type.is_union () ? Backend::union_type (fields, false)
     515        15384 :                                        : Backend::struct_type (fields, false);
     516        15623 :     }
     517              :   else
     518              :     {
     519              :       // see:
     520              :       // https://github.com/bminor/binutils-gdb/blob/527b8861cd472385fa9160a91dd6d65a25c41987/gdb/dwarf2/read.c#L9010-L9241
     521              :       //
     522              :       // enums are actually a big union so for example the rust enum:
     523              :       //
     524              :       // enum AnEnum {
     525              :       //   A,
     526              :       //   B,
     527              :       //   C (char),
     528              :       //   D { x: i64, y: i64 },
     529              :       // }
     530              :       //
     531              :       // we actually turn this into
     532              :       //
     533              :       // union {
     534              :       //   struct A { int RUST$ENUM$DISR; }; <- this is a data-less variant
     535              :       //   struct B { int RUST$ENUM$DISR; }; <- this is a data-less variant
     536              :       //   struct C { int RUST$ENUM$DISR; char __0; };
     537              :       //   struct D { int RUST$ENUM$DISR; i64 x; i64 y; };
     538              :       // }
     539              :       //
     540              :       // Ada, qual_union_types might still work for this but I am not 100% sure.
     541              :       // I ran into some issues lets reuse our normal union and ask Ada people
     542              :       // about it.
     543              :       //
     544              :       // I think the above is actually wrong and it should actually be this
     545              :       //
     546              :       // struct {
     547              :       //     int RUST$ENUM$DISR; // take into account the repr for this TODO
     548              :       //     union {
     549              :       //         // Variant A
     550              :       //         struct {
     551              :       //             // No additional fields
     552              :       //         } A;
     553              : 
     554              :       //         // Variant B
     555              :       //         struct {
     556              :       //             // No additional fields
     557              :       //         } B;
     558              : 
     559              :       //         // Variant C
     560              :       //         struct {
     561              :       //             char c;
     562              :       //         } C;
     563              : 
     564              :       //         // Variant D
     565              :       //         struct {
     566              :       //             int64_t x;
     567              :       //             int64_t y;
     568              :       //         } D;
     569              :       //     } payload; // The union of all variant data
     570              :       // };
     571              : 
     572         6752 :       std::vector<tree> variant_records;
     573        23639 :       for (auto &variant : type.get_variants ())
     574              :         {
     575        16887 :           std::vector<Backend::typed_identifier> fields;
     576        23255 :           for (size_t i = 0; i < variant->num_fields (); i++)
     577              :             {
     578         6368 :               const TyTy::StructFieldType *field
     579         6368 :                 = variant->get_field_at_index (i);
     580         6368 :               tree compiled_field_ty
     581         6368 :                 = TyTyResolveCompile::compile (ctx, field->get_field_type ());
     582              : 
     583         6368 :               std::string field_name = field->get_name ();
     584         6368 :               if (variant->get_variant_type ()
     585              :                   == TyTy::VariantDef::VariantType::TUPLE)
     586         4863 :                 field_name = "__" + field->get_name ();
     587              : 
     588        12736 :               fields.emplace_back (field_name, compiled_field_ty,
     589         6368 :                                    ctx->get_mappings ().lookup_location (
     590              :                                      type.get_ty_ref ()));
     591         6368 :             }
     592              : 
     593        16887 :           tree variant_record = Backend::struct_type (fields);
     594        16887 :           tree named_variant_record
     595        16887 :             = Backend::named_type (variant->get_ident ().path.get (),
     596        33774 :                                    variant_record, variant->get_ident ().locus);
     597              : 
     598              :           // add them to the list
     599        16887 :           variant_records.push_back (named_variant_record);
     600        16887 :         }
     601              : 
     602              :       // now we need to make the actual union, but first we need to make
     603              :       // named_type TYPE_DECL's out of the variants
     604              : 
     605         6752 :       size_t i = 0;
     606         6752 :       std::vector<Backend::typed_identifier> enum_fields;
     607        23639 :       for (auto &variant_record : variant_records)
     608              :         {
     609        16887 :           TyTy::VariantDef *variant = type.get_variants ().at (i++);
     610        16887 :           std::string implicit_variant_name = variant->get_identifier ();
     611              : 
     612        33774 :           enum_fields.emplace_back (implicit_variant_name, variant_record,
     613        16887 :                                     ctx->get_mappings ().lookup_location (
     614              :                                       type.get_ty_ref ()));
     615        16887 :         }
     616              : 
     617              :       //
     618         6752 :       location_t locus = ctx->get_mappings ().lookup_location (type.get_ref ());
     619              : 
     620              :       // finally make the union or the enum
     621         6752 :       tree variants_union = Backend::union_type (enum_fields, false);
     622         6752 :       layout_type (variants_union);
     623         6752 :       tree named_union_record
     624         6752 :         = Backend::named_type ("payload", variants_union, locus);
     625              : 
     626              :       // create the overall struct
     627         6752 :       tree enumeral_type = TyTyResolveCompile::get_implicit_enumeral_node_type (
     628         6752 :         type.get_repr_options ().repr);
     629         6752 :       Backend::typed_identifier discrim (RUST_ENUM_DISR_FIELD_NAME,
     630         6752 :                                          enumeral_type, locus);
     631         6752 :       Backend::typed_identifier variants_union_field ("payload",
     632              :                                                       named_union_record,
     633         6752 :                                                       locus);
     634              : 
     635         6752 :       std::vector<Backend::typed_identifier> fields
     636         6752 :         = {discrim, variants_union_field};
     637         6752 :       if (cached_incomplete_record)
     638            0 :         type_record = Backend::fill_in_fields (type_record, fields, false);
     639              :       else
     640         6752 :         type_record = Backend::struct_type (fields, false);
     641         6752 :     }
     642              : 
     643              :   // Handle repr options
     644              :   // TODO: "packed" should only narrow type alignment and "align" should only
     645              :   // widen it. Do we need to check and enforce this here, or is it taken care of
     646              :   // later on in the gcc middle-end?
     647        22487 :   if (repr.repr_kind != TyTy::ADTType::ReprKind::TRANSPARENT)
     648              :     {
     649        22397 :       if (repr.pack)
     650              :         {
     651           10 :           TYPE_PACKED (type_record) = 1;
     652           10 :           if (repr.pack > 1)
     653              :             {
     654            5 :               SET_TYPE_ALIGN (type_record, repr.pack * 8);
     655            5 :               TYPE_USER_ALIGN (type_record) = 1;
     656              :             }
     657              :         }
     658        22387 :       else if (repr.align)
     659              :         {
     660           10 :           SET_TYPE_ALIGN (type_record, repr.align * 8);
     661           10 :           TYPE_USER_ALIGN (type_record) = 1;
     662              :         }
     663        22397 :       layout_type (type_record);
     664              :     }
     665              : 
     666        22487 :   if (cached_incomplete_record)
     667              :     {
     668              :       // see gcc/c/c-decl.cc this sets up any incomplete variants of the tree
     669           31 :       for (tree variant = TYPE_NEXT_VARIANT (type_record); variant != NULL_TREE;
     670           12 :            variant = TYPE_NEXT_VARIANT (variant))
     671           12 :         TYPE_FIELDS (variant) = TYPE_FIELDS (type_record);
     672              : 
     673           19 :       translated = type_record;
     674              :     }
     675              :   else
     676              :     {
     677        22468 :       std::string named_struct_str
     678        22468 :         = type.get_ident ().path.get () + type.subst_as_string ();
     679        22468 :       translated = Backend::named_type (named_struct_str, type_record,
     680        22468 :                                         type.get_ident ().locus);
     681        22468 :     }
     682        22487 : }
     683              : 
     684              : void
     685        18705 : TyTyResolveCompile::visit (const TyTy::TupleType &type)
     686              : {
     687        18705 :   if (type.num_fields () == 0)
     688              :     {
     689        16538 :       translated = get_unit_type (ctx);
     690        16538 :       return;
     691              :     }
     692              : 
     693              :   // create implicit struct
     694         2167 :   std::vector<Backend::typed_identifier> fields;
     695         6675 :   for (size_t i = 0; i < type.num_fields (); i++)
     696              :     {
     697         4508 :       TyTy::BaseType *field = type.get_field (i);
     698         4508 :       tree compiled_field_ty = TyTyResolveCompile::compile (ctx, field);
     699              : 
     700              :       // rustc uses the convention __N, where N is an integer, to
     701              :       // name the fields of a tuple.  We follow this as well,
     702              :       // because this is used by GDB.  One further reason to prefer
     703              :       // this, rather than simply emitting the integer, is that this
     704              :       // approach makes it simpler to use a C-only debugger, or
     705              :       // GDB's C mode, when debugging Rust.
     706         4508 :       fields.emplace_back ("__" + std::to_string (i), compiled_field_ty,
     707         9016 :                            ctx->get_mappings ().lookup_location (
     708              :                              type.get_ty_ref ()));
     709              :     }
     710              : 
     711         2167 :   tree struct_type_record = Backend::struct_type (fields);
     712         2167 :   translated = Backend::named_type (type.get_name (), struct_type_record,
     713         2167 :                                     type.get_ident ().locus);
     714         2167 : }
     715              : 
     716              : void
     717         4597 : TyTyResolveCompile::visit (const TyTy::ArrayType &type)
     718              : {
     719         4597 :   tree element_type
     720         4597 :     = TyTyResolveCompile::compile (ctx, type.get_element_type ());
     721         4597 :   auto const_capacity = type.get_capacity ();
     722              : 
     723              :   // Check if capacity is a const type
     724         4597 :   if (const_capacity->get_kind () != TyTy::TypeKind::CONST)
     725              :     {
     726            0 :       rust_error_at (type.get_locus (), "array capacity is not a const type");
     727            0 :       translated = error_mark_node;
     728            0 :       return;
     729              :     }
     730              : 
     731         4597 :   auto *capacity_const = const_capacity->as_const_type ();
     732              : 
     733         4597 :   rust_assert (capacity_const->const_kind ()
     734              :                == TyTy::BaseConstType::ConstKind::Value);
     735         4597 :   auto &capacity_value = *static_cast<TyTy::ConstValueType *> (capacity_const);
     736         4597 :   auto folded_capacity_expr = capacity_value.get_value ();
     737              : 
     738              :   // build_index_type takes the maximum index, which is one less than
     739              :   // the length.
     740         4597 :   tree index_type_tree = build_index_type (
     741              :     fold_build2 (MINUS_EXPR, sizetype, folded_capacity_expr, size_one_node));
     742              : 
     743         4597 :   translated = build_array_type (element_type, index_type_tree, false);
     744              : }
     745              : 
     746              : void
     747          252 : TyTyResolveCompile::visit (const TyTy::SliceType &type)
     748              : {
     749          252 :   tree type_record = create_slice_type_record (type);
     750              : 
     751          252 :   std::string named_struct_str
     752          504 :     = std::string ("[") + type.get_element_type ()->get_name () + "]";
     753          252 :   translated = Backend::named_type (named_struct_str, type_record,
     754          252 :                                     type.get_ident ().locus);
     755          252 : }
     756              : 
     757              : void
     758        11051 : TyTyResolveCompile::visit (const TyTy::BoolType &)
     759              : {
     760        11051 :   translated
     761        11051 :     = Backend::named_type ("bool", boolean_type_node, BUILTINS_LOCATION);
     762        11051 : }
     763              : 
     764              : void
     765        80351 : TyTyResolveCompile::visit (const TyTy::IntType &type)
     766              : {
     767        80351 :   switch (type.get_int_kind ())
     768              :     {
     769        10556 :     case TyTy::IntType::I8:
     770        10556 :       translated = Backend::named_type ("i8", Backend::integer_type (false, 8),
     771              :                                         BUILTINS_LOCATION);
     772        10556 :       return;
     773              : 
     774         5929 :     case TyTy::IntType::I16:
     775         5929 :       translated
     776         5929 :         = Backend::named_type ("i16", Backend::integer_type (false, 16),
     777              :                                BUILTINS_LOCATION);
     778         5929 :       return;
     779              : 
     780        52293 :     case TyTy::IntType::I32:
     781        52293 :       translated
     782        52293 :         = Backend::named_type ("i32", Backend::integer_type (false, 32),
     783              :                                BUILTINS_LOCATION);
     784        52293 :       return;
     785              : 
     786         6102 :     case TyTy::IntType::I64:
     787         6102 :       translated
     788         6102 :         = Backend::named_type ("i64", Backend::integer_type (false, 64),
     789              :                                BUILTINS_LOCATION);
     790         6102 :       return;
     791              : 
     792         5471 :     case TyTy::IntType::I128:
     793         5471 :       translated
     794         5471 :         = Backend::named_type ("i128", Backend::integer_type (false, 128),
     795              :                                BUILTINS_LOCATION);
     796         5471 :       return;
     797              :     }
     798              : }
     799              : 
     800              : void
     801        62001 : TyTyResolveCompile::visit (const TyTy::UintType &type)
     802              : {
     803        62001 :   switch (type.get_uint_kind ())
     804              :     {
     805        16553 :     case TyTy::UintType::U8:
     806        16553 :       translated = Backend::named_type ("u8", Backend::integer_type (true, 8),
     807              :                                         BUILTINS_LOCATION);
     808        16553 :       return;
     809              : 
     810         9967 :     case TyTy::UintType::U16:
     811         9967 :       translated = Backend::named_type ("u16", Backend::integer_type (true, 16),
     812              :                                         BUILTINS_LOCATION);
     813         9967 :       return;
     814              : 
     815        14912 :     case TyTy::UintType::U32:
     816        14912 :       translated = Backend::named_type ("u32", Backend::integer_type (true, 32),
     817              :                                         BUILTINS_LOCATION);
     818        14912 :       return;
     819              : 
     820        15272 :     case TyTy::UintType::U64:
     821        15272 :       translated = Backend::named_type ("u64", Backend::integer_type (true, 64),
     822              :                                         BUILTINS_LOCATION);
     823        15272 :       return;
     824              : 
     825         5297 :     case TyTy::UintType::U128:
     826         5297 :       translated
     827         5297 :         = Backend::named_type ("u128", Backend::integer_type (true, 128),
     828              :                                BUILTINS_LOCATION);
     829         5297 :       return;
     830              :     }
     831              : }
     832              : 
     833              : void
     834        15646 : TyTyResolveCompile::visit (const TyTy::FloatType &type)
     835              : {
     836        15646 :   switch (type.get_float_kind ())
     837              :     {
     838         7614 :     case TyTy::FloatType::F32:
     839         7614 :       translated = Backend::named_type ("f32", Backend::float_type (32),
     840              :                                         BUILTINS_LOCATION);
     841         7614 :       return;
     842              : 
     843         8032 :     case TyTy::FloatType::F64:
     844         8032 :       translated = Backend::named_type ("f64", Backend::float_type (64),
     845              :                                         BUILTINS_LOCATION);
     846         8032 :       return;
     847              :     }
     848              : }
     849              : 
     850              : void
     851        38321 : TyTyResolveCompile::visit (const TyTy::USizeType &)
     852              : {
     853        38321 :   translated
     854        38321 :     = Backend::named_type ("usize",
     855              :                            Backend::integer_type (true,
     856              :                                                   Backend::get_pointer_size ()),
     857              :                            BUILTINS_LOCATION);
     858        38321 : }
     859              : 
     860              : void
     861        19562 : TyTyResolveCompile::visit (const TyTy::ISizeType &)
     862              : {
     863        19562 :   translated
     864        19562 :     = Backend::named_type ("isize",
     865              :                            Backend::integer_type (false,
     866              :                                                   Backend::get_pointer_size ()),
     867              :                            BUILTINS_LOCATION);
     868        19562 : }
     869              : 
     870              : void
     871         5728 : TyTyResolveCompile::visit (const TyTy::CharType &)
     872              : {
     873         5728 :   translated
     874         5728 :     = Backend::named_type ("char", Backend::wchar_type (), BUILTINS_LOCATION);
     875         5728 : }
     876              : 
     877              : void
     878        19502 : TyTyResolveCompile::visit (const TyTy::ReferenceType &type)
     879              : {
     880        19502 :   const TyTy::SliceType *slice = nullptr;
     881        19502 :   const TyTy::StrType *str = nullptr;
     882        19502 :   const TyTy::DynamicObjectType *dyn = nullptr;
     883        19502 :   const TyTy::ADTType *adt = nullptr;
     884        19502 :   if (type.is_dyn_slice_type (&slice))
     885              :     {
     886          625 :       tree type_record = create_slice_type_record (*slice);
     887          625 :       std::string dyn_slice_type_str
     888         1874 :         = std::string (type.is_mutable () ? "&mut " : "&") + "["
     889         1875 :           + slice->get_element_type ()->get_name () + "]";
     890              : 
     891          625 :       translated = Backend::named_type (dyn_slice_type_str, type_record,
     892              :                                         slice->get_locus ());
     893              : 
     894          625 :       return;
     895          625 :     }
     896        18877 :   else if (type.is_dyn_str_type (&str))
     897              :     {
     898         4162 :       tree type_record = create_str_type_record (*str);
     899         4162 :       std::string dyn_str_type_str
     900        12486 :         = std::string (type.is_mutable () ? "&mut " : "&") + "str";
     901              : 
     902         4162 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     903              :                                         str->get_locus ());
     904              : 
     905         4162 :       return;
     906         4162 :     }
     907        14715 :   else if (type.is_dyn_obj_type (&dyn))
     908              :     {
     909          526 :       tree type_record = create_dyn_obj_record (*dyn);
     910          526 :       std::string dyn_str_type_str
     911         1052 :         = std::string (type.is_mutable () ? "&mut " : "& ") + dyn->get_name ();
     912              : 
     913          526 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     914              :                                         dyn->get_locus ());
     915              : 
     916          526 :       return;
     917          526 :     }
     918        14189 :   else if (type.is_dyn_adt_type (&adt))
     919              :     {
     920           76 :       tree type_record = create_dyn_adt_record (*adt);
     921           76 :       std::string dyn_str_type_str
     922          152 :         = std::string (type.is_mutable () ? "&mut" : "& ") + adt->get_name ();
     923              : 
     924           76 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     925              :                                         adt->get_locus ());
     926           76 :       return;
     927           76 :     }
     928              :   // Check for CStr, create a specific record for it
     929        14113 :   else if (type.is_dyn_cstr_type (&adt))
     930              :     {
     931              :       // CStr in core crate is defined as the following:
     932              :       //
     933              :       // #[repr(transparent)]
     934              :       // pub struct CStr {
     935              :       //    inner: [u8]
     936              :       // }
     937              :       //
     938              :       // Reuse the c_char (u8) slice fat-pointer layout
     939            0 :       TyTy::BaseType *u8 = nullptr;
     940            0 :       ctx->get_tyctx ()->lookup_builtin ("u8", &u8);
     941              :       // Create a synthetic SliceType over u8 and use that record layout
     942            0 :       TyTy::SliceType synthetic_slice (adt->get_ref (), adt->get_ident ().locus,
     943            0 :                                        TyTy::TyVar (u8->get_ref ()));
     944            0 :       tree type_record = create_slice_type_record (synthetic_slice);
     945            0 :       translated
     946            0 :         = Backend::named_type ("&CStr", type_record, adt->get_ident ().locus);
     947              : 
     948            0 :       return;
     949            0 :     }
     950              : 
     951        14113 :   tree base_compiled_type
     952        14113 :     = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
     953        14113 :   if (type.is_mutable ())
     954              :     {
     955         1346 :       translated = Backend::reference_type (base_compiled_type);
     956              :     }
     957              :   else
     958              :     {
     959              :       // https://doc.rust-lang.org/core/cell/struct.UnsafeCell.html
     960              :       // If you have a reference &T, then normally in Rust the compiler performs
     961              :       // optimizations based on the knowledge that &T points to immutable data.
     962              :       // Mutating that data, for example through an alias or by transmuting a &T
     963              :       // into a &mut T, is considered undefined behavior. UnsafeCell<T> opts-out
     964              :       // of the immutability guarantee for &T: a shared reference &UnsafeCell<T>
     965              :       // may point to data that is being mutated. This is called “interior
     966              :       // mutability”.
     967        12767 :       auto base = type.get_base ()->contains_unsafe_cell ()
     968        12767 :                     ? base_compiled_type
     969        12765 :                     : Backend::immutable_type (base_compiled_type);
     970        12767 :       translated = Backend::reference_type (base);
     971              :     }
     972              : }
     973              : 
     974              : void
     975        11346 : TyTyResolveCompile::visit (const TyTy::PointerType &type)
     976              : {
     977        11346 :   const TyTy::SliceType *slice = nullptr;
     978        11346 :   const TyTy::StrType *str = nullptr;
     979        11346 :   const TyTy::DynamicObjectType *dyn = nullptr;
     980        11346 :   const TyTy::ADTType *adt = nullptr;
     981        11346 :   if (type.is_dyn_slice_type (&slice))
     982              :     {
     983          576 :       tree type_record = create_slice_type_record (*slice);
     984          576 :       std::string dyn_slice_type_str
     985         1668 :         = std::string (type.is_mutable () ? "*mut " : "*const ") + "["
     986         1728 :           + slice->get_element_type ()->get_name () + "]";
     987              : 
     988          576 :       translated = Backend::named_type (dyn_slice_type_str, type_record,
     989              :                                         slice->get_locus ());
     990              : 
     991          576 :       return;
     992          576 :     }
     993        10770 :   else if (type.is_dyn_str_type (&str))
     994              :     {
     995         2671 :       tree type_record = create_str_type_record (*str);
     996         2671 :       std::string dyn_str_type_str
     997         8013 :         = std::string (type.is_mutable () ? "*mut " : "*const ") + "str";
     998              : 
     999         2671 :       translated = Backend::named_type (dyn_str_type_str, type_record,
    1000              :                                         str->get_locus ());
    1001              : 
    1002         2671 :       return;
    1003         2671 :     }
    1004         8099 :   else if (type.is_dyn_obj_type (&dyn))
    1005              :     {
    1006           19 :       tree type_record = create_dyn_obj_record (*dyn);
    1007           19 :       std::string dyn_str_type_str
    1008           55 :         = std::string (type.is_mutable () ? "*mut " : "*const ")
    1009           38 :           + dyn->get_name ();
    1010              : 
    1011           19 :       translated = Backend::named_type (dyn_str_type_str, type_record,
    1012              :                                         dyn->get_locus ());
    1013              : 
    1014           19 :       return;
    1015           19 :     }
    1016         8080 :   else if (type.is_dyn_adt_type (&adt))
    1017              :     {
    1018           21 :       tree type_record = create_dyn_adt_record (*adt);
    1019           21 :       std::string dyn_str_type_str
    1020           63 :         = std::string (type.is_mutable () ? "*mut" : "*const ")
    1021           42 :           + adt->get_name ();
    1022              : 
    1023           21 :       translated = Backend::named_type (dyn_str_type_str, type_record,
    1024              :                                         adt->get_locus ());
    1025           21 :       return;
    1026           21 :     }
    1027              : 
    1028         8059 :   tree base_compiled_type
    1029         8059 :     = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
    1030         8059 :   if (type.is_mutable ())
    1031              :     {
    1032         2087 :       translated = Backend::pointer_type (base_compiled_type);
    1033              :     }
    1034              :   else
    1035              :     {
    1036         5972 :       auto base = Backend::immutable_type (base_compiled_type);
    1037         5972 :       translated = Backend::pointer_type (base);
    1038              :     }
    1039              : }
    1040              : 
    1041              : void
    1042         4768 : TyTyResolveCompile::visit (const TyTy::StrType &type)
    1043              : {
    1044         4768 :   tree raw_str = create_str_type_record (type);
    1045         4768 :   translated = Backend::named_type ("str", raw_str, BUILTINS_LOCATION);
    1046         4768 : }
    1047              : 
    1048              : void
    1049         5055 : TyTyResolveCompile::visit (const TyTy::NeverType &)
    1050              : {
    1051         5055 :   translated = get_unit_type (ctx);
    1052         5055 : }
    1053              : 
    1054              : void
    1055          188 : TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type)
    1056              : {
    1057          188 :   if (trait_object_mode)
    1058              :     {
    1059            0 :       translated = Backend::integer_type (true, Backend::get_pointer_size ());
    1060            0 :       return;
    1061              :     }
    1062              : 
    1063          188 :   tree type_record = create_dyn_obj_record (type);
    1064          188 :   translated = Backend::named_type (type.get_name (), type_record,
    1065          188 :                                     type.get_ident ().locus);
    1066              : }
    1067              : 
    1068              : void
    1069            0 : TyTyResolveCompile::visit (const TyTy::OpaqueType &type)
    1070              : {
    1071            0 :   rust_assert (type.can_resolve ());
    1072            0 :   auto underlying = type.resolve ();
    1073            0 :   translated = TyTyResolveCompile::compile (ctx, underlying, trait_object_mode);
    1074            0 : }
    1075              : 
    1076              : tree
    1077          742 : TyTyResolveCompile::create_dyn_obj_record (const TyTy::DynamicObjectType &type)
    1078              : {
    1079          742 :   location_t locus = ctx->get_mappings ().lookup_location (type.get_ty_ref ());
    1080              :   // create implicit struct
    1081          742 :   std::vector<Backend::typed_identifier> fields;
    1082              : 
    1083          742 :   tree voidptr_ty = build_pointer_type (void_type_node);
    1084              : 
    1085          742 :   fields.emplace_back ("data", voidptr_ty, locus);
    1086              : 
    1087          742 :   std::vector<Backend::typed_identifier> vtable_fields;
    1088              : 
    1089              :   // drop_in_place is not implemented yet!
    1090          742 :   vtable_fields.emplace_back ("__drop_in_place", voidptr_ty, locus);
    1091          742 :   vtable_fields.emplace_back ("__size", size_type_node, locus);
    1092          742 :   vtable_fields.emplace_back ("__align", size_type_node, locus);
    1093              : 
    1094          742 :   size_t items_size = type.get_object_items ().size ();
    1095         1745 :   for (size_t method_idx = 0; method_idx < items_size; method_idx++)
    1096         1003 :     vtable_fields.emplace_back ("__method_" + std::to_string (method_idx),
    1097              :                                 voidptr_ty, locus);
    1098              : 
    1099          742 :   tree vtable_record = Backend::struct_type (vtable_fields);
    1100          742 :   tree vtable_ptr_ty = build_pointer_type (vtable_record);
    1101              : 
    1102          742 :   fields.emplace_back ("vtable", vtable_ptr_ty, locus);
    1103              : 
    1104          742 :   tree record = Backend::struct_type (fields);
    1105          742 :   RS_DST_FLAG (record) = 1;
    1106          742 :   TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
    1107              : 
    1108          742 :   return record;
    1109          742 : }
    1110              : 
    1111              : tree
    1112         1453 : TyTyResolveCompile::create_slice_type_record (const TyTy::SliceType &type)
    1113              : {
    1114              :   // lookup usize
    1115         1453 :   TyTy::BaseType *usize = nullptr;
    1116         1453 :   bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
    1117         1453 :   rust_assert (ok);
    1118              : 
    1119         1453 :   tree element_type
    1120         1453 :     = TyTyResolveCompile::compile (ctx, type.get_element_type ());
    1121         1453 :   tree data_field_ty = build_pointer_type (element_type);
    1122         1453 :   Backend::typed_identifier data_field ("data", data_field_ty,
    1123         1453 :                                         type.get_locus ());
    1124              : 
    1125         1453 :   tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
    1126         1453 :   Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
    1127              : 
    1128         1453 :   tree record = Backend::struct_type ({data_field, len_field});
    1129         1453 :   RS_DST_FLAG (record) = 1;
    1130         1453 :   TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
    1131              : 
    1132         1453 :   return record;
    1133              : }
    1134              : 
    1135              : tree
    1136        11601 : TyTyResolveCompile::create_str_type_record (const TyTy::StrType &type)
    1137              : {
    1138              :   // lookup usize
    1139        11601 :   TyTy::BaseType *usize = nullptr;
    1140        11601 :   bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
    1141        11601 :   rust_assert (ok);
    1142              : 
    1143        11601 :   tree char_ptr = build_pointer_type (char_type_node);
    1144        11601 :   tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
    1145              : 
    1146        11601 :   tree element_type = const_char_type;
    1147        11601 :   tree data_field_ty = build_pointer_type (element_type);
    1148        11601 :   Backend::typed_identifier data_field ("data", data_field_ty,
    1149        11601 :                                         type.get_locus ());
    1150              : 
    1151        11601 :   tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
    1152        11601 :   Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
    1153              : 
    1154        11601 :   tree record = Backend::struct_type ({data_field, len_field});
    1155        11601 :   RS_DST_FLAG (record) = 1;
    1156        11601 :   TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
    1157              : 
    1158        11601 :   return record;
    1159              : }
    1160              : 
    1161              : tree
    1162          103 : TyTyResolveCompile::create_dyn_adt_record (const TyTy::ADTType &type)
    1163              : {
    1164          103 :   location_t locus = type.get_locus ();
    1165              : 
    1166          103 :   tree adt_record = TyTyResolveCompile::compile (ctx, &type);
    1167          103 :   tree data_field_ty = build_pointer_type (adt_record);
    1168          103 :   Backend::typed_identifier data_field ("data", data_field_ty, locus);
    1169              : 
    1170          103 :   rust_assert (type.number_of_variants () > 0);
    1171          103 :   TyTy::VariantDef &variant = *type.get_variants ().front ();
    1172          103 :   rust_assert (variant.num_fields () > 0);
    1173              : 
    1174          103 :   const TyTy::BaseType *tail_field
    1175          103 :     = variant.get_field_at_index (variant.num_fields () - 1)->get_field_type ();
    1176              : 
    1177          103 :   tree meta_field_ty = error_mark_node;
    1178          103 :   std::string meta = "meta";
    1179              : 
    1180          103 :   if (tail_field->get_kind () == TyTy::TypeKind::SLICE
    1181          103 :       || tail_field->get_kind () == TyTy::TypeKind::STR)
    1182              :     {
    1183           88 :       TyTy::BaseType *usize = nullptr;
    1184           88 :       bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
    1185           88 :       rust_assert (ok);
    1186           88 :       meta_field_ty = TyTyResolveCompile::compile (ctx, usize);
    1187           88 :       meta = "len";
    1188              :     }
    1189           15 :   else if (tail_field->get_kind () == TyTy::TypeKind::DYNAMIC)
    1190              :     {
    1191            9 :       const TyTy::DynamicObjectType *dyn
    1192              :         = static_cast<const TyTy::DynamicObjectType *> (tail_field);
    1193            9 :       tree dyn_record = create_dyn_obj_record (*dyn);
    1194            9 :       tree vtable_field = DECL_CHAIN (TYPE_FIELDS (dyn_record));
    1195            9 :       meta_field_ty = TREE_TYPE (vtable_field);
    1196            9 :       meta = "vtable";
    1197              :     }
    1198            6 :   else if (tail_field->get_kind () == TyTy::TypeKind::ADT)
    1199              :     {
    1200            6 :       const TyTy::ADTType *inner_adt
    1201              :         = static_cast<const TyTy::ADTType *> (tail_field);
    1202            6 :       tree inner_fat_ptr = create_dyn_adt_record (*inner_adt);
    1203            6 :       tree inner_meta_field = DECL_CHAIN (TYPE_FIELDS (inner_fat_ptr));
    1204            6 :       meta_field_ty = TREE_TYPE (inner_meta_field);
    1205            6 :       tree name_ident = DECL_NAME (inner_meta_field);
    1206            6 :       if (name_ident != NULL_TREE)
    1207            6 :         meta = IDENTIFIER_POINTER (name_ident);
    1208              :     }
    1209              :   else
    1210            0 :     rust_unreachable ();
    1211              : 
    1212          103 :   Backend::typed_identifier meta_field (meta, meta_field_ty, locus);
    1213          103 :   tree record = Backend::struct_type ({data_field, meta_field});
    1214          103 :   RS_DST_FLAG (record) = 1;
    1215          103 :   TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
    1216              : 
    1217          103 :   return record;
    1218          103 : }
    1219              : 
    1220              : } // namespace Compile
    1221              : } // namespace Rust
        

Generated by: LCOV version 2.5.0-beta

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