LCOV - code coverage report
Current view: top level - gcc/rust/hir - rust-ast-lower-expr.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.0 % 721 627
Test Date: 2026-09-19 16:22:48 Functions: 90.5 % 63 57
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #include "rust-ast-lower-expr.h"
      20              : #include "optional.h"
      21              : #include "rust-ast-lower-base.h"
      22              : #include "rust-ast-lower-block.h"
      23              : #include "rust-ast-lower-struct-field-expr.h"
      24              : #include "rust-ast-lower-pattern.h"
      25              : #include "rust-ast-lower-type.h"
      26              : #include "rust-ast.h"
      27              : #include "rust-builtin-ast-nodes.h"
      28              : #include "rust-diagnostics.h"
      29              : #include "rust-hir-map.h"
      30              : #include "rust-system.h"
      31              : #include "tree/rust-hir-expr.h"
      32              : 
      33              : namespace Rust {
      34              : namespace HIR {
      35              : 
      36       133150 : ASTLoweringExpr::ASTLoweringExpr ()
      37       133150 :   : ASTLoweringBase (), translated (nullptr), translated_array_elems (nullptr),
      38       133150 :     terminated (false)
      39       133150 : {}
      40              : 
      41              : HIR::Expr *
      42       133150 : ASTLoweringExpr::translate (AST::Expr &expr, bool *terminated)
      43              : {
      44       133150 :   ASTLoweringExpr resolver;
      45       133150 :   expr.accept_vis (resolver);
      46       133150 :   if (resolver.translated == nullptr)
      47              :     {
      48            0 :       rust_fatal_error (expr.get_locus (), "Failed to lower expr: [%s]",
      49            0 :                         expr.as_string ().c_str ());
      50              :       return nullptr;
      51              :     }
      52              : 
      53       133150 :   resolver.mappings.insert_hir_expr (resolver.translated);
      54       133150 :   resolver.mappings.insert_location (
      55       133150 :     resolver.translated->get_mappings ().get_hirid (), expr.get_locus ());
      56              : 
      57       133150 :   if (terminated != nullptr)
      58        31776 :     *terminated = resolver.terminated;
      59              : 
      60       133150 :   return resolver.translated;
      61       133150 : }
      62              : 
      63              : void
      64          921 : ASTLoweringExpr::visit (AST::TupleIndexExpr &expr)
      65              : {
      66          921 :   HIR::Expr *tuple_expr
      67          921 :     = ASTLoweringExpr::translate (expr.get_tuple_expr (), &terminated);
      68              : 
      69          921 :   auto crate_num = mappings.get_current_crate ();
      70         1842 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
      71          921 :                                  mappings.get_next_hir_id (crate_num),
      72          921 :                                  UNKNOWN_LOCAL_DEFID);
      73              : 
      74          921 :   translated
      75          921 :     = new HIR::TupleIndexExpr (mapping, std::unique_ptr<HIR::Expr> (tuple_expr),
      76          921 :                                expr.get_tuple_index (), expr.get_outer_attrs (),
      77         1842 :                                expr.get_locus ());
      78          921 : }
      79              : 
      80              : void
      81          626 : ASTLoweringExpr::visit (AST::TupleExpr &expr)
      82              : {
      83          626 :   std::vector<std::unique_ptr<HIR::Expr>> tuple_elements;
      84          626 :   tuple_elements.reserve (expr.get_tuple_elems ().size ());
      85              : 
      86         1722 :   for (auto &e : expr.get_tuple_elems ())
      87         1096 :     tuple_elements.emplace_back (ASTLoweringExpr::translate (*e));
      88              : 
      89          626 :   auto crate_num = mappings.get_current_crate ();
      90         1252 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
      91          626 :                                  mappings.get_next_hir_id (crate_num),
      92          626 :                                  UNKNOWN_LOCAL_DEFID);
      93              : 
      94          626 :   translated
      95          626 :     = new HIR::TupleExpr (std::move (mapping), std::move (tuple_elements),
      96         1252 :                           expr.get_inner_attrs (), expr.get_outer_attrs (),
      97          626 :                           expr.get_locus ());
      98          626 : }
      99              : 
     100              : void
     101         1276 : ASTLoweringExpr::visit (AST::IfExpr &expr)
     102              : {
     103         1276 :   translated = ASTLoweringIfBlock::translate (expr, &terminated);
     104         1276 : }
     105              : 
     106              : void
     107          986 : ASTLoweringExpr::visit (AST::IfExprConseqElse &expr)
     108              : {
     109          986 :   translated = ASTLoweringIfBlock::translate (expr, &terminated);
     110          986 : }
     111              : 
     112              : void
     113           17 : ASTLoweringExpr::visit (AST::IfLetExpr &expr)
     114              : {
     115           17 :   translated = ASTLoweringIfLetBlock::translate (expr);
     116           17 : }
     117              : 
     118              : void
     119           11 : ASTLoweringExpr::visit (AST::IfLetExprConseqElse &expr)
     120              : {
     121           11 :   translated = ASTLoweringIfLetBlock::translate (expr);
     122           11 : }
     123              : 
     124              : void
     125         1733 : ASTLoweringExpr::visit (AST::BlockExpr &expr)
     126              : {
     127         1733 :   translated = ASTLoweringBlock::translate (expr, &terminated);
     128         1733 : }
     129              : 
     130              : void
     131          813 : ASTLoweringExpr::visit (AST::AnonConst &expr)
     132              : {
     133          813 :   auto &mappings = Analysis::Mappings::get ();
     134          813 :   auto crate_num = mappings.get_current_crate ();
     135         1626 :   auto mapping = Analysis::NodeMapping (crate_num, expr.get_node_id (),
     136              :                                         mappings.get_next_hir_id (crate_num),
     137          813 :                                         UNKNOWN_LOCAL_DEFID);
     138              : 
     139          813 :   if (expr.is_deferred ())
     140              :     {
     141           13 :       translated = new HIR::AnonConst (std::move (mapping), expr.get_locus ());
     142              :     }
     143              :   else
     144              :     {
     145          800 :       auto inner_expr = ASTLoweringExpr::translate (expr.get_inner_expr ());
     146              : 
     147         1600 :       translated = new HIR::AnonConst (std::move (mapping),
     148          800 :                                        std::unique_ptr<Expr> (inner_expr),
     149          800 :                                        expr.get_locus ());
     150              :     }
     151          813 : }
     152              : 
     153              : void
     154           15 : ASTLoweringExpr::visit (AST::ConstBlock &expr)
     155              : {
     156           15 :   auto inner_expr = ASTLoweringExpr::translate (expr.get_const_expr ());
     157              : 
     158              :   // we know this will always be an `AnonConst`, or we have an issue. Let's
     159              :   // assert just to be sure.
     160           15 :   rust_assert (inner_expr->get_expression_type () == Expr::ExprType::AnonConst);
     161           15 :   auto anon_const = static_cast<AnonConst *> (inner_expr);
     162              : 
     163           15 :   auto &mappings = Analysis::Mappings::get ();
     164           15 :   auto crate_num = mappings.get_current_crate ();
     165           30 :   auto mapping = Analysis::NodeMapping (crate_num, expr.get_node_id (),
     166              :                                         mappings.get_next_hir_id (crate_num),
     167           15 :                                         UNKNOWN_LOCAL_DEFID);
     168              : 
     169           15 :   translated
     170           15 :     = new HIR::ConstBlock (std::move (mapping), std::move (*anon_const),
     171           15 :                            expr.get_locus (), expr.get_outer_attrs ());
     172           15 : }
     173              : 
     174              : void
     175         4000 : ASTLoweringExpr::visit (AST::UnsafeBlockExpr &expr)
     176              : {
     177         4000 :   translated = ASTLoweringBlock::translate (expr, &terminated);
     178         4000 : }
     179              : 
     180              : void
     181        24068 : ASTLoweringExpr::visit (AST::PathInExpression &expr)
     182              : {
     183        24068 :   translated = ASTLowerPathInExpression::translate (expr);
     184        24068 : }
     185              : 
     186              : void
     187          124 : ASTLoweringExpr::visit (AST::QualifiedPathInExpression &expr)
     188              : {
     189          124 :   translated = ASTLowerQualPathInExpression::translate (expr);
     190          124 : }
     191              : 
     192              : void
     193            6 : ASTLoweringExpr::visit (AST::BoxExpr &expr)
     194              : {
     195            6 :   HIR::Expr *box_expr = ASTLoweringExpr::translate (expr.get_boxed_expr ());
     196              : 
     197            6 :   auto crate_num = mappings.get_current_crate ();
     198           12 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     199            6 :                                  mappings.get_next_hir_id (crate_num),
     200            6 :                                  UNKNOWN_LOCAL_DEFID);
     201              : 
     202           12 :   translated = new HIR::BoxExpr (mapping, expr.get_locus (),
     203            6 :                                  std::unique_ptr<HIR::Expr> (box_expr));
     204            6 : }
     205              : 
     206              : void
     207          579 : ASTLoweringExpr::visit (AST::ReturnExpr &expr)
     208              : {
     209          579 :   terminated = true;
     210          579 :   HIR::Expr *return_expr
     211          579 :     = expr.has_returned_expr ()
     212          579 :         ? ASTLoweringExpr::translate (expr.get_returned_expr ())
     213              :         : nullptr;
     214              : 
     215          579 :   auto crate_num = mappings.get_current_crate ();
     216         1158 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     217          579 :                                  mappings.get_next_hir_id (crate_num),
     218          579 :                                  UNKNOWN_LOCAL_DEFID);
     219              : 
     220         1158 :   translated = new HIR::ReturnExpr (mapping, expr.get_locus (),
     221          579 :                                     std::unique_ptr<HIR::Expr> (return_expr));
     222          579 : }
     223              : 
     224              : void
     225        13582 : ASTLoweringExpr::visit (AST::CallExpr &expr)
     226              : {
     227        13582 :   HIR::Expr *func = ASTLoweringExpr::translate (expr.get_function_expr ());
     228              : 
     229        13582 :   auto const &in_params = expr.get_params ();
     230              : 
     231        13582 :   std::vector<std::unique_ptr<HIR::Expr>> params;
     232        13582 :   params.reserve (in_params.size ());
     233              : 
     234        28767 :   for (auto &param : in_params)
     235        15185 :     params.emplace_back (ASTLoweringExpr::translate (*param));
     236              : 
     237        13582 :   auto crate_num = mappings.get_current_crate ();
     238        13582 :   Analysis::NodeMapping mapping (
     239              :     crate_num, UNKNOWN_NODEID /* this can map back to the AST*/,
     240        13582 :     mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID);
     241              : 
     242        13582 :   translated = new HIR::CallExpr (mapping, std::unique_ptr<HIR::Expr> (func),
     243        13582 :                                   std::move (params), expr.get_outer_attrs (),
     244        27164 :                                   expr.get_locus ());
     245        13582 : }
     246              : 
     247              : void
     248         3158 : ASTLoweringExpr::visit (AST::MethodCallExpr &expr)
     249              : {
     250         3158 :   HIR::PathExprSegment method_path
     251         3158 :     = lower_path_expr_seg (expr.get_method_name ());
     252              : 
     253         3158 :   HIR::Expr *receiver = ASTLoweringExpr::translate (expr.get_receiver_expr ());
     254              : 
     255         3158 :   auto const &in_params = expr.get_params ();
     256         3158 :   std::vector<std::unique_ptr<HIR::Expr>> params;
     257         3158 :   params.reserve (in_params.size ());
     258              : 
     259         5306 :   for (auto &param : in_params)
     260         2148 :     params.emplace_back (ASTLoweringExpr::translate (*param));
     261              : 
     262         3158 :   auto crate_num = mappings.get_current_crate ();
     263         6316 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     264         3158 :                                  mappings.get_next_hir_id (crate_num),
     265         3158 :                                  UNKNOWN_LOCAL_DEFID);
     266              : 
     267         3158 :   translated
     268         3158 :     = new HIR::MethodCallExpr (mapping, std::unique_ptr<HIR::Expr> (receiver),
     269              :                                method_path, std::move (params),
     270         6316 :                                expr.get_outer_attrs (), expr.get_locus ());
     271         3158 : }
     272              : 
     273              : void
     274         2546 : ASTLoweringExpr::visit (AST::AssignmentExpr &expr)
     275              : {
     276         2546 :   HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ());
     277         2546 :   HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ());
     278              : 
     279         2546 :   auto crate_num = mappings.get_current_crate ();
     280         5092 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     281         2546 :                                  mappings.get_next_hir_id (crate_num),
     282         2546 :                                  UNKNOWN_LOCAL_DEFID);
     283              : 
     284         2546 :   translated
     285         2546 :     = new HIR::AssignmentExpr (mapping, std::unique_ptr<HIR::Expr> (lhs),
     286         5092 :                                std::unique_ptr<HIR::Expr> (rhs),
     287         2546 :                                expr.get_locus ());
     288         2546 : }
     289              : 
     290              : void
     291        26440 : ASTLoweringExpr::visit (AST::IdentifierExpr &expr)
     292              : {
     293        26440 :   auto crate_num = mappings.get_current_crate ();
     294        52880 :   Analysis::NodeMapping mapping1 (crate_num, expr.get_node_id (),
     295        26440 :                                   mappings.get_next_hir_id (crate_num),
     296        26440 :                                   UNKNOWN_LOCAL_DEFID);
     297        26440 :   Analysis::NodeMapping mapping2 (mapping1);
     298              : 
     299        52880 :   HIR::PathIdentSegment ident_seg (expr.get_ident ().as_string ());
     300        26440 :   HIR::PathExprSegment seg (mapping1, ident_seg, expr.get_locus (),
     301        52880 :                             HIR::GenericArgs::create_empty ());
     302        52880 :   translated = new HIR::PathInExpression (mapping2, {seg}, expr.get_locus (),
     303        52880 :                                           false, expr.get_outer_attrs ());
     304        26440 : }
     305              : 
     306              : void
     307          452 : ASTLoweringExpr::visit (AST::ArrayExpr &expr)
     308              : {
     309          452 :   expr.get_array_elems ()->accept_vis (*this);
     310          452 :   rust_assert (translated_array_elems != nullptr);
     311          452 :   HIR::ArrayElems *elems = translated_array_elems;
     312              : 
     313          452 :   auto crate_num = mappings.get_current_crate ();
     314          904 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     315          452 :                                  mappings.get_next_hir_id (crate_num),
     316          452 :                                  UNKNOWN_LOCAL_DEFID);
     317              : 
     318          452 :   translated
     319          452 :     = new HIR::ArrayExpr (mapping, std::unique_ptr<HIR::ArrayElems> (elems),
     320          904 :                           expr.get_inner_attrs (), expr.get_outer_attrs (),
     321          904 :                           expr.get_locus ());
     322          452 : }
     323              : 
     324              : void
     325          297 : ASTLoweringExpr::visit (AST::ArrayIndexExpr &expr)
     326              : {
     327          297 :   HIR::Expr *array_expr = ASTLoweringExpr::translate (expr.get_array_expr ());
     328          297 :   HIR::Expr *array_index_expr
     329          297 :     = ASTLoweringExpr::translate (expr.get_index_expr ());
     330              : 
     331          297 :   auto crate_num = mappings.get_current_crate ();
     332          594 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     333          297 :                                  mappings.get_next_hir_id (crate_num),
     334          297 :                                  UNKNOWN_LOCAL_DEFID);
     335              : 
     336          297 :   translated
     337          297 :     = new HIR::ArrayIndexExpr (mapping, std::unique_ptr<HIR::Expr> (array_expr),
     338          594 :                                std::unique_ptr<HIR::Expr> (array_index_expr),
     339          594 :                                expr.get_outer_attrs (), expr.get_locus ());
     340          297 : }
     341              : 
     342              : void
     343          319 : ASTLoweringExpr::visit (AST::ArrayElemsValues &elems)
     344              : {
     345          319 :   std::vector<std::unique_ptr<HIR::Expr>> elements;
     346          319 :   elements.reserve (elems.get_values ().size ());
     347              : 
     348         1861 :   for (auto &elem : elems.get_values ())
     349         1542 :     elements.emplace_back (ASTLoweringExpr::translate (*elem));
     350              : 
     351          319 :   auto crate_num = mappings.get_current_crate ();
     352          319 :   Analysis::NodeMapping mapping (mappings.get_current_crate (),
     353              :                                  elems.get_node_id (),
     354          319 :                                  mappings.get_next_hir_id (crate_num),
     355          319 :                                  UNKNOWN_LOCAL_DEFID);
     356              : 
     357          319 :   translated_array_elems
     358          319 :     = new HIR::ArrayElemsValues (mapping, std::move (elements));
     359          319 : }
     360              : 
     361              : void
     362          133 : ASTLoweringExpr::visit (AST::ArrayElemsCopied &elems)
     363              : {
     364          133 :   HIR::Expr *element = ASTLoweringExpr::translate (elems.get_elem_to_copy ());
     365          133 :   HIR::Expr *num_copies = ASTLoweringExpr::translate (elems.get_num_copies ());
     366              : 
     367          133 :   auto crate_num = mappings.get_current_crate ();
     368          133 :   Analysis::NodeMapping mapping (mappings.get_current_crate (),
     369              :                                  elems.get_node_id (),
     370          133 :                                  mappings.get_next_hir_id (crate_num),
     371          133 :                                  UNKNOWN_LOCAL_DEFID);
     372              : 
     373          133 :   translated_array_elems
     374          133 :     = new HIR::ArrayElemsCopied (mapping, std::unique_ptr<HIR::Expr> (element),
     375          266 :                                  std::unique_ptr<HIR::Expr> (num_copies));
     376          133 : }
     377              : 
     378              : void
     379        21364 : ASTLoweringExpr::visit (AST::LiteralExpr &expr)
     380              : {
     381        21364 :   auto crate_num = mappings.get_current_crate ();
     382        42728 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     383        21364 :                                  mappings.get_next_hir_id (crate_num),
     384        21364 :                                  UNKNOWN_LOCAL_DEFID);
     385              : 
     386        21364 :   HIR::Literal l = lower_literal (expr.get_literal ());
     387        21364 :   translated = new HIR::LiteralExpr (mapping, std::move (l), expr.get_locus (),
     388        42728 :                                      expr.get_outer_attrs ());
     389        21364 : }
     390              : 
     391              : void
     392         3721 : ASTLoweringExpr::visit (AST::ArithmeticOrLogicalExpr &expr)
     393              : {
     394         3721 :   HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ());
     395         3721 :   rust_assert (lhs != nullptr);
     396         3721 :   HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ());
     397         3721 :   rust_assert (rhs != nullptr);
     398              : 
     399         3721 :   auto crate_num = mappings.get_current_crate ();
     400         7442 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     401         3721 :                                  mappings.get_next_hir_id (crate_num),
     402         3721 :                                  UNKNOWN_LOCAL_DEFID);
     403              : 
     404         7442 :   translated = new HIR::ArithmeticOrLogicalExpr (
     405         3721 :     mapping, std::unique_ptr<HIR::Expr> (lhs), std::unique_ptr<HIR::Expr> (rhs),
     406         3721 :     expr.get_expr_type (), expr.get_locus ());
     407         3721 : }
     408              : 
     409              : void
     410         3742 : ASTLoweringExpr::visit (AST::ComparisonExpr &expr)
     411              : {
     412         3742 :   HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ());
     413         3742 :   rust_assert (lhs != nullptr);
     414         3742 :   HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ());
     415         3742 :   rust_assert (rhs != nullptr);
     416              : 
     417         3742 :   auto crate_num = mappings.get_current_crate ();
     418         7484 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     419         3742 :                                  mappings.get_next_hir_id (crate_num),
     420         3742 :                                  UNKNOWN_LOCAL_DEFID);
     421              : 
     422         3742 :   translated
     423         3742 :     = new HIR::ComparisonExpr (mapping, std::unique_ptr<HIR::Expr> (lhs),
     424         7484 :                                std::unique_ptr<HIR::Expr> (rhs),
     425         3742 :                                expr.get_expr_type (), expr.get_locus ());
     426         3742 : }
     427              : 
     428              : void
     429          425 : ASTLoweringExpr::visit (AST::LazyBooleanExpr &expr)
     430              : {
     431          425 :   HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ());
     432          425 :   rust_assert (lhs != nullptr);
     433          425 :   HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ());
     434          425 :   rust_assert (rhs != nullptr);
     435              : 
     436          425 :   auto crate_num = mappings.get_current_crate ();
     437          850 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     438          425 :                                  mappings.get_next_hir_id (crate_num),
     439          425 :                                  UNKNOWN_LOCAL_DEFID);
     440              : 
     441          425 :   translated
     442          425 :     = new HIR::LazyBooleanExpr (mapping, std::unique_ptr<HIR::Expr> (lhs),
     443          850 :                                 std::unique_ptr<HIR::Expr> (rhs),
     444          425 :                                 expr.get_expr_type (), expr.get_locus ());
     445          425 : }
     446              : 
     447              : void
     448          707 : ASTLoweringExpr::visit (AST::NegationExpr &expr)
     449              : {
     450          707 :   HIR::Expr *negated_value
     451          707 :     = ASTLoweringExpr::translate (expr.get_negated_expr ());
     452              : 
     453          707 :   auto crate_num = mappings.get_current_crate ();
     454         1414 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     455          707 :                                  mappings.get_next_hir_id (crate_num),
     456          707 :                                  UNKNOWN_LOCAL_DEFID);
     457          707 :   translated
     458          707 :     = new HIR::NegationExpr (mapping,
     459          707 :                              std::unique_ptr<HIR::Expr> (negated_value),
     460          707 :                              expr.get_expr_type (), expr.get_outer_attrs (),
     461         1414 :                              expr.get_locus ());
     462          707 : }
     463              : 
     464              : void
     465         5690 : ASTLoweringExpr::visit (AST::TypeCastExpr &expr)
     466              : {
     467         5690 :   HIR::Expr *expr_to_cast_to
     468         5690 :     = ASTLoweringExpr::translate (expr.get_casted_expr ());
     469         5690 :   HIR::Type *type_to_cast_to
     470         5690 :     = lower_type_no_bounds (expr.get_type_to_cast_to ());
     471              : 
     472         5690 :   auto crate_num = mappings.get_current_crate ();
     473        11380 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     474         5690 :                                  mappings.get_next_hir_id (crate_num),
     475         5690 :                                  UNKNOWN_LOCAL_DEFID);
     476              : 
     477         5690 :   translated
     478         5690 :     = new HIR::TypeCastExpr (mapping,
     479         5690 :                              std::unique_ptr<HIR::Expr> (expr_to_cast_to),
     480        11380 :                              std::unique_ptr<HIR::Type> (type_to_cast_to),
     481         5690 :                              expr.get_locus ());
     482         5690 : }
     483              : 
     484              : void
     485          705 : ASTLoweringExpr::visit (AST::CompoundAssignmentExpr &expr)
     486              : {
     487          705 :   ArithmeticOrLogicalOperator op;
     488          705 :   switch (expr.get_expr_type ())
     489              :     {
     490              :     case CompoundAssignmentOperator::ADD:
     491              :       op = ArithmeticOrLogicalOperator::ADD;
     492              :       break;
     493              :     case CompoundAssignmentOperator::SUBTRACT:
     494              :       op = ArithmeticOrLogicalOperator::SUBTRACT;
     495              :       break;
     496              :     case CompoundAssignmentOperator::MULTIPLY:
     497              :       op = ArithmeticOrLogicalOperator::MULTIPLY;
     498              :       break;
     499              :     case CompoundAssignmentOperator::DIVIDE:
     500              :       op = ArithmeticOrLogicalOperator::DIVIDE;
     501              :       break;
     502              :     case CompoundAssignmentOperator::MODULUS:
     503              :       op = ArithmeticOrLogicalOperator::MODULUS;
     504              :       break;
     505              :     case CompoundAssignmentOperator::BITWISE_AND:
     506              :       op = ArithmeticOrLogicalOperator::BITWISE_AND;
     507              :       break;
     508              :     case CompoundAssignmentOperator::BITWISE_OR:
     509              :       op = ArithmeticOrLogicalOperator::BITWISE_OR;
     510              :       break;
     511              :     case CompoundAssignmentOperator::BITWISE_XOR:
     512              :       op = ArithmeticOrLogicalOperator::BITWISE_XOR;
     513              :       break;
     514              :     case CompoundAssignmentOperator::LEFT_SHIFT:
     515              :       op = ArithmeticOrLogicalOperator::LEFT_SHIFT;
     516              :       break;
     517              :     case CompoundAssignmentOperator::RIGHT_SHIFT:
     518              :       op = ArithmeticOrLogicalOperator::RIGHT_SHIFT;
     519              :       break;
     520            0 :     default:
     521            0 :       rust_unreachable ();
     522              :     }
     523              : 
     524          705 :   HIR::Expr *asignee_expr = ASTLoweringExpr::translate (expr.get_left_expr ());
     525          705 :   HIR::Expr *value = ASTLoweringExpr::translate (expr.get_right_expr ());
     526              : 
     527          705 :   auto crate_num = mappings.get_current_crate ();
     528         1410 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     529          705 :                                  mappings.get_next_hir_id (crate_num),
     530          705 :                                  UNKNOWN_LOCAL_DEFID);
     531              : 
     532         1410 :   translated = new HIR::CompoundAssignmentExpr (
     533          705 :     mapping, std::unique_ptr<HIR::Expr> (asignee_expr),
     534         1410 :     std::unique_ptr<HIR::Expr> (value), op, expr.get_locus ());
     535          705 : }
     536              : 
     537              : void
     538           81 : ASTLoweringExpr::visit (AST::StructExprStruct &struct_expr)
     539              : {
     540           81 :   HIR::PathInExpression *path
     541           81 :     = ASTLowerPathInExpression::translate (struct_expr.get_struct_name ());
     542           81 :   HIR::PathInExpression copied_path (*path);
     543           81 :   delete path;
     544              : 
     545           81 :   auto crate_num = mappings.get_current_crate ();
     546          162 :   Analysis::NodeMapping mapping (crate_num, struct_expr.get_node_id (),
     547           81 :                                  mappings.get_next_hir_id (crate_num),
     548           81 :                                  UNKNOWN_LOCAL_DEFID);
     549              : 
     550          162 :   translated = new HIR::StructExprStruct (mapping, copied_path,
     551           81 :                                           struct_expr.get_inner_attrs (),
     552           81 :                                           struct_expr.get_outer_attrs (),
     553           81 :                                           struct_expr.get_locus ());
     554           81 : }
     555              : 
     556              : void
     557         1445 : ASTLoweringExpr::visit (AST::StructExprStructFields &struct_expr)
     558              : {
     559              :   // bit of a hack for now
     560         1445 :   HIR::PathInExpression *path
     561         1445 :     = ASTLowerPathInExpression::translate (struct_expr.get_struct_name ());
     562         1445 :   HIR::PathInExpression copied_path (*path);
     563         1445 :   delete path;
     564              : 
     565         1445 :   tl::optional<std::unique_ptr<HIR::StructBase>> base = tl::nullopt;
     566         1445 :   if (struct_expr.has_struct_base ())
     567              :     {
     568           63 :       HIR::Expr *translated_base = ASTLoweringExpr::translate (
     569           63 :         struct_expr.get_struct_base ().get_base_struct ());
     570           63 :       base = tl::optional<std::unique_ptr<HIR::StructBase>> (
     571          126 :         std::make_unique<StructBase> (
     572          126 :           std::unique_ptr<HIR::Expr> (translated_base)));
     573              :     }
     574              : 
     575         1445 :   auto const &in_fields = struct_expr.get_fields ();
     576              : 
     577         1445 :   std::vector<std::unique_ptr<HIR::StructExprField>> fields;
     578         1445 :   fields.reserve (in_fields.size ());
     579              : 
     580         3882 :   for (auto &field : in_fields)
     581         2437 :     fields.emplace_back (ASTLowerStructExprField::translate (*field));
     582              : 
     583         1445 :   auto crate_num = mappings.get_current_crate ();
     584         2890 :   Analysis::NodeMapping mapping (crate_num, struct_expr.get_node_id (),
     585         1445 :                                  mappings.get_next_hir_id (crate_num),
     586         1445 :                                  UNKNOWN_LOCAL_DEFID);
     587              : 
     588         1445 :   translated
     589         1445 :     = new HIR::StructExprStructFields (mapping, copied_path, std::move (fields),
     590              :                                        struct_expr.get_locus (),
     591              :                                        std::move (base),
     592         1445 :                                        struct_expr.get_inner_attrs (),
     593         2953 :                                        struct_expr.get_outer_attrs ());
     594         1508 : }
     595              : 
     596              : void
     597          368 : ASTLoweringExpr::visit (AST::GroupedExpr &expr)
     598              : {
     599          368 :   HIR::Expr *paren_expr
     600          368 :     = ASTLoweringExpr::translate (expr.get_expr_in_parens ());
     601              : 
     602          368 :   auto crate_num = mappings.get_current_crate ();
     603          736 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     604          368 :                                  mappings.get_next_hir_id (crate_num),
     605          368 :                                  UNKNOWN_LOCAL_DEFID);
     606              : 
     607          368 :   translated
     608          368 :     = new HIR::GroupedExpr (mapping, std::unique_ptr<HIR::Expr> (paren_expr),
     609          736 :                             expr.get_inner_attrs (), expr.get_outer_attrs (),
     610          736 :                             expr.get_locus ());
     611          368 : }
     612              : 
     613              : void
     614         5121 : ASTLoweringExpr::visit (AST::FieldAccessExpr &expr)
     615              : {
     616         5121 :   HIR::Expr *receiver = ASTLoweringExpr::translate (expr.get_receiver_expr ());
     617              : 
     618         5121 :   auto crate_num = mappings.get_current_crate ();
     619        10242 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     620         5121 :                                  mappings.get_next_hir_id (crate_num),
     621         5121 :                                  UNKNOWN_LOCAL_DEFID);
     622         5121 :   translated
     623         5121 :     = new HIR::FieldAccessExpr (mapping, std::unique_ptr<HIR::Expr> (receiver),
     624        10242 :                                 expr.get_field_name (), expr.get_outer_attrs (),
     625        10242 :                                 expr.get_locus ());
     626         5121 : }
     627              : 
     628              : void
     629          152 : ASTLoweringExpr::visit (AST::LoopExpr &expr)
     630              : {
     631          152 :   translated = ASTLoweringExprWithBlock::translate (expr, &terminated);
     632          152 : }
     633              : 
     634              : void
     635           94 : ASTLoweringExpr::visit (AST::WhileLoopExpr &expr)
     636              : {
     637           94 :   translated = ASTLoweringExprWithBlock::translate (expr, &terminated);
     638           94 : }
     639              : 
     640              : void
     641          120 : ASTLoweringExpr::visit (AST::BreakExpr &expr)
     642              : {
     643          120 :   tl::optional<HIR::Lifetime> break_label = tl::nullopt;
     644          120 :   if (expr.has_label ())
     645           33 :     break_label = lower_lifetime (expr.get_label_unchecked ().get_lifetime ());
     646              : 
     647          120 :   HIR::Expr *break_expr
     648          120 :     = expr.has_break_expr ()
     649          120 :         ? ASTLoweringExpr::translate (expr.get_break_expr_unchecked ())
     650              :         : nullptr;
     651              : 
     652          120 :   auto crate_num = mappings.get_current_crate ();
     653          240 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     654          120 :                                  mappings.get_next_hir_id (crate_num),
     655          120 :                                  UNKNOWN_LOCAL_DEFID);
     656              : 
     657          120 :   translated
     658          120 :     = new HIR::BreakExpr (mapping, expr.get_locus (), std ::move (break_label),
     659          120 :                           std::unique_ptr<HIR::Expr> (break_expr),
     660          240 :                           expr.get_outer_attrs ());
     661          120 : }
     662              : 
     663              : void
     664           28 : ASTLoweringExpr::visit (AST::ContinueExpr &expr)
     665              : {
     666           28 :   tl::optional<HIR::Lifetime> break_label;
     667           28 :   if (expr.has_label ())
     668            6 :     break_label = lower_lifetime (expr.get_label_unchecked ());
     669              : 
     670           28 :   auto crate_num = mappings.get_current_crate ();
     671           56 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     672           28 :                                  mappings.get_next_hir_id (crate_num),
     673           28 :                                  UNKNOWN_LOCAL_DEFID);
     674              : 
     675           28 :   translated
     676           28 :     = new HIR::ContinueExpr (mapping, expr.get_locus (),
     677           56 :                              std ::move (break_label), expr.get_outer_attrs ());
     678           28 : }
     679              : 
     680              : void
     681         2132 : ASTLoweringExpr::visit (AST::BorrowExpr &expr)
     682              : {
     683         2132 :   HIR::Expr *borrow_lvalue
     684         2132 :     = ASTLoweringExpr::translate (expr.get_borrowed_expr ());
     685              : 
     686         2132 :   auto crate_num = mappings.get_current_crate ();
     687         4264 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     688         2132 :                                  mappings.get_next_hir_id (crate_num),
     689         2132 :                                  UNKNOWN_LOCAL_DEFID);
     690              : 
     691         2132 :   auto *borrow_expr
     692         2132 :     = new HIR::BorrowExpr (mapping, std::unique_ptr<HIR::Expr> (borrow_lvalue),
     693              :                            expr.get_mutability (), expr.is_raw_borrow (),
     694         2132 :                            expr.get_outer_attrs (), expr.get_locus ());
     695              : 
     696         2132 :   if (expr.get_is_double_borrow ())
     697              :     {
     698           23 :       NodeId artificial_double_borrow_id = mappings.get_next_node_id ();
     699           23 :       Analysis::NodeMapping mapping (crate_num, artificial_double_borrow_id,
     700           23 :                                      mappings.get_next_hir_id (crate_num),
     701           23 :                                      UNKNOWN_LOCAL_DEFID);
     702              : 
     703           23 :       borrow_expr
     704           23 :         = new HIR::BorrowExpr (mapping,
     705           23 :                                std::unique_ptr<HIR::Expr> (borrow_expr),
     706              :                                expr.get_mutability (), expr.is_raw_borrow (),
     707           46 :                                expr.get_outer_attrs (), expr.get_locus ());
     708              :     }
     709              : 
     710         2132 :   translated = borrow_expr;
     711         2132 : }
     712              : 
     713              : void
     714         4284 : ASTLoweringExpr::visit (AST::DereferenceExpr &expr)
     715              : {
     716         4284 :   HIR::Expr *dref_lvalue
     717         4284 :     = ASTLoweringExpr::translate (expr.get_dereferenced_expr ());
     718              : 
     719         4284 :   auto crate_num = mappings.get_current_crate ();
     720         8568 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     721         4284 :                                  mappings.get_next_hir_id (crate_num),
     722         4284 :                                  UNKNOWN_LOCAL_DEFID);
     723              : 
     724         4284 :   translated
     725         4284 :     = new HIR::DereferenceExpr (mapping,
     726         4284 :                                 std::unique_ptr<HIR::Expr> (dref_lvalue),
     727         8568 :                                 expr.get_outer_attrs (), expr.get_locus ());
     728         4284 : }
     729              : 
     730              : void
     731         1115 : ASTLoweringExpr::visit (AST::MatchExpr &expr)
     732              : {
     733         1115 :   translated = ASTLoweringExprWithBlock::translate (expr, &terminated);
     734         1115 : }
     735              : 
     736              : void
     737           74 : ASTLoweringExpr::visit (AST::RangeFromToExpr &expr)
     738              : {
     739           74 :   auto crate_num = mappings.get_current_crate ();
     740          148 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     741           74 :                                  mappings.get_next_hir_id (crate_num),
     742           74 :                                  UNKNOWN_LOCAL_DEFID);
     743              : 
     744           74 :   HIR::Expr *range_from = ASTLoweringExpr::translate (expr.get_from_expr ());
     745           74 :   HIR::Expr *range_to = ASTLoweringExpr::translate (expr.get_to_expr ());
     746              : 
     747           74 :   translated
     748           74 :     = new HIR::RangeFromToExpr (mapping,
     749           74 :                                 std::unique_ptr<HIR::Expr> (range_from),
     750          148 :                                 std::unique_ptr<HIR::Expr> (range_to),
     751           74 :                                 expr.get_locus ());
     752           74 : }
     753              : 
     754              : void
     755            7 : ASTLoweringExpr::visit (AST::RangeFromExpr &expr)
     756              : {
     757            7 :   auto crate_num = mappings.get_current_crate ();
     758           14 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     759            7 :                                  mappings.get_next_hir_id (crate_num),
     760            7 :                                  UNKNOWN_LOCAL_DEFID);
     761              : 
     762            7 :   HIR::Expr *range_from = ASTLoweringExpr::translate (expr.get_from_expr ());
     763              : 
     764            7 :   translated
     765            7 :     = new HIR::RangeFromExpr (mapping, std::unique_ptr<HIR::Expr> (range_from),
     766            7 :                               expr.get_locus ());
     767            7 : }
     768              : 
     769              : void
     770            7 : ASTLoweringExpr::visit (AST::RangeToExpr &expr)
     771              : {
     772            7 :   auto crate_num = mappings.get_current_crate ();
     773           14 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     774            7 :                                  mappings.get_next_hir_id (crate_num),
     775            7 :                                  UNKNOWN_LOCAL_DEFID);
     776              : 
     777            7 :   HIR::Expr *range_to = ASTLoweringExpr::translate (expr.get_to_expr ());
     778              : 
     779            7 :   translated
     780            7 :     = new HIR::RangeToExpr (mapping, std::unique_ptr<HIR::Expr> (range_to),
     781            7 :                             expr.get_locus ());
     782            7 : }
     783              : 
     784              : void
     785            0 : ASTLoweringExpr::visit (AST::RangeFullExpr &expr)
     786              : {
     787            0 :   auto crate_num = mappings.get_current_crate ();
     788            0 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     789            0 :                                  mappings.get_next_hir_id (crate_num),
     790            0 :                                  UNKNOWN_LOCAL_DEFID);
     791              : 
     792            0 :   translated = new HIR::RangeFullExpr (mapping, expr.get_locus ());
     793            0 : }
     794              : 
     795              : void
     796            7 : ASTLoweringExpr::visit (AST::RangeFromToInclExpr &expr)
     797              : {
     798            7 :   auto crate_num = mappings.get_current_crate ();
     799           14 :   Analysis::NodeMapping path_mapping (crate_num, mappings.get_next_node_id (),
     800            7 :                                       mappings.get_next_hir_id (crate_num),
     801            7 :                                       UNKNOWN_LOCAL_DEFID);
     802           14 :   Analysis::NodeMapping call_mapping (crate_num, expr.get_node_id (),
     803            7 :                                       mappings.get_next_hir_id (crate_num),
     804            7 :                                       UNKNOWN_LOCAL_DEFID);
     805              : 
     806            7 :   HIR::Expr *func
     807              :     = new HIR::PathInExpression (path_mapping,
     808              :                                  LangItem::Kind::RANGE_INCLUSIVE_NEW,
     809            7 :                                  expr.get_locus (), false);
     810              : 
     811            7 :   HIR::Expr *range_from = ASTLoweringExpr::translate (expr.get_from_expr ());
     812            7 :   HIR::Expr *range_to = ASTLoweringExpr::translate (expr.get_to_expr ());
     813              : 
     814            7 :   std::vector<std::unique_ptr<HIR::Expr>> params;
     815            7 :   params.reserve (2);
     816            7 :   params.emplace_back (std::unique_ptr<HIR::Expr> (range_from));
     817            7 :   params.emplace_back (std::unique_ptr<HIR::Expr> (range_to));
     818              : 
     819            7 :   translated
     820            7 :     = new HIR::CallExpr (call_mapping, std::unique_ptr<HIR::Expr> (func),
     821            7 :                          std::move (params), expr.get_outer_attrs (),
     822           14 :                          expr.get_locus ());
     823            7 : }
     824              : 
     825              : void
     826           37 : ASTLoweringExpr::visit (AST::ClosureExprInner &expr)
     827              : {
     828           37 :   HIR::Expr *closure_expr
     829           37 :     = ASTLoweringExpr::translate (expr.get_definition_expr ());
     830              : 
     831           37 :   std::vector<HIR::ClosureParam> closure_params;
     832           37 :   closure_params.reserve (expr.get_params ().size ());
     833              : 
     834           61 :   for (auto &param : expr.get_params ())
     835           24 :     closure_params.emplace_back (lower_closure_param (param));
     836              : 
     837           37 :   auto crate_num = mappings.get_current_crate ();
     838           74 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     839           37 :                                  mappings.get_next_hir_id (crate_num),
     840           37 :                                  mappings.get_next_localdef_id (crate_num));
     841              : 
     842           37 :   translated
     843           37 :     = new HIR::ClosureExpr (mapping, std::move (closure_params),
     844              :                             nullptr /* closure_return_type */,
     845           37 :                             std::unique_ptr<HIR::Expr> (closure_expr),
     846           37 :                             expr.get_has_move (), expr.get_outer_attrs (),
     847           37 :                             expr.get_locus ());
     848           37 : }
     849              : 
     850              : void
     851           30 : ASTLoweringExpr::visit (AST::ClosureExprInnerTyped &expr)
     852              : {
     853           30 :   HIR::Type *closure_return_type = nullptr;
     854           30 :   HIR::Expr *closure_expr
     855           30 :     = ASTLoweringExpr::translate (expr.get_definition_expr ());
     856              : 
     857           30 :   std::vector<HIR::ClosureParam> closure_params;
     858           30 :   closure_params.reserve (expr.get_params ().size ());
     859              : 
     860           67 :   for (auto &param : expr.get_params ())
     861           37 :     closure_params.emplace_back (lower_closure_param (param));
     862              : 
     863           30 :   auto crate_num = mappings.get_current_crate ();
     864           60 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     865           30 :                                  mappings.get_next_hir_id (crate_num),
     866           30 :                                  mappings.get_next_localdef_id (crate_num));
     867              : 
     868           30 :   translated
     869           30 :     = new HIR::ClosureExpr (mapping, std::move (closure_params),
     870           90 :                             std::unique_ptr<HIR::Type> (closure_return_type),
     871           60 :                             std::unique_ptr<HIR::Expr> (closure_expr),
     872           30 :                             expr.get_has_move (), expr.get_outer_attrs (),
     873           60 :                             expr.get_locus ());
     874           30 : }
     875              : 
     876              : HIR::InlineAsmOperand
     877           10 : translate_operand_in (const AST::InlineAsmOperand &operand)
     878              : {
     879           10 :   auto in_value = operand.get_in ();
     880              : 
     881           10 :   struct HIR::InlineAsmOperand::In in (
     882              :     in_value.reg,
     883           10 :     std::unique_ptr<Expr> (ASTLoweringExpr::translate (*in_value.expr.get ())));
     884           10 :   return in;
     885           10 : }
     886              : 
     887              : HIR::InlineAsmOperand
     888           17 : translate_operand_out (const AST::InlineAsmOperand &operand)
     889              : {
     890           17 :   auto out_value = operand.get_out ();
     891           17 :   struct HIR::InlineAsmOperand::Out out (out_value.reg, out_value.late,
     892           17 :                                          std::unique_ptr<Expr> (
     893              :                                            ASTLoweringExpr::translate (
     894           17 :                                              *out_value.expr.get ())));
     895           17 :   return out;
     896           17 : }
     897              : 
     898              : HIR::InlineAsmOperand
     899            0 : translate_operand_inout (const AST::InlineAsmOperand &operand)
     900              : {
     901            0 :   auto inout_value = operand.get_in_out ();
     902            0 :   struct HIR::InlineAsmOperand::InOut inout (inout_value.reg, inout_value.late,
     903            0 :                                              std::unique_ptr<Expr> (
     904              :                                                ASTLoweringExpr::translate (
     905            0 :                                                  *inout_value.expr.get ())));
     906            0 :   return inout;
     907            0 : }
     908              : 
     909              : HIR::InlineAsmOperand
     910            2 : translate_operand_split_in_out (const AST::InlineAsmOperand &operand)
     911              : {
     912            2 :   auto split_in_out_value = operand.get_split_in_out ();
     913            2 :   struct HIR::InlineAsmOperand::SplitInOut split_in_out (
     914              :     split_in_out_value.reg, split_in_out_value.late,
     915            2 :     std::unique_ptr<Expr> (
     916            2 :       ASTLoweringExpr::translate (*split_in_out_value.in_expr.get ())),
     917            2 :     std::unique_ptr<Expr> (
     918            2 :       ASTLoweringExpr::translate (*split_in_out_value.out_expr.get ())));
     919            2 :   return split_in_out;
     920            2 : }
     921              : 
     922              : HIR::InlineAsmOperand
     923            0 : translate_operand_const (const AST::InlineAsmOperand &operand)
     924              : {
     925            0 :   auto const_value = operand.get_const ();
     926              : 
     927            0 :   auto inner_expr = ASTLoweringExpr::translate (const_value.anon_const);
     928              : 
     929              :   // Like `ConstBlock`, we know this should only be an `AnonConst` - let's
     930              :   // assert to make sure and static cast
     931            0 :   rust_assert (inner_expr->get_expression_type () == Expr::ExprType::AnonConst);
     932              : 
     933            0 :   auto anon_const = static_cast<AnonConst *> (inner_expr);
     934              : 
     935            0 :   return HIR::InlineAsmOperand::Const{*anon_const};
     936            0 : }
     937              : 
     938              : HIR::InlineAsmOperand
     939            0 : translate_operand_sym (const AST::InlineAsmOperand &operand)
     940              : {
     941            0 :   auto sym_value = operand.get_sym ();
     942            0 :   struct HIR::InlineAsmOperand::Sym sym (std::unique_ptr<Expr> (
     943            0 :     ASTLoweringExpr::translate (*sym_value.expr.get ())));
     944            0 :   return sym;
     945            0 : }
     946              : HIR::InlineAsmOperand
     947            0 : translate_operand_label (const AST::InlineAsmOperand &operand)
     948              : {
     949            0 :   auto label_value = operand.get_label ();
     950            0 :   struct HIR::InlineAsmOperand::Label label (label_value.label_name,
     951            0 :                                              std::unique_ptr<Expr> (
     952              :                                                ASTLoweringExpr::translate (
     953            0 :                                                  *label_value.expr.get ())));
     954            0 :   return label;
     955            0 : }
     956              : HIR::InlineAsmOperand
     957           29 : from_operand (const AST::InlineAsmOperand &operand)
     958              : {
     959           29 :   using RegisterType = AST::InlineAsmOperand::RegisterType;
     960           29 :   auto type = operand.get_register_type ();
     961              : 
     962              :   /*In,*/
     963              :   /*Out,*/
     964              :   /*InOut,*/
     965              :   /*SplitInOut,*/
     966              :   /*Const,*/
     967              :   /*Sym,*/
     968              :   /*Label,*/
     969           29 :   switch (type)
     970              :     {
     971           10 :     case RegisterType::In:
     972           10 :       return translate_operand_in (operand);
     973           17 :     case RegisterType::Out:
     974           17 :       return translate_operand_out (operand);
     975            0 :     case RegisterType::InOut:
     976            0 :       return translate_operand_inout (operand);
     977            2 :     case RegisterType::SplitInOut:
     978            2 :       return translate_operand_split_in_out (operand);
     979            0 :     case RegisterType::Const:
     980            0 :       return translate_operand_const (operand);
     981            0 :     case RegisterType::Sym:
     982            0 :       return translate_operand_sym (operand);
     983            0 :     case RegisterType::Label:
     984            0 :       return translate_operand_label (operand);
     985            0 :     default:
     986            0 :       rust_unreachable ();
     987              :     }
     988              : }
     989              : void
     990           27 : ASTLoweringExpr::visit (AST::InlineAsm &expr)
     991              : {
     992           27 :   auto crate_num = mappings.get_current_crate ();
     993           54 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
     994           27 :                                  mappings.get_next_hir_id (crate_num),
     995           27 :                                  mappings.get_next_localdef_id (crate_num));
     996              : 
     997           27 :   std::vector<HIR::InlineAsmOperand> hir_operands;
     998           27 :   const std::vector<AST::InlineAsmOperand> &ast_operands = expr.get_operands ();
     999              :   /*int ast_operands_size = ast_operands.size ();*/
    1000           56 :   for (auto &operand : ast_operands)
    1001              :     {
    1002           29 :       hir_operands.push_back (from_operand (operand));
    1003              :     }
    1004              :   /*int hir_operands_size = hir_operands.size ();*/
    1005              : 
    1006              :   /*rust_debug ("{bdbt} : There are %d ast operands prelowering and %d hir "*/
    1007              :   /*     "operands after lowering\n",*/
    1008              :   /*     ast_operands_size, hir_operands_size);*/
    1009           27 :   translated
    1010           54 :     = new HIR::InlineAsm (expr.get_locus (), expr.is_global_asm,
    1011           54 :                           expr.get_template_ (), expr.get_template_strs (),
    1012           27 :                           hir_operands, expr.get_clobber_abi (),
    1013          108 :                           expr.get_options (), mapping);
    1014           27 : }
    1015              : 
    1016              : namespace {
    1017              : 
    1018              : tl::optional<std::string>
    1019            4 : convert_template_str (const std::string &in_template)
    1020              : {
    1021            4 :   std::string out_template;
    1022            4 :   auto it = in_template.cbegin ();
    1023              : 
    1024            4 :   while (it != in_template.cend ())
    1025              :     {
    1026            0 :       if (*it == '$')
    1027              :         {
    1028            0 :           it++;
    1029            0 :           if (it == in_template.cend ())
    1030              :             {
    1031            0 :               return tl::nullopt;
    1032              :             }
    1033            0 :           else if (*it >= '0' && *it <= '9')
    1034              :             {
    1035            0 :               out_template.push_back ('%');
    1036            0 :               out_template.push_back (*it);
    1037            0 :               it++;
    1038              :             }
    1039            0 :           else if (*it == '$')
    1040              :             {
    1041            0 :               out_template.push_back ('$');
    1042            0 :               it++;
    1043              :             }
    1044            0 :           else if (*it == '{')
    1045              :             {
    1046            0 :               it++;
    1047              :               // converting
    1048              :               //     v
    1049              :               //   ${123:abc}
    1050              :               // to
    1051              :               //   %abc123
    1052            0 :               auto num_it = it;
    1053            0 :               while (true)
    1054              :                 {
    1055            0 :                   if (it == in_template.cend ())
    1056            0 :                     return tl::nullopt;
    1057            0 :                   if (*it == ':')
    1058              :                     break;
    1059            0 :                   it++;
    1060              :                 }
    1061              :               auto colon_it = it;
    1062            0 :               while (true)
    1063              :                 {
    1064            0 :                   if (it == in_template.cend ())
    1065            0 :                     return tl::nullopt;
    1066            0 :                   if (*it == '}')
    1067              :                     break;
    1068            0 :                   it++;
    1069              :                 }
    1070              :               // output
    1071            0 :               out_template.push_back ('%');
    1072            0 :               out_template.append (colon_it + 1, it);
    1073            0 :               out_template.append (num_it, colon_it);
    1074              :               // increment past '}'
    1075            0 :               it++;
    1076              :             }
    1077              :           else
    1078              :             {
    1079            0 :               return tl::nullopt;
    1080              :             }
    1081              :         }
    1082            0 :       else if (*it == '%' || *it == '{' || *it == '|' || *it == '}')
    1083              :         {
    1084            0 :           out_template.push_back ('%');
    1085            0 :           out_template.push_back (*it);
    1086            0 :           it++;
    1087              :         }
    1088              :       else
    1089              :         {
    1090            0 :           out_template.push_back (*it);
    1091            0 :           it++;
    1092              :         }
    1093              :     }
    1094              : 
    1095            4 :   return out_template;
    1096            4 : }
    1097              : 
    1098              : // We're not really supporting llvm_asm, only the bare minimum for libcore
    1099              : // ex: llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
    1100              : bool
    1101            2 : check_llvm_asm_support (const AST::LlvmInlineAsm &expr)
    1102              : {
    1103              :   // TODO: more checks/constraint rewriting?
    1104              : 
    1105            4 :   if (!convert_template_str (expr.get_template ().symbol).has_value ())
    1106              :     return false;
    1107              : 
    1108              :   // TODO: check output constraints?
    1109              : 
    1110              :   // prohibit commas
    1111              :   // GCC uses them to list multiple options for constraints (?)
    1112              :   // while LLVM uses them for inout args (?)
    1113            4 :   for (auto &input : expr.get_inputs ())
    1114            2 :     if (input.constraint.find (',') != std::string::npos)
    1115            2 :       return false;
    1116              : 
    1117              :   // TODO: check clobbers?
    1118              : 
    1119              :   // no alignstack or intel support
    1120            2 :   if (expr.is_stack_aligned ())
    1121              :     return false;
    1122            2 :   if (expr.get_dialect () == AST::LlvmInlineAsm::Dialect::Intel)
    1123            0 :     return false;
    1124              : 
    1125              :   return true;
    1126              : }
    1127              : 
    1128              : } // namespace
    1129              : 
    1130              : void
    1131            2 : ASTLoweringExpr::visit (AST::LlvmInlineAsm &expr)
    1132              : {
    1133            2 :   if (!check_llvm_asm_support (expr))
    1134              :     {
    1135            0 :       rust_error_at (expr.get_locus (), "unsupported %qs construct",
    1136              :                      "llvm_asm");
    1137            0 :       rust_inform (
    1138            0 :         expr.get_locus (),
    1139              :         "%<llvm_asm%> has been replaced with %<asm%>, gccrs only supports a "
    1140              :         "subset of %<llvm_asm%> to compile libcore");
    1141              :     }
    1142              : 
    1143            2 :   auto crate_num = mappings.get_current_crate ();
    1144            4 :   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
    1145            2 :                                  mappings.get_next_hir_id (crate_num),
    1146            2 :                                  mappings.get_next_localdef_id (crate_num));
    1147              : 
    1148            2 :   std::vector<LlvmOperand> inputs;
    1149            2 :   inputs.reserve (expr.get_inputs ().size ());
    1150              : 
    1151            2 :   std::vector<LlvmOperand> outputs;
    1152            2 :   outputs.reserve (expr.get_outputs ().size ());
    1153              : 
    1154            4 :   for (auto i : expr.get_inputs ())
    1155              :     {
    1156            2 :       std::unique_ptr<Expr> inner_expr
    1157            2 :         = std::unique_ptr<Expr> (translate (*i.expr.get ()));
    1158            2 :       inputs.emplace_back (i.constraint, std::move (inner_expr));
    1159            4 :     }
    1160              : 
    1161            2 :   for (auto o : expr.get_outputs ())
    1162              :     {
    1163            0 :       std::unique_ptr<Expr> inner_expr
    1164            0 :         = std::unique_ptr<Expr> (translate (*o.expr.get ()));
    1165            0 :       outputs.emplace_back (o.constraint, std::move (inner_expr));
    1166            0 :     }
    1167              : 
    1168            2 :   HIR::LlvmInlineAsm::Options options{expr.is_volatile (),
    1169            2 :                                       expr.is_stack_aligned (),
    1170            2 :                                       expr.get_dialect ()};
    1171              : 
    1172            2 :   auto new_template = expr.get_template ();
    1173            2 :   new_template.symbol
    1174            2 :     = convert_template_str (new_template.symbol).value_or (std::string ());
    1175              : 
    1176            2 :   rust_debug_fmt_at (expr.get_locus (),
    1177              :                      "converting %<llvm_asm%> template %qs to %qs",
    1178            2 :                      expr.get_template ().symbol.c_str (),
    1179              :                      new_template.symbol.c_str ());
    1180              : 
    1181            2 :   translated
    1182            4 :     = new HIR::LlvmInlineAsm (expr.get_locus (), inputs, outputs,
    1183            2 :                               std::move (new_template), expr.get_clobbers (),
    1184            2 :                               options, expr.get_outer_attrs (), mapping);
    1185            2 : }
    1186              : 
    1187              : void
    1188            0 : ASTLoweringExpr::visit (AST::FormatArgs &fmt)
    1189              : {
    1190            0 :   rust_sorry_at (fmt.get_locus (),
    1191              :                  "FormatArgs lowering is not implemented yet");
    1192            0 : }
    1193              : 
    1194              : void
    1195           15 : ASTLoweringExpr::visit (AST::OffsetOf &offset_of)
    1196              : {
    1197           15 :   auto type = std::unique_ptr<Type> (
    1198           15 :     ASTLoweringType::translate (offset_of.get_type ()));
    1199              : 
    1200           15 :   auto crate_num = mappings.get_current_crate ();
    1201           30 :   Analysis::NodeMapping mapping (crate_num, offset_of.get_node_id (),
    1202           15 :                                  mappings.get_next_hir_id (crate_num),
    1203           15 :                                  mappings.get_next_localdef_id (crate_num));
    1204              : 
    1205           15 :   translated = new HIR::OffsetOf (std::move (type), offset_of.get_field (),
    1206           15 :                                   mapping, offset_of.get_locus ());
    1207           15 : }
    1208              : 
    1209              : } // namespace HIR
    1210              : } // namespace Rust
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.