LCOV - code coverage report
Current view: top level - gcc/rust/backend - rust-compile-type.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.2 % 548 500
Test Date: 2026-09-19 16:22:48 Functions: 81.1 % 37 30
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       338717 : TyTyResolveCompile::TyTyResolveCompile (Context *ctx, bool trait_object_mode)
      35       338717 :   : ctx (ctx), trait_object_mode (trait_object_mode),
      36       338717 :     translated (error_mark_node)
      37       338717 : {}
      38              : 
      39              : tree
      40       338717 : TyTyResolveCompile::compile (Context *ctx, const TyTy::BaseType *ty,
      41              :                              bool trait_object_mode)
      42              : {
      43       338717 :   TyTyResolveCompile compiler (ctx, trait_object_mode);
      44       338717 :   const TyTy::BaseType *destructured = ty->destructure ();
      45       338717 :   destructured->accept_vis (compiler);
      46              : 
      47       338717 :   if (compiler.translated != error_mark_node
      48       338717 :       && TYPE_NAME (compiler.translated) != NULL)
      49              :     {
      50              :       // canonicalize the type
      51       292866 :       compiler.translated = ctx->insert_compiled_type (compiler.translated);
      52              :     }
      53              : 
      54       338717 :   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         6743 : 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         6743 :   return compile (ctx, repr);
      83              : }
      84              : 
      85              : tree
      86        33265 : TyTyResolveCompile::get_unit_type (Context *ctx)
      87              : {
      88        33265 :   static tree unit_type;
      89        33265 :   if (unit_type == nullptr)
      90              :     {
      91         4707 :       auto cn = ctx->get_mappings ().get_current_crate ();
      92         4707 :       auto &c = ctx->get_mappings ().get_ast_crate (cn);
      93         4707 :       location_t locus = BUILTINS_LOCATION;
      94         4707 :       if (c.items.size () > 0)
      95              :         {
      96         4701 :           auto &item = c.items[0];
      97         4701 :           locus = item->get_locus ();
      98              :         }
      99              : 
     100         4707 :       auto unit_type_node = Backend::struct_type ({});
     101         4707 :       unit_type = Backend::named_type ("()", unit_type_node, locus);
     102              :     }
     103        33265 :   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          629 : TyTyResolveCompile::visit (const TyTy::InferType &type)
     114              : {
     115          629 :   const TyTy::BaseType *orig = &type;
     116          629 :   TyTy::BaseType *lookup = nullptr;
     117          629 :   bool ok = ctx->get_tyctx ()->lookup_type (type.get_ref (), &lookup);
     118          629 :   if (!ok)
     119              :     {
     120            0 :       translated = error_mark_node;
     121            7 :       return;
     122              :     }
     123              : 
     124          629 :   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          622 :   translated = TyTyResolveCompile::compile (ctx, lookup);
     138              : }
     139              : 
     140              : void
     141            1 : TyTyResolveCompile::visit (const TyTy::ParamType &type)
     142              : {
     143            1 :   translated = error_mark_node;
     144            1 : }
     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          378 : TyTyResolveCompile::visit (const TyTy::ProjectionType &type)
     172              : {
     173              :   // workaround to get around const here
     174          378 :   TyTy::ProjectionType *projection
     175          378 :     = static_cast<TyTy::ProjectionType *> (type.clone ());
     176          378 :   auto normalized
     177          378 :     = Resolver::normalize_projection (projection, BUILTINS_LOCATION, false,
     178              :                                       false);
     179          378 :   if (normalized == projection)
     180              :     {
     181            0 :       translated = error_mark_node;
     182            0 :       return;
     183              :     }
     184              : 
     185          378 :   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        19006 : TyTyResolveCompile::visit (const TyTy::FnType &type)
     236              : {
     237        19006 :   Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION);
     238        19006 :   std::vector<Backend::typed_identifier> parameters;
     239        19006 :   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        19006 :   auto hir_type = type.get_return_type ()->destructure ();
     244        19006 :   bool return_is_unit = hir_type->is_unit ();
     245        19006 :   bool is_c_abi = type.get_abi () == ABI::C;
     246        19006 :   bool should_be_void = is_c_abi && return_is_unit;
     247        19006 :   if (!should_be_void)
     248              :     {
     249        17906 :       auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode);
     250        17906 :       location_t return_type_locus
     251        17906 :         = ctx->get_mappings ().lookup_location (hir_type->get_ref ());
     252        17906 :       results.emplace_back ("_", ret, return_type_locus);
     253              :     }
     254              : 
     255        38359 :   for (auto &param_pair : type.get_params ())
     256              :     {
     257        19353 :       auto param_tyty = param_pair.get_type ();
     258        19353 :       auto compiled_param_type
     259        19353 :         = TyTyResolveCompile::compile (ctx, param_tyty, trait_object_mode);
     260              : 
     261        19353 :       parameters.emplace_back (param_pair.get_pattern ().to_string (),
     262              :                                compiled_param_type,
     263        38706 :                                ctx->get_mappings ().lookup_location (
     264              :                                  param_tyty->get_ref ()));
     265              :     }
     266              : 
     267        19006 :   if (!type.is_variadic ())
     268        36246 :     translated = Backend::function_type (receiver, parameters, results, NULL,
     269        18123 :                                          type.get_ident ().locus);
     270              :   else
     271          883 :     translated
     272          883 :       = Backend::function_type_variadic (receiver, parameters, results, NULL,
     273          883 :                                          type.get_ident ().locus);
     274        19006 : }
     275              : 
     276              : void
     277          110 : TyTyResolveCompile::visit (const TyTy::FnPtr &type)
     278              : {
     279          110 :   tree result_type = TyTyResolveCompile::compile (ctx, type.get_return_type ());
     280              : 
     281          110 :   std::vector<tree> parameters;
     282              : 
     283          110 :   auto &params = type.get_params ();
     284          200 :   for (auto &p : params)
     285              :     {
     286           90 :       tree pty = TyTyResolveCompile::compile (ctx, p.get_tyty ());
     287           90 :       parameters.push_back (pty);
     288              :     }
     289              : 
     290          110 :   translated = Backend::function_ptr_type (result_type, parameters,
     291          110 :                                            type.get_ident ().locus);
     292          110 : }
     293              : 
     294              : void
     295        22216 : TyTyResolveCompile::visit (const TyTy::ADTType &type)
     296              : {
     297        22216 :   tree type_record = error_mark_node;
     298              : 
     299        22216 :   TyTy::ADTType::ReprOptions repr = type.get_repr_options ();
     300        22216 :   if (repr.repr_kind == TyTy::ADTType::ReprKind::TRANSPARENT)
     301              :     {
     302           90 :       rust_assert (type.number_of_variants () == 1);
     303           90 :       TyTy::VariantDef &variant = *type.get_variants ().at (0);
     304              : 
     305           90 :       if (variant.num_fields () == 0)
     306              :         {
     307              :           // 0-field transparent repr
     308              :           // Rustonomicon states that transparent structs should have a single
     309              :           // non-zero-sized field, but rustc compiles one with 0 fields happily
     310              :           // without errors, so not sure what's the correct treatment.
     311              :           //
     312              :           // For now, treat it as a unit struct
     313            0 :           type_record = Backend::struct_type ({});
     314              :         }
     315           90 :       else if (variant.num_fields () == 1)
     316              :         {
     317              :           // single field transparent repr
     318           90 :           const TyTy::StructFieldType *field = variant.get_field_at_index (0);
     319           90 :           type_record
     320           90 :             = TyTyResolveCompile::compile (ctx, field->get_field_type ());
     321              :         }
     322              :       else
     323              :         {
     324              :           // more than one field - typechecking already ensures there's only one
     325              :           // non-zero-sized field, just compile accessor for that
     326              :           // non-zero-sized.
     327            0 :           for (size_t i = 0; i < variant.num_fields (); i++)
     328              :             {
     329            0 :               auto field_ty = variant.get_field_at_index (i)->get_field_type ();
     330            0 :               if (!field_ty->is_zero_sized ())
     331              :                 {
     332            0 :                   type_record = TyTyResolveCompile::compile (ctx, field_ty);
     333              :                 }
     334              :             }
     335              :         }
     336              :     }
     337        22126 :   else if (repr.repr_kind == TyTy::ADTType::ReprKind::SIMD)
     338              :     {
     339           16 :       TyTy::VariantDef &variant = *type.get_variants ().at (0);
     340           16 :       auto element = variant.get_fields ().at (0)->get_field_type ();
     341           16 :       auto inner_type = compile (ctx, element);
     342              : 
     343           16 :       type_record = build_vector_type (inner_type, variant.num_fields ());
     344              :     }
     345        22110 :   else if (type.get_adt_kind () == TyTy::ADTType::ADTKind::EXTERN)
     346              :     {
     347              :       // Extern types are codegen'd as C's void type. They can only be used
     348              :       // through indirection, so they're effectively always codegen'd as
     349              :       // `void *` types.
     350            6 :       type_record = void_type_node;
     351              :     }
     352        22104 :   else if (!type.is_enum ())
     353              :     {
     354        15361 :       rust_assert (type.number_of_variants () == 1);
     355              : 
     356        15361 :       TyTy::VariantDef &variant = *type.get_variants ().at (0);
     357        15361 :       std::vector<Backend::typed_identifier> fields;
     358        42893 :       for (size_t i = 0; i < variant.num_fields (); i++)
     359              :         {
     360        27532 :           const TyTy::StructFieldType *field = variant.get_field_at_index (i);
     361        27532 :           tree compiled_field_ty
     362        27532 :             = TyTyResolveCompile::compile (ctx, field->get_field_type ());
     363              : 
     364        27532 :           fields.emplace_back (field->get_name (), compiled_field_ty,
     365        55064 :                                ctx->get_mappings ().lookup_location (
     366              :                                  type.get_ty_ref ()));
     367              :         }
     368              : 
     369        15361 :       if (!type.is_union () && variant.num_fields () > 0)
     370              :         {
     371        13214 :           const TyTy::StructFieldType *tail_field
     372        13214 :             = variant.get_field_at_index (variant.num_fields () - 1);
     373        13214 :           TyTy::BaseType *tail_ty = tail_field->get_field_type ();
     374              : 
     375        13214 :           if (tail_ty->is_unsized ())
     376              :             {
     377           57 :               tree raw_dst_type = error_mark_node;
     378              : 
     379           57 :               if (tail_ty->get_kind () == TyTy::TypeKind::SLICE)
     380              :                 {
     381           40 :                   auto slice = static_cast<TyTy::SliceType *> (tail_ty);
     382           40 :                   tree elem_type
     383           40 :                     = TyTyResolveCompile::compile (ctx,
     384           40 :                                                    slice->get_element_type ());
     385           40 :                   raw_dst_type = build_array_type (elem_type, NULL_TREE);
     386              :                 }
     387           17 :               else if (tail_ty->get_kind () == TyTy::TypeKind::DYNAMIC)
     388              :                 {
     389           10 :                   raw_dst_type = make_node (RECORD_TYPE);
     390           10 :                   TYPE_SIZE (raw_dst_type) = bitsize_zero_node;
     391           10 :                   TYPE_SIZE_UNIT (raw_dst_type) = size_zero_node;
     392           10 :                   layout_type (raw_dst_type);
     393              :                 }
     394              :               else
     395              :                 {
     396            7 :                   raw_dst_type = fields.back ().type;
     397              :                 }
     398           57 :               fields.pop_back ();
     399           57 :               fields.emplace_back (tail_field->get_name (), raw_dst_type,
     400          114 :                                    type.get_locus ());
     401              :             }
     402              :         }
     403        15361 :       type_record = type.is_union () ? Backend::union_type (fields, false)
     404        15141 :                                      : Backend::struct_type (fields, false);
     405        15361 :     }
     406              :   else
     407              :     {
     408              :       // see:
     409              :       // https://github.com/bminor/binutils-gdb/blob/527b8861cd472385fa9160a91dd6d65a25c41987/gdb/dwarf2/read.c#L9010-L9241
     410              :       //
     411              :       // enums are actually a big union so for example the rust enum:
     412              :       //
     413              :       // enum AnEnum {
     414              :       //   A,
     415              :       //   B,
     416              :       //   C (char),
     417              :       //   D { x: i64, y: i64 },
     418              :       // }
     419              :       //
     420              :       // we actually turn this into
     421              :       //
     422              :       // union {
     423              :       //   struct A { int RUST$ENUM$DISR; }; <- this is a data-less variant
     424              :       //   struct B { int RUST$ENUM$DISR; }; <- this is a data-less variant
     425              :       //   struct C { int RUST$ENUM$DISR; char __0; };
     426              :       //   struct D { int RUST$ENUM$DISR; i64 x; i64 y; };
     427              :       // }
     428              :       //
     429              :       // Ada, qual_union_types might still work for this but I am not 100% sure.
     430              :       // I ran into some issues lets reuse our normal union and ask Ada people
     431              :       // about it.
     432              :       //
     433              :       // I think the above is actually wrong and it should actually be this
     434              :       //
     435              :       // struct {
     436              :       //     int RUST$ENUM$DISR; // take into account the repr for this TODO
     437              :       //     union {
     438              :       //         // Variant A
     439              :       //         struct {
     440              :       //             // No additional fields
     441              :       //         } A;
     442              : 
     443              :       //         // Variant B
     444              :       //         struct {
     445              :       //             // No additional fields
     446              :       //         } B;
     447              : 
     448              :       //         // Variant C
     449              :       //         struct {
     450              :       //             char c;
     451              :       //         } C;
     452              : 
     453              :       //         // Variant D
     454              :       //         struct {
     455              :       //             int64_t x;
     456              :       //             int64_t y;
     457              :       //         } D;
     458              :       //     } payload; // The union of all variant data
     459              :       // };
     460              : 
     461         6743 :       std::vector<tree> variant_records;
     462        23603 :       for (auto &variant : type.get_variants ())
     463              :         {
     464        16860 :           std::vector<Backend::typed_identifier> fields;
     465        23228 :           for (size_t i = 0; i < variant->num_fields (); i++)
     466              :             {
     467         6368 :               const TyTy::StructFieldType *field
     468         6368 :                 = variant->get_field_at_index (i);
     469         6368 :               tree compiled_field_ty
     470         6368 :                 = TyTyResolveCompile::compile (ctx, field->get_field_type ());
     471              : 
     472         6368 :               std::string field_name = field->get_name ();
     473         6368 :               if (variant->get_variant_type ()
     474              :                   == TyTy::VariantDef::VariantType::TUPLE)
     475         4863 :                 field_name = "__" + field->get_name ();
     476              : 
     477        12736 :               fields.emplace_back (field_name, compiled_field_ty,
     478         6368 :                                    ctx->get_mappings ().lookup_location (
     479              :                                      type.get_ty_ref ()));
     480         6368 :             }
     481              : 
     482        16860 :           tree variant_record = Backend::struct_type (fields);
     483        16860 :           tree named_variant_record
     484        16860 :             = Backend::named_type (variant->get_ident ().path.get (),
     485        33720 :                                    variant_record, variant->get_ident ().locus);
     486              : 
     487              :           // add them to the list
     488        16860 :           variant_records.push_back (named_variant_record);
     489        16860 :         }
     490              : 
     491              :       // now we need to make the actual union, but first we need to make
     492              :       // named_type TYPE_DECL's out of the variants
     493              : 
     494         6743 :       size_t i = 0;
     495         6743 :       std::vector<Backend::typed_identifier> enum_fields;
     496        23603 :       for (auto &variant_record : variant_records)
     497              :         {
     498        16860 :           TyTy::VariantDef *variant = type.get_variants ().at (i++);
     499        16860 :           std::string implicit_variant_name = variant->get_identifier ();
     500              : 
     501        33720 :           enum_fields.emplace_back (implicit_variant_name, variant_record,
     502        16860 :                                     ctx->get_mappings ().lookup_location (
     503              :                                       type.get_ty_ref ()));
     504        16860 :         }
     505              : 
     506              :       //
     507         6743 :       location_t locus = ctx->get_mappings ().lookup_location (type.get_ref ());
     508              : 
     509              :       // finally make the union or the enum
     510         6743 :       tree variants_union = Backend::union_type (enum_fields, false);
     511         6743 :       layout_type (variants_union);
     512         6743 :       tree named_union_record
     513         6743 :         = Backend::named_type ("payload", variants_union, locus);
     514              : 
     515              :       // create the overall struct
     516         6743 :       tree enumeral_type = TyTyResolveCompile::get_implicit_enumeral_node_type (
     517         6743 :         type.get_repr_options ().repr);
     518         6743 :       Backend::typed_identifier discrim (RUST_ENUM_DISR_FIELD_NAME,
     519         6743 :                                          enumeral_type, locus);
     520         6743 :       Backend::typed_identifier variants_union_field ("payload",
     521              :                                                       named_union_record,
     522         6743 :                                                       locus);
     523              : 
     524         6743 :       std::vector<Backend::typed_identifier> fields
     525         6743 :         = {discrim, variants_union_field};
     526         6743 :       type_record = Backend::struct_type (fields, false);
     527         6743 :     }
     528              : 
     529              :   // Handle repr options
     530              :   // TODO: "packed" should only narrow type alignment and "align" should only
     531              :   // widen it. Do we need to check and enforce this here, or is it taken care of
     532              :   // later on in the gcc middle-end?
     533        22216 :   if (repr.repr_kind != TyTy::ADTType::ReprKind::TRANSPARENT)
     534              :     {
     535        22126 :       if (repr.pack)
     536              :         {
     537           10 :           TYPE_PACKED (type_record) = 1;
     538           10 :           if (repr.pack > 1)
     539              :             {
     540            5 :               SET_TYPE_ALIGN (type_record, repr.pack * 8);
     541            5 :               TYPE_USER_ALIGN (type_record) = 1;
     542              :             }
     543              :         }
     544        22116 :       else if (repr.align)
     545              :         {
     546           10 :           SET_TYPE_ALIGN (type_record, repr.align * 8);
     547           10 :           TYPE_USER_ALIGN (type_record) = 1;
     548              :         }
     549        22126 :       layout_type (type_record);
     550              :     }
     551              : 
     552        22216 :   std::string named_struct_str
     553        22216 :     = type.get_ident ().path.get () + type.subst_as_string ();
     554        22216 :   translated = Backend::named_type (named_struct_str, type_record,
     555        22216 :                                     type.get_ident ().locus);
     556        22216 : }
     557              : 
     558              : void
     559        18651 : TyTyResolveCompile::visit (const TyTy::TupleType &type)
     560              : {
     561        18651 :   if (type.num_fields () == 0)
     562              :     {
     563        16486 :       translated = get_unit_type (ctx);
     564        16486 :       return;
     565              :     }
     566              : 
     567              :   // create implicit struct
     568         2165 :   std::vector<Backend::typed_identifier> fields;
     569         6669 :   for (size_t i = 0; i < type.num_fields (); i++)
     570              :     {
     571         4504 :       TyTy::BaseType *field = type.get_field (i);
     572         4504 :       tree compiled_field_ty = TyTyResolveCompile::compile (ctx, field);
     573              : 
     574              :       // rustc uses the convention __N, where N is an integer, to
     575              :       // name the fields of a tuple.  We follow this as well,
     576              :       // because this is used by GDB.  One further reason to prefer
     577              :       // this, rather than simply emitting the integer, is that this
     578              :       // approach makes it simpler to use a C-only debugger, or
     579              :       // GDB's C mode, when debugging Rust.
     580         4504 :       fields.emplace_back ("__" + std::to_string (i), compiled_field_ty,
     581         9008 :                            ctx->get_mappings ().lookup_location (
     582              :                              type.get_ty_ref ()));
     583              :     }
     584              : 
     585         2165 :   tree struct_type_record = Backend::struct_type (fields);
     586         2165 :   translated = Backend::named_type (type.get_name (), struct_type_record,
     587         2165 :                                     type.get_ident ().locus);
     588         2165 : }
     589              : 
     590              : void
     591         4593 : TyTyResolveCompile::visit (const TyTy::ArrayType &type)
     592              : {
     593         4593 :   tree element_type
     594         4593 :     = TyTyResolveCompile::compile (ctx, type.get_element_type ());
     595         4593 :   auto const_capacity = type.get_capacity ();
     596              : 
     597              :   // Check if capacity is a const type
     598         4593 :   if (const_capacity->get_kind () != TyTy::TypeKind::CONST)
     599              :     {
     600            0 :       rust_error_at (type.get_locus (), "array capacity is not a const type");
     601            0 :       translated = error_mark_node;
     602            0 :       return;
     603              :     }
     604              : 
     605         4593 :   auto *capacity_const = const_capacity->as_const_type ();
     606              : 
     607         4593 :   rust_assert (capacity_const->const_kind ()
     608              :                == TyTy::BaseConstType::ConstKind::Value);
     609         4593 :   auto &capacity_value = *static_cast<TyTy::ConstValueType *> (capacity_const);
     610         4593 :   auto folded_capacity_expr = capacity_value.get_value ();
     611              : 
     612              :   // build_index_type takes the maximum index, which is one less than
     613              :   // the length.
     614         4593 :   tree index_type_tree = build_index_type (
     615              :     fold_build2 (MINUS_EXPR, sizetype, folded_capacity_expr, size_one_node));
     616              : 
     617         4593 :   translated = build_array_type (element_type, index_type_tree, false);
     618              : }
     619              : 
     620              : void
     621          251 : TyTyResolveCompile::visit (const TyTy::SliceType &type)
     622              : {
     623          251 :   tree type_record = create_slice_type_record (type);
     624              : 
     625          251 :   std::string named_struct_str
     626          502 :     = std::string ("[") + type.get_element_type ()->get_name () + "]";
     627          251 :   translated = Backend::named_type (named_struct_str, type_record,
     628          251 :                                     type.get_ident ().locus);
     629          251 : }
     630              : 
     631              : void
     632        11016 : TyTyResolveCompile::visit (const TyTy::BoolType &)
     633              : {
     634        11016 :   translated
     635        11016 :     = Backend::named_type ("bool", boolean_type_node, BUILTINS_LOCATION);
     636        11016 : }
     637              : 
     638              : void
     639        80095 : TyTyResolveCompile::visit (const TyTy::IntType &type)
     640              : {
     641        80095 :   switch (type.get_int_kind ())
     642              :     {
     643        10499 :     case TyTy::IntType::I8:
     644        10499 :       translated = Backend::named_type ("i8", Backend::integer_type (false, 8),
     645              :                                         BUILTINS_LOCATION);
     646        10499 :       return;
     647              : 
     648         5894 :     case TyTy::IntType::I16:
     649         5894 :       translated
     650         5894 :         = Backend::named_type ("i16", Backend::integer_type (false, 16),
     651              :                                BUILTINS_LOCATION);
     652         5894 :       return;
     653              : 
     654        52203 :     case TyTy::IntType::I32:
     655        52203 :       translated
     656        52203 :         = Backend::named_type ("i32", Backend::integer_type (false, 32),
     657              :                                BUILTINS_LOCATION);
     658        52203 :       return;
     659              : 
     660         6063 :     case TyTy::IntType::I64:
     661         6063 :       translated
     662         6063 :         = Backend::named_type ("i64", Backend::integer_type (false, 64),
     663              :                                BUILTINS_LOCATION);
     664         6063 :       return;
     665              : 
     666         5436 :     case TyTy::IntType::I128:
     667         5436 :       translated
     668         5436 :         = Backend::named_type ("i128", Backend::integer_type (false, 128),
     669              :                                BUILTINS_LOCATION);
     670         5436 :       return;
     671              :     }
     672              : }
     673              : 
     674              : void
     675        61779 : TyTyResolveCompile::visit (const TyTy::UintType &type)
     676              : {
     677        61779 :   switch (type.get_uint_kind ())
     678              :     {
     679        16485 :     case TyTy::UintType::U8:
     680        16485 :       translated = Backend::named_type ("u8", Backend::integer_type (true, 8),
     681              :                                         BUILTINS_LOCATION);
     682        16485 :       return;
     683              : 
     684         9932 :     case TyTy::UintType::U16:
     685         9932 :       translated = Backend::named_type ("u16", Backend::integer_type (true, 16),
     686              :                                         BUILTINS_LOCATION);
     687         9932 :       return;
     688              : 
     689        14867 :     case TyTy::UintType::U32:
     690        14867 :       translated = Backend::named_type ("u32", Backend::integer_type (true, 32),
     691              :                                         BUILTINS_LOCATION);
     692        14867 :       return;
     693              : 
     694        15233 :     case TyTy::UintType::U64:
     695        15233 :       translated = Backend::named_type ("u64", Backend::integer_type (true, 64),
     696              :                                         BUILTINS_LOCATION);
     697        15233 :       return;
     698              : 
     699         5262 :     case TyTy::UintType::U128:
     700         5262 :       translated
     701         5262 :         = Backend::named_type ("u128", Backend::integer_type (true, 128),
     702              :                                BUILTINS_LOCATION);
     703         5262 :       return;
     704              :     }
     705              : }
     706              : 
     707              : void
     708        15575 : TyTyResolveCompile::visit (const TyTy::FloatType &type)
     709              : {
     710        15575 :   switch (type.get_float_kind ())
     711              :     {
     712         7579 :     case TyTy::FloatType::F32:
     713         7579 :       translated = Backend::named_type ("f32", Backend::float_type (32),
     714              :                                         BUILTINS_LOCATION);
     715         7579 :       return;
     716              : 
     717         7996 :     case TyTy::FloatType::F64:
     718         7996 :       translated = Backend::named_type ("f64", Backend::float_type (64),
     719              :                                         BUILTINS_LOCATION);
     720         7996 :       return;
     721              :     }
     722              : }
     723              : 
     724              : void
     725        38228 : TyTyResolveCompile::visit (const TyTy::USizeType &)
     726              : {
     727        38228 :   translated
     728        38228 :     = Backend::named_type ("usize",
     729              :                            Backend::integer_type (true,
     730              :                                                   Backend::get_pointer_size ()),
     731              :                            BUILTINS_LOCATION);
     732        38228 : }
     733              : 
     734              : void
     735        19516 : TyTyResolveCompile::visit (const TyTy::ISizeType &)
     736              : {
     737        19516 :   translated
     738        19516 :     = Backend::named_type ("isize",
     739              :                            Backend::integer_type (false,
     740              :                                                   Backend::get_pointer_size ()),
     741              :                            BUILTINS_LOCATION);
     742        19516 : }
     743              : 
     744              : void
     745         5693 : TyTyResolveCompile::visit (const TyTy::CharType &)
     746              : {
     747         5693 :   translated
     748         5693 :     = Backend::named_type ("char", Backend::wchar_type (), BUILTINS_LOCATION);
     749         5693 : }
     750              : 
     751              : void
     752        19467 : TyTyResolveCompile::visit (const TyTy::ReferenceType &type)
     753              : {
     754        19467 :   const TyTy::SliceType *slice = nullptr;
     755        19467 :   const TyTy::StrType *str = nullptr;
     756        19467 :   const TyTy::DynamicObjectType *dyn = nullptr;
     757        19467 :   const TyTy::ADTType *adt = nullptr;
     758        19467 :   if (type.is_dyn_slice_type (&slice))
     759              :     {
     760          623 :       tree type_record = create_slice_type_record (*slice);
     761          623 :       std::string dyn_slice_type_str
     762         1868 :         = std::string (type.is_mutable () ? "&mut " : "&") + "["
     763         1869 :           + slice->get_element_type ()->get_name () + "]";
     764              : 
     765          623 :       translated = Backend::named_type (dyn_slice_type_str, type_record,
     766              :                                         slice->get_locus ());
     767              : 
     768          623 :       return;
     769          623 :     }
     770        18844 :   else if (type.is_dyn_str_type (&str))
     771              :     {
     772         4162 :       tree type_record = create_str_type_record (*str);
     773         4162 :       std::string dyn_str_type_str
     774        12486 :         = std::string (type.is_mutable () ? "&mut " : "&") + "str";
     775              : 
     776         4162 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     777              :                                         str->get_locus ());
     778              : 
     779         4162 :       return;
     780         4162 :     }
     781        14682 :   else if (type.is_dyn_obj_type (&dyn))
     782              :     {
     783          526 :       tree type_record = create_dyn_obj_record (*dyn);
     784          526 :       std::string dyn_str_type_str
     785         1052 :         = std::string (type.is_mutable () ? "&mut " : "& ") + dyn->get_name ();
     786              : 
     787          526 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     788              :                                         dyn->get_locus ());
     789              : 
     790          526 :       return;
     791          526 :     }
     792        14156 :   else if (type.is_dyn_adt_type (&adt))
     793              :     {
     794           76 :       tree type_record = create_dyn_adt_record (*adt);
     795           76 :       std::string dyn_str_type_str
     796          152 :         = std::string (type.is_mutable () ? "&mut" : "& ") + adt->get_name ();
     797              : 
     798           76 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     799              :                                         adt->get_locus ());
     800           76 :       return;
     801           76 :     }
     802              :   // Check for CStr, create a specific record for it
     803        14080 :   else if (type.is_dyn_cstr_type (&adt))
     804              :     {
     805              :       // CStr in core crate is defined as the following:
     806              :       //
     807              :       // #[repr(transparent)]
     808              :       // pub struct CStr {
     809              :       //    inner: [u8]
     810              :       // }
     811              :       //
     812              :       // Reuse the c_char (u8) slice fat-pointer layout
     813            0 :       TyTy::BaseType *u8 = nullptr;
     814            0 :       ctx->get_tyctx ()->lookup_builtin ("u8", &u8);
     815              :       // Create a synthetic SliceType over u8 and use that record layout
     816            0 :       TyTy::SliceType synthetic_slice (adt->get_ref (), adt->get_ident ().locus,
     817            0 :                                        TyTy::TyVar (u8->get_ref ()));
     818            0 :       tree type_record = create_slice_type_record (synthetic_slice);
     819            0 :       translated
     820            0 :         = Backend::named_type ("&CStr", type_record, adt->get_ident ().locus);
     821              : 
     822            0 :       return;
     823            0 :     }
     824              : 
     825        14080 :   tree base_compiled_type
     826        14080 :     = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
     827        14080 :   if (type.is_mutable ())
     828              :     {
     829         1346 :       translated = Backend::reference_type (base_compiled_type);
     830              :     }
     831              :   else
     832              :     {
     833              :       // https://doc.rust-lang.org/core/cell/struct.UnsafeCell.html
     834              :       // If you have a reference &T, then normally in Rust the compiler performs
     835              :       // optimizations based on the knowledge that &T points to immutable data.
     836              :       // Mutating that data, for example through an alias or by transmuting a &T
     837              :       // into a &mut T, is considered undefined behavior. UnsafeCell<T> opts-out
     838              :       // of the immutability guarantee for &T: a shared reference &UnsafeCell<T>
     839              :       // may point to data that is being mutated. This is called “interior
     840              :       // mutability”.
     841        12734 :       auto base = type.get_base ()->contains_unsafe_cell ()
     842        12734 :                     ? base_compiled_type
     843        12732 :                     : Backend::immutable_type (base_compiled_type);
     844        12734 :       translated = Backend::reference_type (base);
     845              :     }
     846              : }
     847              : 
     848              : void
     849        11333 : TyTyResolveCompile::visit (const TyTy::PointerType &type)
     850              : {
     851        11333 :   const TyTy::SliceType *slice = nullptr;
     852        11333 :   const TyTy::StrType *str = nullptr;
     853        11333 :   const TyTy::DynamicObjectType *dyn = nullptr;
     854        11333 :   const TyTy::ADTType *adt = nullptr;
     855        11333 :   if (type.is_dyn_slice_type (&slice))
     856              :     {
     857          576 :       tree type_record = create_slice_type_record (*slice);
     858          576 :       std::string dyn_slice_type_str
     859         1668 :         = std::string (type.is_mutable () ? "*mut " : "*const ") + "["
     860         1728 :           + slice->get_element_type ()->get_name () + "]";
     861              : 
     862          576 :       translated = Backend::named_type (dyn_slice_type_str, type_record,
     863              :                                         slice->get_locus ());
     864              : 
     865          576 :       return;
     866          576 :     }
     867        10757 :   else if (type.is_dyn_str_type (&str))
     868              :     {
     869         2671 :       tree type_record = create_str_type_record (*str);
     870         2671 :       std::string dyn_str_type_str
     871         8013 :         = std::string (type.is_mutable () ? "*mut " : "*const ") + "str";
     872              : 
     873         2671 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     874              :                                         str->get_locus ());
     875              : 
     876         2671 :       return;
     877         2671 :     }
     878         8086 :   else if (type.is_dyn_obj_type (&dyn))
     879              :     {
     880           19 :       tree type_record = create_dyn_obj_record (*dyn);
     881           19 :       std::string dyn_str_type_str
     882           55 :         = std::string (type.is_mutable () ? "*mut " : "*const ")
     883           38 :           + dyn->get_name ();
     884              : 
     885           19 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     886              :                                         dyn->get_locus ());
     887              : 
     888           19 :       return;
     889           19 :     }
     890         8067 :   else if (type.is_dyn_adt_type (&adt))
     891              :     {
     892           21 :       tree type_record = create_dyn_adt_record (*adt);
     893           21 :       std::string dyn_str_type_str
     894           63 :         = std::string (type.is_mutable () ? "*mut" : "*const ")
     895           42 :           + adt->get_name ();
     896              : 
     897           21 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     898              :                                         adt->get_locus ());
     899           21 :       return;
     900           21 :     }
     901              : 
     902         8046 :   tree base_compiled_type
     903         8046 :     = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
     904         8046 :   if (type.is_mutable ())
     905              :     {
     906         2086 :       translated = Backend::pointer_type (base_compiled_type);
     907              :     }
     908              :   else
     909              :     {
     910         5960 :       auto base = Backend::immutable_type (base_compiled_type);
     911         5960 :       translated = Backend::pointer_type (base);
     912              :     }
     913              : }
     914              : 
     915              : void
     916         4733 : TyTyResolveCompile::visit (const TyTy::StrType &type)
     917              : {
     918         4733 :   tree raw_str = create_str_type_record (type);
     919         4733 :   translated = Backend::named_type ("str", raw_str, BUILTINS_LOCATION);
     920         4733 : }
     921              : 
     922              : void
     923         5016 : TyTyResolveCompile::visit (const TyTy::NeverType &)
     924              : {
     925         5016 :   translated = get_unit_type (ctx);
     926         5016 : }
     927              : 
     928              : void
     929          188 : TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type)
     930              : {
     931          188 :   if (trait_object_mode)
     932              :     {
     933            0 :       translated = Backend::integer_type (true, Backend::get_pointer_size ());
     934            0 :       return;
     935              :     }
     936              : 
     937          188 :   tree type_record = create_dyn_obj_record (type);
     938          188 :   translated = Backend::named_type (type.get_name (), type_record,
     939          188 :                                     type.get_ident ().locus);
     940              : }
     941              : 
     942              : void
     943            0 : TyTyResolveCompile::visit (const TyTy::OpaqueType &type)
     944              : {
     945            0 :   rust_assert (type.can_resolve ());
     946            0 :   auto underlying = type.resolve ();
     947            0 :   translated = TyTyResolveCompile::compile (ctx, underlying, trait_object_mode);
     948            0 : }
     949              : 
     950              : tree
     951          742 : TyTyResolveCompile::create_dyn_obj_record (const TyTy::DynamicObjectType &type)
     952              : {
     953          742 :   location_t locus = ctx->get_mappings ().lookup_location (type.get_ty_ref ());
     954              :   // create implicit struct
     955          742 :   std::vector<Backend::typed_identifier> fields;
     956              : 
     957          742 :   tree voidptr_ty = build_pointer_type (void_type_node);
     958              : 
     959          742 :   fields.emplace_back ("data", voidptr_ty, locus);
     960              : 
     961          742 :   std::vector<Backend::typed_identifier> vtable_fields;
     962              : 
     963              :   // drop_in_place is not implemented yet!
     964          742 :   vtable_fields.emplace_back ("__drop_in_place", voidptr_ty, locus);
     965          742 :   vtable_fields.emplace_back ("__size", size_type_node, locus);
     966          742 :   vtable_fields.emplace_back ("__align", size_type_node, locus);
     967              : 
     968          742 :   size_t items_size = type.get_object_items ().size ();
     969         1745 :   for (size_t method_idx = 0; method_idx < items_size; method_idx++)
     970         1003 :     vtable_fields.emplace_back ("__method_" + std::to_string (method_idx),
     971              :                                 voidptr_ty, locus);
     972              : 
     973          742 :   tree vtable_record = Backend::struct_type (vtable_fields);
     974          742 :   tree vtable_ptr_ty = build_pointer_type (vtable_record);
     975              : 
     976          742 :   fields.emplace_back ("vtable", vtable_ptr_ty, locus);
     977              : 
     978          742 :   tree record = Backend::struct_type (fields);
     979          742 :   RS_DST_FLAG (record) = 1;
     980          742 :   TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
     981              : 
     982          742 :   return record;
     983          742 : }
     984              : 
     985              : tree
     986         1450 : TyTyResolveCompile::create_slice_type_record (const TyTy::SliceType &type)
     987              : {
     988              :   // lookup usize
     989         1450 :   TyTy::BaseType *usize = nullptr;
     990         1450 :   bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
     991         1450 :   rust_assert (ok);
     992              : 
     993         1450 :   tree element_type
     994         1450 :     = TyTyResolveCompile::compile (ctx, type.get_element_type ());
     995         1450 :   tree data_field_ty = build_pointer_type (element_type);
     996         1450 :   Backend::typed_identifier data_field ("data", data_field_ty,
     997         1450 :                                         type.get_locus ());
     998              : 
     999         1450 :   tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
    1000         1450 :   Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
    1001              : 
    1002         1450 :   tree record = Backend::struct_type ({data_field, len_field});
    1003         1450 :   RS_DST_FLAG (record) = 1;
    1004         1450 :   TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
    1005              : 
    1006         1450 :   return record;
    1007              : }
    1008              : 
    1009              : tree
    1010        11566 : TyTyResolveCompile::create_str_type_record (const TyTy::StrType &type)
    1011              : {
    1012              :   // lookup usize
    1013        11566 :   TyTy::BaseType *usize = nullptr;
    1014        11566 :   bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
    1015        11566 :   rust_assert (ok);
    1016              : 
    1017        11566 :   tree char_ptr = build_pointer_type (char_type_node);
    1018        11566 :   tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
    1019              : 
    1020        11566 :   tree element_type = const_char_type;
    1021        11566 :   tree data_field_ty = build_pointer_type (element_type);
    1022        11566 :   Backend::typed_identifier data_field ("data", data_field_ty,
    1023        11566 :                                         type.get_locus ());
    1024              : 
    1025        11566 :   tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
    1026        11566 :   Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
    1027              : 
    1028        11566 :   tree record = Backend::struct_type ({data_field, len_field});
    1029        11566 :   RS_DST_FLAG (record) = 1;
    1030        11566 :   TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
    1031              : 
    1032        11566 :   return record;
    1033              : }
    1034              : 
    1035              : tree
    1036          103 : TyTyResolveCompile::create_dyn_adt_record (const TyTy::ADTType &type)
    1037              : {
    1038          103 :   location_t locus = type.get_locus ();
    1039              : 
    1040          103 :   tree adt_record = TyTyResolveCompile::compile (ctx, &type);
    1041          103 :   tree data_field_ty = build_pointer_type (adt_record);
    1042          103 :   Backend::typed_identifier data_field ("data", data_field_ty, locus);
    1043              : 
    1044          103 :   rust_assert (type.number_of_variants () > 0);
    1045          103 :   TyTy::VariantDef &variant = *type.get_variants ().front ();
    1046          103 :   rust_assert (variant.num_fields () > 0);
    1047              : 
    1048          103 :   const TyTy::BaseType *tail_field
    1049          103 :     = variant.get_field_at_index (variant.num_fields () - 1)->get_field_type ();
    1050              : 
    1051          103 :   tree meta_field_ty = error_mark_node;
    1052          103 :   std::string meta = "meta";
    1053              : 
    1054          103 :   if (tail_field->get_kind () == TyTy::TypeKind::SLICE
    1055          103 :       || tail_field->get_kind () == TyTy::TypeKind::STR)
    1056              :     {
    1057           88 :       TyTy::BaseType *usize = nullptr;
    1058           88 :       bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
    1059           88 :       rust_assert (ok);
    1060           88 :       meta_field_ty = TyTyResolveCompile::compile (ctx, usize);
    1061           88 :       meta = "len";
    1062              :     }
    1063           15 :   else if (tail_field->get_kind () == TyTy::TypeKind::DYNAMIC)
    1064              :     {
    1065            9 :       const TyTy::DynamicObjectType *dyn
    1066              :         = static_cast<const TyTy::DynamicObjectType *> (tail_field);
    1067            9 :       tree dyn_record = create_dyn_obj_record (*dyn);
    1068            9 :       tree vtable_field = DECL_CHAIN (TYPE_FIELDS (dyn_record));
    1069            9 :       meta_field_ty = TREE_TYPE (vtable_field);
    1070            9 :       meta = "vtable";
    1071              :     }
    1072            6 :   else if (tail_field->get_kind () == TyTy::TypeKind::ADT)
    1073              :     {
    1074            6 :       const TyTy::ADTType *inner_adt
    1075              :         = static_cast<const TyTy::ADTType *> (tail_field);
    1076            6 :       tree inner_fat_ptr = create_dyn_adt_record (*inner_adt);
    1077            6 :       tree inner_meta_field = DECL_CHAIN (TYPE_FIELDS (inner_fat_ptr));
    1078            6 :       meta_field_ty = TREE_TYPE (inner_meta_field);
    1079            6 :       tree name_ident = DECL_NAME (inner_meta_field);
    1080            6 :       if (name_ident != NULL_TREE)
    1081            6 :         meta = IDENTIFIER_POINTER (name_ident);
    1082              :     }
    1083              :   else
    1084            0 :     rust_unreachable ();
    1085              : 
    1086          103 :   Backend::typed_identifier meta_field (meta, meta_field_ty, locus);
    1087          103 :   tree record = Backend::struct_type ({data_field, meta_field});
    1088          103 :   RS_DST_FLAG (record) = 1;
    1089          103 :   TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
    1090              : 
    1091          103 :   return record;
    1092          103 : }
    1093              : 
    1094              : } // namespace Compile
    1095              : } // 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.