LCOV - code coverage report
Current view: top level - gcc/rust/backend - rust-compile-expr.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.8 % 1408 1307
Test Date: 2025-09-20 13:40:47 Functions: 98.6 % 69 68
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

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

Generated by: LCOV version 2.1-beta

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