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