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