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: 2025-06-21 16:26:05 Functions: 100.0 % 7 7
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                 :             : #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.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.