LCOV - code coverage report
Current view: top level - gcc/rust/backend - rust-compile-type.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 88.5 % 427 378
Test Date: 2026-02-28 14:20:25 Functions: 72.2 % 36 26
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              : 
      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       302799 : TyTyResolveCompile::TyTyResolveCompile (Context *ctx, bool trait_object_mode)
      33       302799 :   : ctx (ctx), trait_object_mode (trait_object_mode),
      34       302799 :     translated (error_mark_node)
      35       302799 : {}
      36              : 
      37              : tree
      38       302799 : TyTyResolveCompile::compile (Context *ctx, const TyTy::BaseType *ty,
      39              :                              bool trait_object_mode)
      40              : {
      41       302799 :   TyTyResolveCompile compiler (ctx, trait_object_mode);
      42       302799 :   const TyTy::BaseType *destructured = ty->destructure ();
      43       302799 :   destructured->accept_vis (compiler);
      44              : 
      45       302799 :   if (compiler.translated != error_mark_node
      46       302799 :       && TYPE_NAME (compiler.translated) != NULL)
      47              :     {
      48              :       // canonicalize the type
      49       262389 :       compiler.translated = ctx->insert_compiled_type (compiler.translated);
      50              :     }
      51              : 
      52       302799 :   return compiler.translated;
      53              : }
      54              : 
      55              : // see: gcc/c/c-decl.cc:8230-8241
      56              : // https://github.com/Rust-GCC/gccrs/blob/0024bc2f028369b871a65ceb11b2fddfb0f9c3aa/gcc/c/c-decl.c#L8229-L8241
      57              : tree
      58         6368 : TyTyResolveCompile::get_implicit_enumeral_node_type (TyTy::BaseType *repr)
      59              : {
      60              :   // static tree enum_node = NULL_TREE;
      61              :   // if (enum_node == NULL_TREE)
      62              :   //   {
      63              :   //     enum_node = make_node (ENUMERAL_TYPE);
      64              :   //     SET_TYPE_MODE (enum_node, TYPE_MODE (unsigned_type_node));
      65              :   //     SET_TYPE_ALIGN (enum_node, TYPE_ALIGN (unsigned_type_node));
      66              :   //     TYPE_USER_ALIGN (enum_node) = 0;
      67              :   //     TYPE_UNSIGNED (enum_node) = 1;
      68              :   //     TYPE_PRECISION (enum_node) = TYPE_PRECISION (unsigned_type_node);
      69              :   //     TYPE_MIN_VALUE (enum_node) = TYPE_MIN_VALUE (unsigned_type_node);
      70              :   //     TYPE_MAX_VALUE (enum_node) = TYPE_MAX_VALUE (unsigned_type_node);
      71              : 
      72              :   //     // tree identifier = ctx->get_backend ()->get_identifier_node
      73              :   //     // ("enumeral"); tree enum_decl
      74              :   //     //   = build_decl (BUILTINS_LOCATION, TYPE_DECL, identifier,
      75              :   //     enum_node);
      76              :   //     // TYPE_NAME (enum_node) = enum_decl;
      77              :   //   }
      78              :   // return enum_node;
      79              : 
      80         6368 :   return compile (ctx, repr);
      81              : }
      82              : 
      83              : tree
      84        26378 : TyTyResolveCompile::get_unit_type (Context *ctx)
      85              : {
      86        26378 :   static tree unit_type;
      87        26378 :   if (unit_type == nullptr)
      88              :     {
      89         4301 :       auto cn = ctx->get_mappings ().get_current_crate ();
      90         4301 :       auto &c = ctx->get_mappings ().get_ast_crate (cn);
      91         4301 :       location_t locus = BUILTINS_LOCATION;
      92         4301 :       if (c.items.size () > 0)
      93              :         {
      94         4299 :           auto &item = c.items[0];
      95         4299 :           locus = item->get_locus ();
      96              :         }
      97              : 
      98         4301 :       auto unit_type_node = Backend::struct_type ({});
      99         4301 :       unit_type = Backend::named_type ("()", unit_type_node, locus);
     100              :     }
     101        26378 :   return unit_type;
     102              : }
     103              : 
     104              : void
     105            0 : TyTyResolveCompile::visit (const TyTy::ErrorType &)
     106              : {
     107            0 :   translated = error_mark_node;
     108            0 : }
     109              : 
     110              : void
     111          568 : TyTyResolveCompile::visit (const TyTy::InferType &type)
     112              : {
     113          568 :   const TyTy::BaseType *orig = &type;
     114          568 :   TyTy::BaseType *lookup = nullptr;
     115          568 :   bool ok = ctx->get_tyctx ()->lookup_type (type.get_ref (), &lookup);
     116          568 :   if (!ok)
     117              :     {
     118            0 :       translated = error_mark_node;
     119            7 :       return;
     120              :     }
     121              : 
     122          568 :   if (orig == lookup)
     123              :     {
     124            7 :       TyTy::BaseType *def = nullptr;
     125            7 :       if (type.default_type (&def))
     126              :         {
     127            7 :           translated = TyTyResolveCompile::compile (ctx, def);
     128            7 :           return;
     129              :         }
     130              : 
     131            0 :       translated = error_mark_node;
     132            0 :       return;
     133              :     }
     134              : 
     135          561 :   translated = TyTyResolveCompile::compile (ctx, lookup);
     136              : }
     137              : 
     138              : void
     139            0 : TyTyResolveCompile::visit (const TyTy::ParamType &type)
     140              : {
     141            0 :   translated = error_mark_node;
     142            0 : }
     143              : 
     144              : void
     145            0 : TyTyResolveCompile::visit (const TyTy::ConstParamType &type)
     146              : {
     147            0 :   translated = error_mark_node;
     148            0 : }
     149              : 
     150              : void
     151            0 : TyTyResolveCompile::visit (const TyTy::ConstValueType &type)
     152              : {
     153            0 :   translated = error_mark_node;
     154            0 : }
     155              : 
     156              : void
     157            0 : TyTyResolveCompile::visit (const TyTy::ConstInferType &type)
     158              : {
     159            0 :   translated = error_mark_node;
     160            0 : }
     161              : 
     162              : void
     163            0 : TyTyResolveCompile::visit (const TyTy::ConstErrorType &type)
     164              : {
     165            0 :   translated = error_mark_node;
     166            0 : }
     167              : 
     168              : void
     169            0 : TyTyResolveCompile::visit (const TyTy::ProjectionType &type)
     170              : {
     171            0 :   translated = error_mark_node;
     172            0 : }
     173              : 
     174              : void
     175            0 : TyTyResolveCompile::visit (const TyTy::PlaceholderType &type)
     176              : {
     177            0 :   translated = error_mark_node;
     178            0 : }
     179              : 
     180              : void
     181          243 : TyTyResolveCompile::visit (const TyTy::ClosureType &type)
     182              : {
     183          243 :   auto &mappings = ctx->get_mappings ();
     184              : 
     185          243 :   std::vector<Backend::typed_identifier> fields;
     186              : 
     187          243 :   size_t i = 0;
     188          334 :   for (const auto &capture : type.get_captures ())
     189              :     {
     190              :       // lookup the HirId
     191           91 :       tl::optional<HirId> hid = mappings.lookup_node_to_hir (capture);
     192           91 :       rust_assert (hid.has_value ());
     193           91 :       auto ref = hid.value ();
     194              : 
     195              :       // lookup the var decl type
     196           91 :       TyTy::BaseType *lookup = nullptr;
     197           91 :       bool found = ctx->get_tyctx ()->lookup_type (ref, &lookup);
     198           91 :       rust_assert (found);
     199              : 
     200              :       // FIXME get the var pattern name
     201           91 :       std::string mappings_name = "capture_" + std::to_string (i);
     202              : 
     203              :       // FIXME
     204              :       // this should be based on the closure move-ability
     205           91 :       tree decl_type = TyTyResolveCompile::compile (ctx, lookup);
     206           91 :       tree capture_type = build_reference_type (decl_type);
     207           91 :       fields.emplace_back (mappings_name, capture_type,
     208           91 :                            type.get_ident ().locus);
     209           91 :     }
     210              : 
     211          243 :   tree type_record = Backend::struct_type (fields);
     212          243 :   RS_CLOSURE_FLAG (type_record) = 1;
     213              : 
     214          243 :   std::string named_struct_str
     215          486 :     = type.get_ident ().path.get () + "::{{closure}}";
     216          243 :   translated = Backend::named_type (named_struct_str, type_record,
     217          243 :                                     type.get_ident ().locus);
     218          243 : }
     219              : 
     220              : void
     221        16241 : TyTyResolveCompile::visit (const TyTy::FnType &type)
     222              : {
     223        16241 :   Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION);
     224        16241 :   std::vector<Backend::typed_identifier> parameters;
     225        16241 :   std::vector<Backend::typed_identifier> results;
     226              : 
     227              :   // we can only return unit-type if its not the C ABI because it will expect
     228              :   // void
     229        16241 :   auto hir_type = type.get_return_type ()->destructure ();
     230        16241 :   bool return_is_unit = hir_type->is_unit ();
     231        16241 :   bool is_c_abi = type.get_abi () == ABI::C;
     232        16241 :   bool should_be_void = is_c_abi && return_is_unit;
     233        16241 :   if (!should_be_void)
     234              :     {
     235        15210 :       auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode);
     236        15210 :       location_t return_type_locus
     237        15210 :         = ctx->get_mappings ().lookup_location (hir_type->get_ref ());
     238        15210 :       results.emplace_back ("_", ret, return_type_locus);
     239              :     }
     240              : 
     241        32434 :   for (auto &param_pair : type.get_params ())
     242              :     {
     243        16193 :       auto param_tyty = param_pair.get_type ();
     244        16193 :       auto compiled_param_type
     245        16193 :         = TyTyResolveCompile::compile (ctx, param_tyty, trait_object_mode);
     246              : 
     247        16193 :       parameters.emplace_back (param_pair.get_pattern ().to_string (),
     248              :                                compiled_param_type,
     249        32386 :                                ctx->get_mappings ().lookup_location (
     250              :                                  param_tyty->get_ref ()));
     251              :     }
     252              : 
     253        16241 :   if (!type.is_variadic ())
     254        15417 :     translated = Backend::function_type (receiver, parameters, results, NULL,
     255        15417 :                                          type.get_ident ().locus);
     256              :   else
     257          824 :     translated
     258          824 :       = Backend::function_type_variadic (receiver, parameters, results, NULL,
     259          824 :                                          type.get_ident ().locus);
     260        16241 : }
     261              : 
     262              : void
     263           94 : TyTyResolveCompile::visit (const TyTy::FnPtr &type)
     264              : {
     265           94 :   tree result_type = TyTyResolveCompile::compile (ctx, type.get_return_type ());
     266              : 
     267           94 :   std::vector<tree> parameters;
     268              : 
     269           94 :   auto &params = type.get_params ();
     270          168 :   for (auto &p : params)
     271              :     {
     272           74 :       tree pty = TyTyResolveCompile::compile (ctx, p.get_tyty ());
     273           74 :       parameters.push_back (pty);
     274              :     }
     275              : 
     276           94 :   translated = Backend::function_ptr_type (result_type, parameters,
     277           94 :                                            type.get_ident ().locus);
     278           94 : }
     279              : 
     280              : void
     281        20623 : TyTyResolveCompile::visit (const TyTy::ADTType &type)
     282              : {
     283        20623 :   tree type_record = error_mark_node;
     284        20623 :   if (!type.is_enum ())
     285              :     {
     286        14255 :       rust_assert (type.number_of_variants () == 1);
     287              : 
     288        14255 :       TyTy::VariantDef &variant = *type.get_variants ().at (0);
     289        14255 :       std::vector<Backend::typed_identifier> fields;
     290        40200 :       for (size_t i = 0; i < variant.num_fields (); i++)
     291              :         {
     292        25945 :           const TyTy::StructFieldType *field = variant.get_field_at_index (i);
     293        25945 :           tree compiled_field_ty
     294        25945 :             = TyTyResolveCompile::compile (ctx, field->get_field_type ());
     295              : 
     296        25945 :           fields.emplace_back (field->get_name (), compiled_field_ty,
     297        51890 :                                ctx->get_mappings ().lookup_location (
     298              :                                  type.get_ty_ref ()));
     299              :         }
     300              : 
     301        14255 :       type_record = type.is_union () ? Backend::union_type (fields, false)
     302        14055 :                                      : Backend::struct_type (fields, false);
     303        14255 :     }
     304              :   else
     305              :     {
     306              :       // see:
     307              :       // https://github.com/bminor/binutils-gdb/blob/527b8861cd472385fa9160a91dd6d65a25c41987/gdb/dwarf2/read.c#L9010-L9241
     308              :       //
     309              :       // enums are actually a big union so for example the rust enum:
     310              :       //
     311              :       // enum AnEnum {
     312              :       //   A,
     313              :       //   B,
     314              :       //   C (char),
     315              :       //   D { x: i64, y: i64 },
     316              :       // }
     317              :       //
     318              :       // we actually turn this into
     319              :       //
     320              :       // union {
     321              :       //   struct A { int RUST$ENUM$DISR; }; <- this is a data-less variant
     322              :       //   struct B { int RUST$ENUM$DISR; }; <- this is a data-less variant
     323              :       //   struct C { int RUST$ENUM$DISR; char __0; };
     324              :       //   struct D { int RUST$ENUM$DISR; i64 x; i64 y; };
     325              :       // }
     326              :       //
     327              :       // Ada, qual_union_types might still work for this but I am not 100% sure.
     328              :       // I ran into some issues lets reuse our normal union and ask Ada people
     329              :       // about it.
     330              :       //
     331              :       // I think the above is actually wrong and it should actually be this
     332              :       //
     333              :       // struct {
     334              :       //     int RUST$ENUM$DISR; // take into account the repr for this TODO
     335              :       //     union {
     336              :       //         // Variant A
     337              :       //         struct {
     338              :       //             // No additional fields
     339              :       //         } A;
     340              : 
     341              :       //         // Variant B
     342              :       //         struct {
     343              :       //             // No additional fields
     344              :       //         } B;
     345              : 
     346              :       //         // Variant C
     347              :       //         struct {
     348              :       //             char c;
     349              :       //         } C;
     350              : 
     351              :       //         // Variant D
     352              :       //         struct {
     353              :       //             int64_t x;
     354              :       //             int64_t y;
     355              :       //         } D;
     356              :       //     } payload; // The union of all variant data
     357              :       // };
     358              : 
     359         6368 :       std::vector<tree> variant_records;
     360        22442 :       for (auto &variant : type.get_variants ())
     361              :         {
     362        16074 :           std::vector<Backend::typed_identifier> fields;
     363        22092 :           for (size_t i = 0; i < variant->num_fields (); i++)
     364              :             {
     365         6018 :               const TyTy::StructFieldType *field
     366         6018 :                 = variant->get_field_at_index (i);
     367         6018 :               tree compiled_field_ty
     368         6018 :                 = TyTyResolveCompile::compile (ctx, field->get_field_type ());
     369              : 
     370         6018 :               std::string field_name = field->get_name ();
     371         6018 :               if (variant->get_variant_type ()
     372              :                   == TyTy::VariantDef::VariantType::TUPLE)
     373         4513 :                 field_name = "__" + field->get_name ();
     374              : 
     375        12036 :               fields.emplace_back (field_name, compiled_field_ty,
     376         6018 :                                    ctx->get_mappings ().lookup_location (
     377              :                                      type.get_ty_ref ()));
     378         6018 :             }
     379              : 
     380        16074 :           tree variant_record = Backend::struct_type (fields);
     381        16074 :           tree named_variant_record
     382        16074 :             = Backend::named_type (variant->get_ident ().path.get (),
     383        32148 :                                    variant_record, variant->get_ident ().locus);
     384              : 
     385              :           // add them to the list
     386        16074 :           variant_records.push_back (named_variant_record);
     387        16074 :         }
     388              : 
     389              :       // now we need to make the actual union, but first we need to make
     390              :       // named_type TYPE_DECL's out of the variants
     391              : 
     392         6368 :       size_t i = 0;
     393         6368 :       std::vector<Backend::typed_identifier> enum_fields;
     394        22442 :       for (auto &variant_record : variant_records)
     395              :         {
     396        16074 :           TyTy::VariantDef *variant = type.get_variants ().at (i++);
     397        16074 :           std::string implicit_variant_name = variant->get_identifier ();
     398              : 
     399        32148 :           enum_fields.emplace_back (implicit_variant_name, variant_record,
     400        16074 :                                     ctx->get_mappings ().lookup_location (
     401              :                                       type.get_ty_ref ()));
     402        16074 :         }
     403              : 
     404              :       //
     405         6368 :       location_t locus = ctx->get_mappings ().lookup_location (type.get_ref ());
     406              : 
     407              :       // finally make the union or the enum
     408         6368 :       tree variants_union = Backend::union_type (enum_fields, false);
     409         6368 :       layout_type (variants_union);
     410         6368 :       tree named_union_record
     411         6368 :         = Backend::named_type ("payload", variants_union, locus);
     412              : 
     413              :       // create the overall struct
     414         6368 :       tree enumeral_type = TyTyResolveCompile::get_implicit_enumeral_node_type (
     415         6368 :         type.get_repr_options ().repr);
     416         6368 :       Backend::typed_identifier discrim (RUST_ENUM_DISR_FIELD_NAME,
     417         6368 :                                          enumeral_type, locus);
     418         6368 :       Backend::typed_identifier variants_union_field ("payload",
     419              :                                                       named_union_record,
     420         6368 :                                                       locus);
     421              : 
     422         6368 :       std::vector<Backend::typed_identifier> fields
     423         6368 :         = {discrim, variants_union_field};
     424         6368 :       type_record = Backend::struct_type (fields, false);
     425         6368 :     }
     426              : 
     427              :   // Handle repr options
     428              :   // TODO: "packed" should only narrow type alignment and "align" should only
     429              :   // widen it. Do we need to check and enforce this here, or is it taken care of
     430              :   // later on in the gcc middle-end?
     431        20623 :   TyTy::ADTType::ReprOptions repr = type.get_repr_options ();
     432        20623 :   if (repr.pack)
     433              :     {
     434           10 :       TYPE_PACKED (type_record) = 1;
     435           10 :       if (repr.pack > 1)
     436              :         {
     437            5 :           SET_TYPE_ALIGN (type_record, repr.pack * 8);
     438            5 :           TYPE_USER_ALIGN (type_record) = 1;
     439              :         }
     440              :     }
     441        20613 :   else if (repr.align)
     442              :     {
     443           10 :       SET_TYPE_ALIGN (type_record, repr.align * 8);
     444           10 :       TYPE_USER_ALIGN (type_record) = 1;
     445              :     }
     446        20623 :   layout_type (type_record);
     447              : 
     448        20623 :   std::string named_struct_str
     449        20623 :     = type.get_ident ().path.get () + type.subst_as_string ();
     450        20623 :   translated = Backend::named_type (named_struct_str, type_record,
     451        20623 :                                     type.get_ident ().locus);
     452        20623 : }
     453              : 
     454              : void
     455        17030 : TyTyResolveCompile::visit (const TyTy::TupleType &type)
     456              : {
     457        17030 :   if (type.num_fields () == 0)
     458              :     {
     459        15203 :       translated = get_unit_type (ctx);
     460        15203 :       return;
     461              :     }
     462              : 
     463              :   // create implicit struct
     464         1827 :   std::vector<Backend::typed_identifier> fields;
     465         5659 :   for (size_t i = 0; i < type.num_fields (); i++)
     466              :     {
     467         3832 :       TyTy::BaseType *field = type.get_field (i);
     468         3832 :       tree compiled_field_ty = TyTyResolveCompile::compile (ctx, field);
     469              : 
     470              :       // rustc uses the convention __N, where N is an integer, to
     471              :       // name the fields of a tuple.  We follow this as well,
     472              :       // because this is used by GDB.  One further reason to prefer
     473              :       // this, rather than simply emitting the integer, is that this
     474              :       // approach makes it simpler to use a C-only debugger, or
     475              :       // GDB's C mode, when debugging Rust.
     476         3832 :       fields.emplace_back ("__" + std::to_string (i), compiled_field_ty,
     477         7664 :                            ctx->get_mappings ().lookup_location (
     478              :                              type.get_ty_ref ()));
     479              :     }
     480              : 
     481         1827 :   tree struct_type_record = Backend::struct_type (fields);
     482         1827 :   translated = Backend::named_type (type.get_name (), struct_type_record,
     483         1827 :                                     type.get_ident ().locus);
     484         1827 : }
     485              : 
     486              : void
     487         4092 : TyTyResolveCompile::visit (const TyTy::ArrayType &type)
     488              : {
     489         4092 :   tree element_type
     490         4092 :     = TyTyResolveCompile::compile (ctx, type.get_element_type ());
     491         4092 :   auto const_capacity = type.get_capacity ();
     492              : 
     493              :   // Check if capacity is a const type
     494         4092 :   if (const_capacity->get_kind () != TyTy::TypeKind::CONST)
     495              :     {
     496            0 :       rust_error_at (type.get_locus (), "array capacity is not a const type");
     497            0 :       translated = error_mark_node;
     498            0 :       return;
     499              :     }
     500              : 
     501         4092 :   auto *capacity_const = const_capacity->as_const_type ();
     502              : 
     503         4092 :   rust_assert (capacity_const->const_kind ()
     504              :                == TyTy::BaseConstType::ConstKind::Value);
     505         4092 :   auto &capacity_value = *static_cast<TyTy::ConstValueType *> (capacity_const);
     506         4092 :   auto folded_capacity_expr = capacity_value.get_value ();
     507              : 
     508              :   // build_index_type takes the maximum index, which is one less than
     509              :   // the length.
     510         4092 :   tree index_type_tree = build_index_type (
     511              :     fold_build2 (MINUS_EXPR, sizetype, folded_capacity_expr, size_one_node));
     512              : 
     513         4092 :   translated = build_array_type (element_type, index_type_tree, false);
     514              : }
     515              : 
     516              : void
     517          102 : TyTyResolveCompile::visit (const TyTy::SliceType &type)
     518              : {
     519          102 :   tree type_record = create_slice_type_record (type);
     520              : 
     521          102 :   std::string named_struct_str
     522          204 :     = std::string ("[") + type.get_element_type ()->get_name () + "]";
     523          102 :   translated = Backend::named_type (named_struct_str, type_record,
     524          102 :                                     type.get_ident ().locus);
     525          102 : }
     526              : 
     527              : void
     528        10048 : TyTyResolveCompile::visit (const TyTy::BoolType &)
     529              : {
     530        10048 :   translated
     531        10048 :     = Backend::named_type ("bool", boolean_type_node, BUILTINS_LOCATION);
     532        10048 : }
     533              : 
     534              : void
     535        72436 : TyTyResolveCompile::visit (const TyTy::IntType &type)
     536              : {
     537        72436 :   switch (type.get_int_kind ())
     538              :     {
     539         8913 :     case TyTy::IntType::I8:
     540         8913 :       translated = Backend::named_type ("i8", Backend::integer_type (false, 8),
     541              :                                         BUILTINS_LOCATION);
     542         8913 :       return;
     543              : 
     544         4963 :     case TyTy::IntType::I16:
     545         4963 :       translated
     546         4963 :         = Backend::named_type ("i16", Backend::integer_type (false, 16),
     547              :                                BUILTINS_LOCATION);
     548         4963 :       return;
     549              : 
     550        48433 :     case TyTy::IntType::I32:
     551        48433 :       translated
     552        48433 :         = Backend::named_type ("i32", Backend::integer_type (false, 32),
     553              :                                BUILTINS_LOCATION);
     554        48433 :       return;
     555              : 
     556         5130 :     case TyTy::IntType::I64:
     557         5130 :       translated
     558         5130 :         = Backend::named_type ("i64", Backend::integer_type (false, 64),
     559              :                                BUILTINS_LOCATION);
     560         5130 :       return;
     561              : 
     562         4997 :     case TyTy::IntType::I128:
     563         4997 :       translated
     564         4997 :         = Backend::named_type ("i128", Backend::integer_type (false, 128),
     565              :                                BUILTINS_LOCATION);
     566         4997 :       return;
     567              :     }
     568              : }
     569              : 
     570              : void
     571        52282 : TyTyResolveCompile::visit (const TyTy::UintType &type)
     572              : {
     573        52282 :   switch (type.get_uint_kind ())
     574              :     {
     575        13708 :     case TyTy::UintType::U8:
     576        13708 :       translated = Backend::named_type ("u8", Backend::integer_type (true, 8),
     577              :                                         BUILTINS_LOCATION);
     578        13708 :       return;
     579              : 
     580         8122 :     case TyTy::UintType::U16:
     581         8122 :       translated = Backend::named_type ("u16", Backend::integer_type (true, 16),
     582              :                                         BUILTINS_LOCATION);
     583         8122 :       return;
     584              : 
     585        12809 :     case TyTy::UintType::U32:
     586        12809 :       translated = Backend::named_type ("u32", Backend::integer_type (true, 32),
     587              :                                         BUILTINS_LOCATION);
     588        12809 :       return;
     589              : 
     590        12910 :     case TyTy::UintType::U64:
     591        12910 :       translated = Backend::named_type ("u64", Backend::integer_type (true, 64),
     592              :                                         BUILTINS_LOCATION);
     593        12910 :       return;
     594              : 
     595         4733 :     case TyTy::UintType::U128:
     596         4733 :       translated
     597         4733 :         = Backend::named_type ("u128", Backend::integer_type (true, 128),
     598              :                                BUILTINS_LOCATION);
     599         4733 :       return;
     600              :     }
     601              : }
     602              : 
     603              : void
     604        14431 : TyTyResolveCompile::visit (const TyTy::FloatType &type)
     605              : {
     606        14431 :   switch (type.get_float_kind ())
     607              :     {
     608         7008 :     case TyTy::FloatType::F32:
     609         7008 :       translated = Backend::named_type ("f32", Backend::float_type (32),
     610              :                                         BUILTINS_LOCATION);
     611         7008 :       return;
     612              : 
     613         7423 :     case TyTy::FloatType::F64:
     614         7423 :       translated = Backend::named_type ("f64", Backend::float_type (64),
     615              :                                         BUILTINS_LOCATION);
     616         7423 :       return;
     617              :     }
     618              : }
     619              : 
     620              : void
     621        33943 : TyTyResolveCompile::visit (const TyTy::USizeType &)
     622              : {
     623        33943 :   translated
     624        33943 :     = Backend::named_type ("usize",
     625              :                            Backend::integer_type (true,
     626              :                                                   Backend::get_pointer_size ()),
     627              :                            BUILTINS_LOCATION);
     628        33943 : }
     629              : 
     630              : void
     631        18271 : TyTyResolveCompile::visit (const TyTy::ISizeType &)
     632              : {
     633        18271 :   translated
     634        18271 :     = Backend::named_type ("isize",
     635              :                            Backend::integer_type (false,
     636              :                                                   Backend::get_pointer_size ()),
     637              :                            BUILTINS_LOCATION);
     638        18271 : }
     639              : 
     640              : void
     641         5228 : TyTyResolveCompile::visit (const TyTy::CharType &)
     642              : {
     643         5228 :   translated
     644         5228 :     = Backend::named_type ("char", Backend::wchar_type (), BUILTINS_LOCATION);
     645         5228 : }
     646              : 
     647              : void
     648        18126 : TyTyResolveCompile::visit (const TyTy::ReferenceType &type)
     649              : {
     650        18126 :   const TyTy::SliceType *slice = nullptr;
     651        18126 :   const TyTy::StrType *str = nullptr;
     652        18126 :   const TyTy::DynamicObjectType *dyn = nullptr;
     653        18126 :   if (type.is_dyn_slice_type (&slice))
     654              :     {
     655          609 :       tree type_record = create_slice_type_record (*slice);
     656          609 :       std::string dyn_slice_type_str
     657         1827 :         = std::string (type.is_mutable () ? "&mut " : "&") + "["
     658         1827 :           + slice->get_element_type ()->get_name () + "]";
     659              : 
     660          609 :       translated = Backend::named_type (dyn_slice_type_str, type_record,
     661              :                                         slice->get_locus ());
     662              : 
     663          609 :       return;
     664          609 :     }
     665        17517 :   else if (type.is_dyn_str_type (&str))
     666              :     {
     667         4049 :       tree type_record = create_str_type_record (*str);
     668         4049 :       std::string dyn_str_type_str
     669        12147 :         = std::string (type.is_mutable () ? "&mut " : "&") + "str";
     670              : 
     671         4049 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     672              :                                         str->get_locus ());
     673              : 
     674         4049 :       return;
     675         4049 :     }
     676        13468 :   else if (type.is_dyn_obj_type (&dyn))
     677              :     {
     678          549 :       tree type_record = create_dyn_obj_record (*dyn);
     679          549 :       std::string dyn_str_type_str
     680         1098 :         = std::string (type.is_mutable () ? "&mut " : "& ") + dyn->get_name ();
     681              : 
     682          549 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     683              :                                         dyn->get_locus ());
     684              : 
     685          549 :       return;
     686          549 :     }
     687              : 
     688        12919 :   tree base_compiled_type
     689        12919 :     = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
     690        12919 :   if (type.is_mutable ())
     691              :     {
     692         1108 :       translated = Backend::reference_type (base_compiled_type);
     693              :     }
     694              :   else
     695              :     {
     696        11811 :       auto base = Backend::immutable_type (base_compiled_type);
     697        11811 :       translated = Backend::reference_type (base);
     698              :     }
     699              : }
     700              : 
     701              : void
     702        10179 : TyTyResolveCompile::visit (const TyTy::PointerType &type)
     703              : {
     704        10179 :   const TyTy::SliceType *slice = nullptr;
     705        10179 :   const TyTy::StrType *str = nullptr;
     706        10179 :   const TyTy::DynamicObjectType *dyn = nullptr;
     707        10179 :   if (type.is_dyn_slice_type (&slice))
     708              :     {
     709          533 :       tree type_record = create_slice_type_record (*slice);
     710          533 :       std::string dyn_slice_type_str
     711         1543 :         = std::string (type.is_mutable () ? "*mut " : "*const ") + "["
     712         1599 :           + slice->get_element_type ()->get_name () + "]";
     713              : 
     714          533 :       translated = Backend::named_type (dyn_slice_type_str, type_record,
     715              :                                         slice->get_locus ());
     716              : 
     717          533 :       return;
     718          533 :     }
     719         9646 :   else if (type.is_dyn_str_type (&str))
     720              :     {
     721         2582 :       tree type_record = create_str_type_record (*str);
     722         2582 :       std::string dyn_str_type_str
     723         7746 :         = std::string (type.is_mutable () ? "*mut " : "*const ") + "str";
     724              : 
     725         2582 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     726              :                                         str->get_locus ());
     727              : 
     728         2582 :       return;
     729         2582 :     }
     730         7064 :   else if (type.is_dyn_obj_type (&dyn))
     731              :     {
     732            0 :       tree type_record = create_dyn_obj_record (*dyn);
     733            0 :       std::string dyn_str_type_str
     734            0 :         = std::string (type.is_mutable () ? "*mut " : "*const ")
     735            0 :           + dyn->get_name ();
     736              : 
     737            0 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     738              :                                         dyn->get_locus ());
     739              : 
     740            0 :       return;
     741            0 :     }
     742              : 
     743         7064 :   tree base_compiled_type
     744         7064 :     = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
     745         7064 :   if (type.is_mutable ())
     746              :     {
     747         1681 :       translated = Backend::pointer_type (base_compiled_type);
     748              :     }
     749              :   else
     750              :     {
     751         5383 :       auto base = Backend::immutable_type (base_compiled_type);
     752         5383 :       translated = Backend::pointer_type (base);
     753              :     }
     754              : }
     755              : 
     756              : void
     757         4301 : TyTyResolveCompile::visit (const TyTy::StrType &type)
     758              : {
     759         4301 :   tree raw_str = create_str_type_record (type);
     760         4301 :   translated = Backend::named_type ("str", raw_str, BUILTINS_LOCATION);
     761         4301 : }
     762              : 
     763              : void
     764         4561 : TyTyResolveCompile::visit (const TyTy::NeverType &)
     765              : {
     766         4561 :   translated = get_unit_type (ctx);
     767         4561 : }
     768              : 
     769              : void
     770            0 : TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type)
     771              : {
     772            0 :   if (trait_object_mode)
     773              :     {
     774            0 :       translated = Backend::integer_type (true, Backend::get_pointer_size ());
     775            0 :       return;
     776              :     }
     777              : 
     778            0 :   tree type_record = create_dyn_obj_record (type);
     779            0 :   translated = Backend::named_type (type.get_name (), type_record,
     780            0 :                                     type.get_ident ().locus);
     781              : }
     782              : 
     783              : void
     784            0 : TyTyResolveCompile::visit (const TyTy::OpaqueType &type)
     785              : {
     786            0 :   rust_assert (type.can_resolve ());
     787            0 :   auto underlying = type.resolve ();
     788            0 :   translated = TyTyResolveCompile::compile (ctx, underlying, trait_object_mode);
     789            0 : }
     790              : 
     791              : tree
     792          549 : TyTyResolveCompile::create_dyn_obj_record (const TyTy::DynamicObjectType &type)
     793              : {
     794              :   // create implicit struct
     795          549 :   auto items = type.get_object_items ();
     796          549 :   std::vector<Backend::typed_identifier> fields;
     797              : 
     798          549 :   tree uint = Backend::integer_type (true, Backend::get_pointer_size ());
     799          549 :   tree uintptr_ty = build_pointer_type (uint);
     800              : 
     801         1098 :   fields.emplace_back ("pointer", uintptr_ty,
     802          549 :                        ctx->get_mappings ().lookup_location (
     803              :                          type.get_ty_ref ()));
     804              : 
     805          549 :   tree vtable_size = build_int_cst (size_type_node, items.size ());
     806          549 :   tree vtable_type = Backend::array_type (uintptr_ty, vtable_size);
     807         1098 :   fields.emplace_back ("vtable", vtable_type,
     808          549 :                        ctx->get_mappings ().lookup_location (
     809              :                          type.get_ty_ref ()));
     810              : 
     811          549 :   tree record = Backend::struct_type (fields);
     812          549 :   RS_DST_FLAG (record) = 1;
     813          549 :   TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
     814              : 
     815          549 :   return record;
     816          549 : }
     817              : 
     818              : tree
     819         1244 : TyTyResolveCompile::create_slice_type_record (const TyTy::SliceType &type)
     820              : {
     821              :   // lookup usize
     822         1244 :   TyTy::BaseType *usize = nullptr;
     823         1244 :   bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
     824         1244 :   rust_assert (ok);
     825              : 
     826         1244 :   tree element_type
     827         1244 :     = TyTyResolveCompile::compile (ctx, type.get_element_type ());
     828         1244 :   tree data_field_ty = build_pointer_type (element_type);
     829         1244 :   Backend::typed_identifier data_field ("data", data_field_ty,
     830         1244 :                                         type.get_locus ());
     831              : 
     832         1244 :   tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
     833         1244 :   Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
     834              : 
     835         1244 :   tree record = Backend::struct_type ({data_field, len_field});
     836         1244 :   RS_DST_FLAG (record) = 1;
     837         1244 :   TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
     838              : 
     839         1244 :   return record;
     840              : }
     841              : 
     842              : tree
     843        10932 : TyTyResolveCompile::create_str_type_record (const TyTy::StrType &type)
     844              : {
     845              :   // lookup usize
     846        10932 :   TyTy::BaseType *usize = nullptr;
     847        10932 :   bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
     848        10932 :   rust_assert (ok);
     849              : 
     850        10932 :   tree char_ptr = build_pointer_type (char_type_node);
     851        10932 :   tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
     852              : 
     853        10932 :   tree element_type = const_char_type;
     854        10932 :   tree data_field_ty = build_pointer_type (element_type);
     855        10932 :   Backend::typed_identifier data_field ("data", data_field_ty,
     856        10932 :                                         type.get_locus ());
     857              : 
     858        10932 :   tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
     859        10932 :   Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
     860              : 
     861        10932 :   tree record = Backend::struct_type ({data_field, len_field});
     862        10932 :   RS_DST_FLAG (record) = 1;
     863        10932 :   TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
     864              : 
     865        10932 :   return record;
     866              : }
     867              : 
     868              : } // namespace Compile
     869              : } // 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.