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