LCOV - code coverage report
Current view: top level - gcc/rust/checks/errors/borrowck - rust-bir-builder.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 95.3 % 86 82
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 7 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_BIR_BUILDER_H
      20              : #define RUST_BIR_BUILDER_H
      21              : 
      22              : #include "rust-bir-builder-internal.h"
      23              : #include "rust-bir-builder-pattern.h"
      24              : #include "rust-bir-builder-expr-stmt.h"
      25              : 
      26              : namespace Rust {
      27              : namespace BIR {
      28              : 
      29              : /** Top-level builder, which compiles a HIR function into a BIR function. */
      30           36 : class Builder final : public AbstractBuilder
      31              : {
      32              :   std::vector<std::pair<FreeRegion, FreeRegion>> universal_region_bounds;
      33              : 
      34              : public:
      35           36 :   explicit Builder (BuilderContext &ctx) : AbstractBuilder (ctx) {}
      36              : 
      37           36 :   Function build (HIR::Function &function)
      38              :   {
      39           36 :     rust_debug ("BIR::Builder::build function={%s}",
      40              :                 function.get_function_name ().as_string ().c_str ());
      41              : 
      42           36 :     auto fn_ty = lookup_type (function)->as<TyTy::FnType> ();
      43              : 
      44           36 :     handle_lifetime_params (fn_ty->get_num_lifetime_params ());
      45           36 :     handle_lifetime_param_constraints (fn_ty->get_region_constraints ());
      46              : 
      47           36 :     handle_return (fn_ty);
      48              : 
      49           54 :     for (auto &param : function.get_function_params ())
      50           18 :       handle_param (param);
      51              : 
      52           36 :     handle_body (function.get_definition ());
      53           36 :     auto region_hir_map
      54           36 :       = map_region_to_hir (function.get_generic_params (), ctx.fn_free_regions);
      55              : 
      56           36 :     return Function{
      57           36 :       std::move (ctx.place_db),
      58           36 :       std::move (ctx.arguments),
      59           36 :       std::move (ctx.basic_blocks),
      60           36 :       std::move (ctx.fn_free_regions),
      61           36 :       std::move (universal_region_bounds),
      62              :       std::move (region_hir_map),
      63           36 :       function.get_locus (),
      64           36 :     };
      65           36 :   }
      66              : 
      67              : private:
      68              :   /** Instantiate `num_lifetime_params` free regions. */
      69           36 :   void handle_lifetime_params (size_t num_lifetime_params)
      70              :   {
      71           36 :     FreeRegions regions;
      72           47 :     for (size_t i = 0; i < num_lifetime_params; i++)
      73              :       {
      74           11 :         regions.push_back (ctx.place_db.get_next_free_region ());
      75              :       }
      76              : 
      77           36 :     rust_debug ("\tctx.fn_free_region={%s}",
      78              :                 ctx.fn_free_regions.to_string ().c_str ());
      79           36 :     ctx.fn_free_regions = regions;
      80           36 :   }
      81              : 
      82           36 :   void handle_lifetime_param_constraints (
      83              :     const TyTy::RegionConstraints &region_constraints)
      84              :   {
      85           36 :     rust_debug ("\thandle_lifetime_param_constraints");
      86              : 
      87           38 :     for (auto bound : region_constraints.region_region)
      88              :       {
      89            2 :         rust_assert (bound.first.is_early_bound ());
      90            2 :         rust_assert (bound.second.is_early_bound ());
      91              : 
      92            2 :         universal_region_bounds.emplace_back (
      93              :           ctx.fn_free_regions[bound.first.get_index ()],
      94            2 :           ctx.fn_free_regions[bound.second.get_index ()]);
      95              : 
      96            2 :         auto last_bound = universal_region_bounds.back ();
      97            2 :         rust_debug ("\t\t %lu: %lu", (unsigned long) last_bound.first.value,
      98              :                     (unsigned long) last_bound.second.value);
      99              :       }
     100              : 
     101              :     // TODO: handle type_region constraints
     102           36 :   }
     103              : 
     104           36 :   void handle_return (TyTy::FnType *fn_ty)
     105              :   {
     106           36 :     TyTy::BaseType *return_ty = fn_ty->get_return_type ();
     107              : 
     108           36 :     PlaceId return_place = ctx.place_db.add_temporary (return_ty);
     109           36 :     rust_assert (return_place == RETURN_VALUE_PLACE);
     110              : 
     111              :     // Set return place to use functions regions, not the fresh ones.
     112           36 :     ctx.place_db[return_place].regions
     113           72 :       = bind_regions (Resolver::TypeCheckContext::get ()
     114           36 :                         ->get_variance_analysis_ctx ()
     115           72 :                         .query_type_regions (fn_ty->get_return_type ()),
     116           72 :                       ctx.fn_free_regions);
     117           36 :   }
     118              : 
     119           18 :   void handle_param (HIR::FunctionParam &param)
     120              :   {
     121           18 :     auto param_type = lookup_type (param.get_param_name ());
     122              : 
     123           18 :     auto &pattern = param.get_param_name ();
     124           18 :     if (pattern.get_pattern_type () == HIR::Pattern::IDENTIFIER
     125           18 :         && !static_cast<HIR::IdentifierPattern &> (pattern).get_is_ref ())
     126              :       {
     127              :         // Avoid useless temporary variable for parameter to look like MIR.
     128           18 :         translated = declare_variable (pattern.get_mappings ());
     129           18 :         ctx.arguments.push_back (translated);
     130              :       }
     131              :     else
     132              :       {
     133            0 :         translated = ctx.place_db.add_temporary (param_type);
     134            0 :         ctx.arguments.push_back (translated);
     135            0 :         PatternBindingBuilder (ctx, translated, tl::nullopt)
     136            0 :           .go (param.get_param_name ());
     137              :       }
     138              : 
     139              :     // Set parameter place to use functions regions, not the fresh ones.
     140           18 :     ctx.place_db[translated].regions
     141           36 :       = bind_regions (Resolver::TypeCheckContext::get ()
     142           18 :                         ->get_variance_analysis_ctx ()
     143           36 :                         .query_type_regions (param_type),
     144           36 :                       ctx.fn_free_regions);
     145           18 :   }
     146              : 
     147           36 :   void handle_body (HIR::BlockExpr &body)
     148              :   {
     149           36 :     translated = ExprStmtBuilder (ctx).build (body, RETURN_VALUE_PLACE);
     150           36 :     if (!ctx.get_current_bb ().is_terminated ())
     151              :       {
     152           36 :         if (ctx.place_db[RETURN_VALUE_PLACE].tyty->is_unit ())
     153              :           {
     154           28 :             push_assignment (RETURN_VALUE_PLACE,
     155           28 :                              ctx.place_db.get_constant (
     156           28 :                                ctx.place_db[RETURN_VALUE_PLACE].tyty),
     157              :                              body.get_end_locus ());
     158              :           }
     159           36 :         auto return_location = body.has_expr ()
     160           36 :                                  ? body.get_final_expr ().get_locus ()
     161           26 :                                  : body.get_end_locus ();
     162           36 :         push_return (return_location);
     163              :       }
     164           36 :   }
     165              : 
     166              :   // Maps named lifetime parameters to their respective HIR node
     167              :   const std::unordered_map<Polonius::Origin, HIR::LifetimeParam *>
     168           36 :   map_region_to_hir (
     169              :     const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
     170              :     const FreeRegions &regions)
     171              :   {
     172           36 :     std::unordered_map<Polonius::Origin, HIR::LifetimeParam *> result;
     173           36 :     size_t region_index = 0;
     174           47 :     for (auto &generic_param : generic_params)
     175              :       {
     176           11 :         if (generic_param->get_kind ()
     177              :             == HIR::GenericParam::GenericKind::LIFETIME)
     178              :           {
     179           11 :             result[regions[region_index++].value]
     180           22 :               = static_cast<HIR::LifetimeParam *> (generic_param.get ());
     181              :           }
     182              :       }
     183           36 :     return result;
     184              :   }
     185              : };
     186              : 
     187              : } // namespace BIR
     188              : } // namespace Rust
     189              : 
     190              : #endif // RUST_BIR_BUILDER_H
        

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.