LCOV - code coverage report
Current view: top level - gcc/rust/backend - rust-compile-expr.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.4 % 1615 1524
Test Date: 2026-07-11 15:47:05 Functions: 98.7 % 78 77
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-compile-expr.h"
      20              : #include "rust-backend.h"
      21              : #include "rust-compile-context.h"
      22              : #include "rust-compile-type.h"
      23              : #include "rust-compile-struct-field-expr.h"
      24              : #include "rust-compile-pattern.h"
      25              : #include "rust-compile-resolve-path.h"
      26              : #include "rust-compile-block.h"
      27              : #include "rust-compile-implitem.h"
      28              : #include "rust-constexpr.h"
      29              : #include "rust-compile-type.h"
      30              : #include "rust-finalized-name-resolution-context.h"
      31              : #include "rust-gcc.h"
      32              : #include "rust-compile-asm.h"
      33              : #include "fold-const.h"
      34              : #include "realmpfr.h"
      35              : #include "convert.h"
      36              : #include "print-tree.h"
      37              : #include "rust-hir-bound.h"
      38              : #include "rust-hir-expr.h"
      39              : #include "rust-rib.h"
      40              : #include "rust-system.h"
      41              : #include "rust-tree.h"
      42              : #include "rust-tyty.h"
      43              : #include "tree-core.h"
      44              : 
      45              : namespace Rust {
      46              : namespace Compile {
      47              : 
      48              : namespace {
      49              : tree
      50            6 : compile_box_struct (Context *ctx, TyTy::BaseType *curr_ty, tree typed_ptr,
      51              :                     location_t locus, int depth = 0)
      52              : {
      53              :   // infinite loop guard
      54            7 :   rust_assert (depth < 100);
      55              : 
      56            7 :   if (curr_ty->get_kind () == TyTy::TypeKind::POINTER
      57            7 :       || curr_ty->get_kind () == TyTy::TypeKind::REF)
      58            1 :     return typed_ptr;
      59              : 
      60            6 :   if (curr_ty->get_kind () == TyTy::TypeKind::ADT)
      61              :     {
      62            5 :       TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (curr_ty);
      63            5 :       tree adt_ty_tree = TyTyResolveCompile::compile (ctx, adt);
      64            5 :       tree size_tree = TYPE_SIZE_UNIT (adt_ty_tree);
      65              : 
      66            5 :       if (integer_zerop (size_tree))
      67            2 :         return Backend::constructor_expression (adt_ty_tree, false, {}, -1,
      68              :                                                 locus);
      69            3 :       rust_assert (!adt->is_enum ());
      70            3 :       rust_assert (adt->number_of_variants () == 1);
      71              : 
      72            3 :       std::vector<tree> args;
      73            3 :       TyTy::VariantDef *variant = adt->get_variants ().at (0);
      74            8 :       for (size_t i = 0; i < variant->num_fields (); i++)
      75              :         {
      76            5 :           TyTy::StructFieldType *field = variant->get_field_at_index (i);
      77            5 :           TyTy::BaseType *field_ty = field->get_field_type ();
      78            5 :           tree field_tree
      79            5 :             = compile_box_struct (ctx, field_ty, typed_ptr, locus, depth + 1);
      80            5 :           args.push_back (field_tree);
      81              :         }
      82            3 :       return Backend::constructor_expression (adt_ty_tree, false, args, -1,
      83              :                                               locus);
      84            3 :     }
      85            1 :   if (curr_ty->get_kind () == TyTy::TypeKind::PARAM)
      86              :     {
      87            1 :       TyTy::ParamType *param_ty = static_cast<TyTy::ParamType *> (curr_ty);
      88            1 :       TyTy::BaseType *resolved_ty = param_ty->resolve ();
      89            1 :       rust_assert (resolved_ty != nullptr && resolved_ty != curr_ty);
      90            1 :       return compile_box_struct (ctx, resolved_ty, typed_ptr, locus, depth + 1);
      91              :     }
      92            0 :   rust_unreachable ();
      93              :   return error_mark_node;
      94              : };
      95              : 
      96              : tree
      97            1 : compile_box (Context *ctx, TyTy::BaseType *box_tyty, TyTy::BaseType *inner_tyty,
      98              :              tree inner_expr_tree, location_t locus)
      99              : {
     100            1 :   tree inner_type_tree = TyTyResolveCompile::compile (ctx, inner_tyty);
     101              : 
     102            1 :   if (!COMPLETE_TYPE_P (inner_type_tree))
     103              :     {
     104            0 :       rust_sorry_at (locus,
     105              :                      "dynamically sized types in boxes are not supported yet");
     106            0 :       return error_mark_node;
     107              :     }
     108            1 :   tree size_tree = TYPE_SIZE_UNIT (inner_type_tree);
     109            1 :   tree align_tree
     110            1 :     = build_int_cst (size_type_node, TYPE_ALIGN_UNIT (inner_type_tree));
     111              : 
     112            1 :   DefId exchange_malloc_defid
     113            1 :     = ctx->get_mappings ().get_lang_item (LangItem::Kind::EXCHANGE_MALLOC,
     114              :                                           locus);
     115            1 :   HIR::Item *item
     116            1 :     = ctx->get_mappings ().lookup_defid (exchange_malloc_defid).value ();
     117              : 
     118            1 :   tree exchange_malloc_decl = nullptr;
     119            1 :   ctx->lookup_function_decl (item->get_mappings ().get_hirid (),
     120              :                              &exchange_malloc_decl, exchange_malloc_defid);
     121              : 
     122            1 :   tree raw_ptr = save_expr (build_call_expr_loc (locus, exchange_malloc_decl, 2,
     123              :                                                  size_tree, align_tree));
     124            1 :   tree typed_ptr = fold_convert (build_pointer_type (inner_type_tree), raw_ptr);
     125              : 
     126            1 :   tree deref = build1_loc (locus, INDIRECT_REF, inner_type_tree, typed_ptr);
     127            1 :   tree assignment
     128            1 :     = build2_loc (locus, MODIFY_EXPR, inner_type_tree, deref, inner_expr_tree);
     129              : 
     130            1 :   tree box_struct = compile_box_struct (ctx, box_tyty, typed_ptr, locus);
     131              : 
     132            1 :   return build2_loc (locus, COMPOUND_EXPR, TREE_TYPE (box_struct), assignment,
     133            1 :                      box_struct);
     134              : }
     135              : 
     136              : tree
     137            3 : build_box_inner_ptr (tree main_expr, location_t locus)
     138              : {
     139              :   // We continuously extract the first field of the struct until we hit the
     140              :   // actual underlying raw pointer. This handles both simple Box layouts (ptr:
     141              :   // *mut T) and complex ones like this (Box<Unique<NonNull<T>>>). This relies
     142              :   // on the standard library's layout guarantees and will break if a stateful
     143              :   // custom allocator is placed as the first field in the RECORD_TYPE.
     144           12 :   while (TREE_CODE (TREE_TYPE (main_expr)) == RECORD_TYPE)
     145              :     {
     146            9 :       tree first_field = TYPE_FIELDS (TREE_TYPE (main_expr));
     147            9 :       if (first_field == NULL_TREE)
     148              :         break;
     149            9 :       main_expr = build3_loc (locus, COMPONENT_REF, TREE_TYPE (first_field),
     150              :                               main_expr, first_field, NULL_TREE);
     151              :     }
     152            3 :   return main_expr;
     153              : }
     154              : } // namespace
     155              : 
     156       122354 : CompileExpr::CompileExpr (Context *ctx)
     157       122354 :   : HIRCompileBase (ctx), translated (error_mark_node)
     158       122354 : {}
     159              : 
     160              : tree
     161       122354 : CompileExpr::Compile (HIR::Expr &expr, Context *ctx)
     162              : {
     163       122354 :   CompileExpr compiler (ctx);
     164       122354 :   expr.accept_vis (compiler);
     165       122354 :   return compiler.translated;
     166       122354 : }
     167              : 
     168              : void
     169          884 : CompileExpr::visit (HIR::TupleIndexExpr &expr)
     170              : {
     171          884 :   HIR::Expr &tuple_expr = expr.get_tuple_expr ();
     172          884 :   TupleIndex index = expr.get_tuple_index ();
     173              : 
     174          884 :   tree receiver_ref = CompileExpr::Compile (tuple_expr, ctx);
     175              : 
     176          884 :   TyTy::BaseType *tuple_expr_ty = nullptr;
     177          884 :   bool ok
     178          884 :     = ctx->get_tyctx ()->lookup_type (tuple_expr.get_mappings ().get_hirid (),
     179              :                                       &tuple_expr_ty);
     180          884 :   rust_assert (ok);
     181              : 
     182              :   // do we need to add an indirect reference
     183          884 :   if (tuple_expr_ty->get_kind () == TyTy::TypeKind::REF)
     184              :     {
     185          299 :       tree indirect = indirect_expression (receiver_ref, expr.get_locus ());
     186          299 :       receiver_ref = indirect;
     187              :     }
     188              : 
     189          884 :   translated
     190          884 :     = Backend::struct_field_expression (receiver_ref, index, expr.get_locus ());
     191          884 : }
     192              : 
     193              : void
     194          570 : CompileExpr::visit (HIR::TupleExpr &expr)
     195              : {
     196          570 :   if (expr.is_unit ())
     197              :     {
     198          139 :       translated = unit_expression (expr.get_locus ());
     199          139 :       return;
     200              :     }
     201              : 
     202          431 :   TyTy::BaseType *tyty = nullptr;
     203          431 :   if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
     204              :                                        &tyty))
     205              :     {
     206            0 :       rust_fatal_error (expr.get_locus (),
     207              :                         "did not resolve type for this TupleExpr");
     208              :       return;
     209              :     }
     210              : 
     211          431 :   tree tuple_type = TyTyResolveCompile::compile (ctx, tyty);
     212          431 :   rust_assert (tuple_type != nullptr);
     213              : 
     214              :   // this assumes all fields are in order from type resolution
     215          431 :   std::vector<tree> vals;
     216         1428 :   for (auto &elem : expr.get_tuple_elems ())
     217              :     {
     218          997 :       auto e = CompileExpr::Compile (*elem, ctx);
     219          997 :       vals.push_back (e);
     220              :     }
     221              : 
     222          431 :   translated = Backend::constructor_expression (tuple_type, false, vals, -1,
     223              :                                                 expr.get_locus ());
     224          431 : }
     225              : 
     226              : void
     227            1 : CompileExpr::visit (HIR::BoxExpr &expr)
     228              : {
     229            1 :   TyTy::BaseType *inner_tyty = nullptr;
     230            1 :   bool ok = ctx->get_tyctx ()->lookup_type (
     231            1 :     expr.get_expr ().get_mappings ().get_hirid (), &inner_tyty);
     232            1 :   rust_assert (ok);
     233              : 
     234            1 :   TyTy::BaseType *box_tyty = nullptr;
     235            1 :   ok = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
     236              :                                        &box_tyty);
     237            1 :   rust_assert (ok);
     238              : 
     239            1 :   tree inner_expr_tree
     240            1 :     = save_expr (CompileExpr::Compile (expr.get_expr (), ctx));
     241              : 
     242            1 :   translated = compile_box (ctx, box_tyty, inner_tyty, inner_expr_tree,
     243              :                             expr.get_locus ());
     244            1 : }
     245              : 
     246              : void
     247          522 : CompileExpr::visit (HIR::ReturnExpr &expr)
     248              : {
     249          522 :   auto fncontext = ctx->peek_fn ();
     250              : 
     251          522 :   tree return_value = expr.has_return_expr ()
     252          522 :                         ? CompileExpr::Compile (expr.get_expr (), ctx)
     253           38 :                         : unit_expression (expr.get_locus ());
     254              : 
     255          522 :   if (expr.has_return_expr ())
     256              :     {
     257          484 :       HirId id = expr.get_mappings ().get_hirid ();
     258          484 :       location_t rvalue_locus = expr.return_expr->get_locus ();
     259              : 
     260          484 :       TyTy::BaseType *expected = fncontext.retty;
     261          484 :       location_t lvalue_locus
     262          484 :         = ctx->get_mappings ().lookup_location (expected->get_ref ());
     263              : 
     264          484 :       TyTy::BaseType *actual = nullptr;
     265          484 :       bool ok = ctx->get_tyctx ()->lookup_type (
     266          484 :         expr.return_expr->get_mappings ().get_hirid (), &actual);
     267          484 :       rust_assert (ok);
     268              : 
     269          484 :       return_value = coercion_site (id, return_value, actual, expected,
     270              :                                     lvalue_locus, rvalue_locus);
     271              :     }
     272              : 
     273          522 :   tree return_stmt = Backend::return_statement (fncontext.fndecl, return_value,
     274              :                                                 expr.get_locus ());
     275          522 :   ctx->add_statement (return_stmt);
     276          522 : }
     277              : 
     278              : void
     279         3427 : CompileExpr::visit (HIR::ArithmeticOrLogicalExpr &expr)
     280              : {
     281         3427 :   auto op = expr.get_expr_type ();
     282         3427 :   auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx);
     283         3427 :   auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx);
     284              : 
     285              :   // this might be an operator overload situation lets check
     286         3427 :   TyTy::FnType *fntype;
     287         3427 :   bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
     288         3427 :     expr.get_mappings ().get_hirid (), &fntype);
     289         3427 :   if (is_op_overload)
     290              :     {
     291          166 :       auto lang_item_type
     292          166 :         = LangItem::OperatorToLangItem (expr.get_expr_type ());
     293          166 :       translated = resolve_operator_overload (
     294          332 :         lang_item_type, expr, lhs, rhs, expr.get_lhs (),
     295          166 :         tl::optional<std::reference_wrapper<HIR::Expr>> (expr.get_rhs ()));
     296          440 :       return;
     297              :     }
     298              : 
     299         3261 :   bool can_generate_overflow_checks
     300         3261 :     = (ctx->in_fn () && !ctx->const_context_p ()) && flag_overflow_checks;
     301         3261 :   if (!can_generate_overflow_checks)
     302              :     {
     303          274 :       translated
     304          274 :         = Backend::arithmetic_or_logical_expression (op, lhs, rhs,
     305              :                                                      expr.get_locus ());
     306          274 :       return;
     307              :     }
     308              : 
     309         2987 :   auto receiver_tmp = NULL_TREE;
     310         2987 :   Bvariable *receiver
     311         2987 :     = Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE,
     312         2987 :                                    TREE_TYPE (lhs), lhs, true,
     313              :                                    expr.get_locus (), &receiver_tmp);
     314         2987 :   auto check
     315         2987 :     = Backend::arithmetic_or_logical_expression_checked (op, lhs, rhs,
     316              :                                                          expr.get_locus (),
     317              :                                                          receiver);
     318              : 
     319         2987 :   ctx->add_statement (check);
     320         2987 :   translated = receiver->get_tree (expr.get_locus ());
     321              : }
     322              : 
     323              : void
     324          753 : CompileExpr::visit (HIR::CompoundAssignmentExpr &expr)
     325              : {
     326          753 :   auto op = expr.get_expr_type ();
     327          753 :   tree lhs = CompileExpr::Compile (expr.get_lhs (), ctx);
     328          753 :   tree rhs = CompileExpr::Compile (expr.get_rhs (), ctx);
     329          753 :   tree compound_assignment = NULL_TREE;
     330              :   // this might be an operator overload situation lets check
     331          753 :   TyTy::FnType *fntype;
     332          753 :   bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
     333          753 :     expr.get_mappings ().get_hirid (), &fntype);
     334          753 :   if (is_op_overload)
     335              :     {
     336           14 :       auto lang_item_type = LangItem::CompoundAssignmentOperatorToLangItem (
     337              :         expr.get_expr_type ());
     338           14 :       compound_assignment
     339           14 :         = resolve_operator_overload (lang_item_type, expr, lhs, rhs,
     340           14 :                                      expr.get_lhs (), expr.get_rhs ());
     341              :     }
     342          739 :   else if (ctx->in_fn () && !ctx->const_context_p ())
     343              :     {
     344          736 :       tree tmp = NULL_TREE;
     345          736 :       Bvariable *receiver
     346          736 :         = Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE,
     347          736 :                                        TREE_TYPE (lhs), lhs, true,
     348              :                                        expr.get_locus (), &tmp);
     349          736 :       tree check
     350          736 :         = Backend::arithmetic_or_logical_expression_checked (op, lhs, rhs,
     351              :                                                              expr.get_locus (),
     352              :                                                              receiver);
     353          736 :       ctx->add_statement (check);
     354          736 :       compound_assignment
     355          736 :         = Backend::assignment_statement (lhs,
     356              :                                          receiver->get_tree (expr.get_locus ()),
     357              :                                          expr.get_locus ());
     358              :     }
     359              :   else
     360              :     {
     361            3 :       tree expr_tree
     362            3 :         = Backend::arithmetic_or_logical_expression (op, lhs, rhs,
     363              :                                                      expr.get_locus ());
     364            3 :       compound_assignment
     365            3 :         = Backend::assignment_statement (lhs, expr_tree, expr.get_locus ());
     366              :     }
     367          753 :   ctx->add_statement (compound_assignment);
     368          753 :   translated = unit_expression (expr.get_locus ());
     369          753 : }
     370              : 
     371              : void
     372          835 : CompileExpr::visit (HIR::NegationExpr &expr)
     373              : {
     374          835 :   auto op = expr.get_expr_type ();
     375              : 
     376          835 :   auto &literal_expr = expr.get_expr ();
     377              : 
     378              :   // If it's a negated integer/float literal, we can return early
     379          835 :   if (op == NegationOperator::NEGATE
     380          835 :       && literal_expr.get_expression_type () == HIR::Expr::ExprType::Lit)
     381              :     {
     382          629 :       auto &new_literal_expr = static_cast<HIR::LiteralExpr &> (literal_expr);
     383          629 :       auto lit_type = new_literal_expr.get_lit_type ();
     384          629 :       if (lit_type == HIR::Literal::LitType::INT
     385          629 :           || lit_type == HIR::Literal::LitType::FLOAT)
     386              :         {
     387          629 :           new_literal_expr.set_negative ();
     388          629 :           translated = CompileExpr::Compile (literal_expr, ctx);
     389          643 :           return;
     390              :         }
     391              :     }
     392              : 
     393          206 :   auto negated_expr = CompileExpr::Compile (literal_expr, ctx);
     394          206 :   auto location = expr.get_locus ();
     395              : 
     396              :   // this might be an operator overload situation lets check
     397          206 :   TyTy::FnType *fntype;
     398          206 :   bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
     399          206 :     expr.get_mappings ().get_hirid (), &fntype);
     400          206 :   if (is_op_overload)
     401              :     {
     402           14 :       auto lang_item_type = LangItem::NegationOperatorToLangItem (op);
     403           14 :       translated
     404           14 :         = resolve_operator_overload (lang_item_type, expr, negated_expr,
     405              :                                      nullptr, expr.get_expr (), tl::nullopt);
     406           14 :       return;
     407              :     }
     408              : 
     409          192 :   translated = Backend::negation_expression (op, negated_expr, location);
     410              : }
     411              : 
     412              : void
     413         3386 : CompileExpr::visit (HIR::ComparisonExpr &expr)
     414              : {
     415         3386 :   auto op = expr.get_expr_type ();
     416         3386 :   auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx);
     417         3386 :   auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx);
     418         3386 :   auto location = expr.get_locus ();
     419              : 
     420              :   // this might be an operator overload situation lets check
     421         3386 :   TyTy::FnType *fntype;
     422         3386 :   bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
     423         3386 :     expr.get_mappings ().get_hirid (), &fntype);
     424         3386 :   if (is_op_overload)
     425              :     {
     426          840 :       auto seg_name = LangItem::ComparisonToSegment (expr.get_expr_type ());
     427         1680 :       auto segment = HIR::PathIdentSegment (seg_name);
     428          840 :       auto lang_item_type
     429          840 :         = LangItem::ComparisonToLangItem (expr.get_expr_type ());
     430              : 
     431          840 :       rhs = address_expression (rhs, EXPR_LOCATION (rhs));
     432              : 
     433         1680 :       translated = resolve_operator_overload (
     434         1680 :         lang_item_type, expr, lhs, rhs, expr.get_lhs (),
     435          840 :         tl::optional<std::reference_wrapper<HIR::Expr>> (expr.get_rhs ()),
     436              :         segment);
     437          840 :       return;
     438          840 :     }
     439              : 
     440         2546 :   translated = Backend::comparison_expression (op, lhs, rhs, location);
     441              : }
     442              : 
     443              : void
     444          395 : CompileExpr::visit (HIR::LazyBooleanExpr &expr)
     445              : {
     446          395 :   auto op = expr.get_expr_type ();
     447          395 :   auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx);
     448          395 :   auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx);
     449          395 :   auto location = expr.get_locus ();
     450              : 
     451          395 :   translated = Backend::lazy_boolean_expression (op, lhs, rhs, location);
     452          395 : }
     453              : 
     454              : void
     455         4954 : CompileExpr::visit (HIR::TypeCastExpr &expr)
     456              : {
     457         4954 :   TyTy::BaseType *type_to_cast_to_ty = nullptr;
     458         4954 :   if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
     459              :                                        &type_to_cast_to_ty))
     460              :     {
     461            0 :       translated = error_mark_node;
     462            0 :       return;
     463              :     }
     464              : 
     465         4954 :   TyTy::BaseType *casted_tyty = nullptr;
     466         4954 :   if (!ctx->get_tyctx ()->lookup_type (
     467         4954 :         expr.get_casted_expr ().get_mappings ().get_hirid (), &casted_tyty))
     468              :     {
     469            0 :       translated = error_mark_node;
     470            0 :       return;
     471              :     }
     472              : 
     473         4954 :   auto type_to_cast_to = TyTyResolveCompile::compile (ctx, type_to_cast_to_ty);
     474         4954 :   auto casted_expr = CompileExpr::Compile (expr.get_casted_expr (), ctx);
     475              : 
     476         4954 :   std::vector<Resolver::Adjustment> *adjustments = nullptr;
     477         4954 :   bool ok = ctx->get_tyctx ()->lookup_cast_autoderef_mappings (
     478         4954 :     expr.get_mappings ().get_hirid (), &adjustments);
     479         4954 :   if (ok)
     480              :     {
     481         4954 :       casted_expr
     482         4954 :         = resolve_adjustements (*adjustments, casted_expr, expr.get_locus ());
     483              :     }
     484              : 
     485         4954 :   translated
     486         4954 :     = type_cast_expression (type_to_cast_to, casted_expr, expr.get_locus ());
     487              : }
     488              : 
     489              : void
     490         1217 : CompileExpr::visit (HIR::IfExpr &expr)
     491              : {
     492         1217 :   auto stmt = CompileConditionalBlocks::compile (&expr, ctx, nullptr);
     493         1217 :   ctx->add_statement (stmt);
     494         1217 :   translated = unit_expression (expr.get_locus ());
     495         1217 : }
     496              : 
     497              : void
     498           26 : CompileExpr::visit (HIR::InlineAsm &expr)
     499              : {
     500           26 :   CompileAsm asm_codegen (ctx);
     501           26 :   ctx->add_statement (asm_codegen.tree_codegen_asm (expr));
     502           26 :   translated = unit_expression (expr.get_locus ());
     503           26 : }
     504              : 
     505              : void
     506            2 : CompileExpr::visit (HIR::LlvmInlineAsm &expr)
     507              : {
     508            2 :   CompileLlvmAsm asm_codegen (ctx);
     509            2 :   ctx->add_statement (asm_codegen.tree_codegen_asm (expr));
     510            2 :   translated = unit_expression (expr.get_locus ());
     511            2 : }
     512              : 
     513              : void
     514           14 : CompileExpr::visit (HIR::OffsetOf &expr)
     515              : {
     516           14 :   TyTy::BaseType *type = nullptr;
     517           14 :   if (!ctx->get_tyctx ()->lookup_type (
     518           14 :         expr.get_type ().get_mappings ().get_hirid (), &type))
     519              :     {
     520            0 :       translated = error_mark_node;
     521            0 :       return;
     522              :     }
     523              : 
     524           14 :   auto compiled_ty = TyTyResolveCompile::compile (ctx, type);
     525              : 
     526           14 :   rust_assert (TREE_CODE (compiled_ty) == RECORD_TYPE);
     527              : 
     528              :   // Create an identifier node for the field
     529           14 :   auto field_id = Backend::get_identifier_node (expr.get_field ().as_string ());
     530              : 
     531              :   // And now look it up and get its value for `byte_position`
     532           14 :   auto field = Backend::lookup_field (compiled_ty, field_id);
     533           14 :   auto field_value = TREE_VALUE (field);
     534              : 
     535           14 :   translated = byte_position (field_value);
     536              : }
     537              : 
     538              : void
     539          823 : CompileExpr::visit (HIR::IfExprConseqElse &expr)
     540              : {
     541          823 :   TyTy::BaseType *if_type = nullptr;
     542          823 :   if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
     543              :                                        &if_type))
     544              :     {
     545            0 :       rust_error_at (expr.get_locus (),
     546              :                      "failed to lookup type of IfExprConseqElse");
     547            0 :       return;
     548              :     }
     549              : 
     550          823 :   Bvariable *tmp = NULL;
     551          823 :   fncontext fnctx = ctx->peek_fn ();
     552          823 :   tree enclosing_scope = ctx->peek_enclosing_scope ();
     553          823 :   tree block_type = TyTyResolveCompile::compile (ctx, if_type);
     554              : 
     555          823 :   bool is_address_taken = false;
     556          823 :   tree ret_var_stmt = nullptr;
     557          823 :   tmp = Backend::temporary_variable (fnctx.fndecl, enclosing_scope, block_type,
     558              :                                      NULL, is_address_taken, expr.get_locus (),
     559              :                                      &ret_var_stmt);
     560          823 :   ctx->add_statement (ret_var_stmt);
     561              : 
     562          823 :   auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp);
     563          823 :   ctx->add_statement (stmt);
     564              : 
     565          823 :   translated = Backend::var_expression (tmp, expr.get_locus ());
     566              : }
     567              : 
     568              : void
     569         4813 : CompileExpr::visit (HIR::BlockExpr &expr)
     570              : {
     571         4813 :   TyTy::BaseType *block_tyty = nullptr;
     572         4813 :   if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
     573              :                                        &block_tyty))
     574              :     {
     575            0 :       rust_error_at (expr.get_locus (), "failed to lookup type of BlockExpr");
     576            0 :       return;
     577              :     }
     578              : 
     579         4813 :   Bvariable *tmp = NULL;
     580         4813 :   fncontext fnctx = ctx->peek_fn ();
     581         4813 :   tree enclosing_scope = ctx->peek_enclosing_scope ();
     582         4813 :   tree block_type = TyTyResolveCompile::compile (ctx, block_tyty);
     583         4813 :   tree block_label = NULL_TREE;
     584              : 
     585         4813 :   bool is_address_taken = false;
     586         4813 :   tree ret_var_stmt = nullptr;
     587         4813 :   tmp = Backend::temporary_variable (fnctx.fndecl, enclosing_scope, block_type,
     588              :                                      NULL, is_address_taken, expr.get_locus (),
     589              :                                      &ret_var_stmt);
     590              : 
     591         4813 :   ctx->add_statement (ret_var_stmt);
     592              : 
     593         4813 :   if (expr.has_label ())
     594              :     {
     595            3 :       ctx->insert_var_decl (
     596            3 :         expr.get_label ().get_lifetime ().get_mappings ().get_hirid (), tmp);
     597            3 :       block_label = construct_block_label (expr);
     598              :     }
     599              : 
     600         4813 :   auto block_stmt = CompileBlock::compile (expr, ctx, tmp);
     601         4813 :   rust_assert (TREE_CODE (block_stmt) == BIND_EXPR);
     602         4813 :   ctx->add_statement (block_stmt);
     603              : 
     604         4813 :   if (block_label != NULL_TREE)
     605              :     {
     606            3 :       ctx->add_statement (block_label);
     607              :     }
     608         4813 :   translated = Backend::var_expression (tmp, expr.get_locus ());
     609              : }
     610              : 
     611              : void
     612          650 : CompileExpr::visit (HIR::AnonConst &expr)
     613              : {
     614          650 :   expr.get_inner_expr ().accept_vis (*this);
     615          650 : }
     616              : 
     617              : void
     618           15 : CompileExpr::visit (HIR::ConstBlock &expr)
     619              : {
     620           15 :   expr.get_const_expr ().accept_vis (*this);
     621           15 : }
     622              : 
     623              : void
     624         3391 : CompileExpr::visit (HIR::UnsafeBlockExpr &expr)
     625              : {
     626         3391 :   expr.get_block_expr ().accept_vis (*this);
     627         3391 : }
     628              : 
     629              : void
     630           79 : CompileExpr::visit (HIR::StructExprStruct &struct_expr)
     631              : {
     632           79 :   TyTy::BaseType *tyty = nullptr;
     633           79 :   if (!ctx->get_tyctx ()->lookup_type (struct_expr.get_mappings ().get_hirid (),
     634              :                                        &tyty))
     635              :     {
     636            0 :       rust_error_at (struct_expr.get_locus (), "unknown type");
     637            0 :       return;
     638              :     }
     639              : 
     640           79 :   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyty);
     641           79 :   TyTy::VariantDef *variant = nullptr;
     642           79 :   if (adt->is_enum ())
     643              :     {
     644              :       // unwrap variant and ensure that it can be resolved
     645            3 :       HirId variant_id;
     646            3 :       bool ok = ctx->get_tyctx ()->lookup_variant_definition (
     647            3 :         struct_expr.get_struct_name ().get_mappings ().get_hirid (),
     648              :         &variant_id);
     649            3 :       rust_assert (ok);
     650              : 
     651            3 :       ok = adt->lookup_variant_by_id (variant_id, &variant);
     652            3 :       rust_assert (ok);
     653              :     }
     654              :   else
     655              :     {
     656           76 :       rust_assert (tyty->is_unit ());
     657              :     }
     658              : 
     659           79 :   translated = unit_expression (struct_expr.get_locus ());
     660              : }
     661              : 
     662              : void
     663         1280 : CompileExpr::visit (HIR::StructExprStructFields &struct_expr)
     664              : {
     665         1280 :   TyTy::BaseType *tyty = nullptr;
     666         1280 :   if (!ctx->get_tyctx ()->lookup_type (struct_expr.get_mappings ().get_hirid (),
     667              :                                        &tyty))
     668              :     {
     669            0 :       rust_error_at (struct_expr.get_locus (), "unknown type");
     670         1194 :       return;
     671              :     }
     672         1280 :   if (!tyty->is<TyTy::ADTType> ())
     673              :     return;
     674              : 
     675              :   // it must be an ADT
     676         1280 :   rust_assert (tyty->get_kind () == TyTy::TypeKind::ADT);
     677         1280 :   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyty);
     678              : 
     679              :   // what variant is it?
     680         1280 :   int union_disriminator = struct_expr.union_index;
     681         1280 :   TyTy::VariantDef *variant = nullptr;
     682         1280 :   if (!adt->is_enum ())
     683              :     {
     684         1194 :       rust_assert (adt->number_of_variants () == 1);
     685         1194 :       variant = adt->get_variants ().at (0);
     686              :     }
     687              :   else
     688              :     {
     689           86 :       HirId variant_id;
     690           86 :       bool ok = ctx->get_tyctx ()->lookup_variant_definition (
     691           86 :         struct_expr.get_struct_name ().get_mappings ().get_hirid (),
     692              :         &variant_id);
     693           86 :       rust_assert (ok);
     694              : 
     695           86 :       ok
     696           86 :         = adt->lookup_variant_by_id (variant_id, &variant, &union_disriminator);
     697           86 :       rust_assert (ok);
     698              :     }
     699              : 
     700              :   // compile it
     701         1280 :   tree compiled_adt_type = TyTyResolveCompile::compile (ctx, tyty);
     702              : 
     703         1280 :   std::vector<tree> arguments;
     704         1280 :   if (adt->is_union ())
     705              :     {
     706          100 :       rust_assert (struct_expr.get_fields ().size () == 1);
     707              : 
     708              :       // assignments are coercion sites so lets convert the rvalue if
     709              :       // necessary
     710          100 :       auto respective_field = variant->get_field_at_index (union_disriminator);
     711          100 :       auto expected = respective_field->get_field_type ();
     712              : 
     713              :       // process arguments
     714          100 :       auto &argument = struct_expr.get_fields ().at (0);
     715          100 :       auto lvalue_locus
     716          100 :         = ctx->get_mappings ().lookup_location (expected->get_ty_ref ());
     717          100 :       auto rvalue_locus = argument->get_locus ();
     718          100 :       auto rvalue = CompileStructExprField::Compile (*argument, ctx);
     719              : 
     720          100 :       TyTy::BaseType *actual = nullptr;
     721          100 :       bool ok = ctx->get_tyctx ()->lookup_type (
     722          100 :         argument->get_mappings ().get_hirid (), &actual);
     723              : 
     724          100 :       if (ok)
     725              :         {
     726          100 :           rvalue
     727          100 :             = coercion_site (argument->get_mappings ().get_hirid (), rvalue,
     728              :                              actual, expected, lvalue_locus, rvalue_locus);
     729              :         }
     730              : 
     731              :       // add it to the list
     732          100 :       arguments.push_back (rvalue);
     733              :     }
     734              :   else
     735              :     {
     736              :       // this assumes all fields are in order from type resolution and if a
     737              :       // base struct was specified those fields are filed via accessors
     738         3992 :       for (size_t i = 0; i < struct_expr.get_fields ().size (); i++)
     739              :         {
     740              :           // assignments are coercion sites so lets convert the rvalue if
     741              :           // necessary
     742         2812 :           auto respective_field = variant->get_field_at_index (i);
     743         2812 :           auto expected = respective_field->get_field_type ();
     744              : 
     745              :           // process arguments
     746         2812 :           auto &argument = struct_expr.get_fields ().at (i);
     747         2812 :           auto lvalue_locus
     748         2812 :             = ctx->get_mappings ().lookup_location (expected->get_ty_ref ());
     749         2812 :           auto rvalue_locus = argument->get_locus ();
     750         2812 :           auto rvalue = CompileStructExprField::Compile (*argument, ctx);
     751              : 
     752         2812 :           TyTy::BaseType *actual = nullptr;
     753         2812 :           bool ok = ctx->get_tyctx ()->lookup_type (
     754         2812 :             argument->get_mappings ().get_hirid (), &actual);
     755              : 
     756              :           // coerce it if required/possible see
     757              :           // compile/torture/struct_base_init_1.rs
     758         2812 :           if (ok)
     759              :             {
     760         2196 :               rvalue
     761         2196 :                 = coercion_site (argument->get_mappings ().get_hirid (), rvalue,
     762              :                                  actual, expected, lvalue_locus, rvalue_locus);
     763              :             }
     764              : 
     765              :           // add it to the list
     766         2812 :           arguments.push_back (rvalue);
     767              :         }
     768              :     }
     769              : 
     770         1280 :   if (!adt->is_enum ())
     771              :     {
     772         1194 :       translated
     773         1194 :         = Backend::constructor_expression (compiled_adt_type, adt->is_enum (),
     774              :                                            arguments, union_disriminator,
     775              :                                            struct_expr.get_locus ());
     776         1194 :       return;
     777              :     }
     778              : 
     779           86 :   HIR::Expr &discrim_expr = variant->get_discriminant ();
     780           86 :   tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
     781           86 :   tree folded_discrim_expr = fold_expr (discrim_expr_node);
     782           86 :   tree qualifier = folded_discrim_expr;
     783              : 
     784           86 :   tree enum_root_files = TYPE_FIELDS (compiled_adt_type);
     785           86 :   tree payload_root = DECL_CHAIN (enum_root_files);
     786              : 
     787           86 :   tree payload = Backend::constructor_expression (TREE_TYPE (payload_root),
     788           86 :                                                   adt->is_enum (), arguments,
     789              :                                                   union_disriminator,
     790              :                                                   struct_expr.get_locus ());
     791              : 
     792           86 :   std::vector<tree> ctor_arguments = {qualifier, payload};
     793              : 
     794           86 :   translated
     795           86 :     = Backend::constructor_expression (compiled_adt_type, 0, ctor_arguments, -1,
     796              :                                        struct_expr.get_locus ());
     797         1280 : }
     798              : 
     799              : void
     800          335 : CompileExpr::visit (HIR::GroupedExpr &expr)
     801              : {
     802          335 :   translated = CompileExpr::Compile (expr.get_expr_in_parens (), ctx);
     803          335 : }
     804              : 
     805              : void
     806         5654 : CompileExpr::visit (HIR::FieldAccessExpr &expr)
     807              : {
     808         5654 :   HIR::Expr &receiver_expr = expr.get_receiver_expr ();
     809         5654 :   tree receiver_ref = CompileExpr::Compile (receiver_expr, ctx);
     810              : 
     811              :   // resolve the receiver back to ADT type
     812         5654 :   TyTy::BaseType *receiver = nullptr;
     813         5654 :   if (!ctx->get_tyctx ()->lookup_type (
     814         5654 :         expr.get_receiver_expr ().get_mappings ().get_hirid (), &receiver))
     815              :     {
     816            0 :       rust_error_at (expr.get_receiver_expr ().get_locus (),
     817              :                      "unresolved type for receiver");
     818           14 :       return;
     819              :     }
     820              : 
     821         5654 :   size_t field_index = 0;
     822              : 
     823         5654 :   if (auto inner_ty = TyTy::try_get_box_inner_type (receiver))
     824              :     {
     825            1 :       rust_assert ((*inner_ty)->get_kind () == TyTy::TypeKind::ADT);
     826            1 :       TyTy::ADTType *inner_adt = static_cast<TyTy::ADTType *> (*inner_ty);
     827            1 :       TyTy::VariantDef *variant = inner_adt->get_variants ().at (0);
     828              : 
     829            1 :       bool ok = variant->lookup_field (expr.get_field_name ().as_string (),
     830              :                                        nullptr, &field_index);
     831            1 :       rust_assert (ok);
     832              : 
     833            1 :       receiver_ref = build_box_inner_ptr (receiver_ref, expr.get_locus ());
     834            1 :       receiver_ref = indirect_expression (receiver_ref, expr.get_locus ());
     835              :     }
     836         5653 :   else if (receiver->get_kind () == TyTy::TypeKind::ADT)
     837              :     {
     838         2059 :       TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver);
     839         2059 :       rust_assert (!adt->is_enum ());
     840         2059 :       rust_assert (adt->number_of_variants () == 1);
     841              : 
     842         2059 :       TyTy::VariantDef *variant = adt->get_variants ().at (0);
     843         2059 :       bool ok = variant->lookup_field (expr.get_field_name ().as_string (),
     844              :                                        nullptr, &field_index);
     845         2059 :       rust_assert (ok);
     846              :     }
     847         3594 :   else if (receiver->get_kind () == TyTy::TypeKind::REF)
     848              :     {
     849         3594 :       TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (receiver);
     850         3594 :       TyTy::BaseType *b = r->get_base ();
     851         3594 :       rust_assert (b->get_kind () == TyTy::TypeKind::ADT);
     852              : 
     853         3594 :       TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (b);
     854         3594 :       rust_assert (!adt->is_enum ());
     855         3594 :       rust_assert (adt->number_of_variants () == 1);
     856              : 
     857         3594 :       TyTy::VariantDef *variant = adt->get_variants ().at (0);
     858         3594 :       bool ok = variant->lookup_field (expr.get_field_name ().as_string (),
     859              :                                        nullptr, &field_index);
     860         3594 :       rust_assert (ok);
     861              : 
     862              :       // TODO this check is only used for CStr, test again when we support
     863              :       // compilation of #[repr(transparent)] structs
     864         3594 :       if (RS_DST_FLAG_P (TREE_TYPE (receiver_ref)))
     865              :         {
     866           14 :           const TyTy::StructFieldType *field
     867           14 :             = variant->get_field_at_index (field_index);
     868           14 :           tree field_type
     869           14 :             = TyTyResolveCompile::compile (ctx, field->get_field_type ());
     870           14 :           translated = fold_build1_loc (expr.get_locus (), VIEW_CONVERT_EXPR,
     871              :                                         field_type, receiver_ref);
     872           14 :           return;
     873              :         }
     874              :       else
     875              :         {
     876         3580 :           tree indirect = indirect_expression (receiver_ref, expr.get_locus ());
     877         3580 :           receiver_ref = indirect;
     878              :         }
     879              :     }
     880              : 
     881         5640 :   translated = Backend::struct_field_expression (receiver_ref, field_index,
     882              :                                                  expr.get_locus ());
     883              : }
     884              : 
     885              : void
     886          114 : CompileExpr::visit (HIR::QualifiedPathInExpression &expr)
     887              : {
     888          114 :   translated = ResolvePathRef::Compile (expr, ctx);
     889          114 : }
     890              : 
     891              : void
     892        43329 : CompileExpr::visit (HIR::PathInExpression &expr)
     893              : {
     894        43329 :   translated = ResolvePathRef::Compile (expr, ctx);
     895        43329 : }
     896              : 
     897              : void
     898          126 : CompileExpr::visit (HIR::LoopExpr &expr)
     899              : {
     900          126 :   TyTy::BaseType *block_tyty = nullptr;
     901          126 :   fncontext fnctx = ctx->peek_fn ();
     902          126 :   if (ctx->const_context_p () && !DECL_DECLARED_CONSTEXPR_P (fnctx.fndecl))
     903              :     {
     904            3 :       rich_location r (line_table, expr.get_locus ());
     905            3 :       rust_error_at (r, ErrorCode::E0658,
     906              :                      "%<loop%> is not allowed in const context");
     907            3 :       return;
     908            3 :     }
     909              : 
     910          123 :   if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
     911              :                                        &block_tyty))
     912              :     {
     913            0 :       rust_error_at (expr.get_locus (), "failed to lookup type of BlockExpr");
     914            0 :       return;
     915              :     }
     916              : 
     917          123 :   tree enclosing_scope = ctx->peek_enclosing_scope ();
     918          123 :   tree block_type = TyTyResolveCompile::compile (ctx, block_tyty);
     919              : 
     920          123 :   bool is_address_taken = false;
     921          123 :   tree ret_var_stmt = NULL_TREE;
     922          123 :   Bvariable *tmp
     923          123 :     = Backend::temporary_variable (fnctx.fndecl, enclosing_scope, block_type,
     924              :                                    NULL, is_address_taken, expr.get_locus (),
     925              :                                    &ret_var_stmt);
     926          123 :   ctx->add_statement (ret_var_stmt);
     927          123 :   ctx->push_loop_context (tmp);
     928              : 
     929          123 :   if (expr.has_loop_label ())
     930              :     {
     931           35 :       HIR::LoopLabel &loop_label = expr.get_loop_label ();
     932           35 :       tree label
     933           35 :         = Backend::label (fnctx.fndecl, loop_label.get_lifetime ().get_name (),
     934              :                           loop_label.get_locus ());
     935           35 :       tree label_decl = Backend::label_definition_statement (label);
     936           35 :       ctx->add_statement (label_decl);
     937           35 :       ctx->insert_label_decl (
     938           35 :         loop_label.get_lifetime ().get_mappings ().get_hirid (), label);
     939              :       // Associate the loop's result temporary with the label so that a
     940              :       // `break 'label value` can locate it (see visit (HIR::BreakExpr)).
     941           35 :       ctx->insert_var_decl (
     942           70 :         loop_label.get_lifetime ().get_mappings ().get_hirid (), tmp);
     943              :     }
     944              : 
     945          123 :   tree loop_begin_label
     946          123 :     = Backend::label (fnctx.fndecl, tl::nullopt, expr.get_locus ());
     947          123 :   tree loop_begin_label_decl
     948          123 :     = Backend::label_definition_statement (loop_begin_label);
     949          123 :   ctx->add_statement (loop_begin_label_decl);
     950          123 :   ctx->push_loop_begin_label (loop_begin_label);
     951              : 
     952          123 :   tree code_block
     953          123 :     = CompileBlock::compile (expr.get_loop_block (), ctx, nullptr);
     954          123 :   tree loop_expr = Backend::loop_expression (code_block, expr.get_locus ());
     955          123 :   ctx->add_statement (loop_expr);
     956              : 
     957          123 :   ctx->pop_loop_context ();
     958          123 :   translated = Backend::var_expression (tmp, expr.get_locus ());
     959              : 
     960          123 :   ctx->pop_loop_begin_label ();
     961              : }
     962              : 
     963              : void
     964           82 : CompileExpr::visit (HIR::WhileLoopExpr &expr)
     965              : {
     966           82 :   fncontext fnctx = ctx->peek_fn ();
     967           82 :   if (expr.has_loop_label ())
     968              :     {
     969            2 :       HIR::LoopLabel &loop_label = expr.get_loop_label ();
     970            2 :       tree label
     971            2 :         = Backend::label (fnctx.fndecl, loop_label.get_lifetime ().get_name (),
     972              :                           loop_label.get_locus ());
     973            2 :       tree label_decl = Backend::label_definition_statement (label);
     974            2 :       ctx->add_statement (label_decl);
     975            2 :       ctx->insert_label_decl (
     976            4 :         loop_label.get_lifetime ().get_mappings ().get_hirid (), label);
     977              :     }
     978              : 
     979           82 :   std::vector<Bvariable *> locals;
     980           82 :   location_t start_location = expr.get_loop_block ().get_locus ();
     981           82 :   location_t end_location = expr.get_loop_block ().get_locus (); // FIXME
     982              : 
     983           82 :   tree enclosing_scope = ctx->peek_enclosing_scope ();
     984           82 :   tree loop_block = Backend::block (fnctx.fndecl, enclosing_scope, locals,
     985              :                                     start_location, end_location);
     986           82 :   ctx->push_block (loop_block);
     987              : 
     988           82 :   tree loop_begin_label
     989           82 :     = Backend::label (fnctx.fndecl, tl::nullopt, expr.get_locus ());
     990           82 :   tree loop_begin_label_decl
     991           82 :     = Backend::label_definition_statement (loop_begin_label);
     992           82 :   ctx->add_statement (loop_begin_label_decl);
     993           82 :   ctx->push_loop_begin_label (loop_begin_label);
     994              : 
     995           82 :   HIR::Expr &predicate = expr.get_predicate_expr ();
     996           82 :   TyTy::BaseType *predicate_type = nullptr;
     997           82 :   bool ok
     998           82 :     = ctx->get_tyctx ()->lookup_type (predicate.get_mappings ().get_hirid (),
     999              :                                       &predicate_type);
    1000           82 :   rust_assert (ok && predicate_type != nullptr);
    1001           82 :   tree condition = CompileExpr::Compile (predicate, ctx);
    1002           82 :   if (predicate_type->get_kind () == TyTy::TypeKind::NEVER)
    1003              :     {
    1004            9 :       ctx->add_statement (condition);
    1005            9 :       condition = boolean_true_node;
    1006              :     }
    1007           82 :   tree exit_condition = fold_build1_loc (expr.get_locus (), TRUTH_NOT_EXPR,
    1008              :                                          boolean_type_node, condition);
    1009           82 :   tree exit_expr = Backend::exit_expression (exit_condition, expr.get_locus ());
    1010           82 :   ctx->add_statement (exit_expr);
    1011              : 
    1012           82 :   tree code_block_stmt
    1013           82 :     = CompileBlock::compile (expr.get_loop_block (), ctx, nullptr);
    1014           82 :   rust_assert (TREE_CODE (code_block_stmt) == BIND_EXPR);
    1015           82 :   ctx->add_statement (code_block_stmt);
    1016              : 
    1017           82 :   ctx->pop_loop_begin_label ();
    1018           82 :   ctx->pop_block ();
    1019              : 
    1020           82 :   tree loop_expr = Backend::loop_expression (loop_block, expr.get_locus ());
    1021           82 :   ctx->add_statement (loop_expr);
    1022           82 :   translated = unit_expression (expr.get_locus ());
    1023           82 : }
    1024              : 
    1025              : void
    1026           86 : CompileExpr::visit (HIR::BreakExpr &expr)
    1027              : {
    1028           86 :   if (expr.has_break_expr () && expr.has_label ())
    1029              :     {
    1030            4 :       HIR::Lifetime &label = expr.get_label ();
    1031            4 :       auto tvar = lookup_label_temp_var (label.get_mappings ().get_nodeid ());
    1032            4 :       tree value = CompileExpr::Compile (expr.get_expr (), ctx);
    1033            4 :       tree assign
    1034            4 :         = Backend::assignment_statement (tvar->get_tree (label.get_locus ()),
    1035              :                                          value, label.get_locus ());
    1036            4 :       tree block_label = lookup_label (label.get_mappings ().get_nodeid ());
    1037            4 :       tree go_to = Backend::goto_statement (block_label, label.get_locus ());
    1038            4 :       ctx->add_statement (assign);
    1039            4 :       ctx->add_statement (go_to);
    1040            4 :       return;
    1041              :     }
    1042           82 :   if (expr.has_break_expr ())
    1043              :     {
    1044           16 :       tree compiled_expr = CompileExpr::Compile (expr.get_expr (), ctx);
    1045           16 :       translated = error_mark_node;
    1046              : 
    1047           16 :       if (!ctx->have_loop_context ())
    1048              :         return;
    1049              : 
    1050           15 :       Bvariable *loop_result_holder = ctx->peek_loop_context ();
    1051           15 :       tree result_reference
    1052           15 :         = Backend::var_expression (loop_result_holder,
    1053           15 :                                    expr.get_expr ().get_locus ());
    1054              : 
    1055           15 :       tree assignment
    1056           15 :         = Backend::assignment_statement (result_reference, compiled_expr,
    1057              :                                          expr.get_locus ());
    1058           15 :       ctx->add_statement (assignment);
    1059              :     }
    1060              : 
    1061           81 :   if (expr.has_label ())
    1062              :     {
    1063           18 :       auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
    1064              : 
    1065           18 :       NodeId resolved_node_id;
    1066           18 :       if (auto id
    1067           18 :           = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid (),
    1068           18 :                            Resolver2_0::Namespace::Labels))
    1069              :         {
    1070           18 :           resolved_node_id = *id;
    1071              :         }
    1072              :       else
    1073              :         {
    1074            0 :           rust_error_at (
    1075            0 :             expr.get_label ().get_locus (),
    1076              :             "failed to resolve compiled label for label %s",
    1077            0 :             expr.get_label ().get_mappings ().as_string ().c_str ());
    1078            0 :           return;
    1079              :         }
    1080           18 :       tl::optional<HirId> hid
    1081           18 :         = ctx->get_mappings ().lookup_node_to_hir (resolved_node_id);
    1082           18 :       if (!hid.has_value ())
    1083              :         {
    1084            0 :           rust_fatal_error (expr.get_locus (), "reverse lookup label failure");
    1085              :           return;
    1086              :         }
    1087           18 :       auto ref = hid.value ();
    1088              : 
    1089           18 :       tree label = NULL_TREE;
    1090           18 :       if (!ctx->lookup_label_decl (ref, &label))
    1091              :         {
    1092            0 :           rust_error_at (expr.get_label ().get_locus (),
    1093              :                          "failed to lookup compiled label");
    1094            0 :           return;
    1095              :         }
    1096              : 
    1097           18 :       tree goto_label = Backend::goto_statement (label, expr.get_locus ());
    1098           18 :       ctx->add_statement (goto_label);
    1099              :     }
    1100              :   else
    1101              :     {
    1102           63 :       tree exit_expr
    1103           63 :         = Backend::exit_expression (Backend::boolean_constant_expression (true),
    1104              :                                     expr.get_locus ());
    1105           63 :       ctx->add_statement (exit_expr);
    1106              :     }
    1107              : }
    1108              : 
    1109              : void
    1110           13 : CompileExpr::visit (HIR::ContinueExpr &expr)
    1111              : {
    1112           13 :   translated = error_mark_node;
    1113           13 :   if (!ctx->have_loop_context ())
    1114            0 :     return;
    1115              : 
    1116           13 :   tree label = ctx->peek_loop_begin_label ();
    1117           13 :   if (expr.has_label ())
    1118              :     {
    1119            2 :       auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
    1120              : 
    1121            2 :       NodeId resolved_node_id;
    1122            2 :       if (auto id
    1123            2 :           = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid (),
    1124            2 :                            Resolver2_0::Namespace::Labels))
    1125              :         {
    1126            2 :           resolved_node_id = *id;
    1127              :         }
    1128              :       else
    1129              :         {
    1130            0 :           rust_error_at (
    1131            0 :             expr.get_label ().get_locus (),
    1132              :             "failed to resolve compiled label for label %s",
    1133            0 :             expr.get_label ().get_mappings ().as_string ().c_str ());
    1134            0 :           return;
    1135              :         }
    1136              : 
    1137            2 :       tl::optional<HirId> hid
    1138            2 :         = ctx->get_mappings ().lookup_node_to_hir (resolved_node_id);
    1139            2 :       if (!hid.has_value ())
    1140              :         {
    1141            0 :           rust_fatal_error (expr.get_locus (), "reverse lookup label failure");
    1142              :           return;
    1143              :         }
    1144            2 :       auto ref = hid.value ();
    1145              : 
    1146            2 :       if (!ctx->lookup_label_decl (ref, &label))
    1147              :         {
    1148            0 :           rust_error_at (expr.get_label ().get_locus (),
    1149              :                          "failed to lookup compiled label");
    1150            0 :           return;
    1151              :         }
    1152              :     }
    1153              : 
    1154           13 :   translated = Backend::goto_statement (label, expr.get_locus ());
    1155              : }
    1156              : 
    1157              : void
    1158         1895 : CompileExpr::visit (HIR::BorrowExpr &expr)
    1159              : {
    1160         1895 :   tree main_expr = CompileExpr::Compile (expr.get_expr (), ctx);
    1161         1895 :   if (RS_DST_FLAG_P (TREE_TYPE (main_expr)))
    1162              :     {
    1163           93 :       translated = main_expr;
    1164           93 :       return;
    1165              :     }
    1166              : 
    1167         1802 :   TyTy::BaseType *tyty = nullptr;
    1168         1802 :   if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
    1169              :                                        &tyty))
    1170              :     return;
    1171              : 
    1172         1802 :   tree expected_type = TyTyResolveCompile::compile (ctx, tyty);
    1173         1802 :   translated = address_expression (main_expr, expr.get_locus (), expected_type);
    1174              : }
    1175              : 
    1176              : void
    1177         3662 : CompileExpr::visit (HIR::DereferenceExpr &expr)
    1178              : {
    1179         3662 :   TyTy::BaseType *tyty = nullptr;
    1180         3662 :   if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
    1181              :                                        &tyty))
    1182              :     {
    1183            0 :       rust_fatal_error (expr.get_locus (),
    1184              :                         "did not resolve type for this TupleExpr");
    1185           35 :       return;
    1186              :     }
    1187              : 
    1188         3662 :   tree main_expr = CompileExpr::Compile (expr.get_expr (), ctx);
    1189              : 
    1190              :   // Box<T> Dereference Hook
    1191              :   // Typechecker treats 'Box<T>' as a privileged pointer and allows
    1192              :   // explicit dereferencing.However, the backend sees Box as a normal
    1193              :   // RECORD_TYPE (struct). To solve this, if the type is the 'owned_box'
    1194              :   // lang item, we drill down.
    1195         3662 :   TyTy::BaseType *base_tyty;
    1196         3662 :   if (ctx->get_tyctx ()->lookup_type (
    1197         3662 :         expr.get_expr ().get_mappings ().get_hirid (), &base_tyty))
    1198              :     {
    1199         3662 :       if (TyTy::try_get_box_inner_type (base_tyty))
    1200              :         {
    1201            1 :           main_expr = build_box_inner_ptr (main_expr, expr.get_locus ());
    1202              :         }
    1203              :     }
    1204              : 
    1205              :   // this might be an operator overload situation lets check
    1206         3662 :   TyTy::FnType *fntype;
    1207         3662 :   bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
    1208         3662 :     expr.get_mappings ().get_hirid (), &fntype);
    1209         3662 :   if (is_op_overload)
    1210              :     {
    1211           49 :       auto lang_item_type = LangItem::Kind::DEREF;
    1212           49 :       tree operator_overload_call
    1213           49 :         = resolve_operator_overload (lang_item_type, expr, main_expr, nullptr,
    1214              :                                      expr.get_expr (), tl::nullopt);
    1215              : 
    1216              :       // rust deref always returns a reference from this overload then we can
    1217              :       // actually do the indirection
    1218           49 :       main_expr = operator_overload_call;
    1219              :     }
    1220              : 
    1221         3662 :   tree expected_type = TyTyResolveCompile::compile (ctx, tyty);
    1222         3662 :   if (RS_DST_FLAG_P (TREE_TYPE (main_expr)) && RS_DST_FLAG_P (expected_type))
    1223              :     {
    1224           35 :       translated = main_expr;
    1225           35 :       return;
    1226              :     }
    1227              : 
    1228         3627 :   translated = indirect_expression (main_expr, expr.get_locus ());
    1229              : }
    1230              : 
    1231              : void
    1232        24040 : CompileExpr::visit (HIR::LiteralExpr &expr)
    1233              : {
    1234        24040 :   TyTy::BaseType *tyty = nullptr;
    1235        24040 :   if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
    1236              :                                        &tyty))
    1237        24040 :     return;
    1238              : 
    1239        24040 :   switch (expr.get_lit_type ())
    1240              :     {
    1241          904 :     case HIR::Literal::BOOL:
    1242          904 :       translated = compile_bool_literal (expr, tyty);
    1243          904 :       return;
    1244              : 
    1245        19188 :     case HIR::Literal::INT:
    1246        19188 :       translated = compile_integer_literal (expr, tyty);
    1247        19188 :       return;
    1248              : 
    1249          998 :     case HIR::Literal::FLOAT:
    1250          998 :       translated = compile_float_literal (expr, tyty);
    1251          998 :       return;
    1252              : 
    1253          183 :     case HIR::Literal::CHAR:
    1254          183 :       translated = compile_char_literal (expr, tyty);
    1255          183 :       return;
    1256              : 
    1257          408 :     case HIR::Literal::BYTE:
    1258          408 :       translated = compile_byte_literal (expr, tyty);
    1259          408 :       return;
    1260              : 
    1261         2310 :     case HIR::Literal::STRING:
    1262         2310 :       translated = compile_string_literal (expr, tyty);
    1263         2310 :       return;
    1264              : 
    1265           35 :     case HIR::Literal::BYTE_STRING:
    1266           35 :       translated = compile_byte_string_literal (expr, tyty);
    1267           35 :       return;
    1268              : 
    1269           14 :     case HIR::Literal::C_STRING:
    1270           14 :       translated = compile_c_string_literal (expr, tyty);
    1271           14 :       return;
    1272              :     }
    1273              : }
    1274              : 
    1275              : void
    1276         2433 : CompileExpr::visit (HIR::AssignmentExpr &expr)
    1277              : {
    1278         2433 :   auto lvalue = CompileExpr::Compile (expr.get_lhs (), ctx);
    1279         2433 :   auto rvalue = CompileExpr::Compile (expr.get_rhs (), ctx);
    1280              : 
    1281              :   // assignments are coercion sites so lets convert the rvalue if necessary
    1282         2433 :   TyTy::BaseType *expected = nullptr;
    1283         2433 :   TyTy::BaseType *actual = nullptr;
    1284              : 
    1285         2433 :   bool ok;
    1286         2433 :   ok = ctx->get_tyctx ()->lookup_type (
    1287         2433 :     expr.get_lhs ().get_mappings ().get_hirid (), &expected);
    1288         2433 :   rust_assert (ok);
    1289              : 
    1290         2433 :   ok = ctx->get_tyctx ()->lookup_type (
    1291         2433 :     expr.get_rhs ().get_mappings ().get_hirid (), &actual);
    1292         2433 :   rust_assert (ok);
    1293              : 
    1294         2433 :   rvalue = coercion_site (expr.get_mappings ().get_hirid (), rvalue, actual,
    1295         2433 :                           expected, expr.get_lhs ().get_locus (),
    1296         2433 :                           expr.get_rhs ().get_locus ());
    1297              : 
    1298              :   // rust_debug_loc (expr.get_locus (), "XXXXXX assignment");
    1299              :   // debug_tree (rvalue);
    1300              :   // debug_tree (lvalue);
    1301              : 
    1302         2433 :   tree assignment
    1303         2433 :     = Backend::assignment_statement (lvalue, rvalue, expr.get_locus ());
    1304              : 
    1305         2433 :   ctx->add_statement (assignment);
    1306         2433 :   translated = unit_expression (expr.get_locus ());
    1307         2433 : }
    1308              : 
    1309              : // Helper for CompileExpr::visit (HIR::MatchExpr).
    1310              : // Check that the scrutinee of EXPR is a valid kind of expression to match on.
    1311              : // Return the TypeKind of the scrutinee if it is valid, or TyTy::TypeKind::ERROR
    1312              : // if not.
    1313              : static TyTy::TypeKind
    1314          874 : check_match_scrutinee (HIR::MatchExpr &expr, Context *ctx)
    1315              : {
    1316          874 :   TyTy::BaseType *scrutinee_expr_tyty = nullptr;
    1317          874 :   if (!ctx->get_tyctx ()->lookup_type (
    1318          874 :         expr.get_scrutinee_expr ().get_mappings ().get_hirid (),
    1319              :         &scrutinee_expr_tyty))
    1320              :     {
    1321              :       return TyTy::TypeKind::ERROR;
    1322              :     }
    1323              : 
    1324          874 :   TyTy::TypeKind scrutinee_kind = scrutinee_expr_tyty->get_kind ();
    1325              : 
    1326          874 :   if (scrutinee_kind == TyTy::TypeKind::FLOAT)
    1327              :     {
    1328              :       // FIXME: CASE_LABEL_EXPR does not support floating point types.
    1329              :       // Find another way to compile these.
    1330            2 :       rust_sorry_at (expr.get_locus (),
    1331              :                      "match on floating-point types is not yet supported");
    1332              :     }
    1333              : 
    1334          874 :   TyTy::BaseType *expr_tyty = nullptr;
    1335          874 :   if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
    1336              :                                        &expr_tyty))
    1337              :     {
    1338              :       return TyTy::TypeKind::ERROR;
    1339              :     }
    1340              : 
    1341              :   return scrutinee_kind;
    1342              : }
    1343              : 
    1344              : void
    1345          874 : CompileExpr::visit (HIR::MatchExpr &expr)
    1346              : {
    1347              :   // https://gcc.gnu.org/onlinedocs/gccint/Basic-Statements.html#Basic-Statements
    1348              :   // TODO
    1349              :   // SWITCH_ALL_CASES_P is true if the switch includes a default label or the
    1350              :   // case label ranges cover all possible values of the condition expression
    1351              : 
    1352          874 :   TyTy::TypeKind scrutinee_kind = check_match_scrutinee (expr, ctx);
    1353          874 :   if (scrutinee_kind == TyTy::TypeKind::ERROR)
    1354              :     {
    1355            0 :       translated = error_mark_node;
    1356            4 :       return;
    1357              :     }
    1358              : 
    1359          874 :   TyTy::BaseType *expr_tyty = nullptr;
    1360          874 :   if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
    1361              :                                        &expr_tyty))
    1362              :     {
    1363            0 :       translated = error_mark_node;
    1364            0 :       return;
    1365              :     }
    1366              : 
    1367              :   // if the result of this expression is meant to be never type then we can
    1368              :   // optimise this away but there is the case where match arms resolve to !
    1369              :   // because of return statements we need to special case this
    1370          874 :   if (!expr.has_match_arms () && expr_tyty->is<TyTy::NeverType> ())
    1371              :     {
    1372            4 :       translated = unit_expression (expr.get_locus ());
    1373            4 :       return;
    1374              :     }
    1375              : 
    1376          870 :   fncontext fnctx = ctx->peek_fn ();
    1377          870 :   Bvariable *tmp = NULL;
    1378          870 :   tree enclosing_scope = ctx->peek_enclosing_scope ();
    1379          870 :   tree block_type = TyTyResolveCompile::compile (ctx, expr_tyty);
    1380              : 
    1381          870 :   bool is_address_taken = false;
    1382          870 :   tree ret_var_stmt = nullptr;
    1383          870 :   tmp = Backend::temporary_variable (fnctx.fndecl, enclosing_scope, block_type,
    1384              :                                      NULL, is_address_taken, expr.get_locus (),
    1385              :                                      &ret_var_stmt);
    1386          870 :   ctx->add_statement (ret_var_stmt);
    1387              : 
    1388              :   // lets compile the scrutinee expression
    1389          870 :   tree match_scrutinee_rval
    1390          870 :     = CompileExpr::Compile (expr.get_scrutinee_expr (), ctx);
    1391              : 
    1392          870 :   Bvariable *match_scrutinee_tmp_var
    1393          870 :     = Backend::temporary_variable (fnctx.fndecl, enclosing_scope,
    1394          870 :                                    TREE_TYPE (match_scrutinee_rval), NULL,
    1395              :                                    is_address_taken, expr.get_locus (),
    1396              :                                    &ret_var_stmt);
    1397          870 :   ctx->add_statement (ret_var_stmt);
    1398              : 
    1399          870 :   tree match_scrutinee_expr = match_scrutinee_tmp_var->get_tree (
    1400          870 :     expr.get_scrutinee_expr ().get_locus ());
    1401              : 
    1402          870 :   tree assignment
    1403          870 :     = Backend::assignment_statement (match_scrutinee_expr, match_scrutinee_rval,
    1404              :                                      expr.get_locus ());
    1405          870 :   ctx->add_statement (assignment);
    1406              : 
    1407              :   // setup the end label so the cases can exit properly
    1408          870 :   tree fndecl = fnctx.fndecl;
    1409          870 :   location_t end_label_locus = expr.get_locus (); // FIXME
    1410              :   // tl::nullopt creates an artificial label
    1411          870 :   tree end_label = Backend::label (fndecl, tl::nullopt, end_label_locus);
    1412          870 :   tree end_label_decl_statement
    1413          870 :     = Backend::label_definition_statement (end_label);
    1414              : 
    1415         2940 :   for (auto &kase : expr.get_match_cases ())
    1416              :     {
    1417              :       // for now lets just get single pattern's working
    1418         2070 :       HIR::MatchArm &kase_arm = kase.get_arm ();
    1419         2070 :       rust_assert (kase_arm.get_pattern () != nullptr);
    1420              : 
    1421         2070 :       auto &kase_pattern = kase_arm.get_pattern ();
    1422              :       // setup the match-arm-body-block
    1423         2070 :       location_t start_location = UNKNOWN_LOCATION; // FIXME
    1424         2070 :       location_t end_location = UNKNOWN_LOCATION;   // FIXME
    1425         2070 :       tree arm_body_block = Backend::block (fndecl, enclosing_scope, {},
    1426              :                                             start_location, end_location);
    1427              : 
    1428         2070 :       ctx->push_block (arm_body_block);
    1429              : 
    1430              :       // setup the bindings for the block
    1431         2070 :       CompilePatternBindings::Compile (*kase_pattern, match_scrutinee_expr,
    1432              :                                        ctx);
    1433              : 
    1434              :       // compile the expr and setup the assignment if required when tmp !=
    1435              :       // NULL
    1436         2070 :       location_t arm_locus = kase_arm.get_locus ();
    1437         2070 :       tree kase_expr_tree = CompileExpr::Compile (kase.get_expr (), ctx);
    1438         2070 :       tree result_reference = Backend::var_expression (tmp, arm_locus);
    1439              : 
    1440         2070 :       TyTy::BaseType *actual = nullptr;
    1441         2070 :       bool ok = ctx->get_tyctx ()->lookup_type (
    1442         2070 :         kase.get_expr ().get_mappings ().get_hirid (), &actual);
    1443         2070 :       rust_assert (ok);
    1444              : 
    1445         2070 :       tree coerced_result
    1446         2070 :         = coercion_site (kase.get_expr ().get_mappings ().get_hirid (),
    1447              :                          kase_expr_tree, actual, expr_tyty, expr.get_locus (),
    1448              :                          arm_locus);
    1449              : 
    1450         2070 :       tree assignment
    1451         2070 :         = Backend::assignment_statement (result_reference, coerced_result,
    1452              :                                          arm_locus);
    1453         2070 :       ctx->add_statement (assignment);
    1454              : 
    1455              :       // go to end label
    1456         2070 :       tree goto_end_label
    1457         2070 :         = build1_loc (arm_locus, GOTO_EXPR, void_type_node, end_label);
    1458         2070 :       ctx->add_statement (goto_end_label);
    1459              : 
    1460         2070 :       ctx->pop_block ();
    1461              : 
    1462         2070 :       tree check_expr
    1463         2070 :         = CompilePatternCheckExpr::Compile (*kase_pattern, match_scrutinee_expr,
    1464              :                                             ctx);
    1465              : 
    1466         2070 :       tree check_stmt
    1467         2070 :         = Backend::if_statement (NULL_TREE, check_expr, arm_body_block,
    1468         2070 :                                  NULL_TREE, kase_pattern->get_locus ());
    1469              : 
    1470         2070 :       ctx->add_statement (check_stmt);
    1471              :     }
    1472              : 
    1473              :   // setup the switch expression
    1474          870 :   ctx->add_statement (end_label_decl_statement);
    1475              : 
    1476          870 :   translated = Backend::var_expression (tmp, expr.get_locus ());
    1477              : }
    1478              : 
    1479              : void
    1480        12318 : CompileExpr::visit (HIR::CallExpr &expr)
    1481              : {
    1482        12318 :   TyTy::BaseType *tyty = nullptr;
    1483        12318 :   if (!ctx->get_tyctx ()->lookup_type (
    1484        12318 :         expr.get_fnexpr ().get_mappings ().get_hirid (), &tyty))
    1485              :     {
    1486            0 :       rust_error_at (expr.get_locus (), "unknown type");
    1487         1810 :       return;
    1488              :     }
    1489              : 
    1490              :   // must be a tuple constructor
    1491        12318 :   bool is_adt_ctor = tyty->get_kind () == TyTy::TypeKind::ADT;
    1492        12318 :   if (is_adt_ctor)
    1493              :     {
    1494         1748 :       rust_assert (tyty->get_kind () == TyTy::TypeKind::ADT);
    1495         1748 :       TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyty);
    1496         1748 :       tree compiled_adt_type = TyTyResolveCompile::compile (ctx, tyty);
    1497              : 
    1498              :       // what variant is it?
    1499         1748 :       int union_disriminator = -1;
    1500         1748 :       TyTy::VariantDef *variant = nullptr;
    1501         1748 :       if (!adt->is_enum ())
    1502              :         {
    1503          924 :           rust_assert (adt->number_of_variants () == 1);
    1504          924 :           variant = adt->get_variants ().at (0);
    1505              :         }
    1506              :       else
    1507              :         {
    1508          824 :           HirId variant_id;
    1509          824 :           bool ok = ctx->get_tyctx ()->lookup_variant_definition (
    1510          824 :             expr.get_fnexpr ().get_mappings ().get_hirid (), &variant_id);
    1511          824 :           rust_assert (ok);
    1512              : 
    1513          824 :           ok = adt->lookup_variant_by_id (variant_id, &variant,
    1514              :                                           &union_disriminator);
    1515          824 :           rust_assert (ok);
    1516              :         }
    1517              : 
    1518              :       // this assumes all fields are in order from type resolution and if a
    1519              :       // base struct was specified those fields are filed via accessors
    1520         1748 :       std::vector<tree> arguments;
    1521         4030 :       for (size_t i = 0; i < expr.num_params (); i++)
    1522              :         {
    1523         2282 :           auto &argument = expr.get_arguments ().at (i);
    1524         2282 :           auto rvalue = CompileExpr::Compile (*argument, ctx);
    1525              : 
    1526              :           // assignments are coercion sites so lets convert the rvalue if
    1527              :           // necessary
    1528         2282 :           auto respective_field = variant->get_field_at_index (i);
    1529         2282 :           auto expected = respective_field->get_field_type ();
    1530              : 
    1531         2282 :           TyTy::BaseType *actual = nullptr;
    1532         2282 :           bool ok = ctx->get_tyctx ()->lookup_type (
    1533         2282 :             argument->get_mappings ().get_hirid (), &actual);
    1534         2282 :           rust_assert (ok);
    1535              : 
    1536              :           // coerce it if required
    1537         2282 :           location_t lvalue_locus
    1538         2282 :             = ctx->get_mappings ().lookup_location (expected->get_ty_ref ());
    1539         2282 :           location_t rvalue_locus = argument->get_locus ();
    1540         2282 :           rvalue
    1541         2282 :             = coercion_site (argument->get_mappings ().get_hirid (), rvalue,
    1542              :                              actual, expected, lvalue_locus, rvalue_locus);
    1543              : 
    1544              :           // add it to the list
    1545         2282 :           arguments.push_back (rvalue);
    1546              :         }
    1547              : 
    1548         1748 :       if (!adt->is_enum ())
    1549              :         {
    1550          924 :           translated
    1551         1848 :             = Backend::constructor_expression (compiled_adt_type,
    1552          924 :                                                adt->is_enum (), arguments,
    1553              :                                                union_disriminator,
    1554              :                                                expr.get_locus ());
    1555          924 :           return;
    1556              :         }
    1557              : 
    1558          824 :       HIR::Expr &discrim_expr = variant->get_discriminant ();
    1559          824 :       tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
    1560          824 :       tree folded_discrim_expr = fold_expr (discrim_expr_node);
    1561          824 :       tree qualifier = folded_discrim_expr;
    1562              : 
    1563          824 :       tree enum_root_files = TYPE_FIELDS (compiled_adt_type);
    1564          824 :       tree payload_root = DECL_CHAIN (enum_root_files);
    1565              : 
    1566          824 :       tree payload
    1567          824 :         = Backend::constructor_expression (TREE_TYPE (payload_root), true,
    1568              :                                            {arguments}, union_disriminator,
    1569              :                                            expr.get_locus ());
    1570              : 
    1571          824 :       std::vector<tree> ctor_arguments = {qualifier, payload};
    1572          824 :       translated = Backend::constructor_expression (compiled_adt_type, false,
    1573              :                                                     ctor_arguments, -1,
    1574              :                                                     expr.get_locus ());
    1575              : 
    1576          824 :       return;
    1577         2572 :     }
    1578              : 
    1579        10570 :   auto get_parameter_tyty_at_index
    1580        10468 :     = [] (const TyTy::BaseType *base, size_t index,
    1581              :           TyTy::BaseType **result) -> bool {
    1582        10468 :     bool is_fn = base->get_kind () == TyTy::TypeKind::FNDEF
    1583        10468 :                  || base->get_kind () == TyTy::TypeKind::FNPTR;
    1584            0 :     rust_assert (is_fn);
    1585              : 
    1586        10468 :     if (base->get_kind () == TyTy::TypeKind::FNPTR)
    1587              :       {
    1588           28 :         const TyTy::FnPtr *fn = static_cast<const TyTy::FnPtr *> (base);
    1589           28 :         *result = fn->get_param_type_at (index);
    1590              : 
    1591           28 :         return true;
    1592              :       }
    1593              : 
    1594        10440 :     const TyTy::FnType *fn = static_cast<const TyTy::FnType *> (base);
    1595        10440 :     auto &param = fn->param_at (index);
    1596        10440 :     *result = param.get_type ();
    1597              : 
    1598        10440 :     return true;
    1599              :   };
    1600              : 
    1601        10570 :   auto fn_address = CompileExpr::Compile (expr.get_fnexpr (), ctx);
    1602        10570 :   if (ctx->const_context_p ())
    1603              :     {
    1604          871 :       if (!FUNCTION_POINTER_TYPE_P (TREE_TYPE (fn_address)))
    1605              :         {
    1606            1 :           rust_error_at (expr.get_locus (),
    1607              :                          "calls in constants are limited to constant "
    1608              :                          "functions, tuple structs and tuple variants");
    1609            1 :           return;
    1610              :         }
    1611              : 
    1612          870 :       if (TREE_CODE (fn_address) == ADDR_EXPR)
    1613              :         {
    1614          870 :           tree fndecl = TREE_OPERAND (fn_address, 0);
    1615          870 :           if (!DECL_DECLARED_CONSTEXPR_P (fndecl))
    1616              :             {
    1617            1 :               rust_error_at (expr.get_locus (),
    1618              :                              "calls in constants are limited to constant "
    1619              :                              "functions, tuple structs and tuple variants");
    1620            1 :               return;
    1621              :             }
    1622              :         }
    1623              :     }
    1624              : 
    1625              :   // is this a closure call?
    1626        10568 :   bool possible_trait_call
    1627        10568 :     = generate_possible_fn_trait_call (expr, fn_address, &translated);
    1628        10568 :   if (possible_trait_call)
    1629              :     return;
    1630              : 
    1631        10508 :   bool is_variadic = false;
    1632        10508 :   size_t required_num_args = expr.get_arguments ().size ();
    1633              : 
    1634        10508 :   if (tyty->get_kind () == TyTy::TypeKind::FNDEF)
    1635              :     {
    1636        10480 :       const TyTy::FnType *fn = static_cast<const TyTy::FnType *> (tyty);
    1637        10480 :       required_num_args = fn->num_params ();
    1638        10480 :       is_variadic = fn->is_variadic ();
    1639              :     }
    1640           28 :   else if (tyty->get_kind () == TyTy::TypeKind::FNPTR)
    1641              :     {
    1642           28 :       const TyTy::FnPtr *fn = static_cast<const TyTy::FnPtr *> (tyty);
    1643           28 :       required_num_args = fn->num_params ();
    1644              :     }
    1645              : 
    1646        10508 :   std::vector<tree> args;
    1647        21754 :   for (size_t i = 0; i < expr.get_arguments ().size (); i++)
    1648              :     {
    1649        11246 :       auto &argument = expr.get_arguments ().at (i);
    1650        11246 :       auto rvalue = CompileExpr::Compile (*argument, ctx);
    1651              : 
    1652        11246 :       if (is_variadic && i >= required_num_args)
    1653              :         {
    1654          778 :           args.push_back (rvalue);
    1655          778 :           continue;
    1656              :         }
    1657              : 
    1658              :       // assignments are coercion sites so lets convert the rvalue if
    1659              :       // necessary
    1660        10468 :       bool ok;
    1661        10468 :       TyTy::BaseType *expected = nullptr;
    1662        10468 :       ok = get_parameter_tyty_at_index (tyty, i, &expected);
    1663        10468 :       rust_assert (ok);
    1664              : 
    1665        10468 :       TyTy::BaseType *actual = nullptr;
    1666        10468 :       ok = ctx->get_tyctx ()->lookup_type (
    1667        10468 :         argument->get_mappings ().get_hirid (), &actual);
    1668        10468 :       rust_assert (ok);
    1669              : 
    1670              :       // coerce it if required
    1671        10468 :       location_t lvalue_locus
    1672        10468 :         = ctx->get_mappings ().lookup_location (expected->get_ty_ref ());
    1673        10468 :       location_t rvalue_locus = argument->get_locus ();
    1674        10468 :       rvalue = coercion_site (argument->get_mappings ().get_hirid (), rvalue,
    1675              :                               actual, expected, lvalue_locus, rvalue_locus);
    1676              : 
    1677              :       // add it to the list
    1678        10468 :       args.push_back (rvalue);
    1679              :     }
    1680              : 
    1681              :   // must be a regular call to a function
    1682        10508 :   translated
    1683        10508 :     = Backend::call_expression (fn_address, args, nullptr, expr.get_locus ());
    1684        10508 : }
    1685              : 
    1686              : void
    1687         2579 : CompileExpr::visit (HIR::MethodCallExpr &expr)
    1688              : {
    1689              :   // method receiver
    1690         2579 :   tree self = CompileExpr::Compile (expr.get_receiver (), ctx);
    1691              : 
    1692              :   // lookup the expected function type
    1693         2579 :   TyTy::BaseType *lookup_fntype = nullptr;
    1694         2579 :   bool ok = ctx->get_tyctx ()->lookup_type (
    1695         2579 :     expr.get_method_name ().get_mappings ().get_hirid (), &lookup_fntype);
    1696         2579 :   rust_assert (ok);
    1697         2579 :   rust_assert (lookup_fntype->get_kind () == TyTy::TypeKind::FNDEF);
    1698         2579 :   TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup_fntype);
    1699              : 
    1700         2579 :   TyTy::BaseType *receiver = nullptr;
    1701         2579 :   ok = ctx->get_tyctx ()->lookup_type (
    1702         2579 :     expr.get_receiver ().get_mappings ().get_hirid (), &receiver);
    1703         2579 :   rust_assert (ok);
    1704              : 
    1705         2579 :   bool is_dyn_dispatch
    1706         2579 :     = receiver->get_root ()->get_kind () == TyTy::TypeKind::DYNAMIC;
    1707         2579 :   bool is_generic_receiver = receiver->get_kind () == TyTy::TypeKind::PARAM;
    1708         2579 :   if (is_generic_receiver)
    1709              :     {
    1710          193 :       TyTy::ParamType *p = static_cast<TyTy::ParamType *> (receiver);
    1711          193 :       receiver = p->resolve ();
    1712              :     }
    1713              : 
    1714         2579 :   tree fn_expr = error_mark_node;
    1715         2579 :   if (is_dyn_dispatch)
    1716              :     {
    1717          207 :       const TyTy::DynamicObjectType *dyn
    1718          207 :         = static_cast<const TyTy::DynamicObjectType *> (receiver->get_root ());
    1719          207 :       fn_expr
    1720          207 :         = get_fn_addr_from_dyn (dyn, receiver, fntype, self, expr.get_locus ());
    1721          207 :       self = get_receiver_from_dyn (dyn, receiver, fntype, self,
    1722              :                                     expr.get_locus ());
    1723              :     }
    1724              :   else
    1725              :     // lookup compiled functions since it may have already been compiled
    1726         2372 :     fn_expr = resolve_method_address (fntype, receiver, expr.get_locus ());
    1727              : 
    1728              :   // lookup the autoderef mappings
    1729         2579 :   HirId autoderef_mappings_id
    1730         2579 :     = expr.get_receiver ().get_mappings ().get_hirid ();
    1731         2579 :   std::vector<Resolver::Adjustment> *adjustments = nullptr;
    1732         2579 :   ok = ctx->get_tyctx ()->lookup_autoderef_mappings (autoderef_mappings_id,
    1733              :                                                      &adjustments);
    1734         2579 :   rust_assert (ok);
    1735              : 
    1736              :   // apply adjustments for the fn call
    1737         2579 :   self = resolve_adjustements (*adjustments, self,
    1738         2579 :                                expr.get_receiver ().get_locus ());
    1739              : 
    1740         2579 :   std::vector<tree> args;
    1741         2579 :   args.push_back (self); // adjusted self
    1742              : 
    1743              :   // normal args
    1744         4262 :   for (size_t i = 0; i < expr.get_arguments ().size (); i++)
    1745              :     {
    1746         1683 :       auto &argument = expr.get_arguments ().at (i);
    1747         1683 :       auto rvalue = CompileExpr::Compile (*argument, ctx);
    1748              : 
    1749              :       // assignments are coercion sites so lets convert the rvalue if
    1750              :       // necessary, offset from the already adjusted implicit self
    1751         1683 :       bool ok;
    1752         1683 :       TyTy::BaseType *expected = fntype->param_at (i + 1).get_type ();
    1753              : 
    1754         1683 :       TyTy::BaseType *actual = nullptr;
    1755         1683 :       ok = ctx->get_tyctx ()->lookup_type (
    1756         1683 :         argument->get_mappings ().get_hirid (), &actual);
    1757         1683 :       rust_assert (ok);
    1758              : 
    1759              :       // coerce it if required
    1760         1683 :       location_t lvalue_locus
    1761         1683 :         = ctx->get_mappings ().lookup_location (expected->get_ty_ref ());
    1762         1683 :       location_t rvalue_locus = argument->get_locus ();
    1763         1683 :       rvalue = coercion_site (argument->get_mappings ().get_hirid (), rvalue,
    1764              :                               actual, expected, lvalue_locus, rvalue_locus);
    1765              : 
    1766              :       // add it to the list
    1767         1683 :       args.push_back (rvalue);
    1768              :     }
    1769              : 
    1770         2579 :   translated
    1771         2579 :     = Backend::call_expression (fn_expr, args, nullptr, expr.get_locus ());
    1772         2579 : }
    1773              : 
    1774              : tree
    1775          207 : CompileExpr::get_fn_addr_from_dyn (const TyTy::DynamicObjectType *dyn,
    1776              :                                    TyTy::BaseType *receiver,
    1777              :                                    TyTy::FnType *fntype, tree receiver_ref,
    1778              :                                    location_t expr_locus)
    1779              : {
    1780          207 :   size_t offs = 0;
    1781          207 :   const Resolver::TraitItemReference *ref = nullptr;
    1782          265 :   for (auto &bound : dyn->get_object_items ())
    1783              :     {
    1784          265 :       const Resolver::TraitItemReference *item = bound.first;
    1785          265 :       auto t = item->get_tyty ();
    1786          265 :       rust_assert (t->get_kind () == TyTy::TypeKind::FNDEF);
    1787          265 :       auto ft = static_cast<TyTy::FnType *> (t);
    1788              : 
    1789          472 :       if (ft->get_id () == fntype->get_id ())
    1790              :         {
    1791              :           ref = item;
    1792              :           break;
    1793              :         }
    1794           58 :       offs++;
    1795          207 :     }
    1796              : 
    1797          207 :   if (ref == nullptr)
    1798            0 :     return error_mark_node;
    1799              : 
    1800              :   // cast it to the correct fntype
    1801          207 :   tree expected_fntype = TyTyResolveCompile::compile (ctx, fntype, true);
    1802          207 :   tree idx = build_int_cst (size_type_node, offs);
    1803              : 
    1804          207 :   tree vtable_ptr
    1805          207 :     = Backend::struct_field_expression (receiver_ref, 1, expr_locus);
    1806          207 :   tree vtable_struct_type = TREE_TYPE (TREE_TYPE (vtable_ptr));
    1807          207 :   rust_assert (TREE_CODE (vtable_struct_type) == RECORD_TYPE);
    1808          207 :   tree vtable_field = TYPE_FIELDS (vtable_struct_type);
    1809          886 :   for (size_t i = 0; i < offs + 3; i++) // drop, size, align, [methods]
    1810          679 :     vtable_field = DECL_CHAIN (vtable_field);
    1811          207 :   rust_assert (vtable_field != NULL_TREE);
    1812          207 :   tree vtable = build_fold_indirect_ref_loc (expr_locus, vtable_ptr);
    1813          207 :   tree vtable_field_access
    1814          207 :     = build3_loc (expr_locus, COMPONENT_REF, TREE_TYPE (vtable_field), vtable,
    1815              :                   vtable_field, NULL_TREE);
    1816              : 
    1817          207 :   tree vcall = build3_loc (expr_locus, OBJ_TYPE_REF, expected_fntype,
    1818              :                            vtable_field_access, receiver_ref, idx);
    1819              : 
    1820          207 :   return vcall;
    1821              : }
    1822              : 
    1823              : tree
    1824          207 : CompileExpr::get_receiver_from_dyn (const TyTy::DynamicObjectType *dyn,
    1825              :                                     TyTy::BaseType *receiver,
    1826              :                                     TyTy::FnType *fntype, tree receiver_ref,
    1827              :                                     location_t expr_locus)
    1828              : {
    1829              :   // access the offs + 1 for the fnptr and offs=0 for the reciever obj
    1830          207 :   return Backend::struct_field_expression (receiver_ref, 0, expr_locus);
    1831              : }
    1832              : 
    1833              : tree
    1834         1146 : CompileExpr::resolve_operator_overload (
    1835              :   LangItem::Kind lang_item_type, HIR::OperatorExprMeta expr, tree lhs, tree rhs,
    1836              :   HIR::Expr &lhs_expr, tl::optional<std::reference_wrapper<HIR::Expr>> rhs_expr,
    1837              :   HIR::PathIdentSegment specified_segment)
    1838              : {
    1839         1146 :   TyTy::FnType *fntype;
    1840         1146 :   bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
    1841         1146 :     expr.get_mappings ().get_hirid (), &fntype);
    1842         1146 :   rust_assert (is_op_overload);
    1843              : 
    1844         1146 :   TyTy::BaseType *receiver = nullptr;
    1845         1146 :   bool ok
    1846         1146 :     = ctx->get_tyctx ()->lookup_type (lhs_expr.get_mappings ().get_hirid (),
    1847              :                                       &receiver);
    1848         1146 :   rust_assert (ok);
    1849              : 
    1850         1146 :   bool is_generic_receiver = receiver->get_kind () == TyTy::TypeKind::PARAM;
    1851         1146 :   if (is_generic_receiver)
    1852              :     {
    1853           14 :       TyTy::ParamType *p = static_cast<TyTy::ParamType *> (receiver);
    1854           14 :       receiver = p->resolve ();
    1855              :     }
    1856              : 
    1857              :   // lookup compiled functions since it may have already been compiled
    1858         1146 :   HIR::PathIdentSegment segment_name
    1859         1146 :     = specified_segment.is_error ()
    1860         1452 :         ? HIR::PathIdentSegment (LangItem::ToString (lang_item_type))
    1861         1146 :         : specified_segment;
    1862         1146 :   tree fn_expr = resolve_method_address (fntype, receiver, expr.get_locus ());
    1863              : 
    1864              :   // lookup the autoderef mappings
    1865         1146 :   std::vector<Resolver::Adjustment> *adjustments = nullptr;
    1866         1146 :   ok = ctx->get_tyctx ()->lookup_autoderef_mappings (
    1867         1146 :     expr.get_lvalue_mappings ().get_hirid (), &adjustments);
    1868         1146 :   rust_assert (ok);
    1869              : 
    1870              :   // apply adjustments for the fn call
    1871         1146 :   tree self = resolve_adjustements (*adjustments, lhs, lhs_expr.get_locus ());
    1872              : 
    1873         1146 :   std::vector<tree> args;
    1874         1146 :   args.push_back (self); // adjusted self
    1875         1146 :   if (rhs != nullptr)    // can be null for negation_expr (unary ones)
    1876         1083 :     args.push_back (rhs);
    1877              : 
    1878         1146 :   return Backend::call_expression (fn_expr, args, nullptr, expr.get_locus ());
    1879         1146 : }
    1880              : 
    1881              : tree
    1882          904 : CompileExpr::compile_bool_literal (const HIR::LiteralExpr &expr,
    1883              :                                    const TyTy::BaseType *tyty)
    1884              : {
    1885          904 :   rust_assert (expr.get_lit_type () == HIR::Literal::BOOL);
    1886              : 
    1887          904 :   const auto literal_value = expr.get_literal ();
    1888         1808 :   bool bval = literal_value.as_string ().compare ("true") == 0;
    1889          904 :   return Backend::boolean_constant_expression (bval);
    1890          904 : }
    1891              : 
    1892              : tree
    1893        19188 : CompileExpr::compile_integer_literal (const HIR::LiteralExpr &expr,
    1894              :                                       const TyTy::BaseType *tyty)
    1895              : {
    1896        19188 :   rust_assert (expr.get_lit_type () == HIR::Literal::INT);
    1897        19188 :   const auto &literal_value = expr.get_literal ();
    1898        19188 :   tree type = TyTyResolveCompile::compile (ctx, tyty);
    1899              : 
    1900        19188 :   std::string s = literal_value.as_string ();
    1901        19188 :   s.erase (std::remove (s.begin (), s.end (), '_'), s.end ());
    1902              : 
    1903        19188 :   int base = 0;
    1904        19188 :   mpz_t ival;
    1905        19188 :   if (mpz_init_set_str (ival, s.c_str (), base) != 0)
    1906              :     {
    1907            0 :       rust_error_at (expr.get_locus (), "failed to load number literal");
    1908            0 :       return error_mark_node;
    1909              :     }
    1910        19188 :   if (expr.is_negative ())
    1911          660 :     mpz_neg (ival, ival);
    1912              : 
    1913        19188 :   mpz_t type_min, type_max;
    1914        19188 :   mpz_init (type_min);
    1915        19188 :   mpz_init (type_max);
    1916        19188 :   get_type_static_bounds (type, type_min, type_max);
    1917              : 
    1918        19188 :   if (mpz_cmp (ival, type_min) < 0 || mpz_cmp (ival, type_max) > 0)
    1919              :     {
    1920            2 :       rust_error_at (expr.get_locus (),
    1921              :                      "integer overflows the respective type %qs",
    1922            2 :                      tyty->get_name ().c_str ());
    1923            2 :       mpz_clear (type_min);
    1924            2 :       mpz_clear (type_max);
    1925            2 :       mpz_clear (ival);
    1926            2 :       return error_mark_node;
    1927              :     }
    1928              : 
    1929        19186 :   tree result = wide_int_to_tree (type, wi::from_mpz (type, ival, true));
    1930        19186 :   mpz_clear (type_min);
    1931        19186 :   mpz_clear (type_max);
    1932        19186 :   mpz_clear (ival);
    1933              : 
    1934        19186 :   return result;
    1935        19188 : }
    1936              : 
    1937              : tree
    1938          998 : CompileExpr::compile_float_literal (const HIR::LiteralExpr &expr,
    1939              :                                     const TyTy::BaseType *tyty)
    1940              : {
    1941          998 :   rust_assert (expr.get_lit_type () == HIR::Literal::FLOAT);
    1942          998 :   const auto literal_value = expr.get_literal ();
    1943              : 
    1944          998 :   tree type = TyTyResolveCompile::compile (ctx, tyty);
    1945              : 
    1946          998 :   mpfr_t fval;
    1947         2994 :   if (mpfr_init_set_str (fval, literal_value.as_string ().c_str (), 10,
    1948              :                          MPFR_RNDN)
    1949          998 :       != 0)
    1950              :     {
    1951            0 :       rust_error_at (expr.get_locus (), "bad number in literal");
    1952            0 :       return error_mark_node;
    1953              :     }
    1954          998 :   if (expr.is_negative ())
    1955            6 :     mpfr_neg (fval, fval, MPFR_RNDN);
    1956              : 
    1957              :   // taken from:
    1958              :   // see go/gofrontend/expressions.cc:check_float_type
    1959          998 :   bool real_value_overflow;
    1960              : 
    1961          998 :   if (mpfr_regular_p (fval) != 0)
    1962              :     {
    1963          893 :       mpfr_exp_t exp = mpfr_get_exp (fval);
    1964          893 :       mpfr_exp_t min_exp;
    1965          893 :       mpfr_exp_t max_exp;
    1966              : 
    1967              :       /*
    1968              :        * By convention, the radix point of the significand is just before the
    1969              :        * first digit (which is always 1 due to normalization), like in the C
    1970              :        * language, but unlike in IEEE 754 (thus, for a given number, the
    1971              :        * exponent values in MPFR and in IEEE 754 differ by 1).
    1972              :        */
    1973          893 :       switch (TYPE_PRECISION (type))
    1974              :         {
    1975              :         case 32:
    1976              :           min_exp = -128 + 1;
    1977              :           max_exp = 127 + 1;
    1978              :           break;
    1979          321 :         case 64:
    1980          321 :           min_exp = -1024 + 1;
    1981          321 :           max_exp = 1023 + 1;
    1982          321 :           break;
    1983            0 :         default:
    1984            0 :           rust_error_at (expr.get_locus (),
    1985              :                          "precision of type %<%s%> not supported",
    1986            0 :                          tyty->get_name ().c_str ());
    1987            0 :           return error_mark_node;
    1988              :         }
    1989          893 :       real_value_overflow = exp < min_exp || exp > max_exp;
    1990              :     }
    1991              :   else
    1992              :     {
    1993              :       real_value_overflow = false;
    1994              :     }
    1995              : 
    1996          998 :   REAL_VALUE_TYPE r1;
    1997          998 :   real_from_mpfr (&r1, fval, type, GMP_RNDN);
    1998          998 :   REAL_VALUE_TYPE r2;
    1999          998 :   real_convert (&r2, TYPE_MODE (type), &r1);
    2000              : 
    2001          998 :   tree real_value = build_real (type, r2);
    2002          998 :   if (TREE_OVERFLOW (real_value) || real_value_overflow)
    2003              :     {
    2004            1 :       rust_error_at (expr.get_locus (),
    2005              :                      "decimal overflows the respective type %qs",
    2006            1 :                      tyty->get_name ().c_str ());
    2007            1 :       return error_mark_node;
    2008              :     }
    2009              : 
    2010              :   return real_value;
    2011          998 : }
    2012              : 
    2013              : tree
    2014          183 : CompileExpr::compile_char_literal (const HIR::LiteralExpr &expr,
    2015              :                                    const TyTy::BaseType *tyty)
    2016              : {
    2017          183 :   rust_assert (expr.get_lit_type () == HIR::Literal::CHAR);
    2018          183 :   const auto literal_value = expr.get_literal ();
    2019              : 
    2020              :   // FIXME needs wchar_t
    2021          366 :   char c = literal_value.as_string ().c_str ()[0];
    2022          183 :   return Backend::wchar_constant_expression (c);
    2023          183 : }
    2024              : 
    2025              : tree
    2026          408 : CompileExpr::compile_byte_literal (const HIR::LiteralExpr &expr,
    2027              :                                    const TyTy::BaseType *tyty)
    2028              : {
    2029          408 :   rust_assert (expr.get_lit_type () == HIR::Literal::BYTE);
    2030          408 :   const auto literal_value = expr.get_literal ();
    2031              : 
    2032          408 :   tree type = TyTyResolveCompile::compile (ctx, tyty);
    2033          816 :   char c = literal_value.as_string ().c_str ()[0];
    2034          408 :   return build_int_cst (type, c);
    2035          408 : }
    2036              : 
    2037              : tree
    2038         2310 : CompileExpr::compile_string_literal (const HIR::LiteralExpr &expr,
    2039              :                                      const TyTy::BaseType *tyty)
    2040              : {
    2041         2310 :   tree fat_pointer = TyTyResolveCompile::compile (ctx, tyty);
    2042              : 
    2043         2310 :   rust_assert (expr.get_lit_type () == HIR::Literal::STRING);
    2044         2310 :   const auto literal_value = expr.get_literal ();
    2045              : 
    2046         4620 :   auto base = Backend::string_constant_expression (literal_value.as_string ());
    2047         2310 :   tree data = address_expression (base, expr.get_locus ());
    2048              : 
    2049         2310 :   TyTy::BaseType *usize = nullptr;
    2050         2310 :   bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
    2051         2310 :   rust_assert (ok);
    2052         2310 :   tree type = TyTyResolveCompile::compile (ctx, usize);
    2053              : 
    2054         4620 :   tree size = build_int_cstu (type, literal_value.as_string ().size ());
    2055              : 
    2056         2310 :   return Backend::constructor_expression (fat_pointer, false, {data, size}, -1,
    2057         2310 :                                           expr.get_locus ());
    2058         2310 : }
    2059              : 
    2060              : tree
    2061           35 : CompileExpr::compile_byte_string_literal (const HIR::LiteralExpr &expr,
    2062              :                                           const TyTy::BaseType *tyty)
    2063              : {
    2064           35 :   rust_assert (expr.get_lit_type () == HIR::Literal::BYTE_STRING);
    2065              : 
    2066              :   // the type here is &[ty; capacity]
    2067           35 :   rust_assert (tyty->get_kind () == TyTy::TypeKind::REF);
    2068           35 :   const auto ref_tyty = static_cast<const TyTy::ReferenceType *> (tyty);
    2069           35 :   auto base_tyty = ref_tyty->get_base ();
    2070           35 :   rust_assert (base_tyty->get_kind () == TyTy::TypeKind::ARRAY);
    2071           35 :   auto array_tyty = static_cast<TyTy::ArrayType *> (base_tyty);
    2072              : 
    2073           35 :   std::string value_str = expr.get_literal ().as_string ();
    2074           35 :   std::vector<tree> vals;
    2075           35 :   std::vector<unsigned long> indexes;
    2076          273 :   for (size_t i = 0; i < value_str.size (); i++)
    2077              :     {
    2078          238 :       char b = value_str.at (i);
    2079          238 :       tree bb = Backend::char_constant_expression (b);
    2080          238 :       vals.push_back (bb);
    2081          238 :       indexes.push_back (i);
    2082              :     }
    2083              : 
    2084           35 :   tree array_type = TyTyResolveCompile::compile (ctx, array_tyty);
    2085           35 :   tree constructed
    2086           35 :     = Backend::array_constructor_expression (array_type, indexes, vals,
    2087              :                                              expr.get_locus ());
    2088              : 
    2089           35 :   return address_expression (constructed, expr.get_locus ());
    2090           35 : }
    2091              : 
    2092              : tree
    2093           14 : CompileExpr::compile_c_string_literal (const HIR::LiteralExpr &expr,
    2094              :                                        const TyTy::BaseType *tyty)
    2095              : {
    2096              :   // Copied from compile_string_literal
    2097           14 :   tree fat_pointer = TyTyResolveCompile::compile (ctx, tyty);
    2098              : 
    2099           14 :   rust_assert (expr.get_lit_type () == HIR::Literal::C_STRING);
    2100           14 :   const auto literal_value = expr.get_literal ();
    2101              : 
    2102           28 :   auto base = Backend::string_constant_expression (literal_value.as_string ());
    2103           14 :   tree data = address_expression (base, expr.get_locus ());
    2104              : 
    2105           14 :   TyTy::BaseType *usize = nullptr;
    2106           14 :   bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
    2107           14 :   rust_assert (ok);
    2108           14 :   tree type = TyTyResolveCompile::compile (ctx, usize);
    2109              : 
    2110              :   // +1 for null terminator, unlike Rust string literals.
    2111           28 :   tree size = build_int_cstu (type, literal_value.as_string ().size () + 1);
    2112              : 
    2113           14 :   return Backend::constructor_expression (fat_pointer, false, {data, size}, -1,
    2114           14 :                                           expr.get_locus ());
    2115           14 : }
    2116              : 
    2117              : tree
    2118         4954 : CompileExpr::type_cast_expression (tree type_to_cast_to, tree expr_tree,
    2119              :                                    location_t location)
    2120              : {
    2121         4954 :   if (type_to_cast_to == error_mark_node || expr_tree == error_mark_node
    2122         9908 :       || TREE_TYPE (expr_tree) == error_mark_node)
    2123              :     return error_mark_node;
    2124              : 
    2125         4954 :   if (Backend::type_size (type_to_cast_to) == 0
    2126         4954 :       || TREE_TYPE (expr_tree) == void_type_node)
    2127              :     {
    2128              :       // Do not convert zero-sized types.
    2129              :       return expr_tree;
    2130              :     }
    2131         4954 :   else if (TREE_CODE (type_to_cast_to) == INTEGER_TYPE)
    2132              :     {
    2133         1302 :       tree cast = convert_to_integer (type_to_cast_to, expr_tree);
    2134              :       // FIXME check for TREE_OVERFLOW?
    2135         1302 :       return cast;
    2136              :     }
    2137         3652 :   else if (TREE_CODE (type_to_cast_to) == REAL_TYPE)
    2138              :     {
    2139            9 :       tree cast = convert_to_real (type_to_cast_to, expr_tree);
    2140              :       // FIXME
    2141              :       // We might need to check that the tree is MAX val and thusly saturate it
    2142              :       // to inf. we can get the bounds and check the value if its >= or <= to
    2143              :       // the min and max bounds
    2144              :       //
    2145              :       // https://github.com/Rust-GCC/gccrs/issues/635
    2146            9 :       return cast;
    2147              :     }
    2148         3643 :   else if (TREE_CODE (type_to_cast_to) == COMPLEX_TYPE)
    2149              :     {
    2150            0 :       return convert_to_complex (type_to_cast_to, expr_tree);
    2151              :     }
    2152         3643 :   else if (TREE_CODE (type_to_cast_to) == POINTER_TYPE
    2153         3643 :            && TREE_CODE (TREE_TYPE (expr_tree)) == INTEGER_TYPE)
    2154              :     {
    2155           11 :       return convert_to_pointer (type_to_cast_to, expr_tree);
    2156              :     }
    2157         3632 :   else if (TREE_CODE (type_to_cast_to) == RECORD_TYPE
    2158         3632 :            || TREE_CODE (type_to_cast_to) == ARRAY_TYPE)
    2159              :     {
    2160         1675 :       return fold_build1_loc (location, VIEW_CONVERT_EXPR, type_to_cast_to,
    2161         1675 :                               expr_tree);
    2162              :     }
    2163         1957 :   else if (TREE_CODE (type_to_cast_to) == POINTER_TYPE
    2164         1957 :            && RS_DST_FLAG (TREE_TYPE (expr_tree)))
    2165              :     {
    2166              :       // returning a raw cast using NOP_EXPR seems to resut in an ICE:
    2167              :       //
    2168              :       // Analyzing compilation unit
    2169              :       // Performing interprocedural optimizations
    2170              :       //  <*free_lang_data> {heap 2644k} <visibility> {heap 2644k}
    2171              :       //  <build_ssa_passes> {heap 2644k} <opt_local_passes> {heap 2644k}during
    2172              :       //  GIMPLE pass: cddce
    2173              :       // In function ‘*T::as_ptr<i32>’:
    2174              :       // rust1: internal compiler error: in propagate_necessity, at
    2175              :       // tree-ssa-dce.cc:984 0x1d5b43e propagate_necessity
    2176              :       //         ../../gccrs/gcc/tree-ssa-dce.cc:984
    2177              :       // 0x1d5e180 perform_tree_ssa_dce
    2178              :       //         ../../gccrs/gcc/tree-ssa-dce.cc:1876
    2179              :       // 0x1d5e2c8 tree_ssa_cd_dce
    2180              :       //         ../../gccrs/gcc/tree-ssa-dce.cc:1920
    2181              :       // 0x1d5e49a execute
    2182              :       //         ../../gccrs/gcc/tree-ssa-dce.cc:1992
    2183              : 
    2184              :       // this is returning the direct raw pointer of the slice an assumes a very
    2185              :       // specific layout
    2186         1676 :       return Backend::struct_field_expression (expr_tree, 0, location);
    2187              :     }
    2188              : 
    2189          281 :   return fold_convert_loc (location, type_to_cast_to, expr_tree);
    2190              : }
    2191              : 
    2192              : void
    2193          398 : CompileExpr::visit (HIR::ArrayExpr &expr)
    2194              : {
    2195          398 :   TyTy::BaseType *tyty = nullptr;
    2196          398 :   if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
    2197              :                                        &tyty))
    2198              :     {
    2199            0 :       rust_fatal_error (expr.get_locus (),
    2200              :                         "did not resolve type for this array expr");
    2201          286 :       return;
    2202              :     }
    2203              : 
    2204          398 :   tree array_type = TyTyResolveCompile::compile (ctx, tyty);
    2205          398 :   if (TREE_CODE (array_type) != ARRAY_TYPE)
    2206              :     {
    2207            0 :       translated = error_mark_node;
    2208            0 :       return;
    2209              :     }
    2210              : 
    2211          398 :   rust_assert (tyty->get_kind () == TyTy::TypeKind::ARRAY);
    2212          398 :   const TyTy::ArrayType &array_tyty
    2213              :     = static_cast<const TyTy::ArrayType &> (*tyty);
    2214              : 
    2215          398 :   HIR::ArrayElems &elements = expr.get_internal_elements ();
    2216          398 :   switch (elements.get_array_expr_type ())
    2217              :     {
    2218          286 :     case HIR::ArrayElems::ArrayExprType::VALUES:
    2219          286 :       {
    2220          286 :         HIR::ArrayElemsValues &elems
    2221              :           = static_cast<HIR::ArrayElemsValues &> (elements);
    2222          286 :         translated
    2223          286 :           = array_value_expr (expr.get_locus (), array_tyty, array_type, elems);
    2224              :       }
    2225          286 :       return;
    2226              : 
    2227          112 :     case HIR::ArrayElems::ArrayExprType::COPIED:
    2228          112 :       HIR::ArrayElemsCopied &elems
    2229              :         = static_cast<HIR::ArrayElemsCopied &> (elements);
    2230          112 :       translated
    2231          112 :         = array_copied_expr (expr.get_locus (), array_tyty, array_type, elems);
    2232              :     }
    2233              : }
    2234              : 
    2235              : tree
    2236          286 : CompileExpr::array_value_expr (location_t expr_locus,
    2237              :                                const TyTy::ArrayType &array_tyty,
    2238              :                                tree array_type, HIR::ArrayElemsValues &elems)
    2239              : {
    2240          286 :   std::vector<unsigned long> indexes;
    2241          286 :   std::vector<tree> constructor;
    2242          286 :   size_t i = 0;
    2243         1754 :   for (auto &elem : elems.get_values ())
    2244              :     {
    2245         1469 :       tree translated_expr = CompileExpr::Compile (*elem, ctx);
    2246         1469 :       if (translated_expr == error_mark_node)
    2247              :         {
    2248            1 :           rich_location r (line_table, expr_locus);
    2249            1 :           r.add_fixit_replace (elem->get_locus (), "not a value");
    2250            1 :           rust_error_at (r, ErrorCode::E0423, "expected value");
    2251            1 :           return error_mark_node;
    2252            1 :         }
    2253              : 
    2254         1468 :       constructor.push_back (translated_expr);
    2255         1468 :       indexes.push_back (i++);
    2256              :     }
    2257              : 
    2258          285 :   return Backend::array_constructor_expression (array_type, indexes,
    2259          285 :                                                 constructor, expr_locus);
    2260          286 : }
    2261              : 
    2262              : tree
    2263          112 : CompileExpr::array_copied_expr (location_t expr_locus,
    2264              :                                 const TyTy::ArrayType &array_tyty,
    2265              :                                 tree array_type, HIR::ArrayElemsCopied &elems)
    2266              : {
    2267              :   //  see gcc/cp/typeck2.cc:1369-1401
    2268          112 :   gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
    2269          112 :   tree domain = TYPE_DOMAIN (array_type);
    2270          112 :   if (!domain)
    2271            0 :     return error_mark_node;
    2272              : 
    2273          112 :   if (!TREE_CONSTANT (TYPE_MAX_VALUE (domain)))
    2274              :     {
    2275            0 :       rust_error_at (expr_locus, "non const capacity domain %qT", array_type);
    2276            0 :       return error_mark_node;
    2277              :     }
    2278              : 
    2279          112 :   auto capacity_ty = array_tyty.get_capacity ();
    2280              : 
    2281              :   // Check if capacity is a const type
    2282          112 :   if (capacity_ty->get_kind () != TyTy::TypeKind::CONST)
    2283              :     {
    2284            0 :       rust_error_at (array_tyty.get_locus (),
    2285              :                      "array capacity is not a const type");
    2286            0 :       return error_mark_node;
    2287              :     }
    2288              : 
    2289          112 :   auto *capacity_const = capacity_ty->as_const_type ();
    2290              : 
    2291          112 :   rust_assert (capacity_const->const_kind ()
    2292              :                == TyTy::BaseConstType::ConstKind::Value);
    2293          112 :   auto &capacity_value = *static_cast<TyTy::ConstValueType *> (capacity_const);
    2294          112 :   auto cap_tree = capacity_value.get_value ();
    2295          112 :   if (error_operand_p (cap_tree) || !TREE_CONSTANT (cap_tree))
    2296              :     {
    2297            0 :       rust_error_at (expr_locus, "non const num copies %qT", cap_tree);
    2298            0 :       return error_mark_node;
    2299              :     }
    2300              : 
    2301              :   // get the compiled value
    2302          112 :   tree translated_expr = CompileExpr::Compile (elems.get_elem_to_copy (), ctx);
    2303              : 
    2304          112 :   tree max_domain = TYPE_MAX_VALUE (domain);
    2305          112 :   tree min_domain = TYPE_MIN_VALUE (domain);
    2306              : 
    2307          112 :   auto max = wi::to_offset (max_domain);
    2308          112 :   auto min = wi::to_offset (min_domain);
    2309          112 :   auto precision = TYPE_PRECISION (TREE_TYPE (domain));
    2310          112 :   auto sign = TYPE_SIGN (TREE_TYPE (domain));
    2311          112 :   unsigned HOST_WIDE_INT len
    2312          112 :     = wi::ext (max - min + 1, precision, sign).to_uhwi ();
    2313              : 
    2314              :   // In a const context we must initialize the entire array, which entails
    2315              :   // allocating for each element. If the user wants a huge array, we will OOM
    2316              :   // and die horribly.
    2317          112 :   if (ctx->const_context_p ())
    2318              :     {
    2319            8 :       size_t idx = 0;
    2320              : 
    2321            8 :       std::vector<unsigned long> indexes;
    2322            8 :       std::vector<tree> constructor;
    2323              : 
    2324            8 :       indexes.reserve (len);
    2325            8 :       constructor.reserve (len);
    2326          130 :       for (unsigned HOST_WIDE_INT i = 0; i < len; i++)
    2327              :         {
    2328          122 :           constructor.push_back (translated_expr);
    2329          122 :           indexes.push_back (idx++);
    2330              :         }
    2331              : 
    2332            8 :       return Backend::array_constructor_expression (array_type, indexes,
    2333              :                                                     constructor, expr_locus);
    2334            8 :     }
    2335              : 
    2336              :   else
    2337              :     {
    2338              :       // Create a new block scope in which to initialize the array
    2339          104 :       tree fndecl = NULL_TREE;
    2340          104 :       if (ctx->in_fn ())
    2341          104 :         fndecl = ctx->peek_fn ().fndecl;
    2342              : 
    2343          104 :       std::vector<Bvariable *> locals;
    2344          104 :       tree enclosing_scope = ctx->peek_enclosing_scope ();
    2345          104 :       tree init_block = Backend::block (fndecl, enclosing_scope, locals,
    2346              :                                         expr_locus, expr_locus);
    2347          104 :       ctx->push_block (init_block);
    2348              : 
    2349          104 :       tree tmp;
    2350          104 :       tree stmts
    2351          104 :         = Backend::array_initializer (fndecl, init_block, array_type, cap_tree,
    2352              :                                       translated_expr, &tmp, expr_locus);
    2353          104 :       ctx->add_statement (stmts);
    2354              : 
    2355          104 :       tree block = ctx->pop_block ();
    2356              : 
    2357              :       // The result is a compound expression which creates a temporary array,
    2358              :       // initializes all the elements in a loop, and then yeilds the array.
    2359          104 :       return Backend::compound_expression (block, tmp, expr_locus);
    2360          104 :     }
    2361              : }
    2362              : 
    2363              : tree
    2364        39711 : HIRCompileBase::resolve_adjustements (
    2365              :   std::vector<Resolver::Adjustment> &adjustments, tree expression,
    2366              :   location_t locus)
    2367              : {
    2368        39711 :   tree e = expression;
    2369        41999 :   for (auto &adjustment : adjustments)
    2370              :     {
    2371         2289 :       if (e == error_mark_node)
    2372              :         return error_mark_node;
    2373              : 
    2374         2288 :       switch (adjustment.get_type ())
    2375              :         {
    2376              :         case Resolver::Adjustment::AdjustmentType::ERROR:
    2377              :           return error_mark_node;
    2378              : 
    2379         1698 :         case Resolver::Adjustment::AdjustmentType::IMM_REF:
    2380         1698 :         case Resolver::Adjustment::AdjustmentType::MUT_REF:
    2381         1698 :           {
    2382         1698 :             if (!RS_DST_FLAG (TREE_TYPE (e)))
    2383              :               {
    2384         1461 :                 e = address_expression (e, locus);
    2385              :               }
    2386              :           }
    2387              :           break;
    2388              : 
    2389           57 :         case Resolver::Adjustment::AdjustmentType::DEREF:
    2390           57 :         case Resolver::Adjustment::AdjustmentType::DEREF_MUT:
    2391           57 :           e = resolve_deref_adjustment (adjustment, e, locus);
    2392           57 :           break;
    2393              : 
    2394          296 :         case Resolver::Adjustment::AdjustmentType::INDIRECTION:
    2395          296 :           e = resolve_indirection_adjustment (adjustment, e, locus);
    2396          296 :           break;
    2397              : 
    2398          237 :         case Resolver::Adjustment::AdjustmentType::UNSIZE:
    2399          237 :           e = resolve_unsized_adjustment (adjustment, e, locus);
    2400          237 :           break;
    2401              :         }
    2402              :     }
    2403              : 
    2404              :   return e;
    2405              : }
    2406              : 
    2407              : tree
    2408           57 : HIRCompileBase::resolve_deref_adjustment (Resolver::Adjustment &adjustment,
    2409              :                                           tree expression, location_t locus)
    2410              : {
    2411           57 :   rust_assert (adjustment.is_deref_adjustment ()
    2412              :                || adjustment.is_deref_mut_adjustment ());
    2413           57 :   if (!adjustment.has_operator_overload ())
    2414              :     {
    2415            1 :       TyTy::BaseType *receiver = adjustment.get_actual ();
    2416            1 :       if (TyTy::try_get_box_inner_type (receiver))
    2417              :         {
    2418            1 :           tree receiver_ref = expression;
    2419            1 :           receiver_ref = build_box_inner_ptr (receiver_ref, locus);
    2420            1 :           return indirect_expression (receiver_ref, locus);
    2421              :         }
    2422            0 :       rust_assert (false);
    2423              :     }
    2424              : 
    2425           56 :   TyTy::FnType *lookup = adjustment.get_deref_operator_fn ();
    2426           56 :   TyTy::BaseType *receiver = adjustment.get_actual ();
    2427           56 :   tree fn_address = resolve_method_address (lookup, receiver, locus);
    2428              : 
    2429              :   // does it need a reference to call
    2430           56 :   tree adjusted_argument = expression;
    2431           56 :   bool needs_borrow = adjustment.get_deref_adjustment_type ()
    2432           56 :                       != Resolver::Adjustment::AdjustmentType::ERROR;
    2433           56 :   if (needs_borrow)
    2434              :     {
    2435           56 :       adjusted_argument = address_expression (expression, locus);
    2436              :     }
    2437              : 
    2438              :   // make the call
    2439           56 :   return Backend::call_expression (fn_address, {adjusted_argument}, nullptr,
    2440              :                                    locus);
    2441              : }
    2442              : 
    2443              : tree
    2444          296 : HIRCompileBase::resolve_indirection_adjustment (
    2445              :   Resolver::Adjustment &adjustment, tree expression, location_t locus)
    2446              : {
    2447          296 :   return indirect_expression (expression, locus);
    2448              : }
    2449              : 
    2450              : tree
    2451          237 : HIRCompileBase::resolve_unsized_adjustment (Resolver::Adjustment &adjustment,
    2452              :                                             tree expression, location_t locus)
    2453              : {
    2454          237 :   bool expect_slice
    2455          237 :     = adjustment.get_expected ()->get_kind () == TyTy::TypeKind::SLICE;
    2456          237 :   bool expect_dyn
    2457          237 :     = adjustment.get_expected ()->get_kind () == TyTy::TypeKind::DYNAMIC;
    2458              : 
    2459              :   // assumes this is an array
    2460          237 :   tree expr_type = TREE_TYPE (expression);
    2461          237 :   if (expect_slice)
    2462              :     {
    2463           68 :       rust_assert (TREE_CODE (expr_type) == ARRAY_TYPE);
    2464           68 :       return resolve_unsized_slice_adjustment (adjustment, expression, locus);
    2465              :     }
    2466              : 
    2467          169 :   rust_assert (expect_dyn);
    2468          169 :   return resolve_unsized_dyn_adjustment (adjustment, expression, locus);
    2469              : }
    2470              : 
    2471              : tree
    2472           68 : HIRCompileBase::resolve_unsized_slice_adjustment (
    2473              :   Resolver::Adjustment &adjustment, tree expression, location_t locus)
    2474              : {
    2475              :   // assumes this is an array
    2476           68 :   tree expr_type = TREE_TYPE (expression);
    2477           68 :   rust_assert (TREE_CODE (expr_type) == ARRAY_TYPE);
    2478              : 
    2479              :   // takes an array and returns a fat-pointer so this becomes a constructor
    2480              :   // expression
    2481           68 :   rust_assert (adjustment.get_expected ()->get_kind ()
    2482              :                == TyTy::TypeKind::SLICE);
    2483           68 :   tree fat_pointer
    2484           68 :     = TyTyResolveCompile::compile (ctx, adjustment.get_expected ());
    2485              : 
    2486              :   // make a constructor for this
    2487           68 :   tree data = address_expression (expression, locus);
    2488              : 
    2489              :   // fetch the size from the domain
    2490           68 :   tree domain = TYPE_DOMAIN (expr_type);
    2491           68 :   unsigned HOST_WIDE_INT array_size
    2492          136 :     = wi::ext (wi::to_offset (TYPE_MAX_VALUE (domain))
    2493          136 :                  - wi::to_offset (TYPE_MIN_VALUE (domain)) + 1,
    2494           68 :                TYPE_PRECISION (TREE_TYPE (domain)),
    2495           68 :                TYPE_SIGN (TREE_TYPE (domain)))
    2496           68 :         .to_uhwi ();
    2497           68 :   tree size = build_int_cstu (size_type_node, array_size);
    2498              : 
    2499           68 :   return Backend::constructor_expression (fat_pointer, false, {data, size}, -1,
    2500           68 :                                           locus);
    2501              : }
    2502              : 
    2503              : tree
    2504          169 : HIRCompileBase::resolve_unsized_dyn_adjustment (
    2505              :   Resolver::Adjustment &adjustment, tree expression, location_t locus)
    2506              : {
    2507          169 :   tree rvalue = expression;
    2508          169 :   location_t rvalue_locus = locus;
    2509              : 
    2510          169 :   auto actual = adjustment.get_actual ();
    2511          169 :   auto expected = adjustment.get_expected ();
    2512              : 
    2513          169 :   const auto dyn = static_cast<const TyTy::DynamicObjectType *> (expected);
    2514              : 
    2515          169 :   rust_debug ("resolve_unsized_dyn_adjustment actual={%s} dyn={%s}",
    2516              :               actual->debug_str ().c_str (), dyn->debug_str ().c_str ());
    2517              : 
    2518          169 :   return coerce_to_dyn_object (rvalue, actual, dyn, rvalue_locus);
    2519              : }
    2520              : 
    2521              : void
    2522           66 : CompileExpr::visit (HIR::RangeFromToExpr &expr)
    2523              : {
    2524           66 :   tree from = CompileExpr::Compile (expr.get_from_expr (), ctx);
    2525           66 :   tree to = CompileExpr::Compile (expr.get_to_expr (), ctx);
    2526           66 :   if (from == error_mark_node || to == error_mark_node)
    2527              :     {
    2528            0 :       translated = error_mark_node;
    2529            0 :       return;
    2530              :     }
    2531              : 
    2532           66 :   TyTy::BaseType *tyty = nullptr;
    2533           66 :   bool ok
    2534           66 :     = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &tyty);
    2535           66 :   rust_assert (ok);
    2536              : 
    2537           66 :   tree adt = TyTyResolveCompile::compile (ctx, tyty);
    2538              : 
    2539              :   // make the constructor
    2540           66 :   translated = Backend::constructor_expression (adt, false, {from, to}, -1,
    2541              :                                                 expr.get_locus ());
    2542              : }
    2543              : 
    2544              : void
    2545            7 : CompileExpr::visit (HIR::RangeFromExpr &expr)
    2546              : {
    2547            7 :   tree from = CompileExpr::Compile (expr.get_from_expr (), ctx);
    2548            7 :   if (from == error_mark_node)
    2549              :     {
    2550            0 :       translated = error_mark_node;
    2551            0 :       return;
    2552              :     }
    2553              : 
    2554            7 :   TyTy::BaseType *tyty = nullptr;
    2555            7 :   bool ok
    2556            7 :     = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &tyty);
    2557            7 :   rust_assert (ok);
    2558              : 
    2559            7 :   tree adt = TyTyResolveCompile::compile (ctx, tyty);
    2560              : 
    2561              :   // make the constructor
    2562            7 :   translated = Backend::constructor_expression (adt, false, {from}, -1,
    2563              :                                                 expr.get_locus ());
    2564              : }
    2565              : 
    2566              : void
    2567            7 : CompileExpr::visit (HIR::RangeToExpr &expr)
    2568              : {
    2569            7 :   tree to = CompileExpr::Compile (expr.get_to_expr (), ctx);
    2570            7 :   if (to == error_mark_node)
    2571              :     {
    2572            0 :       translated = error_mark_node;
    2573            0 :       return;
    2574              :     }
    2575              : 
    2576            7 :   TyTy::BaseType *tyty = nullptr;
    2577            7 :   bool ok
    2578            7 :     = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &tyty);
    2579            7 :   rust_assert (ok);
    2580              : 
    2581            7 :   tree adt = TyTyResolveCompile::compile (ctx, tyty);
    2582              : 
    2583              :   // make the constructor
    2584            7 :   translated
    2585            7 :     = Backend::constructor_expression (adt, false, {to}, -1, expr.get_locus ());
    2586              : }
    2587              : 
    2588              : void
    2589            0 : CompileExpr::visit (HIR::RangeFullExpr &expr)
    2590              : {
    2591            0 :   TyTy::BaseType *tyty = nullptr;
    2592            0 :   bool ok
    2593            0 :     = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &tyty);
    2594            0 :   rust_assert (ok);
    2595              : 
    2596            0 :   tree adt = TyTyResolveCompile::compile (ctx, tyty);
    2597            0 :   translated
    2598            0 :     = Backend::constructor_expression (adt, false, {}, -1, expr.get_locus ());
    2599            0 : }
    2600              : 
    2601              : void
    2602            7 : CompileExpr::visit (HIR::RangeFromToInclExpr &expr)
    2603              : {
    2604            7 :   tree from = CompileExpr::Compile (expr.get_from_expr (), ctx);
    2605            7 :   tree to = CompileExpr::Compile (expr.get_to_expr (), ctx);
    2606            7 :   if (from == error_mark_node || to == error_mark_node)
    2607              :     {
    2608            0 :       translated = error_mark_node;
    2609            0 :       return;
    2610              :     }
    2611              : 
    2612            7 :   TyTy::BaseType *tyty = nullptr;
    2613            7 :   bool ok
    2614            7 :     = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &tyty);
    2615            7 :   rust_assert (ok);
    2616              : 
    2617            7 :   tree adt = TyTyResolveCompile::compile (ctx, tyty);
    2618              : 
    2619              :   // make the constructor
    2620            7 :   translated = Backend::constructor_expression (adt, false, {from, to}, -1,
    2621              :                                                 expr.get_locus ());
    2622              : }
    2623              : 
    2624              : void
    2625          287 : CompileExpr::visit (HIR::ArrayIndexExpr &expr)
    2626              : {
    2627          287 :   tree array_reference = CompileExpr::Compile (expr.get_array_expr (), ctx);
    2628          287 :   tree index = CompileExpr::Compile (expr.get_index_expr (), ctx);
    2629              : 
    2630              :   // this might be an core::ops::index lang item situation
    2631          287 :   TyTy::FnType *fntype;
    2632          287 :   bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
    2633          287 :     expr.get_mappings ().get_hirid (), &fntype);
    2634          287 :   if (is_op_overload)
    2635              :     {
    2636           63 :       auto lang_item_type = LangItem::Kind::INDEX;
    2637           63 :       tree operator_overload_call
    2638           63 :         = resolve_operator_overload (lang_item_type, expr, array_reference,
    2639              :                                      index, expr.get_array_expr (),
    2640           63 :                                      expr.get_index_expr ());
    2641              : 
    2642           63 :       tree actual_type = TREE_TYPE (operator_overload_call);
    2643           63 :       bool can_indirect = TYPE_PTR_P (actual_type) || TYPE_REF_P (actual_type);
    2644           63 :       if (!can_indirect)
    2645              :         {
    2646              :           // nothing to do
    2647           35 :           translated = operator_overload_call;
    2648           63 :           return;
    2649              :         }
    2650              : 
    2651              :       // rust deref always returns a reference from this overload then we can
    2652              :       // actually do the indirection
    2653           28 :       translated
    2654           28 :         = indirect_expression (operator_overload_call, expr.get_locus ());
    2655           28 :       return;
    2656              :     }
    2657              : 
    2658              :   // lets check if the array is a reference type then we can add an
    2659              :   // indirection if required
    2660          224 :   TyTy::BaseType *array_expr_ty = nullptr;
    2661          224 :   bool ok = ctx->get_tyctx ()->lookup_type (
    2662          224 :     expr.get_array_expr ().get_mappings ().get_hirid (), &array_expr_ty);
    2663          224 :   rust_assert (ok);
    2664              : 
    2665              :   // do we need to add an indirect reference
    2666          224 :   if (array_expr_ty->get_kind () == TyTy::TypeKind::REF)
    2667              :     {
    2668           15 :       array_reference
    2669           15 :         = indirect_expression (array_reference, expr.get_locus ());
    2670              :     }
    2671              : 
    2672          224 :   translated = Backend::array_index_expression (array_reference, index,
    2673              :                                                 expr.get_locus ());
    2674              : }
    2675              : 
    2676              : void
    2677           61 : CompileExpr::visit (HIR::ClosureExpr &expr)
    2678              : {
    2679           61 :   TyTy::BaseType *closure_expr_ty = nullptr;
    2680           61 :   if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
    2681              :                                        &closure_expr_ty))
    2682              :     {
    2683            0 :       rust_fatal_error (expr.get_locus (),
    2684              :                         "did not resolve type for this ClosureExpr");
    2685              :       return;
    2686              :     }
    2687           61 :   rust_assert (closure_expr_ty->get_kind () == TyTy::TypeKind::CLOSURE);
    2688           61 :   TyTy::ClosureType *closure_tyty
    2689              :     = static_cast<TyTy::ClosureType *> (closure_expr_ty);
    2690           61 :   tree compiled_closure_tyty = TyTyResolveCompile::compile (ctx, closure_tyty);
    2691              : 
    2692              :   // generate closure function
    2693           61 :   generate_closure_function (expr, *closure_tyty, compiled_closure_tyty);
    2694              : 
    2695              :   // lets ignore state capture for now we need to instantiate the struct anyway
    2696              :   // then generate the function
    2697           61 :   std::vector<tree> vals;
    2698           82 :   for (const auto &capture : closure_tyty->get_captures ())
    2699              :     {
    2700              :       // lookup the HirId
    2701           21 :       if (auto hid = ctx->get_mappings ().lookup_node_to_hir (capture))
    2702              :         {
    2703              :           // lookup the var decl
    2704           21 :           Bvariable *var = nullptr;
    2705           21 :           bool found = ctx->lookup_var_decl (*hid, &var);
    2706           21 :           rust_assert (found);
    2707              : 
    2708              :           // FIXME
    2709              :           // this should bes based on the closure move-ability
    2710           21 :           tree var_expr = var->get_tree (expr.get_locus ());
    2711           21 :           tree val = address_expression (var_expr, expr.get_locus ());
    2712           21 :           vals.push_back (val);
    2713              :         }
    2714              :       else
    2715            0 :         rust_unreachable ();
    2716              :     }
    2717              : 
    2718           61 :   translated = Backend::constructor_expression (compiled_closure_tyty, false,
    2719              :                                                 vals, -1, expr.get_locus ());
    2720           61 : }
    2721              : 
    2722              : tree
    2723           61 : CompileExpr::generate_closure_function (HIR::ClosureExpr &expr,
    2724              :                                         TyTy::ClosureType &closure_tyty,
    2725              :                                         tree compiled_closure_tyty)
    2726              : {
    2727           61 :   TyTy::FnType *fn_tyty = nullptr;
    2728           61 :   tree compiled_fn_type
    2729           61 :     = generate_closure_fntype (expr, closure_tyty, compiled_closure_tyty,
    2730              :                                &fn_tyty);
    2731           61 :   if (compiled_fn_type == error_mark_node)
    2732              :     return error_mark_node;
    2733              : 
    2734           61 :   const Resolver::CanonicalPath &parent_canonical_path
    2735           61 :     = closure_tyty.get_ident ().path;
    2736              : 
    2737           61 :   tl::optional<NodeId> nid = ctx->get_mappings ().lookup_hir_to_node (
    2738           61 :     expr.get_mappings ().get_hirid ());
    2739           61 :   rust_assert (nid.has_value ());
    2740           61 :   auto node_id = nid.value ();
    2741              : 
    2742           61 :   Resolver::CanonicalPath path = parent_canonical_path.append (
    2743           61 :     Resolver::CanonicalPath::new_seg (node_id, "{{closure}}"));
    2744              : 
    2745           61 :   std::string ir_symbol_name = path.get ();
    2746           61 :   std::string asm_name = ctx->mangle_item (&closure_tyty, path);
    2747              : 
    2748           61 :   unsigned int flags = 0;
    2749           61 :   tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name, asm_name,
    2750              :                                    flags, expr.get_locus ());
    2751              : 
    2752              :   // insert into the context
    2753           61 :   ctx->insert_function_decl (fn_tyty, fndecl);
    2754           61 :   ctx->insert_closure_decl (&closure_tyty, fndecl);
    2755              : 
    2756              :   // setup the parameters
    2757           61 :   std::vector<Bvariable *> param_vars;
    2758              : 
    2759              :   // closure self
    2760           61 :   Bvariable *self_param
    2761           61 :     = Backend::parameter_variable (fndecl, "$closure", compiled_closure_tyty,
    2762           61 :                                    expr.get_locus ());
    2763           61 :   DECL_ARTIFICIAL (self_param->get_decl ()) = 1;
    2764           61 :   param_vars.push_back (self_param);
    2765              : 
    2766              :   // push a new context
    2767           61 :   ctx->push_closure_context (expr.get_mappings ().get_hirid ());
    2768              : 
    2769              :   // setup the implicit argument captures
    2770           61 :   size_t idx = 0;
    2771           82 :   for (const auto &capture : closure_tyty.get_captures ())
    2772              :     {
    2773              :       // lookup the HirId
    2774           21 :       if (auto hid = ctx->get_mappings ().lookup_node_to_hir (capture))
    2775              :         {
    2776              :           // get the assessor
    2777           21 :           tree binding = Backend::struct_field_expression (
    2778              :             self_param->get_tree (expr.get_locus ()), idx, expr.get_locus ());
    2779           21 :           tree indirection = indirect_expression (binding, expr.get_locus ());
    2780              : 
    2781              :           // insert bindings
    2782           21 :           ctx->insert_closure_binding (*hid, indirection);
    2783              : 
    2784              :           // continue
    2785           21 :           idx++;
    2786              :         }
    2787              :       else
    2788            0 :         rust_unreachable ();
    2789              :     }
    2790              : 
    2791              :   // args tuple
    2792           61 :   tree args_type
    2793           61 :     = TyTyResolveCompile::compile (ctx, &closure_tyty.get_parameters ());
    2794           61 :   Bvariable *args_param
    2795           61 :     = Backend::parameter_variable (fndecl, "args", args_type,
    2796           61 :                                    expr.get_locus ());
    2797           61 :   param_vars.push_back (args_param);
    2798              : 
    2799              :   // setup the implicit mappings for the arguments. Since argument passing to
    2800              :   // closure functions is done via passing a tuple but the closure body expects
    2801              :   // just normal arguments this means we need to destructure them similar to
    2802              :   // what we do in MatchExpr's. This means when we have a closure-param of a we
    2803              :   // actually setup the destructure to take from the args tuple
    2804              : 
    2805           61 :   tree args_param_expr = args_param->get_tree (expr.get_locus ());
    2806           61 :   size_t i = 0;
    2807          120 :   for (auto &closure_param : expr.get_params ())
    2808              :     {
    2809           59 :       tree compiled_param_var
    2810           59 :         = Backend::struct_field_expression (args_param_expr, i,
    2811              :                                             closure_param.get_locus ());
    2812              : 
    2813           59 :       CompilePatternBindings::Compile (closure_param.get_pattern (),
    2814              :                                        compiled_param_var, ctx);
    2815           59 :       i++;
    2816              :     }
    2817              : 
    2818           61 :   if (!Backend::function_set_parameters (fndecl, param_vars))
    2819              :     {
    2820            0 :       ctx->pop_closure_context ();
    2821            0 :       return error_mark_node;
    2822              :     }
    2823              : 
    2824              :   // lookup locals
    2825           61 :   HIR::Expr &function_body = expr.get_expr ();
    2826           61 :   bool is_block_expr
    2827           61 :     = function_body.get_expression_type () == HIR::Expr::ExprType::Block;
    2828              : 
    2829           61 :   if (is_block_expr)
    2830              :     {
    2831           52 :       auto body_mappings = function_body.get_mappings ();
    2832           52 :       auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
    2833              : 
    2834           52 :       auto candidate
    2835           52 :         = nr_ctx.get_underlying ().values.to_rib (body_mappings.get_nodeid ());
    2836              : 
    2837           52 :       rust_assert (candidate.has_value ());
    2838              :     }
    2839              : 
    2840           61 :   tree enclosing_scope = NULL_TREE;
    2841           61 :   location_t start_location = function_body.get_locus ();
    2842           61 :   location_t end_location = function_body.get_locus ();
    2843           61 :   if (is_block_expr)
    2844              :     {
    2845           52 :       auto &body = static_cast<HIR::BlockExpr &> (function_body);
    2846           52 :       start_location = body.get_locus ();
    2847           52 :       end_location = body.get_end_locus ();
    2848              :     }
    2849              : 
    2850           61 :   tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/,
    2851              :                                     start_location, end_location);
    2852           61 :   ctx->push_block (code_block);
    2853              : 
    2854           61 :   TyTy::BaseType *tyret = &closure_tyty.get_result_type ();
    2855           61 :   Bvariable *return_address = nullptr;
    2856              : 
    2857           61 :   tree return_type = TyTyResolveCompile::compile (ctx, tyret);
    2858           61 :   bool address_is_taken = false;
    2859           61 :   tree ret_var_stmt = NULL_TREE;
    2860              : 
    2861           61 :   return_address
    2862           61 :     = Backend::temporary_variable (fndecl, code_block, return_type, NULL,
    2863              :                                    address_is_taken, expr.get_locus (),
    2864              :                                    &ret_var_stmt);
    2865              : 
    2866           61 :   ctx->add_statement (ret_var_stmt);
    2867              : 
    2868           61 :   ctx->push_fn (fndecl, return_address, tyret);
    2869              : 
    2870           61 :   if (is_block_expr)
    2871              :     {
    2872           52 :       auto &body = static_cast<HIR::BlockExpr &> (function_body);
    2873           52 :       compile_function_body (fndecl, body, tyret);
    2874              :     }
    2875              :   else
    2876              :     {
    2877            9 :       tree value = CompileExpr::Compile (function_body, ctx);
    2878            9 :       tree return_expr
    2879            9 :         = Backend::return_statement (fndecl, value, function_body.get_locus ());
    2880            9 :       ctx->add_statement (return_expr);
    2881              :     }
    2882              : 
    2883           61 :   tree bind_tree = ctx->pop_block ();
    2884              : 
    2885           61 :   gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
    2886           61 :   DECL_SAVED_TREE (fndecl) = bind_tree;
    2887              : 
    2888           61 :   ctx->pop_closure_context ();
    2889           61 :   ctx->pop_fn ();
    2890           61 :   ctx->push_function (fndecl);
    2891              : 
    2892           61 :   return fndecl;
    2893           61 : }
    2894              : 
    2895              : tree
    2896           61 : CompileExpr::generate_closure_fntype (HIR::ClosureExpr &expr,
    2897              :                                       const TyTy::ClosureType &closure_tyty,
    2898              :                                       tree compiled_closure_tyty,
    2899              :                                       TyTy::FnType **fn_tyty)
    2900              : {
    2901              :   // grab the specified_bound
    2902           61 :   rust_assert (closure_tyty.num_specified_bounds () == 1);
    2903           61 :   const TyTy::TypeBoundPredicate &predicate
    2904           61 :     = *closure_tyty.get_specified_bounds ().begin ();
    2905              : 
    2906              :   // FnOnce::Output is normalized on demand by normalize_projection's closure
    2907              :   // special-case
    2908              : 
    2909              :   // the function signature is based on the trait bound that the closure
    2910              :   // implements which is determined at the type resolution time
    2911              :   //
    2912              :   // https://github.com/rust-lang/rust/blob/7807a694c2f079fd3f395821bcc357eee8650071/library/core/src/ops/function.rs#L54-L71
    2913              : 
    2914           61 :   TyTy::TypeBoundPredicateItem item = TyTy::TypeBoundPredicateItem::error ();
    2915           61 :   if (predicate.get_name ().compare ("FnOnce") == 0)
    2916              :     {
    2917          122 :       item = predicate.lookup_associated_item ("call_once").value ();
    2918              :     }
    2919            0 :   else if (predicate.get_name ().compare ("FnMut") == 0)
    2920              :     {
    2921            0 :       item = predicate.lookup_associated_item ("call_mut").value ();
    2922              :     }
    2923            0 :   else if (predicate.get_name ().compare ("Fn") == 0)
    2924              :     {
    2925            0 :       item = predicate.lookup_associated_item ("call").value ();
    2926              :     }
    2927              :   else
    2928              :     {
    2929              :       // FIXME error message?
    2930            0 :       rust_unreachable ();
    2931              :       return error_mark_node;
    2932              :     }
    2933              : 
    2934           61 :   rust_assert (!item.is_error ());
    2935              : 
    2936           61 :   TyTy::BaseType *item_tyty = item.get_tyty_for_receiver (&closure_tyty);
    2937           61 :   rust_assert (item_tyty->get_kind () == TyTy::TypeKind::FNDEF);
    2938           61 :   *fn_tyty = static_cast<TyTy::FnType *> (item_tyty);
    2939           61 :   return TyTyResolveCompile::compile (ctx, item_tyty);
    2940           61 : }
    2941              : 
    2942              : bool
    2943        10568 : CompileExpr::generate_possible_fn_trait_call (HIR::CallExpr &expr,
    2944              :                                               tree receiver, tree *result)
    2945              : {
    2946        10568 :   TyTy::FnType *fn_sig = nullptr;
    2947        10568 :   bool found_overload = ctx->get_tyctx ()->lookup_operator_overload (
    2948        10568 :     expr.get_mappings ().get_hirid (), &fn_sig);
    2949        10568 :   if (!found_overload)
    2950              :     return false;
    2951              : 
    2952           60 :   auto id = fn_sig->get_ty_ref ();
    2953           60 :   auto dId = fn_sig->get_id ();
    2954              : 
    2955           60 :   tree function = error_mark_node;
    2956           60 :   bool found_closure = ctx->lookup_function_decl (id, &function, dId, fn_sig);
    2957           60 :   if (!found_closure)
    2958              :     {
    2959              :       // something went wrong we still return true as this was meant to be an fn
    2960              :       // trait call
    2961            0 :       *result = error_mark_node;
    2962            0 :       return true;
    2963              :     }
    2964              : 
    2965              :   // need to apply any autoderef's to the self argument
    2966           60 :   HIR::Expr &fnexpr = expr.get_fnexpr ();
    2967           60 :   HirId autoderef_mappings_id = fnexpr.get_mappings ().get_hirid ();
    2968           60 :   std::vector<Resolver::Adjustment> *adjustments = nullptr;
    2969           60 :   bool ok = ctx->get_tyctx ()->lookup_autoderef_mappings (autoderef_mappings_id,
    2970              :                                                           &adjustments);
    2971           60 :   rust_assert (ok);
    2972              : 
    2973              :   // apply adjustments for the fn call
    2974           60 :   tree self = resolve_adjustements (*adjustments, receiver, expr.get_locus ());
    2975              : 
    2976              :   // resolve the arguments
    2977           60 :   std::vector<tree> tuple_arg_vals;
    2978          120 :   for (auto &argument : expr.get_arguments ())
    2979              :     {
    2980           60 :       auto rvalue = CompileExpr::Compile (*argument, ctx);
    2981           60 :       tuple_arg_vals.push_back (rvalue);
    2982              :     }
    2983              : 
    2984              :   // this is always the 2nd argument in the function signature
    2985           60 :   tree fnty = TREE_TYPE (function);
    2986           60 :   tree fn_arg_tys = TYPE_ARG_TYPES (fnty);
    2987           60 :   tree tuple_args_tyty_chain = TREE_CHAIN (fn_arg_tys);
    2988           60 :   tree tuple_args_tyty = TREE_VALUE (tuple_args_tyty_chain);
    2989              : 
    2990           60 :   tree tuple_args
    2991           60 :     = Backend::constructor_expression (tuple_args_tyty, false, tuple_arg_vals,
    2992           60 :                                        -1, expr.get_locus ());
    2993              : 
    2994              :   // args are always self, and the tuple of the args we are passing where
    2995              :   // self is the path of the call-expr in this case the fn_address
    2996           60 :   std::vector<tree> args;
    2997           60 :   args.push_back (self);
    2998           60 :   args.push_back (tuple_args);
    2999              : 
    3000           60 :   tree call_address = address_expression (function, expr.get_locus ());
    3001           60 :   *result
    3002           60 :     = Backend::call_expression (call_address, args, nullptr /* static chain ?*/,
    3003              :                                 expr.get_locus ());
    3004           60 :   return true;
    3005           60 : }
    3006              : 
    3007              : tree
    3008            3 : CompileExpr::construct_block_label (HIR::BlockExpr &expr)
    3009              : {
    3010            3 :   if (expr.has_label ())
    3011              :     {
    3012            3 :       fncontext fnctx = ctx->peek_fn ();
    3013            3 :       HIR::LoopLabel &label = expr.get_label ();
    3014            3 :       std::string label_name = label.get_lifetime ().get_name ();
    3015            3 :       HirId label_id = label.get_lifetime ().get_mappings ().get_hirid ();
    3016            3 :       tree label_decl
    3017            3 :         = Backend::label (fnctx.fndecl, label_name, label.get_locus ());
    3018            3 :       tree label_expr = Backend::label_definition_statement (label_decl);
    3019            3 :       ctx->insert_label_decl (label_id, label_decl);
    3020            3 :       return label_expr;
    3021            3 :     }
    3022              :   return NULL_TREE;
    3023              : }
    3024              : 
    3025              : tree
    3026            4 : CompileExpr::lookup_label (NodeId to_be_resolved)
    3027              : {
    3028            4 :   HirId ref = resolve_nodeid (to_be_resolved, Resolver2_0::Namespace::Labels);
    3029            4 :   tree label = NULL_TREE;
    3030            4 :   rust_assert (ctx->lookup_label_decl (ref, &label)
    3031              :                && "failed to lookup a label");
    3032            4 :   return label;
    3033              : }
    3034              : 
    3035              : Bvariable *
    3036            4 : CompileExpr::lookup_label_temp_var (NodeId to_be_resolved)
    3037              : {
    3038              :   // TODO: Not sure that this temp var should have been inserted in the Labels
    3039              :   // namespace? Why not values?
    3040            4 :   HirId ref = resolve_nodeid (to_be_resolved, Resolver2_0::Namespace::Labels);
    3041            4 :   Bvariable *ltemp = nullptr;
    3042            4 :   rust_assert (ctx->lookup_var_decl (ref, &ltemp)
    3043              :                && "failed to lookup a temp var");
    3044            4 :   return ltemp;
    3045              : }
    3046              : 
    3047              : HirId
    3048            8 : CompileExpr::resolve_nodeid (NodeId to_be_resolved, Resolver2_0::Namespace ns)
    3049              : {
    3050            8 :   auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
    3051              : 
    3052            8 :   NodeId resolved_node_id;
    3053            8 :   resolved_node_id = nr_ctx.lookup (to_be_resolved, ns).value ();
    3054              : 
    3055            8 :   HirId ref
    3056            8 :     = ctx->get_mappings ().lookup_node_to_hir (resolved_node_id).value ();
    3057            8 :   return ref;
    3058              : }
    3059              : 
    3060              : } // namespace Compile
    3061              : } // 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.