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: 2025-11-22 14:42:49 Functions: 72.2 % 36 26
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : // Copyright (C) 2020-2025 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                 :      386661 : TyTyResolveCompile::TyTyResolveCompile (Context *ctx, bool trait_object_mode)
      33                 :      386661 :   : ctx (ctx), trait_object_mode (trait_object_mode),
      34                 :      386661 :     translated (error_mark_node)
      35                 :      386661 : {}
      36                 :             : 
      37                 :             : tree
      38                 :      386661 : TyTyResolveCompile::compile (Context *ctx, const TyTy::BaseType *ty,
      39                 :             :                              bool trait_object_mode)
      40                 :             : {
      41                 :      386661 :   TyTyResolveCompile compiler (ctx, trait_object_mode);
      42                 :      386661 :   const TyTy::BaseType *destructured = ty->destructure ();
      43                 :      386661 :   destructured->accept_vis (compiler);
      44                 :             : 
      45                 :      386661 :   if (compiler.translated != error_mark_node
      46                 :      386661 :       && TYPE_NAME (compiler.translated) != NULL)
      47                 :             :     {
      48                 :             :       // canonicalize the type
      49                 :      346318 :       compiler.translated = ctx->insert_compiled_type (compiler.translated);
      50                 :             :     }
      51                 :             : 
      52                 :      386661 :   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                 :        6362 : 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                 :        6362 :   return compile (ctx, repr);
      81                 :             : }
      82                 :             : 
      83                 :             : tree
      84                 :       34659 : TyTyResolveCompile::get_unit_type (Context *ctx)
      85                 :             : {
      86                 :       34659 :   static tree unit_type;
      87                 :       34659 :   if (unit_type == nullptr)
      88                 :             :     {
      89                 :        4260 :       auto cn = ctx->get_mappings ().get_current_crate ();
      90                 :        4260 :       auto &c = ctx->get_mappings ().get_ast_crate (cn);
      91                 :        4260 :       location_t locus = BUILTINS_LOCATION;
      92                 :        4260 :       if (c.items.size () > 0)
      93                 :             :         {
      94                 :        4258 :           auto &item = c.items[0];
      95                 :        4258 :           locus = item->get_locus ();
      96                 :             :         }
      97                 :             : 
      98                 :        4260 :       auto unit_type_node = Backend::struct_type ({});
      99                 :        4260 :       unit_type = Backend::named_type ("()", unit_type_node, locus);
     100                 :             :     }
     101                 :       34659 :   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                 :       16183 : TyTyResolveCompile::visit (const TyTy::FnType &type)
     222                 :             : {
     223                 :       16183 :   Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION);
     224                 :       16183 :   std::vector<Backend::typed_identifier> parameters;
     225                 :       16183 :   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                 :       16183 :   auto hir_type = type.get_return_type ()->destructure ();
     230                 :       16183 :   bool return_is_unit = hir_type->is_unit ();
     231                 :       16183 :   bool is_c_abi = type.get_abi () == ABI::C;
     232                 :       16183 :   bool should_be_void = is_c_abi && return_is_unit;
     233                 :       16183 :   if (!should_be_void)
     234                 :             :     {
     235                 :       15153 :       auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode);
     236                 :       15153 :       location_t return_type_locus
     237                 :       15153 :         = ctx->get_mappings ().lookup_location (hir_type->get_ref ());
     238                 :       15153 :       results.emplace_back ("_", ret, return_type_locus);
     239                 :             :     }
     240                 :             : 
     241                 :       32367 :   for (auto &param_pair : type.get_params ())
     242                 :             :     {
     243                 :       16184 :       auto param_tyty = param_pair.get_type ();
     244                 :       16184 :       auto compiled_param_type
     245                 :       16184 :         = TyTyResolveCompile::compile (ctx, param_tyty, trait_object_mode);
     246                 :             : 
     247                 :       16184 :       parameters.emplace_back (param_pair.get_pattern ().as_string (),
     248                 :             :                                compiled_param_type,
     249                 :       32368 :                                ctx->get_mappings ().lookup_location (
     250                 :             :                                  param_tyty->get_ref ()));
     251                 :             :     }
     252                 :             : 
     253                 :       16183 :   if (!type.is_variadic ())
     254                 :       15360 :     translated = Backend::function_type (receiver, parameters, results, NULL,
     255                 :       15360 :                                          type.get_ident ().locus);
     256                 :             :   else
     257                 :         823 :     translated
     258                 :         823 :       = Backend::function_type_variadic (receiver, parameters, results, NULL,
     259                 :         823 :                                          type.get_ident ().locus);
     260                 :       16183 : }
     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                 :       20581 : TyTyResolveCompile::visit (const TyTy::ADTType &type)
     282                 :             : {
     283                 :       20581 :   tree type_record = error_mark_node;
     284                 :       20581 :   if (!type.is_enum ())
     285                 :             :     {
     286                 :       14219 :       rust_assert (type.number_of_variants () == 1);
     287                 :             : 
     288                 :       14219 :       TyTy::VariantDef &variant = *type.get_variants ().at (0);
     289                 :       14219 :       std::vector<Backend::typed_identifier> fields;
     290                 :       40110 :       for (size_t i = 0; i < variant.num_fields (); i++)
     291                 :             :         {
     292                 :       25891 :           const TyTy::StructFieldType *field = variant.get_field_at_index (i);
     293                 :       25891 :           tree compiled_field_ty
     294                 :       25891 :             = TyTyResolveCompile::compile (ctx, field->get_field_type ());
     295                 :             : 
     296                 :       25891 :           fields.emplace_back (field->get_name (), compiled_field_ty,
     297                 :       51782 :                                ctx->get_mappings ().lookup_location (
     298                 :             :                                  type.get_ty_ref ()));
     299                 :             :         }
     300                 :             : 
     301                 :       14219 :       type_record = type.is_union () ? Backend::union_type (fields, false)
     302                 :       14019 :                                      : Backend::struct_type (fields, false);
     303                 :       14219 :     }
     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                 :        6362 :       std::vector<tree> variant_records;
     360                 :       22422 :       for (auto &variant : type.get_variants ())
     361                 :             :         {
     362                 :       16060 :           std::vector<Backend::typed_identifier> fields;
     363                 :       22075 :           for (size_t i = 0; i < variant->num_fields (); i++)
     364                 :             :             {
     365                 :        6015 :               const TyTy::StructFieldType *field
     366                 :        6015 :                 = variant->get_field_at_index (i);
     367                 :        6015 :               tree compiled_field_ty
     368                 :        6015 :                 = TyTyResolveCompile::compile (ctx, field->get_field_type ());
     369                 :             : 
     370                 :        6015 :               std::string field_name = field->get_name ();
     371                 :        6015 :               if (variant->get_variant_type ()
     372                 :             :                   == TyTy::VariantDef::VariantType::TUPLE)
     373                 :        4512 :                 field_name = "__" + field->get_name ();
     374                 :             : 
     375                 :       12030 :               fields.emplace_back (field_name, compiled_field_ty,
     376                 :        6015 :                                    ctx->get_mappings ().lookup_location (
     377                 :             :                                      type.get_ty_ref ()));
     378                 :        6015 :             }
     379                 :             : 
     380                 :       16060 :           tree variant_record = Backend::struct_type (fields);
     381                 :       16060 :           tree named_variant_record
     382                 :       16060 :             = Backend::named_type (variant->get_ident ().path.get (),
     383                 :       32120 :                                    variant_record, variant->get_ident ().locus);
     384                 :             : 
     385                 :             :           // add them to the list
     386                 :       16060 :           variant_records.push_back (named_variant_record);
     387                 :       16060 :         }
     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                 :        6362 :       size_t i = 0;
     393                 :        6362 :       std::vector<Backend::typed_identifier> enum_fields;
     394                 :       22422 :       for (auto &variant_record : variant_records)
     395                 :             :         {
     396                 :       16060 :           TyTy::VariantDef *variant = type.get_variants ().at (i++);
     397                 :       16060 :           std::string implicit_variant_name = variant->get_identifier ();
     398                 :             : 
     399                 :       32120 :           enum_fields.emplace_back (implicit_variant_name, variant_record,
     400                 :       16060 :                                     ctx->get_mappings ().lookup_location (
     401                 :             :                                       type.get_ty_ref ()));
     402                 :       16060 :         }
     403                 :             : 
     404                 :             :       //
     405                 :        6362 :       location_t locus = ctx->get_mappings ().lookup_location (type.get_ref ());
     406                 :             : 
     407                 :             :       // finally make the union or the enum
     408                 :        6362 :       tree variants_union = Backend::union_type (enum_fields, false);
     409                 :        6362 :       layout_type (variants_union);
     410                 :        6362 :       tree named_union_record
     411                 :        6362 :         = Backend::named_type ("payload", variants_union, locus);
     412                 :             : 
     413                 :             :       // create the overall struct
     414                 :        6362 :       tree enumeral_type = TyTyResolveCompile::get_implicit_enumeral_node_type (
     415                 :        6362 :         type.get_repr_options ().repr);
     416                 :        6362 :       Backend::typed_identifier discrim (RUST_ENUM_DISR_FIELD_NAME,
     417                 :        6362 :                                          enumeral_type, locus);
     418                 :        6362 :       Backend::typed_identifier variants_union_field ("payload",
     419                 :             :                                                       named_union_record,
     420                 :        6362 :                                                       locus);
     421                 :             : 
     422                 :        6362 :       std::vector<Backend::typed_identifier> fields
     423                 :        6362 :         = {discrim, variants_union_field};
     424                 :        6362 :       type_record = Backend::struct_type (fields, false);
     425                 :        6362 :     }
     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                 :       20581 :   TyTy::ADTType::ReprOptions repr = type.get_repr_options ();
     432                 :       20581 :   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                 :       20571 :   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                 :       20581 :   layout_type (type_record);
     447                 :             : 
     448                 :       20581 :   std::string named_struct_str
     449                 :       20581 :     = type.get_ident ().path.get () + type.subst_as_string ();
     450                 :       20581 :   translated = Backend::named_type (named_struct_str, type_record,
     451                 :       20581 :                                     type.get_ident ().locus);
     452                 :       20581 : }
     453                 :             : 
     454                 :             : void
     455                 :       21139 : TyTyResolveCompile::visit (const TyTy::TupleType &type)
     456                 :             : {
     457                 :       21139 :   if (type.num_fields () == 0)
     458                 :             :     {
     459                 :       19320 :       translated = get_unit_type (ctx);
     460                 :       19320 :       return;
     461                 :             :     }
     462                 :             : 
     463                 :             :   // create implicit struct
     464                 :        1819 :   std::vector<Backend::typed_identifier> fields;
     465                 :        5635 :   for (size_t i = 0; i < type.num_fields (); i++)
     466                 :             :     {
     467                 :        3816 :       TyTy::BaseType *field = type.get_field (i);
     468                 :        3816 :       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                 :        3816 :       fields.emplace_back ("__" + std::to_string (i), compiled_field_ty,
     477                 :        7632 :                            ctx->get_mappings ().lookup_location (
     478                 :             :                              type.get_ty_ref ()));
     479                 :             :     }
     480                 :             : 
     481                 :        1819 :   tree struct_type_record = Backend::struct_type (fields);
     482                 :        1819 :   translated = Backend::named_type (type.get_name (), struct_type_record,
     483                 :        1819 :                                     type.get_ident ().locus);
     484                 :        1819 : }
     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                 :       14267 : TyTyResolveCompile::visit (const TyTy::BoolType &)
     529                 :             : {
     530                 :       14267 :   translated
     531                 :       14267 :     = Backend::named_type ("bool", boolean_type_node, BUILTINS_LOCATION);
     532                 :       14267 : }
     533                 :             : 
     534                 :             : void
     535                 :       93294 : TyTyResolveCompile::visit (const TyTy::IntType &type)
     536                 :             : {
     537                 :       93294 :   switch (type.get_int_kind ())
     538                 :             :     {
     539                 :       13127 :     case TyTy::IntType::I8:
     540                 :       13127 :       translated = Backend::named_type ("i8", Backend::integer_type (false, 8),
     541                 :             :                                         BUILTINS_LOCATION);
     542                 :       13127 :       return;
     543                 :             : 
     544                 :        9182 :     case TyTy::IntType::I16:
     545                 :        9182 :       translated
     546                 :        9182 :         = Backend::named_type ("i16", Backend::integer_type (false, 16),
     547                 :             :                                BUILTINS_LOCATION);
     548                 :        9182 :       return;
     549                 :             : 
     550                 :       52420 :     case TyTy::IntType::I32:
     551                 :       52420 :       translated
     552                 :       52420 :         = Backend::named_type ("i32", Backend::integer_type (false, 32),
     553                 :             :                                BUILTINS_LOCATION);
     554                 :       52420 :       return;
     555                 :             : 
     556                 :        9349 :     case TyTy::IntType::I64:
     557                 :        9349 :       translated
     558                 :        9349 :         = Backend::named_type ("i64", Backend::integer_type (false, 64),
     559                 :             :                                BUILTINS_LOCATION);
     560                 :        9349 :       return;
     561                 :             : 
     562                 :        9216 :     case TyTy::IntType::I128:
     563                 :        9216 :       translated
     564                 :        9216 :         = Backend::named_type ("i128", Backend::integer_type (false, 128),
     565                 :             :                                BUILTINS_LOCATION);
     566                 :        9216 :       return;
     567                 :             :     }
     568                 :             : }
     569                 :             : 
     570                 :             : void
     571                 :       73358 : TyTyResolveCompile::visit (const TyTy::UintType &type)
     572                 :             : {
     573                 :       73358 :   switch (type.get_uint_kind ())
     574                 :             :     {
     575                 :       17922 :     case TyTy::UintType::U8:
     576                 :       17922 :       translated = Backend::named_type ("u8", Backend::integer_type (true, 8),
     577                 :             :                                         BUILTINS_LOCATION);
     578                 :       17922 :       return;
     579                 :             : 
     580                 :       12341 :     case TyTy::UintType::U16:
     581                 :       12341 :       translated = Backend::named_type ("u16", Backend::integer_type (true, 16),
     582                 :             :                                         BUILTINS_LOCATION);
     583                 :       12341 :       return;
     584                 :             : 
     585                 :       17014 :     case TyTy::UintType::U32:
     586                 :       17014 :       translated = Backend::named_type ("u32", Backend::integer_type (true, 32),
     587                 :             :                                         BUILTINS_LOCATION);
     588                 :       17014 :       return;
     589                 :             : 
     590                 :       17129 :     case TyTy::UintType::U64:
     591                 :       17129 :       translated = Backend::named_type ("u64", Backend::integer_type (true, 64),
     592                 :             :                                         BUILTINS_LOCATION);
     593                 :       17129 :       return;
     594                 :             : 
     595                 :        8952 :     case TyTy::UintType::U128:
     596                 :        8952 :       translated
     597                 :        8952 :         = Backend::named_type ("u128", Backend::integer_type (true, 128),
     598                 :             :                                BUILTINS_LOCATION);
     599                 :        8952 :       return;
     600                 :             :     }
     601                 :             : }
     602                 :             : 
     603                 :             : void
     604                 :       22861 : TyTyResolveCompile::visit (const TyTy::FloatType &type)
     605                 :             : {
     606                 :       22861 :   switch (type.get_float_kind ())
     607                 :             :     {
     608                 :       11219 :     case TyTy::FloatType::F32:
     609                 :       11219 :       translated = Backend::named_type ("f32", Backend::float_type (32),
     610                 :             :                                         BUILTINS_LOCATION);
     611                 :       11219 :       return;
     612                 :             : 
     613                 :       11642 :     case TyTy::FloatType::F64:
     614                 :       11642 :       translated = Backend::named_type ("f64", Backend::float_type (64),
     615                 :             :                                         BUILTINS_LOCATION);
     616                 :       11642 :       return;
     617                 :             :     }
     618                 :             : }
     619                 :             : 
     620                 :             : void
     621                 :       42367 : TyTyResolveCompile::visit (const TyTy::USizeType &)
     622                 :             : {
     623                 :       42367 :   translated
     624                 :       42367 :     = Backend::named_type ("usize",
     625                 :             :                            Backend::integer_type (true,
     626                 :             :                                                   Backend::get_pointer_size ()),
     627                 :             :                            BUILTINS_LOCATION);
     628                 :       42367 : }
     629                 :             : 
     630                 :             : void
     631                 :       22482 : TyTyResolveCompile::visit (const TyTy::ISizeType &)
     632                 :             : {
     633                 :       22482 :   translated
     634                 :       22482 :     = Backend::named_type ("isize",
     635                 :             :                            Backend::integer_type (false,
     636                 :             :                                                   Backend::get_pointer_size ()),
     637                 :             :                            BUILTINS_LOCATION);
     638                 :       22482 : }
     639                 :             : 
     640                 :             : void
     641                 :        9447 : TyTyResolveCompile::visit (const TyTy::CharType &)
     642                 :             : {
     643                 :        9447 :   translated
     644                 :        9447 :     = Backend::named_type ("char", Backend::wchar_type (), BUILTINS_LOCATION);
     645                 :        9447 : }
     646                 :             : 
     647                 :             : void
     648                 :       18118 : TyTyResolveCompile::visit (const TyTy::ReferenceType &type)
     649                 :             : {
     650                 :       18118 :   const TyTy::SliceType *slice = nullptr;
     651                 :       18118 :   const TyTy::StrType *str = nullptr;
     652                 :       18118 :   const TyTy::DynamicObjectType *dyn = nullptr;
     653                 :       18118 :   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                 :       17509 :   else if (type.is_dyn_str_type (&str))
     666                 :             :     {
     667                 :        4045 :       tree type_record = create_str_type_record (*str);
     668                 :        4045 :       std::string dyn_str_type_str
     669                 :       12135 :         = std::string (type.is_mutable () ? "&mut " : "&") + "str";
     670                 :             : 
     671                 :        4045 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     672                 :             :                                         str->get_locus ());
     673                 :             : 
     674                 :        4045 :       return;
     675                 :        4045 :     }
     676                 :       13464 :   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                 :       12915 :   tree base_compiled_type
     689                 :       12915 :     = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
     690                 :       12915 :   if (type.is_mutable ())
     691                 :             :     {
     692                 :        1108 :       translated = Backend::reference_type (base_compiled_type);
     693                 :             :     }
     694                 :             :   else
     695                 :             :     {
     696                 :       11807 :       auto base = Backend::immutable_type (base_compiled_type);
     697                 :       11807 :       translated = Backend::reference_type (base);
     698                 :             :     }
     699                 :             : }
     700                 :             : 
     701                 :             : void
     702                 :       10170 : TyTyResolveCompile::visit (const TyTy::PointerType &type)
     703                 :             : {
     704                 :       10170 :   const TyTy::SliceType *slice = nullptr;
     705                 :       10170 :   const TyTy::StrType *str = nullptr;
     706                 :       10170 :   const TyTy::DynamicObjectType *dyn = nullptr;
     707                 :       10170 :   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                 :        9637 :   else if (type.is_dyn_str_type (&str))
     720                 :             :     {
     721                 :        2578 :       tree type_record = create_str_type_record (*str);
     722                 :        2578 :       std::string dyn_str_type_str
     723                 :        7734 :         = std::string (type.is_mutable () ? "*mut " : "*const ") + "str";
     724                 :             : 
     725                 :        2578 :       translated = Backend::named_type (dyn_str_type_str, type_record,
     726                 :             :                                         str->get_locus ());
     727                 :             : 
     728                 :        2578 :       return;
     729                 :        2578 :     }
     730                 :        7059 :   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                 :        7059 :   tree base_compiled_type
     744                 :        7059 :     = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
     745                 :        7059 :   if (type.is_mutable ())
     746                 :             :     {
     747                 :        1681 :       translated = Backend::pointer_type (base_compiled_type);
     748                 :             :     }
     749                 :             :   else
     750                 :             :     {
     751                 :        5378 :       auto base = Backend::immutable_type (base_compiled_type);
     752                 :        5378 :       translated = Backend::pointer_type (base);
     753                 :             :     }
     754                 :             : }
     755                 :             : 
     756                 :             : void
     757                 :        8520 : TyTyResolveCompile::visit (const TyTy::StrType &type)
     758                 :             : {
     759                 :        8520 :   tree raw_str = create_str_type_record (type);
     760                 :        8520 :   translated = Backend::named_type ("str", raw_str, BUILTINS_LOCATION);
     761                 :        8520 : }
     762                 :             : 
     763                 :             : void
     764                 :        8775 : TyTyResolveCompile::visit (const TyTy::NeverType &)
     765                 :             : {
     766                 :        8775 :   translated = get_unit_type (ctx);
     767                 :        8775 : }
     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                 :       15143 : TyTyResolveCompile::create_str_type_record (const TyTy::StrType &type)
     844                 :             : {
     845                 :             :   // lookup usize
     846                 :       15143 :   TyTy::BaseType *usize = nullptr;
     847                 :       15143 :   bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
     848                 :       15143 :   rust_assert (ok);
     849                 :             : 
     850                 :       15143 :   tree char_ptr = build_pointer_type (char_type_node);
     851                 :       15143 :   tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
     852                 :             : 
     853                 :       15143 :   tree element_type = const_char_type;
     854                 :       15143 :   tree data_field_ty = build_pointer_type (element_type);
     855                 :       15143 :   Backend::typed_identifier data_field ("data", data_field_ty,
     856                 :       15143 :                                         type.get_locus ());
     857                 :             : 
     858                 :       15143 :   tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
     859                 :       15143 :   Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
     860                 :             : 
     861                 :       15143 :   tree record = Backend::struct_type ({data_field, len_field});
     862                 :       15143 :   RS_DST_FLAG (record) = 1;
     863                 :       15143 :   TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
     864                 :             : 
     865                 :       15143 :   return record;
     866                 :             : }
     867                 :             : 
     868                 :             : } // namespace Compile
     869                 :             : } // namespace Rust
        

Generated by: LCOV version 2.1-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.