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