LCOV - code coverage report
Current view: top level - gcc/rust/backend - rust-compile-var-decl.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.7 % 164 152
Test Date: 2026-09-19 16:22:48 Functions: 53.8 % 13 7
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              : #ifndef RUST_COMPILE_VAR_DECL
      20              : #define RUST_COMPILE_VAR_DECL
      21              : 
      22              : #include "rust-compile-base.h"
      23              : #include "rust-compile-type.h"
      24              : #include "rust-hir-visitor.h"
      25              : 
      26              : namespace Rust {
      27              : namespace Compile {
      28              : 
      29        27438 : class CompileVarDecl : public HIRCompileBase, public HIR::HIRPatternVisitor
      30              : {
      31              :   using HIR::HIRPatternVisitor::visit;
      32              : 
      33              : public:
      34        13719 :   static std::vector<Bvariable *> compile (tree fndecl, tree translated_type,
      35              :                                            HIR::Pattern *pattern, Context *ctx)
      36              :   {
      37        13719 :     CompileVarDecl compiler (ctx, fndecl, translated_type);
      38        13719 :     pattern->accept_vis (compiler);
      39        13719 :     return compiler.vars;
      40        13719 :   }
      41              : 
      42        12993 :   void visit (HIR::IdentifierPattern &pattern) override
      43              :   {
      44        12993 :     if (!pattern.is_mut ())
      45        12026 :       translated_type = Backend::immutable_type (translated_type);
      46              : 
      47        12993 :     tree bind_tree = ctx->peek_enclosing_scope ();
      48        25986 :     std::string identifier = pattern.get_identifier ().as_string ();
      49        12993 :     tree decl
      50        12993 :       = build_decl (pattern.get_locus (), VAR_DECL,
      51              :                     Backend::get_identifier_node (identifier), translated_type);
      52        12993 :     DECL_CONTEXT (decl) = fndecl;
      53              : 
      54        12993 :     gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
      55        12993 :     tree block_tree = BIND_EXPR_BLOCK (bind_tree);
      56        12993 :     gcc_assert (TREE_CODE (block_tree) == BLOCK);
      57        12993 :     DECL_CHAIN (decl) = BLOCK_VARS (block_tree);
      58        12993 :     BLOCK_VARS (block_tree) = decl;
      59        12993 :     BIND_EXPR_VARS (bind_tree) = BLOCK_VARS (block_tree);
      60              : 
      61        12993 :     rust_preserve_from_gc (decl);
      62        12993 :     Bvariable *var = new Bvariable (decl);
      63              : 
      64        12993 :     HirId stmt_id = pattern.get_mappings ().get_hirid ();
      65        12993 :     ctx->insert_var_decl (stmt_id, var);
      66              : 
      67        12993 :     vars.push_back (var);
      68              : 
      69        12993 :     if (pattern.has_subpattern ())
      70              :       {
      71           16 :         auto subpattern_vars
      72              :           = CompileVarDecl::compile (fndecl, translated_type,
      73           16 :                                      &pattern.get_subpattern (), ctx);
      74           16 :         vars.insert (vars.end (), subpattern_vars.begin (),
      75              :                      subpattern_vars.end ());
      76           16 :       }
      77        12993 :   }
      78              : 
      79          375 :   void visit (HIR::TuplePattern &pattern) override
      80              :   {
      81          375 :     rust_assert (TREE_CODE (translated_type) == RECORD_TYPE);
      82          375 :     switch (pattern.get_items ().get_item_type ())
      83              :       {
      84          370 :       case HIR::TuplePatternItems::ItemType::NO_REST:
      85          370 :         {
      86          370 :           auto &items_no_rest = static_cast<HIR::TuplePatternItemsNoRest &> (
      87          370 :             pattern.get_items ());
      88              : 
      89          370 :           tree field = TYPE_FIELDS (translated_type);
      90         1122 :           for (auto &sub : items_no_rest.get_patterns ())
      91              :             {
      92          752 :               gcc_assert (field != NULL_TREE);
      93          752 :               tree sub_ty = TREE_TYPE (field);
      94          752 :               CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx);
      95          752 :               field = DECL_CHAIN (field);
      96              :             }
      97              :         }
      98              :         break;
      99              : 
     100            5 :       case HIR::TuplePatternItems::ItemType::HAS_REST:
     101            5 :         {
     102            5 :           auto &items_has_rest = static_cast<HIR::TuplePatternItemsHasRest &> (
     103            5 :             pattern.get_items ());
     104              : 
     105              :           // count total fields in translated_type
     106            5 :           size_t total_fields = 0;
     107           17 :           for (tree t = TYPE_FIELDS (translated_type); t; t = DECL_CHAIN (t))
     108              :             {
     109           12 :               total_fields++;
     110              :             }
     111              : 
     112              :           // process lower patterns
     113            5 :           tree field = TYPE_FIELDS (translated_type);
     114            8 :           for (auto &sub : items_has_rest.get_lower_patterns ())
     115              :             {
     116            3 :               gcc_assert (field != NULL_TREE);
     117            3 :               tree sub_ty = TREE_TYPE (field);
     118            3 :               CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx);
     119            3 :               field = DECL_CHAIN (field);
     120              :             }
     121              : 
     122              :           // process upper patterns
     123            5 :           if (!items_has_rest.get_upper_patterns ().empty ())
     124              :             {
     125            3 :               size_t upper_start
     126            3 :                 = total_fields - items_has_rest.get_upper_patterns ().size ();
     127            3 :               field = TYPE_FIELDS (translated_type);
     128            8 :               for (size_t i = 0; i < upper_start; i++)
     129              :                 {
     130            5 :                   field = DECL_CHAIN (field);
     131            5 :                   gcc_assert (field != NULL_TREE);
     132              :                 }
     133              : 
     134            6 :               for (auto &sub : items_has_rest.get_upper_patterns ())
     135              :                 {
     136            3 :                   gcc_assert (field != NULL_TREE);
     137            3 :                   tree sub_ty = TREE_TYPE (field);
     138            3 :                   CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx);
     139            3 :                   field = DECL_CHAIN (field);
     140              :                 }
     141              :             }
     142              :         }
     143              :         break;
     144              : 
     145              :       default:
     146              :         break;
     147              :       }
     148          375 :   }
     149              : 
     150           32 :   void visit (HIR::StructPattern &pattern) override
     151              :   {
     152              :     // lookup the type
     153           32 :     TyTy::BaseType *lookup = nullptr;
     154           32 :     bool ok = ctx->get_tyctx ()->lookup_type (
     155           32 :       pattern.get_path ().get_mappings ().get_hirid (), &lookup);
     156           32 :     rust_assert (ok);
     157              : 
     158           32 :     rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
     159           32 :     TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
     160              : 
     161              :     // only structs and single-variant enums are irrefutable, this check should
     162              :     // already be handled by type check
     163           32 :     rust_assert (adt->number_of_variants () == 1);
     164              : 
     165           32 :     int variant_index = 0;
     166           32 :     TyTy::VariantDef *variant = nullptr;
     167           32 :     if (adt->is_enum ())
     168              :       {
     169              :         // lookup the variant
     170            0 :         HirId variant_id = UNKNOWN_HIRID;
     171            0 :         bool ok = ctx->get_tyctx ()->lookup_variant_definition (
     172            0 :           pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
     173            0 :         rust_assert (ok);
     174              : 
     175            0 :         ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
     176            0 :         rust_assert (ok);
     177              :       }
     178              :     else
     179              :       {
     180           32 :         variant = adt->get_variants ().at (0);
     181              :       }
     182              : 
     183           32 :     auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
     184           65 :     for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
     185              :       {
     186           33 :         switch (field->get_item_type ())
     187              :           {
     188            8 :           case HIR::StructPatternField::ItemType::TUPLE_PAT:
     189            8 :             {
     190            8 :               HIR::StructPatternFieldTuplePat &tuple_pat
     191            8 :                 = static_cast<HIR::StructPatternFieldTuplePat &> (*field);
     192            8 :               TyTy::StructFieldType *field_ty = nullptr;
     193            8 :               ok = variant->lookup_field (std::to_string (
     194              :                                             tuple_pat.get_index ()),
     195              :                                           &field_ty, nullptr);
     196            8 :               rust_assert (ok);
     197            8 :               tree sub_ty
     198            8 :                 = TyTyResolveCompile::compile (ctx,
     199            8 :                                                field_ty->get_field_type ());
     200            8 :               auto sub_vars
     201              :                 = CompileVarDecl::compile (fndecl, sub_ty,
     202            8 :                                            &tuple_pat.get_tuple_pattern (),
     203            8 :                                            ctx);
     204            8 :               vars.insert (vars.end (), sub_vars.begin (), sub_vars.end ());
     205            8 :             }
     206            8 :             break;
     207           17 :           case HIR::StructPatternField::ItemType::IDENT_PAT:
     208           17 :             {
     209           17 :               HIR::StructPatternFieldIdentPat &ident_pat
     210           17 :                 = static_cast<HIR::StructPatternFieldIdentPat &> (*field);
     211           17 :               TyTy::StructFieldType *field_ty = nullptr;
     212           17 :               ok = variant->lookup_field (
     213           17 :                 ident_pat.get_identifier ().as_string (), &field_ty, nullptr);
     214           17 :               rust_assert (ok);
     215           17 :               tree sub_ty
     216           17 :                 = TyTyResolveCompile::compile (ctx,
     217           17 :                                                field_ty->get_field_type ());
     218           17 :               auto sub_vars
     219              :                 = CompileVarDecl::compile (fndecl, sub_ty,
     220           17 :                                            &ident_pat.get_pattern (), ctx);
     221           17 :               vars.insert (vars.end (), sub_vars.begin (), sub_vars.end ());
     222           17 :             }
     223           17 :             break;
     224            8 :           case HIR::StructPatternField::ItemType::IDENT:
     225            8 :             {
     226            8 :               HIR::StructPatternFieldIdent &ident
     227            8 :                 = static_cast<HIR::StructPatternFieldIdent &> (*field);
     228            8 :               TyTy::StructFieldType *field_ty = nullptr;
     229            8 :               ok = variant->lookup_field (ident.get_identifier ().as_string (),
     230              :                                           &field_ty, nullptr);
     231            8 :               rust_assert (ok);
     232            8 :               tree sub_ty
     233            8 :                 = TyTyResolveCompile::compile (ctx,
     234            8 :                                                field_ty->get_field_type ());
     235              : 
     236              :               // code below is pretty much copied from
     237              :               // visit(IdentifierPattern) above
     238            8 :               if (!ident.is_mut ())
     239            8 :                 sub_ty = Backend::immutable_type (sub_ty);
     240              : 
     241            8 :               tree bind_tree = ctx->peek_enclosing_scope ();
     242           16 :               std::string identifier = ident.get_identifier ().as_string ();
     243            8 :               tree decl = build_decl (ident.get_locus (), VAR_DECL,
     244              :                                       Backend::get_identifier_node (identifier),
     245              :                                       sub_ty);
     246            8 :               DECL_CONTEXT (decl) = fndecl;
     247            8 :               gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
     248            8 :               tree block_tree = BIND_EXPR_BLOCK (bind_tree);
     249            8 :               gcc_assert (TREE_CODE (block_tree) == BLOCK);
     250            8 :               DECL_CHAIN (decl) = BLOCK_VARS (block_tree);
     251            8 :               BLOCK_VARS (block_tree) = decl;
     252            8 :               BIND_EXPR_VARS (bind_tree) = BLOCK_VARS (block_tree);
     253            8 :               rust_preserve_from_gc (decl);
     254            8 :               Bvariable *var = new Bvariable (decl);
     255              : 
     256            8 :               HirId stmt_id = ident.get_mappings ().get_hirid ();
     257            8 :               ctx->insert_var_decl (stmt_id, var);
     258            8 :               vars.push_back (var);
     259            8 :             }
     260            8 :             break;
     261              :           }
     262              :       }
     263           32 :   }
     264              : 
     265              :   // Empty visit for unused Pattern HIR nodes.
     266            0 :   void visit (HIR::AltPattern &) override {}
     267            0 :   void visit (HIR::LiteralPattern &) override {}
     268            0 :   void visit (HIR::PathInExpression &) override {}
     269            0 :   void visit (HIR::QualifiedPathInExpression &) override {}
     270            0 :   void visit (HIR::RangePattern &) override {}
     271            3 :   void visit (HIR::ReferencePattern &) override {}
     272            0 :   void visit (HIR::SlicePattern &) override {}
     273            1 :   void visit (HIR::TupleStructPattern &) override {}
     274          315 :   void visit (HIR::WildcardPattern &) override {}
     275              : 
     276              : private:
     277        13719 :   CompileVarDecl (Context *ctx, tree fndecl, tree translated_type)
     278        13719 :     : HIRCompileBase (ctx), fndecl (fndecl), translated_type (translated_type)
     279              :   {}
     280              : 
     281              :   tree fndecl;
     282              :   tree translated_type;
     283              : 
     284              :   std::vector<Bvariable *> vars;
     285              : };
     286              : 
     287              : } // namespace Compile
     288              : } // namespace Rust
     289              : 
     290              : #endif // RUST_COMPILE_VAR_DECL
        

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.