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 130254 : CompileExpr::CompileExpr (Context *ctx)
157 130254 : : HIRCompileBase (ctx), translated (error_mark_node)
158 130254 : {}
159 :
160 : tree
161 130254 : CompileExpr::Compile (HIR::Expr &expr, Context *ctx)
162 : {
163 130254 : CompileExpr compiler (ctx);
164 130254 : expr.accept_vis (compiler);
165 130254 : return compiler.translated;
166 130254 : }
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 3765 : CompileExpr::visit (HIR::ArithmeticOrLogicalExpr &expr)
310 : {
311 3765 : auto op = expr.get_expr_type ();
312 3765 : auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx);
313 3765 : auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx);
314 :
315 : // this might be an operator overload situation lets check
316 3765 : TyTy::FnType *fntype;
317 3765 : bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
318 3765 : expr.get_mappings ().get_hirid (), &fntype);
319 3765 : 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 490 : return;
327 : }
328 :
329 3564 : bool can_generate_overflow_checks
330 3564 : = (ctx->in_fn () && !ctx->const_context_p ()) && flag_overflow_checks;
331 3564 : if (!can_generate_overflow_checks)
332 : {
333 289 : translated
334 289 : = Backend::arithmetic_or_logical_expression (op, lhs, rhs,
335 : expr.get_locus ());
336 289 : return;
337 : }
338 :
339 3275 : auto receiver_tmp = NULL_TREE;
340 3275 : Bvariable *receiver
341 3275 : = Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE,
342 3275 : TREE_TYPE (lhs), lhs, true,
343 : expr.get_locus (), &receiver_tmp);
344 3275 : auto check
345 3275 : = Backend::arithmetic_or_logical_expression_checked (op, lhs, rhs,
346 : expr.get_locus (),
347 : receiver);
348 :
349 3275 : ctx->add_statement (check);
350 3275 : 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 854 : CompileExpr::visit (HIR::NegationExpr &expr)
403 : {
404 854 : auto op = expr.get_expr_type ();
405 :
406 854 : auto &literal_expr = expr.get_expr ();
407 :
408 : // If it's a negated integer/float literal, we can return early
409 854 : if (op == NegationOperator::NEGATE
410 854 : && literal_expr.get_expression_type () == HIR::Expr::ExprType::Lit)
411 : {
412 630 : auto &new_literal_expr = static_cast<HIR::LiteralExpr &> (literal_expr);
413 630 : auto lit_type = new_literal_expr.get_lit_type ();
414 630 : if (lit_type == HIR::Literal::LitType::INT
415 630 : || lit_type == HIR::Literal::LitType::FLOAT)
416 : {
417 630 : new_literal_expr.set_negative ();
418 630 : translated = CompileExpr::Compile (literal_expr, ctx);
419 644 : 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 5384 : CompileExpr::visit (HIR::TypeCastExpr &expr)
486 : {
487 5384 : TyTy::BaseType *type_to_cast_to_ty = nullptr;
488 5384 : 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 5384 : TyTy::BaseType *casted_tyty = nullptr;
496 5384 : if (!ctx->get_tyctx ()->lookup_type (
497 5384 : expr.get_casted_expr ().get_mappings ().get_hirid (), &casted_tyty))
498 : {
499 0 : translated = error_mark_node;
500 0 : return;
501 : }
502 :
503 5384 : auto type_to_cast_to = TyTyResolveCompile::compile (ctx, type_to_cast_to_ty);
504 5384 : auto casted_expr = CompileExpr::Compile (expr.get_casted_expr (), ctx);
505 :
506 5384 : std::vector<Resolver::Adjustment> *adjustments = nullptr;
507 5384 : bool ok = ctx->get_tyctx ()->lookup_cast_autoderef_mappings (
508 5384 : expr.get_mappings ().get_hirid (), &adjustments);
509 5384 : if (ok)
510 : {
511 5384 : casted_expr
512 5384 : = resolve_adjustments (*adjustments, casted_expr, expr.get_locus ());
513 : }
514 :
515 5384 : translated
516 5384 : = 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 769 : CompileExpr::visit (HIR::AnonConst &expr)
643 : {
644 769 : expr.get_inner_expr ().accept_vis (*this);
645 769 : }
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 1342 : CompileExpr::visit (HIR::StructExprStructFields &struct_expr)
694 : {
695 1342 : TyTy::BaseType *tyty = nullptr;
696 1342 : 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 1256 : return;
701 : }
702 1342 : if (!tyty->is<TyTy::ADTType> ())
703 : return;
704 :
705 : // it must be an ADT
706 1342 : rust_assert (tyty->get_kind () == TyTy::TypeKind::ADT);
707 1342 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyty);
708 :
709 : // what variant is it?
710 1342 : int union_disriminator = struct_expr.union_index;
711 1342 : TyTy::VariantDef *variant = nullptr;
712 1342 : if (!adt->is_enum ())
713 : {
714 1256 : rust_assert (adt->number_of_variants () == 1);
715 1256 : 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 1342 : tree compiled_adt_type = TyTyResolveCompile::compile (ctx, tyty);
732 :
733 1342 : std::vector<tree> arguments;
734 1342 : 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 4146 : 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 2904 : auto respective_field = variant->get_field_at_index (i);
773 2904 : auto expected = respective_field->get_field_type ();
774 :
775 : // process arguments
776 2904 : auto &argument = struct_expr.get_fields ().at (i);
777 2904 : auto lvalue_locus
778 2904 : = ctx->get_mappings ().lookup_location (expected->get_ty_ref ());
779 2904 : auto rvalue_locus = argument->get_locus ();
780 2904 : auto rvalue = CompileStructExprField::Compile (*argument, ctx);
781 :
782 2904 : TyTy::BaseType *actual = nullptr;
783 2904 : bool ok = ctx->get_tyctx ()->lookup_type (
784 2904 : argument->get_mappings ().get_hirid (), &actual);
785 :
786 : // coerce it if required/possible see
787 : // compile/torture/struct_base_init_1.rs
788 2904 : if (ok)
789 : {
790 2288 : rvalue
791 2288 : = coercion_site (argument->get_mappings ().get_hirid (), rvalue,
792 : actual, expected, lvalue_locus, rvalue_locus);
793 : }
794 :
795 : // add it to the list
796 2904 : arguments.push_back (rvalue);
797 : }
798 : }
799 :
800 1342 : if (!adt->is_enum ())
801 : {
802 1256 : auto repr_kind = adt->get_repr_options ().repr_kind;
803 1256 : 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 1254 : translated
812 1254 : = Backend::constructor_expression (compiled_adt_type,
813 : adt->is_enum (), arguments,
814 : union_disriminator,
815 : struct_expr.get_locus ());
816 : }
817 :
818 1256 : 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 1342 : }
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 5719 : CompileExpr::visit (HIR::FieldAccessExpr &expr)
849 : {
850 5719 : HIR::Expr &receiver_expr = expr.get_receiver_expr ();
851 5719 : tree receiver_ref = CompileExpr::Compile (receiver_expr, ctx);
852 :
853 : // resolve the receiver back to ADT type
854 5719 : TyTy::BaseType *receiver = nullptr;
855 5719 : if (!ctx->get_tyctx ()->lookup_type (
856 5719 : 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 5719 : size_t field_index = 0;
864 :
865 5719 : 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 5716 : else if (receiver->get_kind () == TyTy::TypeKind::ADT)
879 : {
880 2088 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver);
881 2088 : rust_assert (!adt->is_enum ());
882 2088 : rust_assert (adt->number_of_variants () == 1);
883 :
884 2088 : TyTy::VariantDef *variant = adt->get_variants ().at (0);
885 2088 : bool ok = variant->lookup_field (expr.get_field_name ().as_string (),
886 : nullptr, &field_index);
887 2088 : rust_assert (ok);
888 :
889 2088 : auto repr_kind = adt->get_repr_options ().repr_kind;
890 2088 : 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 5701 : 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 46799 : CompileExpr::visit (HIR::PathInExpression &expr)
949 : {
950 46799 : translated = ResolvePathRef::Compile (expr, ctx);
951 46799 : }
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 2013 : CompileExpr::visit (HIR::BorrowExpr &expr)
1200 : {
1201 2013 : tree main_expr = CompileExpr::Compile (expr.get_expr (), ctx);
1202 2013 : 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 1920 : 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 1920 : TyTy::BaseType *tyty = nullptr;
1224 1920 : if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
1225 : &tyty))
1226 : return;
1227 :
1228 1920 : tree expected_type = TyTyResolveCompile::compile (ctx, tyty);
1229 :
1230 1920 : bool is_fat_ptr
1231 1920 : = tyty->is<TyTy::ReferenceType> ()
1232 1920 : ? 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 1920 : : false;
1236 :
1237 1920 : 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 1920 : translated = address_expression (main_expr, expr.get_locus (), expected_type);
1273 : }
1274 :
1275 : void
1276 3996 : CompileExpr::visit (HIR::DereferenceExpr &expr)
1277 : {
1278 3996 : TyTy::BaseType *tyty = nullptr;
1279 3996 : 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 3996 : 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 3996 : TyTy::BaseType *base_tyty;
1295 3996 : if (ctx->get_tyctx ()->lookup_type (
1296 3996 : expr.get_expr ().get_mappings ().get_hirid (), &base_tyty))
1297 : {
1298 3996 : 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 3996 : TyTy::FnType *fntype;
1306 3996 : bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
1307 3996 : expr.get_mappings ().get_hirid (), &fntype);
1308 3996 : 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 3996 : tree expected_type = TyTyResolveCompile::compile (ctx, tyty);
1321 3996 : 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 3961 : translated = indirect_expression (main_expr, expr.get_locus ());
1328 : }
1329 :
1330 : void
1331 24976 : CompileExpr::visit (HIR::LiteralExpr &expr)
1332 : {
1333 24976 : TyTy::BaseType *tyty = nullptr;
1334 24976 : if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
1335 : &tyty))
1336 24976 : return;
1337 :
1338 24976 : 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 20030 : case HIR::Literal::INT:
1345 20030 : translated = compile_integer_literal (expr, tyty);
1346 20030 : 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 2474 : CompileExpr::visit (HIR::AssignmentExpr &expr)
1376 : {
1377 2474 : auto lvalue = CompileExpr::Compile (expr.get_lhs (), ctx);
1378 2474 : auto rvalue = CompileExpr::Compile (expr.get_rhs (), ctx);
1379 :
1380 : // assignments are coercion sites so lets convert the rvalue if necessary
1381 2474 : TyTy::BaseType *expected = nullptr;
1382 2474 : TyTy::BaseType *actual = nullptr;
1383 :
1384 2474 : bool ok;
1385 2474 : ok = ctx->get_tyctx ()->lookup_type (
1386 2474 : expr.get_lhs ().get_mappings ().get_hirid (), &expected);
1387 2474 : rust_assert (ok);
1388 :
1389 2474 : ok = ctx->get_tyctx ()->lookup_type (
1390 2474 : expr.get_rhs ().get_mappings ().get_hirid (), &actual);
1391 2474 : rust_assert (ok);
1392 :
1393 2474 : rvalue = coercion_site (expr.get_mappings ().get_hirid (), rvalue, actual,
1394 2474 : expected, expr.get_lhs ().get_locus (),
1395 2474 : 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 2474 : tree assignment
1402 2474 : = Backend::assignment_statement (lvalue, rvalue, expr.get_locus ());
1403 :
1404 2474 : ctx->add_statement (assignment);
1405 2474 : translated = unit_expression (expr.get_locus ());
1406 2474 : }
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 13245 : CompileExpr::visit (HIR::CallExpr &expr)
1580 : {
1581 13245 : TyTy::BaseType *tyty = nullptr;
1582 13245 : if (!ctx->get_tyctx ()->lookup_type (
1583 13245 : 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 13245 : bool is_adt_ctor = tyty->get_kind () == TyTy::TypeKind::ADT;
1591 13245 : 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 11424 : auto get_parameter_tyty_at_index
1679 11546 : = [] (const TyTy::BaseType *base, size_t index,
1680 : TyTy::BaseType **result) -> bool {
1681 11546 : bool is_fn = base->get_kind () == TyTy::TypeKind::FNDEF
1682 11546 : || base->get_kind () == TyTy::TypeKind::FNPTR;
1683 0 : rust_assert (is_fn);
1684 :
1685 11546 : if (base->get_kind () == TyTy::TypeKind::FNPTR)
1686 : {
1687 29 : const TyTy::FnPtr *fn = static_cast<const TyTy::FnPtr *> (base);
1688 29 : *result = fn->get_param_type_at (index);
1689 :
1690 29 : return true;
1691 : }
1692 :
1693 11517 : const TyTy::FnType *fn = static_cast<const TyTy::FnType *> (base);
1694 11517 : auto ¶m = fn->param_at (index);
1695 11517 : *result = param.get_type ();
1696 :
1697 11517 : return true;
1698 : };
1699 :
1700 : // special check for platform-intrinsic functions
1701 11424 : TyTy::FnType *platform_intrinsic = nullptr;
1702 11424 : if (tyty->get_kind () == TyTy::TypeKind::FNDEF)
1703 : {
1704 11334 : auto *fn_ty = static_cast<TyTy::FnType *> (tyty);
1705 11334 : if (fn_ty->get_abi () == ABI::PLATFORM_INTRINSIC)
1706 11424 : platform_intrinsic = fn_ty;
1707 : }
1708 :
1709 11424 : 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 11424 : auto fn_address = CompileExpr::Compile (expr.get_fnexpr (), ctx);
1718 11424 : 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 11422 : bool possible_trait_call
1743 11422 : = generate_possible_fn_trait_call (expr, fn_address, &translated);
1744 11422 : if (possible_trait_call)
1745 : return;
1746 :
1747 11362 : bool is_variadic = false;
1748 11362 : size_t required_num_args = expr.get_arguments ().size ();
1749 :
1750 11362 : if (tyty->get_kind () == TyTy::TypeKind::FNDEF)
1751 : {
1752 11333 : const TyTy::FnType *fn = static_cast<const TyTy::FnType *> (tyty);
1753 11333 : required_num_args = fn->num_params ();
1754 11333 : is_variadic = fn->is_variadic ();
1755 : }
1756 29 : else if (tyty->get_kind () == TyTy::TypeKind::FNPTR)
1757 : {
1758 29 : const TyTy::FnPtr *fn = static_cast<const TyTy::FnPtr *> (tyty);
1759 29 : required_num_args = fn->num_params ();
1760 : }
1761 :
1762 11362 : std::vector<tree> args;
1763 23696 : for (size_t source_argument_index = 0;
1764 23696 : source_argument_index < expr.get_arguments ().size ();
1765 : source_argument_index++)
1766 : {
1767 24668 : if (expr.is_const_argument (source_argument_index))
1768 788 : continue;
1769 :
1770 12333 : auto &argument = expr.get_arguments ().at (source_argument_index);
1771 12333 : size_t runtime_argument_index = args.size ();
1772 12333 : auto rvalue = CompileExpr::Compile (*argument, ctx);
1773 :
1774 12333 : if (is_variadic && runtime_argument_index >= required_num_args)
1775 : {
1776 787 : args.push_back (rvalue);
1777 787 : continue;
1778 : }
1779 :
1780 : // assignments are coercion sites so lets convert the rvalue if
1781 : // necessary
1782 11546 : bool ok;
1783 11546 : TyTy::BaseType *expected = nullptr;
1784 11546 : ok
1785 11546 : = get_parameter_tyty_at_index (tyty, runtime_argument_index, &expected);
1786 11546 : rust_assert (ok);
1787 :
1788 11546 : TyTy::BaseType *actual = nullptr;
1789 11546 : ok = ctx->get_tyctx ()->lookup_type (
1790 11546 : argument->get_mappings ().get_hirid (), &actual);
1791 11546 : rust_assert (ok);
1792 :
1793 : // coerce it if required
1794 11546 : location_t lvalue_locus
1795 11546 : = ctx->get_mappings ().lookup_location (expected->get_ty_ref ());
1796 11546 : location_t rvalue_locus = argument->get_locus ();
1797 11546 : rvalue = coercion_site (argument->get_mappings ().get_hirid (), rvalue,
1798 : actual, expected, lvalue_locus, rvalue_locus);
1799 :
1800 : // add it to the list
1801 11546 : args.push_back (rvalue);
1802 : }
1803 :
1804 11362 : if (platform_intrinsic != nullptr)
1805 : {
1806 0 : translated = PlatformIntrinsic::compile_call (ctx, platform_intrinsic,
1807 : args, expr.get_locus ());
1808 0 : return;
1809 : }
1810 :
1811 : // must be a regular call to a function
1812 11362 : translated
1813 11362 : = Backend::call_expression (fn_address, args, nullptr, expr.get_locus ());
1814 11362 : }
1815 :
1816 : void
1817 2667 : CompileExpr::visit (HIR::MethodCallExpr &expr)
1818 : {
1819 : // method receiver
1820 2667 : tree self = CompileExpr::Compile (expr.get_receiver (), ctx);
1821 :
1822 : // lookup the expected function type
1823 2667 : TyTy::BaseType *lookup_fntype = nullptr;
1824 2667 : bool ok = ctx->get_tyctx ()->lookup_type (
1825 2667 : expr.get_method_name ().get_mappings ().get_hirid (), &lookup_fntype);
1826 2667 : rust_assert (ok);
1827 2667 : rust_assert (lookup_fntype->get_kind () == TyTy::TypeKind::FNDEF);
1828 2667 : TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup_fntype);
1829 :
1830 2667 : TyTy::BaseType *receiver = nullptr;
1831 2667 : ok = ctx->get_tyctx ()->lookup_type (
1832 2667 : expr.get_receiver ().get_mappings ().get_hirid (), &receiver);
1833 2667 : rust_assert (ok);
1834 :
1835 : // lookup the autoderef mappings
1836 2667 : HirId autoderef_mappings_id
1837 2667 : = expr.get_receiver ().get_mappings ().get_hirid ();
1838 2667 : std::vector<Resolver::Adjustment> *adjustments = nullptr;
1839 2667 : ok = ctx->get_tyctx ()->lookup_autoderef_mappings (autoderef_mappings_id,
1840 : &adjustments);
1841 2667 : rust_assert (ok);
1842 :
1843 : // apply adjustments for the fn call
1844 2667 : self = resolve_adjustments (*adjustments, self,
1845 2667 : expr.get_receiver ().get_locus ());
1846 :
1847 2667 : if (adjustments != nullptr && !adjustments->empty ())
1848 622 : receiver = adjustments->back ().get_expected ();
1849 :
1850 2667 : enum
1851 : {
1852 : DYN,
1853 : DYN_BOX,
1854 : NOT_DYN,
1855 2667 : } is_dyn_dispatch
1856 : = NOT_DYN;
1857 2667 : const TyTy::DynamicObjectType *dyn = nullptr;
1858 2667 : if (receiver->get_root ()->get_kind () == TyTy::TypeKind::DYNAMIC)
1859 : {
1860 209 : is_dyn_dispatch = DYN;
1861 209 : dyn
1862 209 : = static_cast<const TyTy::DynamicObjectType *> (receiver->get_root ());
1863 : }
1864 2458 : else if (auto inner = TyTy::try_get_box_inner_type (receiver->get_root ()))
1865 : {
1866 1 : if ((*inner)->get_root ()->get_kind () == TyTy::TypeKind::DYNAMIC)
1867 : {
1868 1 : is_dyn_dispatch = DYN_BOX;
1869 1 : dyn = static_cast<const TyTy::DynamicObjectType *> (
1870 1 : (*inner)->get_root ());
1871 : }
1872 : }
1873 :
1874 2667 : bool is_generic_receiver = receiver->get_kind () == TyTy::TypeKind::PARAM;
1875 2667 : if (is_generic_receiver)
1876 : {
1877 77 : TyTy::ParamType *p = static_cast<TyTy::ParamType *> (receiver);
1878 77 : receiver = p->resolve ();
1879 : }
1880 :
1881 2667 : tree fn_expr = error_mark_node;
1882 2667 : if (is_dyn_dispatch == NOT_DYN)
1883 : // lookup compiled functions since it may have already been compiled
1884 2457 : fn_expr = resolve_method_address (fntype, receiver, expr.get_locus ());
1885 : else
1886 : {
1887 210 : tree target_self
1888 : = is_dyn_dispatch == DYN
1889 210 : ? self
1890 1 : : build_box_inner_ptr (self, expr.get_receiver ().get_locus ());
1891 :
1892 210 : fn_expr = get_fn_addr_from_dyn (dyn, receiver, fntype, target_self,
1893 : expr.get_locus ());
1894 :
1895 210 : self = get_receiver_from_dyn (dyn, receiver, fntype, target_self,
1896 : expr.get_locus ());
1897 : }
1898 :
1899 2667 : std::vector<tree> args;
1900 2667 : args.push_back (self); // adjusted self
1901 :
1902 : // normal args
1903 7096 : for (size_t i = 0; i < expr.get_arguments ().size (); i++)
1904 : {
1905 1762 : auto &argument = expr.get_arguments ().at (i);
1906 1762 : auto rvalue = CompileExpr::Compile (*argument, ctx);
1907 :
1908 : // assignments are coercion sites so lets convert the rvalue if
1909 : // necessary, offset from the already adjusted implicit self
1910 1762 : bool ok;
1911 1762 : TyTy::BaseType *expected = fntype->param_at (i + 1).get_type ();
1912 :
1913 1762 : TyTy::BaseType *actual = nullptr;
1914 1762 : ok = ctx->get_tyctx ()->lookup_type (
1915 1762 : argument->get_mappings ().get_hirid (), &actual);
1916 1762 : rust_assert (ok);
1917 :
1918 : // coerce it if required
1919 1762 : location_t lvalue_locus
1920 1762 : = ctx->get_mappings ().lookup_location (expected->get_ty_ref ());
1921 1762 : location_t rvalue_locus = argument->get_locus ();
1922 1762 : rvalue = coercion_site (argument->get_mappings ().get_hirid (), rvalue,
1923 : actual, expected, lvalue_locus, rvalue_locus);
1924 :
1925 : // add it to the list
1926 1762 : args.push_back (rvalue);
1927 : }
1928 :
1929 2667 : translated
1930 2667 : = Backend::call_expression (fn_expr, args, nullptr, expr.get_locus ());
1931 2667 : }
1932 :
1933 : tree
1934 210 : CompileExpr::get_fn_addr_from_dyn (const TyTy::DynamicObjectType *dyn,
1935 : TyTy::BaseType *receiver,
1936 : TyTy::FnType *fntype, tree receiver_ref,
1937 : location_t expr_locus)
1938 : {
1939 210 : size_t offs = 0;
1940 210 : const Resolver::TraitItemReference *ref = nullptr;
1941 268 : for (auto &bound : dyn->get_object_items ())
1942 : {
1943 268 : const Resolver::TraitItemReference *item = bound.first;
1944 268 : auto t = item->get_tyty ();
1945 268 : rust_assert (t->get_kind () == TyTy::TypeKind::FNDEF);
1946 268 : auto ft = static_cast<TyTy::FnType *> (t);
1947 :
1948 478 : if (ft->get_id () == fntype->get_id ())
1949 : {
1950 : ref = item;
1951 : break;
1952 : }
1953 58 : offs++;
1954 210 : }
1955 :
1956 210 : if (ref == nullptr)
1957 0 : return error_mark_node;
1958 :
1959 : // cast it to the correct fntype
1960 210 : tree expected_fntype = TyTyResolveCompile::compile (ctx, fntype, true);
1961 210 : tree idx = build_int_cst (size_type_node, offs);
1962 :
1963 210 : tree vtable_ptr
1964 210 : = Backend::struct_field_expression (receiver_ref, 1, expr_locus);
1965 210 : tree vtable_struct_type = TREE_TYPE (TREE_TYPE (vtable_ptr));
1966 210 : rust_assert (TREE_CODE (vtable_struct_type) == RECORD_TYPE);
1967 210 : tree vtable_field = TYPE_FIELDS (vtable_struct_type);
1968 898 : for (size_t i = 0; i < offs + 3; i++) // drop, size, align, [methods]
1969 688 : vtable_field = DECL_CHAIN (vtable_field);
1970 210 : rust_assert (vtable_field != NULL_TREE);
1971 210 : tree vtable = build_fold_indirect_ref_loc (expr_locus, vtable_ptr);
1972 210 : tree vtable_field_access
1973 210 : = build3_loc (expr_locus, COMPONENT_REF, TREE_TYPE (vtable_field), vtable,
1974 : vtable_field, NULL_TREE);
1975 :
1976 210 : tree vcall = build3_loc (expr_locus, OBJ_TYPE_REF, expected_fntype,
1977 : vtable_field_access, receiver_ref, idx);
1978 :
1979 210 : return vcall;
1980 : }
1981 :
1982 : tree
1983 210 : CompileExpr::get_receiver_from_dyn (const TyTy::DynamicObjectType *dyn,
1984 : TyTy::BaseType *receiver,
1985 : TyTy::FnType *fntype, tree receiver_ref,
1986 : location_t expr_locus)
1987 : {
1988 : // access the offs + 1 for the fnptr and offs=0 for the reciever obj
1989 210 : return Backend::struct_field_expression (receiver_ref, 0, expr_locus);
1990 : }
1991 :
1992 : tree
1993 1219 : CompileExpr::resolve_operator_overload (
1994 : LangItem::Kind lang_item_type, HIR::OperatorExprMeta expr, tree lhs, tree rhs,
1995 : HIR::Expr &lhs_expr, tl::optional<std::reference_wrapper<HIR::Expr>> rhs_expr,
1996 : HIR::PathIdentSegment specified_segment)
1997 : {
1998 1219 : TyTy::FnType *fntype;
1999 1219 : bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
2000 1219 : expr.get_mappings ().get_hirid (), &fntype);
2001 1219 : rust_assert (is_op_overload);
2002 :
2003 1219 : TyTy::BaseType *receiver = nullptr;
2004 1219 : bool ok
2005 1219 : = ctx->get_tyctx ()->lookup_type (lhs_expr.get_mappings ().get_hirid (),
2006 : &receiver);
2007 1219 : rust_assert (ok);
2008 :
2009 1219 : bool is_generic_receiver = receiver->get_kind () == TyTy::TypeKind::PARAM;
2010 1219 : if (is_generic_receiver)
2011 : {
2012 14 : TyTy::ParamType *p = static_cast<TyTy::ParamType *> (receiver);
2013 14 : receiver = p->resolve ();
2014 : }
2015 :
2016 : // lookup compiled functions since it may have already been compiled
2017 1219 : HIR::PathIdentSegment segment_name
2018 1219 : = specified_segment.is_error ()
2019 1563 : ? HIR::PathIdentSegment (LangItem::ToString (lang_item_type))
2020 1219 : : specified_segment;
2021 1219 : tree fn_expr = resolve_method_address (fntype, receiver, expr.get_locus ());
2022 :
2023 : // lookup the autoderef mappings
2024 1219 : std::vector<Resolver::Adjustment> *adjustments = nullptr;
2025 1219 : ok = ctx->get_tyctx ()->lookup_autoderef_mappings (
2026 1219 : expr.get_lvalue_mappings ().get_hirid (), &adjustments);
2027 1219 : rust_assert (ok);
2028 :
2029 : // apply adjustments for the fn call
2030 1219 : tree self = resolve_adjustments (*adjustments, lhs, lhs_expr.get_locus ());
2031 :
2032 1219 : std::vector<tree> args;
2033 1219 : args.push_back (self); // adjusted self
2034 1219 : if (rhs != nullptr) // can be null for negation_expr (unary ones)
2035 1156 : args.push_back (rhs);
2036 :
2037 1219 : return Backend::call_expression (fn_expr, args, nullptr, expr.get_locus ());
2038 1219 : }
2039 :
2040 : tree
2041 928 : CompileExpr::compile_bool_literal (const HIR::LiteralExpr &expr,
2042 : const TyTy::BaseType *tyty)
2043 : {
2044 928 : rust_assert (expr.get_lit_type () == HIR::Literal::BOOL);
2045 :
2046 928 : const auto literal_value = expr.get_literal ();
2047 1856 : bool bval = literal_value.as_string ().compare ("true") == 0;
2048 928 : return Backend::boolean_constant_expression (bval);
2049 928 : }
2050 :
2051 : tree
2052 20030 : CompileExpr::compile_integer_literal (const HIR::LiteralExpr &expr,
2053 : const TyTy::BaseType *tyty)
2054 : {
2055 20030 : rust_assert (expr.get_lit_type () == HIR::Literal::INT);
2056 20030 : const auto &literal_value = expr.get_literal ();
2057 20030 : tree type = TyTyResolveCompile::compile (ctx, tyty);
2058 :
2059 20030 : std::string s = literal_value.as_string ();
2060 20030 : s.erase (std::remove (s.begin (), s.end (), '_'), s.end ());
2061 :
2062 20030 : int base = 0;
2063 20030 : mpz_t ival;
2064 20030 : if (mpz_init_set_str (ival, s.c_str (), base) != 0)
2065 : {
2066 0 : rust_error_at (expr.get_locus (), "failed to load number literal");
2067 0 : return error_mark_node;
2068 : }
2069 20030 : if (expr.is_negative ())
2070 661 : mpz_neg (ival, ival);
2071 :
2072 20030 : mpz_t type_min, type_max;
2073 20030 : mpz_init (type_min);
2074 20030 : mpz_init (type_max);
2075 20030 : get_type_static_bounds (type, type_min, type_max);
2076 :
2077 20030 : if (mpz_cmp (ival, type_min) < 0 || mpz_cmp (ival, type_max) > 0)
2078 : {
2079 2 : rust_error_at (expr.get_locus (),
2080 : "integer overflows the respective type %qs",
2081 2 : tyty->get_name ().c_str ());
2082 2 : mpz_clear (type_min);
2083 2 : mpz_clear (type_max);
2084 2 : mpz_clear (ival);
2085 2 : return error_mark_node;
2086 : }
2087 :
2088 20028 : tree result = wide_int_to_tree (type, wi::from_mpz (type, ival, true));
2089 20028 : mpz_clear (type_min);
2090 20028 : mpz_clear (type_max);
2091 20028 : mpz_clear (ival);
2092 :
2093 20028 : return result;
2094 20030 : }
2095 :
2096 : tree
2097 999 : CompileExpr::compile_float_literal (const HIR::LiteralExpr &expr,
2098 : const TyTy::BaseType *tyty)
2099 : {
2100 999 : rust_assert (expr.get_lit_type () == HIR::Literal::FLOAT);
2101 999 : const auto literal_value = expr.get_literal ();
2102 :
2103 999 : tree type = TyTyResolveCompile::compile (ctx, tyty);
2104 :
2105 999 : mpfr_t fval;
2106 2997 : if (mpfr_init_set_str (fval, literal_value.as_string ().c_str (), 10,
2107 : MPFR_RNDN)
2108 999 : != 0)
2109 : {
2110 0 : rust_error_at (expr.get_locus (), "bad number in literal");
2111 0 : return error_mark_node;
2112 : }
2113 999 : if (expr.is_negative ())
2114 6 : mpfr_neg (fval, fval, MPFR_RNDN);
2115 :
2116 : // taken from:
2117 : // see go/gofrontend/expressions.cc:check_float_type
2118 999 : bool real_value_overflow;
2119 :
2120 999 : if (mpfr_regular_p (fval) != 0)
2121 : {
2122 893 : mpfr_exp_t exp = mpfr_get_exp (fval);
2123 893 : mpfr_exp_t min_exp;
2124 893 : mpfr_exp_t max_exp;
2125 :
2126 : /*
2127 : * By convention, the radix point of the significand is just before the
2128 : * first digit (which is always 1 due to normalization), like in the C
2129 : * language, but unlike in IEEE 754 (thus, for a given number, the
2130 : * exponent values in MPFR and in IEEE 754 differ by 1).
2131 : */
2132 893 : switch (TYPE_PRECISION (type))
2133 : {
2134 : case 32:
2135 : min_exp = -128 + 1;
2136 : max_exp = 127 + 1;
2137 : break;
2138 321 : case 64:
2139 321 : min_exp = -1024 + 1;
2140 321 : max_exp = 1023 + 1;
2141 321 : break;
2142 0 : default:
2143 0 : rust_error_at (expr.get_locus (),
2144 : "precision of type %<%s%> not supported",
2145 0 : tyty->get_name ().c_str ());
2146 0 : return error_mark_node;
2147 : }
2148 893 : real_value_overflow = exp < min_exp || exp > max_exp;
2149 : }
2150 : else
2151 : {
2152 : real_value_overflow = false;
2153 : }
2154 :
2155 999 : REAL_VALUE_TYPE r1;
2156 999 : real_from_mpfr (&r1, fval, type, GMP_RNDN);
2157 999 : REAL_VALUE_TYPE r2;
2158 999 : real_convert (&r2, TYPE_MODE (type), &r1);
2159 :
2160 999 : tree real_value = build_real (type, r2);
2161 999 : if (TREE_OVERFLOW (real_value) || real_value_overflow)
2162 : {
2163 1 : rust_error_at (expr.get_locus (),
2164 : "decimal overflows the respective type %qs",
2165 1 : tyty->get_name ().c_str ());
2166 1 : return error_mark_node;
2167 : }
2168 :
2169 : return real_value;
2170 999 : }
2171 :
2172 : tree
2173 183 : CompileExpr::compile_char_literal (const HIR::LiteralExpr &expr,
2174 : const TyTy::BaseType *tyty)
2175 : {
2176 183 : rust_assert (expr.get_lit_type () == HIR::Literal::CHAR);
2177 183 : const auto literal_value = expr.get_literal ();
2178 :
2179 : // FIXME needs wchar_t
2180 366 : char c = literal_value.as_string ().c_str ()[0];
2181 183 : return Backend::wchar_constant_expression (c);
2182 183 : }
2183 :
2184 : tree
2185 408 : CompileExpr::compile_byte_literal (const HIR::LiteralExpr &expr,
2186 : const TyTy::BaseType *tyty)
2187 : {
2188 408 : rust_assert (expr.get_lit_type () == HIR::Literal::BYTE);
2189 408 : const auto literal_value = expr.get_literal ();
2190 :
2191 408 : tree type = TyTyResolveCompile::compile (ctx, tyty);
2192 816 : char c = literal_value.as_string ().c_str ()[0];
2193 408 : return build_int_cst (type, c);
2194 408 : }
2195 :
2196 : tree
2197 2379 : CompileExpr::compile_string_literal (const HIR::LiteralExpr &expr,
2198 : const TyTy::BaseType *tyty)
2199 : {
2200 2379 : tree fat_pointer = TyTyResolveCompile::compile (ctx, tyty);
2201 :
2202 2379 : rust_assert (expr.get_lit_type () == HIR::Literal::STRING);
2203 2379 : const auto literal_value = expr.get_literal ();
2204 :
2205 4758 : auto base = Backend::string_constant_expression (literal_value.as_string ());
2206 2379 : tree data = address_expression (base, expr.get_locus ());
2207 :
2208 2379 : TyTy::BaseType *usize = nullptr;
2209 2379 : bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
2210 2379 : rust_assert (ok);
2211 2379 : tree type = TyTyResolveCompile::compile (ctx, usize);
2212 :
2213 4758 : tree size = build_int_cstu (type, literal_value.as_string ().size ());
2214 :
2215 2379 : return Backend::constructor_expression (fat_pointer, false, {data, size}, -1,
2216 2379 : expr.get_locus ());
2217 2379 : }
2218 :
2219 : tree
2220 35 : CompileExpr::compile_byte_string_literal (const HIR::LiteralExpr &expr,
2221 : const TyTy::BaseType *tyty)
2222 : {
2223 35 : rust_assert (expr.get_lit_type () == HIR::Literal::BYTE_STRING);
2224 :
2225 : // the type here is &[ty; capacity]
2226 35 : rust_assert (tyty->get_kind () == TyTy::TypeKind::REF);
2227 35 : const auto ref_tyty = static_cast<const TyTy::ReferenceType *> (tyty);
2228 35 : auto base_tyty = ref_tyty->get_base ();
2229 35 : rust_assert (base_tyty->get_kind () == TyTy::TypeKind::ARRAY);
2230 35 : auto array_tyty = static_cast<TyTy::ArrayType *> (base_tyty);
2231 :
2232 35 : std::string value_str = expr.get_literal ().as_string ();
2233 35 : std::vector<tree> vals;
2234 35 : std::vector<unsigned long> indexes;
2235 273 : for (size_t i = 0; i < value_str.size (); i++)
2236 : {
2237 238 : char b = value_str.at (i);
2238 238 : tree bb = Backend::char_constant_expression (b);
2239 238 : vals.push_back (bb);
2240 238 : indexes.push_back (i);
2241 : }
2242 :
2243 35 : tree array_type = TyTyResolveCompile::compile (ctx, array_tyty);
2244 35 : tree constructed
2245 35 : = Backend::array_constructor_expression (array_type, indexes, vals,
2246 : expr.get_locus ());
2247 :
2248 35 : return address_expression (constructed, expr.get_locus ());
2249 35 : }
2250 :
2251 : tree
2252 14 : CompileExpr::compile_c_string_literal (const HIR::LiteralExpr &expr,
2253 : const TyTy::BaseType *tyty)
2254 : {
2255 : // Copied from compile_string_literal
2256 14 : tree fat_pointer = TyTyResolveCompile::compile (ctx, tyty);
2257 :
2258 14 : rust_assert (expr.get_lit_type () == HIR::Literal::C_STRING);
2259 14 : const auto literal_value = expr.get_literal ();
2260 :
2261 28 : auto base = Backend::string_constant_expression (literal_value.as_string ());
2262 14 : tree data = address_expression (base, expr.get_locus ());
2263 :
2264 14 : TyTy::BaseType *usize = nullptr;
2265 14 : bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
2266 14 : rust_assert (ok);
2267 14 : tree type = TyTyResolveCompile::compile (ctx, usize);
2268 :
2269 : // +1 for null terminator, unlike Rust string literals.
2270 28 : tree size = build_int_cstu (type, literal_value.as_string ().size () + 1);
2271 :
2272 14 : return Backend::constructor_expression (fat_pointer, false, {data, size}, -1,
2273 14 : expr.get_locus ());
2274 14 : }
2275 :
2276 : tree
2277 18 : CompileExpr::compile_transparent_field_access (TyTy::VariantDef *variant,
2278 : location_t locus,
2279 : tree source_expr)
2280 : {
2281 18 : const TyTy::StructFieldType *field = variant->get_field_at_index (0);
2282 18 : tree field_type = TyTyResolveCompile::compile (ctx, field->get_field_type ());
2283 18 : return fold_build1_loc (locus, VIEW_CONVERT_EXPR, field_type, source_expr);
2284 : }
2285 :
2286 : tree
2287 5384 : CompileExpr::type_cast_expression (tree type_to_cast_to, tree expr_tree,
2288 : location_t location)
2289 : {
2290 5384 : if (type_to_cast_to == error_mark_node || expr_tree == error_mark_node
2291 10768 : || TREE_TYPE (expr_tree) == error_mark_node)
2292 : return error_mark_node;
2293 :
2294 5384 : if (Backend::type_size (type_to_cast_to) == 0
2295 5384 : || TREE_TYPE (expr_tree) == void_type_node)
2296 : {
2297 : // Do not convert zero-sized types.
2298 : return expr_tree;
2299 : }
2300 5384 : else if (TREE_CODE (type_to_cast_to) == INTEGER_TYPE)
2301 : {
2302 1531 : tree cast = convert_to_integer (type_to_cast_to, expr_tree);
2303 : // FIXME check for TREE_OVERFLOW?
2304 1531 : return cast;
2305 : }
2306 3853 : else if (TREE_CODE (type_to_cast_to) == REAL_TYPE)
2307 : {
2308 9 : tree cast = convert_to_real (type_to_cast_to, expr_tree);
2309 : // FIXME
2310 : // We might need to check that the tree is MAX val and thusly saturate it
2311 : // to inf. we can get the bounds and check the value if its >= or <= to
2312 : // the min and max bounds
2313 : //
2314 : // https://github.com/Rust-GCC/gccrs/issues/635
2315 9 : return cast;
2316 : }
2317 3844 : else if (TREE_CODE (type_to_cast_to) == COMPLEX_TYPE)
2318 : {
2319 0 : return convert_to_complex (type_to_cast_to, expr_tree);
2320 : }
2321 3844 : else if (TREE_CODE (type_to_cast_to) == POINTER_TYPE
2322 3844 : && TREE_CODE (TREE_TYPE (expr_tree)) == INTEGER_TYPE)
2323 : {
2324 15 : return convert_to_pointer (type_to_cast_to, expr_tree);
2325 : }
2326 3829 : else if (TREE_CODE (type_to_cast_to) == RECORD_TYPE
2327 3829 : || TREE_CODE (type_to_cast_to) == ARRAY_TYPE)
2328 : {
2329 1750 : return fold_build1_loc (location, VIEW_CONVERT_EXPR, type_to_cast_to,
2330 1750 : expr_tree);
2331 : }
2332 2079 : else if (TREE_CODE (type_to_cast_to) == POINTER_TYPE
2333 2079 : && RS_DST_FLAG (TREE_TYPE (expr_tree)))
2334 : {
2335 : // returning a raw cast using NOP_EXPR seems to resut in an ICE:
2336 : //
2337 : // Analyzing compilation unit
2338 : // Performing interprocedural optimizations
2339 : // <*free_lang_data> {heap 2644k} <visibility> {heap 2644k}
2340 : // <build_ssa_passes> {heap 2644k} <opt_local_passes> {heap 2644k}during
2341 : // GIMPLE pass: cddce
2342 : // In function ‘*T::as_ptr<i32>’:
2343 : // rust1: internal compiler error: in propagate_necessity, at
2344 : // tree-ssa-dce.cc:984 0x1d5b43e propagate_necessity
2345 : // ../../gccrs/gcc/tree-ssa-dce.cc:984
2346 : // 0x1d5e180 perform_tree_ssa_dce
2347 : // ../../gccrs/gcc/tree-ssa-dce.cc:1876
2348 : // 0x1d5e2c8 tree_ssa_cd_dce
2349 : // ../../gccrs/gcc/tree-ssa-dce.cc:1920
2350 : // 0x1d5e49a execute
2351 : // ../../gccrs/gcc/tree-ssa-dce.cc:1992
2352 :
2353 : // this is returning the direct raw pointer of the slice an assumes a very
2354 : // specific layout
2355 1746 : return Backend::struct_field_expression (expr_tree, 0, location);
2356 : }
2357 :
2358 333 : return fold_convert_loc (location, type_to_cast_to, expr_tree);
2359 : }
2360 :
2361 : void
2362 408 : CompileExpr::visit (HIR::ArrayExpr &expr)
2363 : {
2364 408 : TyTy::BaseType *tyty = nullptr;
2365 408 : if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
2366 : &tyty))
2367 : {
2368 0 : rust_fatal_error (expr.get_locus (),
2369 : "did not resolve type for this array expr");
2370 293 : return;
2371 : }
2372 :
2373 408 : tree array_type = TyTyResolveCompile::compile (ctx, tyty);
2374 408 : if (TREE_CODE (array_type) != ARRAY_TYPE)
2375 : {
2376 0 : translated = error_mark_node;
2377 0 : return;
2378 : }
2379 :
2380 408 : rust_assert (tyty->get_kind () == TyTy::TypeKind::ARRAY);
2381 408 : const TyTy::ArrayType &array_tyty
2382 : = static_cast<const TyTy::ArrayType &> (*tyty);
2383 :
2384 408 : HIR::ArrayElems &elements = expr.get_internal_elements ();
2385 408 : switch (elements.get_array_expr_type ())
2386 : {
2387 293 : case HIR::ArrayElems::ArrayExprType::VALUES:
2388 293 : {
2389 293 : HIR::ArrayElemsValues &elems
2390 : = static_cast<HIR::ArrayElemsValues &> (elements);
2391 293 : translated
2392 293 : = array_value_expr (expr.get_locus (), array_tyty, array_type, elems);
2393 : }
2394 293 : return;
2395 :
2396 115 : case HIR::ArrayElems::ArrayExprType::COPIED:
2397 115 : HIR::ArrayElemsCopied &elems
2398 : = static_cast<HIR::ArrayElemsCopied &> (elements);
2399 115 : translated
2400 115 : = array_copied_expr (expr.get_locus (), array_tyty, array_type, elems);
2401 : }
2402 : }
2403 :
2404 : tree
2405 293 : CompileExpr::array_value_expr (location_t expr_locus,
2406 : const TyTy::ArrayType &array_tyty,
2407 : tree array_type, HIR::ArrayElemsValues &elems)
2408 : {
2409 293 : std::vector<unsigned long> indexes;
2410 293 : std::vector<tree> constructor;
2411 293 : size_t i = 0;
2412 1782 : for (auto &elem : elems.get_values ())
2413 : {
2414 1490 : tree translated_expr = CompileExpr::Compile (*elem, ctx);
2415 1490 : if (translated_expr == error_mark_node)
2416 : {
2417 1 : rich_location r (line_table, expr_locus);
2418 1 : r.add_fixit_replace (elem->get_locus (), "not a value");
2419 1 : rust_error_at (r, ErrorCode::E0423, "expected value");
2420 1 : return error_mark_node;
2421 1 : }
2422 :
2423 1489 : constructor.push_back (translated_expr);
2424 1489 : indexes.push_back (i++);
2425 : }
2426 :
2427 292 : return Backend::array_constructor_expression (array_type, indexes,
2428 292 : constructor, expr_locus);
2429 293 : }
2430 :
2431 : tree
2432 115 : CompileExpr::array_copied_expr (location_t expr_locus,
2433 : const TyTy::ArrayType &array_tyty,
2434 : tree array_type, HIR::ArrayElemsCopied &elems)
2435 : {
2436 : // see gcc/cp/typeck2.cc:1369-1401
2437 115 : gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
2438 115 : tree domain = TYPE_DOMAIN (array_type);
2439 115 : if (!domain)
2440 0 : return error_mark_node;
2441 :
2442 115 : if (!TREE_CONSTANT (TYPE_MAX_VALUE (domain)))
2443 : {
2444 0 : rust_error_at (expr_locus, "non const capacity domain %qT", array_type);
2445 0 : return error_mark_node;
2446 : }
2447 :
2448 115 : auto capacity_ty = array_tyty.get_capacity ();
2449 :
2450 : // Check if capacity is a const type
2451 115 : if (capacity_ty->get_kind () != TyTy::TypeKind::CONST)
2452 : {
2453 0 : rust_error_at (array_tyty.get_locus (),
2454 : "array capacity is not a const type");
2455 0 : return error_mark_node;
2456 : }
2457 :
2458 115 : auto *capacity_const = capacity_ty->as_const_type ();
2459 :
2460 115 : rust_assert (capacity_const->const_kind ()
2461 : == TyTy::BaseConstType::ConstKind::Value);
2462 115 : auto &capacity_value = *static_cast<TyTy::ConstValueType *> (capacity_const);
2463 115 : auto cap_tree = capacity_value.get_value ();
2464 115 : if (error_operand_p (cap_tree) || !TREE_CONSTANT (cap_tree))
2465 : {
2466 0 : rust_error_at (expr_locus, "non const num copies %qT", cap_tree);
2467 0 : return error_mark_node;
2468 : }
2469 :
2470 : // get the compiled value
2471 115 : tree translated_expr = CompileExpr::Compile (elems.get_elem_to_copy (), ctx);
2472 :
2473 115 : tree max_domain = TYPE_MAX_VALUE (domain);
2474 115 : tree min_domain = TYPE_MIN_VALUE (domain);
2475 :
2476 115 : auto max = wi::to_offset (max_domain);
2477 115 : auto min = wi::to_offset (min_domain);
2478 115 : auto precision = TYPE_PRECISION (TREE_TYPE (domain));
2479 115 : auto sign = TYPE_SIGN (TREE_TYPE (domain));
2480 115 : unsigned HOST_WIDE_INT len
2481 115 : = wi::ext (max - min + 1, precision, sign).to_uhwi ();
2482 :
2483 : // In a const context we must initialize the entire array, which entails
2484 : // allocating for each element. If the user wants a huge array, we will OOM
2485 : // and die horribly.
2486 115 : if (ctx->const_context_p ())
2487 : {
2488 10 : size_t idx = 0;
2489 :
2490 10 : std::vector<unsigned long> indexes;
2491 10 : std::vector<tree> constructor;
2492 :
2493 10 : indexes.reserve (len);
2494 10 : constructor.reserve (len);
2495 188 : for (unsigned HOST_WIDE_INT i = 0; i < len; i++)
2496 : {
2497 168 : constructor.push_back (translated_expr);
2498 168 : indexes.push_back (idx++);
2499 : }
2500 :
2501 10 : return Backend::array_constructor_expression (array_type, indexes,
2502 : constructor, expr_locus);
2503 10 : }
2504 :
2505 : else
2506 : {
2507 : // Create a new block scope in which to initialize the array
2508 105 : tree fndecl = NULL_TREE;
2509 105 : if (ctx->in_fn ())
2510 105 : fndecl = ctx->peek_fn ().fndecl;
2511 :
2512 105 : std::vector<Bvariable *> locals;
2513 105 : tree enclosing_scope = ctx->peek_enclosing_scope ();
2514 105 : tree init_block = Backend::block (fndecl, enclosing_scope, locals,
2515 : expr_locus, expr_locus);
2516 105 : ctx->push_block (init_block);
2517 :
2518 105 : tree tmp;
2519 105 : tree stmts
2520 105 : = Backend::array_initializer (fndecl, init_block, array_type, cap_tree,
2521 : translated_expr, &tmp, expr_locus);
2522 105 : ctx->add_statement (stmts);
2523 :
2524 105 : tree block = ctx->pop_block ();
2525 :
2526 : // The result is a compound expression which creates a temporary array,
2527 : // initializes all the elements in a loop, and then yeilds the array.
2528 105 : return Backend::compound_expression (block, tmp, expr_locus);
2529 105 : }
2530 : }
2531 :
2532 : tree
2533 43219 : HIRCompileBase::resolve_adjustments (
2534 : std::vector<Resolver::Adjustment> &adjustments, tree expression,
2535 : location_t locus)
2536 : {
2537 43219 : tree e = expression;
2538 45648 : for (auto &adjustment : adjustments)
2539 : {
2540 2430 : if (e == error_mark_node)
2541 : return error_mark_node;
2542 :
2543 2429 : switch (adjustment.get_type ())
2544 : {
2545 : case Resolver::Adjustment::AdjustmentType::ERROR:
2546 : return error_mark_node;
2547 :
2548 1771 : case Resolver::Adjustment::AdjustmentType::IMM_REF:
2549 1771 : case Resolver::Adjustment::AdjustmentType::MUT_REF:
2550 1771 : {
2551 1771 : if (!RS_DST_FLAG (TREE_TYPE (e)))
2552 : {
2553 1505 : e = address_expression (e, locus);
2554 : }
2555 : }
2556 : break;
2557 :
2558 62 : case Resolver::Adjustment::AdjustmentType::DEREF:
2559 62 : case Resolver::Adjustment::AdjustmentType::DEREF_MUT:
2560 62 : e = resolve_deref_adjustment (adjustment, e, locus);
2561 62 : break;
2562 :
2563 329 : case Resolver::Adjustment::AdjustmentType::INDIRECTION:
2564 329 : e = resolve_indirection_adjustment (adjustment, e, locus);
2565 329 : break;
2566 :
2567 267 : case Resolver::Adjustment::AdjustmentType::UNSIZE:
2568 267 : e = resolve_unsized_adjustment (adjustment, e, locus);
2569 267 : break;
2570 : }
2571 : }
2572 :
2573 : return e;
2574 : }
2575 :
2576 : tree
2577 62 : HIRCompileBase::resolve_deref_adjustment (Resolver::Adjustment &adjustment,
2578 : tree expression, location_t locus)
2579 : {
2580 62 : rust_assert (adjustment.is_deref_adjustment ()
2581 : || adjustment.is_deref_mut_adjustment ());
2582 62 : if (!adjustment.has_operator_overload ())
2583 : {
2584 6 : if (TyTy::try_get_box_inner_type (adjustment.get_actual ()))
2585 : {
2586 6 : expression = build_box_inner_ptr (expression, locus);
2587 6 : if (TREE_CODE (TREE_TYPE (expression)) == POINTER_TYPE
2588 6 : || TREE_CODE (TREE_TYPE (expression)) == REFERENCE_TYPE)
2589 2 : expression = indirect_expression (expression, locus);
2590 : return expression;
2591 0 : ;
2592 : }
2593 0 : rust_assert (false);
2594 : }
2595 :
2596 56 : TyTy::FnType *lookup = adjustment.get_deref_operator_fn ();
2597 56 : TyTy::BaseType *receiver = adjustment.get_actual ();
2598 56 : tree fn_address = resolve_method_address (lookup, receiver, locus);
2599 :
2600 : // does it need a reference to call
2601 56 : tree adjusted_argument = expression;
2602 56 : bool needs_borrow = adjustment.get_deref_adjustment_type ()
2603 56 : != Resolver::Adjustment::AdjustmentType::ERROR;
2604 56 : if (needs_borrow)
2605 : {
2606 56 : adjusted_argument = address_expression (expression, locus);
2607 : }
2608 :
2609 : // make the call
2610 56 : return Backend::call_expression (fn_address, {adjusted_argument}, nullptr,
2611 : locus);
2612 : }
2613 :
2614 : tree
2615 329 : HIRCompileBase::resolve_indirection_adjustment (
2616 : Resolver::Adjustment &adjustment, tree expression, location_t locus)
2617 : {
2618 329 : return indirect_expression (expression, locus);
2619 : }
2620 :
2621 : tree
2622 276 : HIRCompileBase::resolve_unsized_adjustment (Resolver::Adjustment &adjustment,
2623 : tree expression, location_t locus)
2624 : {
2625 276 : bool expect_slice
2626 276 : = adjustment.get_expected ()->get_kind () == TyTy::TypeKind::SLICE;
2627 276 : bool expect_dyn
2628 276 : = adjustment.get_expected ()->get_kind () == TyTy::TypeKind::DYNAMIC;
2629 276 : bool expect_adt
2630 276 : = adjustment.get_expected ()->get_kind () == TyTy::TypeKind::ADT;
2631 :
2632 : // assumes this is an array
2633 276 : tree expr_type = TREE_TYPE (expression);
2634 276 : if (expect_slice)
2635 : {
2636 88 : rust_assert (TREE_CODE (expr_type) == ARRAY_TYPE);
2637 88 : return resolve_unsized_slice_adjustment (adjustment, expression, locus);
2638 : }
2639 :
2640 188 : if (expect_adt)
2641 14 : return resolve_unsized_adt_adjustment (adjustment, expression, locus);
2642 :
2643 174 : rust_assert (expect_dyn);
2644 174 : return resolve_unsized_dyn_adjustment (adjustment, expression, locus);
2645 : }
2646 :
2647 : tree
2648 88 : HIRCompileBase::resolve_unsized_slice_adjustment (
2649 : Resolver::Adjustment &adjustment, tree expression, location_t locus)
2650 : {
2651 : // assumes this is an array
2652 88 : tree expr_type = TREE_TYPE (expression);
2653 88 : rust_assert (TREE_CODE (expr_type) == ARRAY_TYPE);
2654 :
2655 : // takes an array and returns a fat-pointer so this becomes a constructor
2656 : // expression
2657 88 : rust_assert (adjustment.get_expected ()->get_kind ()
2658 : == TyTy::TypeKind::SLICE);
2659 88 : tree fat_pointer
2660 88 : = TyTyResolveCompile::compile (ctx, adjustment.get_expected ());
2661 :
2662 : // make a constructor for this
2663 88 : tree data = address_expression (expression, locus);
2664 :
2665 : // fetch the size from the domain
2666 88 : tree domain = TYPE_DOMAIN (expr_type);
2667 88 : unsigned HOST_WIDE_INT array_size
2668 176 : = wi::ext (wi::to_offset (TYPE_MAX_VALUE (domain))
2669 176 : - wi::to_offset (TYPE_MIN_VALUE (domain)) + 1,
2670 88 : TYPE_PRECISION (TREE_TYPE (domain)),
2671 88 : TYPE_SIGN (TREE_TYPE (domain)))
2672 88 : .to_uhwi ();
2673 88 : tree size = build_int_cstu (size_type_node, array_size);
2674 :
2675 88 : return Backend::constructor_expression (fat_pointer, false, {data, size}, -1,
2676 88 : locus);
2677 : }
2678 :
2679 : tree
2680 20 : HIRCompileBase::resolve_unsized_adt_adjustment (
2681 : Resolver::Adjustment &adjustment, tree expression, location_t locus)
2682 : {
2683 : /*
2684 : * FIXME: This method is implemented as a temporary workaround to enable the
2685 : * compilation of intra-ADT conversions for the `coerce_unsized` lang item.
2686 : */
2687 :
2688 20 : auto source_adt
2689 20 : = static_cast<const TyTy::ADTType *> (adjustment.get_actual ());
2690 20 : auto target_adt
2691 20 : = static_cast<const TyTy::ADTType *> (adjustment.get_expected ());
2692 :
2693 20 : if (target_adt->is_unsized ())
2694 : {
2695 9 : TyTy::TyVar t_tyvar = TyTy::TyVar::get_implicit_infer_var (locus);
2696 9 : TyTy::BaseType *cloned_target = target_adt->clone ();
2697 9 : cloned_target->set_ref (t_tyvar.get_ref ());
2698 9 : Analysis::NodeMapping pseudo_mapping (
2699 9 : ctx->get_mappings ().crate.get_current_crate (), 0, t_tyvar.get_ref (),
2700 9 : 0);
2701 9 : ctx->get_tyctx ()->insert_type (pseudo_mapping, cloned_target);
2702 :
2703 9 : const TyTy::ReferenceType r (ctx->get_mappings ().get_next_hir_id (),
2704 9 : t_tyvar, Mutability::Imm);
2705 :
2706 9 : tree fat_pointer = TyTyResolveCompile::compile (ctx, &r);
2707 9 : rust_assert (fat_pointer != error_mark_node);
2708 9 : tree data_ptr = address_expression (expression, locus);
2709 :
2710 9 : size_t tail_idx = source_adt->get_variants ().front ()->num_fields () - 1;
2711 9 : tree tail_expr
2712 9 : = Backend::struct_field_expression (expression, tail_idx, locus);
2713 :
2714 9 : auto s_tail_ty = source_adt->get_variants ()
2715 9 : .front ()
2716 : ->get_field_at_index (tail_idx)
2717 9 : ->get_field_type ();
2718 9 : auto t_tail_ty = target_adt->get_variants ()
2719 9 : .front ()
2720 : ->get_field_at_index (tail_idx)
2721 9 : ->get_field_type ();
2722 :
2723 9 : Resolver::Adjustment tail_adj (
2724 9 : Resolver::Adjustment::AdjustmentType::UNSIZE, s_tail_ty, t_tail_ty);
2725 9 : tree inner_fat_ptr
2726 9 : = resolve_unsized_adjustment (tail_adj, tail_expr, locus);
2727 9 : rust_assert (inner_fat_ptr != error_mark_node);
2728 9 : tree meta = error_mark_node;
2729 9 : if (TREE_CODE (inner_fat_ptr) == CONSTRUCTOR)
2730 : {
2731 : unsigned HOST_WIDE_INT ix;
2732 : tree field ATTRIBUTE_UNUSED, val;
2733 18 : FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (inner_fat_ptr), ix, field,
2734 : val)
2735 18 : if (ix == 1)
2736 : {
2737 : meta = val;
2738 : break;
2739 : }
2740 : }
2741 : else
2742 : {
2743 0 : tree meta_field_decl
2744 0 : = DECL_CHAIN (TYPE_FIELDS (TREE_TYPE (inner_fat_ptr)));
2745 0 : meta = fold_build3_loc (locus, COMPONENT_REF,
2746 0 : TREE_TYPE (meta_field_decl), inner_fat_ptr,
2747 : meta_field_decl, NULL_TREE);
2748 : }
2749 :
2750 9 : std::vector<tree> constructor_elements = {data_ptr, meta};
2751 9 : tree result
2752 9 : = Backend::constructor_expression (fat_pointer, false,
2753 : constructor_elements, -1, locus);
2754 9 : rust_assert (result != error_mark_node);
2755 9 : RS_DST_FLAG (TREE_TYPE (result)) = 1;
2756 9 : return result;
2757 9 : }
2758 : else
2759 : {
2760 11 : tree target = TyTyResolveCompile::compile (ctx, target_adt);
2761 11 : size_t coerce_idx = -1;
2762 11 : auto s_variant = source_adt->get_variants ().front ();
2763 11 : auto t_variant = target_adt->get_variants ().front ();
2764 :
2765 11 : for (size_t idx = 0; idx < s_variant->num_fields (); idx++)
2766 : {
2767 11 : auto s_field_ty
2768 11 : = s_variant->get_field_at_index (idx)->get_field_type ();
2769 11 : auto t_field_ty
2770 11 : = t_variant->get_field_at_index (idx)->get_field_type ();
2771 11 : if (!s_field_ty->is_equal (*t_field_ty))
2772 : {
2773 11 : bool is_phantom = false;
2774 11 : if (s_field_ty->is<TyTy::ADTType> ())
2775 12 : if (auto phantom_data
2776 6 : = Analysis::Mappings::get ().lookup_lang_item (
2777 6 : LangItem::Kind::PHANTOM_DATA))
2778 12 : if (s_field_ty->as<TyTy::ADTType> ()->get_id ()
2779 6 : == phantom_data)
2780 0 : is_phantom = true;
2781 :
2782 6 : if (!is_phantom)
2783 : {
2784 : coerce_idx = idx;
2785 : break;
2786 : }
2787 : }
2788 : }
2789 11 : rust_assert (coerce_idx != (size_t) -1);
2790 11 : std::vector<tree> constructor_elements;
2791 25 : for (size_t i = 0; i < s_variant->num_fields (); i++)
2792 : {
2793 14 : tree field_expr
2794 14 : = Backend::struct_field_expression (expression, i, locus);
2795 :
2796 14 : if (i != coerce_idx)
2797 : {
2798 3 : constructor_elements.push_back (field_expr);
2799 : }
2800 : else
2801 : {
2802 11 : auto s_coerce_ty
2803 11 : = s_variant->get_field_at_index (i)->get_field_type ();
2804 11 : auto t_coerce_ty
2805 11 : = t_variant->get_field_at_index (i)->get_field_type ();
2806 :
2807 11 : Resolver::Adjustment adj (adjustment.get_type (), s_coerce_ty,
2808 11 : t_coerce_ty);
2809 11 : tree coerced_inner_expr = error_mark_node;
2810 :
2811 11 : if (t_coerce_ty->get_kind () == TyTy::TypeKind::SLICE
2812 11 : || t_coerce_ty->get_kind () == TyTy::TypeKind::STR)
2813 0 : coerced_inner_expr
2814 0 : = resolve_unsized_slice_adjustment (adj, field_expr, locus);
2815 11 : else if (t_coerce_ty->get_kind () == TyTy::TypeKind::DYNAMIC)
2816 0 : coerced_inner_expr
2817 0 : = resolve_unsized_dyn_adjustment (adj, field_expr, locus);
2818 11 : else if (t_coerce_ty->get_kind () == TyTy::TypeKind::ADT)
2819 6 : coerced_inner_expr
2820 6 : = resolve_unsized_adt_adjustment (adj, field_expr, locus);
2821 5 : else if (t_coerce_ty->get_kind () == TyTy::TypeKind::POINTER
2822 5 : || t_coerce_ty->get_kind () == TyTy::TypeKind::REF)
2823 : {
2824 5 : bool is_ptr
2825 5 : = t_coerce_ty->get_kind () == TyTy::TypeKind::POINTER;
2826 :
2827 5 : TyTy::BaseType *s_base
2828 5 : = is_ptr ? s_coerce_ty->as<TyTy::PointerType> ()
2829 : ->get_base ()
2830 5 : ->monomorphized_clone ()
2831 : : s_coerce_ty->as<TyTy::ReferenceType> ()
2832 : ->get_base ()
2833 0 : ->monomorphized_clone ();
2834 5 : TyTy::BaseType *t_base
2835 5 : = is_ptr ? t_coerce_ty->as<TyTy::PointerType> ()
2836 : ->get_base ()
2837 5 : ->monomorphized_clone ()
2838 : : t_coerce_ty->as<TyTy::ReferenceType> ()
2839 : ->get_base ()
2840 0 : ->monomorphized_clone ();
2841 :
2842 5 : Resolver::Adjustment::AdjustmentType ref_adj_type
2843 : = Resolver::Adjustment::AdjustmentType::IMM_REF;
2844 :
2845 5 : std::vector<Resolver::Adjustment> inner_adjs;
2846 5 : inner_adjs.push_back (Resolver::Adjustment (
2847 : Resolver::Adjustment::AdjustmentType::INDIRECTION,
2848 5 : s_coerce_ty, s_base));
2849 5 : inner_adjs.push_back (Resolver::Adjustment (
2850 : Resolver::Adjustment::AdjustmentType::UNSIZE, s_base,
2851 5 : t_base));
2852 5 : inner_adjs.push_back (
2853 5 : Resolver::Adjustment (ref_adj_type, t_base, t_coerce_ty));
2854 :
2855 5 : coerced_inner_expr
2856 5 : = resolve_adjustments (inner_adjs, field_expr, locus);
2857 5 : }
2858 : else
2859 0 : rust_unreachable ();
2860 :
2861 11 : constructor_elements.push_back (coerced_inner_expr);
2862 : }
2863 : }
2864 :
2865 11 : return Backend::constructor_expression (target, false,
2866 : constructor_elements, -1, locus);
2867 11 : }
2868 :
2869 : return error_mark_node;
2870 : }
2871 :
2872 : tree
2873 174 : HIRCompileBase::resolve_unsized_dyn_adjustment (
2874 : Resolver::Adjustment &adjustment, tree expression, location_t locus)
2875 : {
2876 174 : tree rvalue = expression;
2877 174 : location_t rvalue_locus = locus;
2878 :
2879 174 : auto actual = adjustment.get_actual ();
2880 174 : auto expected = adjustment.get_expected ();
2881 :
2882 174 : const auto dyn = static_cast<const TyTy::DynamicObjectType *> (expected);
2883 :
2884 174 : rust_debug ("resolve_unsized_dyn_adjustment actual={%s} dyn={%s}",
2885 : actual->debug_str ().c_str (), dyn->debug_str ().c_str ());
2886 :
2887 174 : return coerce_to_dyn_object (rvalue, actual, dyn, rvalue_locus);
2888 : }
2889 :
2890 : void
2891 73 : CompileExpr::visit (HIR::RangeFromToExpr &expr)
2892 : {
2893 73 : tree from = CompileExpr::Compile (expr.get_from_expr (), ctx);
2894 73 : tree to = CompileExpr::Compile (expr.get_to_expr (), ctx);
2895 73 : if (from == error_mark_node || to == error_mark_node)
2896 : {
2897 0 : translated = error_mark_node;
2898 0 : return;
2899 : }
2900 :
2901 73 : TyTy::BaseType *tyty = nullptr;
2902 73 : bool ok
2903 73 : = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &tyty);
2904 73 : rust_assert (ok);
2905 :
2906 73 : tree adt = TyTyResolveCompile::compile (ctx, tyty);
2907 :
2908 : // make the constructor
2909 73 : translated = Backend::constructor_expression (adt, false, {from, to}, -1,
2910 : expr.get_locus ());
2911 : }
2912 :
2913 : void
2914 7 : CompileExpr::visit (HIR::RangeFromExpr &expr)
2915 : {
2916 7 : tree from = CompileExpr::Compile (expr.get_from_expr (), ctx);
2917 7 : if (from == error_mark_node)
2918 : {
2919 0 : translated = error_mark_node;
2920 0 : return;
2921 : }
2922 :
2923 7 : TyTy::BaseType *tyty = nullptr;
2924 7 : bool ok
2925 7 : = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &tyty);
2926 7 : rust_assert (ok);
2927 :
2928 7 : tree adt = TyTyResolveCompile::compile (ctx, tyty);
2929 :
2930 : // make the constructor
2931 7 : translated = Backend::constructor_expression (adt, false, {from}, -1,
2932 : expr.get_locus ());
2933 : }
2934 :
2935 : void
2936 7 : CompileExpr::visit (HIR::RangeToExpr &expr)
2937 : {
2938 7 : tree to = CompileExpr::Compile (expr.get_to_expr (), ctx);
2939 7 : if (to == error_mark_node)
2940 : {
2941 0 : translated = error_mark_node;
2942 0 : return;
2943 : }
2944 :
2945 7 : TyTy::BaseType *tyty = nullptr;
2946 7 : bool ok
2947 7 : = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &tyty);
2948 7 : rust_assert (ok);
2949 :
2950 7 : tree adt = TyTyResolveCompile::compile (ctx, tyty);
2951 :
2952 : // make the constructor
2953 7 : translated
2954 7 : = Backend::constructor_expression (adt, false, {to}, -1, expr.get_locus ());
2955 : }
2956 :
2957 : void
2958 0 : CompileExpr::visit (HIR::RangeFullExpr &expr)
2959 : {
2960 0 : TyTy::BaseType *tyty = nullptr;
2961 0 : bool ok
2962 0 : = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &tyty);
2963 0 : rust_assert (ok);
2964 :
2965 0 : tree adt = TyTyResolveCompile::compile (ctx, tyty);
2966 0 : translated
2967 0 : = Backend::constructor_expression (adt, false, {}, -1, expr.get_locus ());
2968 0 : }
2969 :
2970 : void
2971 293 : CompileExpr::visit (HIR::ArrayIndexExpr &expr)
2972 : {
2973 293 : tree array_reference = CompileExpr::Compile (expr.get_array_expr (), ctx);
2974 293 : tree index = CompileExpr::Compile (expr.get_index_expr (), ctx);
2975 :
2976 : // this might be an core::ops::index lang item situation
2977 293 : TyTy::FnType *fntype;
2978 293 : bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
2979 293 : expr.get_mappings ().get_hirid (), &fntype);
2980 293 : if (is_op_overload)
2981 : {
2982 66 : auto lang_item_type = LangItem::Kind::INDEX;
2983 66 : tree operator_overload_call
2984 66 : = resolve_operator_overload (lang_item_type, expr, array_reference,
2985 : index, expr.get_array_expr (),
2986 66 : expr.get_index_expr ());
2987 :
2988 66 : tree actual_type = TREE_TYPE (operator_overload_call);
2989 66 : bool can_indirect = TYPE_PTR_P (actual_type) || TYPE_REF_P (actual_type);
2990 66 : if (!can_indirect)
2991 : {
2992 : // nothing to do
2993 : translated = operator_overload_call;
2994 66 : return;
2995 : }
2996 :
2997 : // rust deref always returns a reference from this overload then we can
2998 : // actually do the indirection
2999 31 : translated
3000 31 : = indirect_expression (operator_overload_call, expr.get_locus ());
3001 31 : return;
3002 : }
3003 :
3004 : // lets check if the array is a reference type then we can add an
3005 : // indirection if required
3006 227 : TyTy::BaseType *array_expr_ty = nullptr;
3007 227 : bool ok = ctx->get_tyctx ()->lookup_type (
3008 227 : expr.get_array_expr ().get_mappings ().get_hirid (), &array_expr_ty);
3009 227 : rust_assert (ok);
3010 :
3011 : // do we need to add an indirect reference
3012 227 : if (array_expr_ty->get_kind () == TyTy::TypeKind::REF)
3013 : {
3014 15 : array_reference
3015 15 : = indirect_expression (array_reference, expr.get_locus ());
3016 : }
3017 212 : else if (TyTy::try_get_box_inner_type (array_expr_ty))
3018 : {
3019 3 : array_reference
3020 3 : = build_box_inner_ptr (array_reference, expr.get_locus ());
3021 3 : array_reference
3022 3 : = indirect_expression (array_reference, expr.get_locus ());
3023 : }
3024 :
3025 227 : translated = Backend::array_index_expression (array_reference, index,
3026 : expr.get_locus ());
3027 : }
3028 :
3029 : void
3030 61 : CompileExpr::visit (HIR::ClosureExpr &expr)
3031 : {
3032 61 : TyTy::BaseType *closure_expr_ty = nullptr;
3033 61 : if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
3034 : &closure_expr_ty))
3035 : {
3036 0 : rust_fatal_error (expr.get_locus (),
3037 : "did not resolve type for this ClosureExpr");
3038 : return;
3039 : }
3040 61 : rust_assert (closure_expr_ty->get_kind () == TyTy::TypeKind::CLOSURE);
3041 61 : TyTy::ClosureType *closure_tyty
3042 : = static_cast<TyTy::ClosureType *> (closure_expr_ty);
3043 61 : tree compiled_closure_tyty = TyTyResolveCompile::compile (ctx, closure_tyty);
3044 :
3045 : // generate closure function
3046 61 : generate_closure_function (expr, *closure_tyty, compiled_closure_tyty);
3047 :
3048 : // lets ignore state capture for now we need to instantiate the struct anyway
3049 : // then generate the function
3050 61 : std::vector<tree> vals;
3051 82 : for (const auto &capture : closure_tyty->get_captures ())
3052 : {
3053 : // lookup the HirId
3054 21 : if (auto hid = ctx->get_mappings ().lookup_node_to_hir (capture))
3055 : {
3056 : // lookup the var decl
3057 21 : Bvariable *var = nullptr;
3058 21 : bool found = ctx->lookup_var_decl (*hid, &var);
3059 21 : rust_assert (found);
3060 :
3061 : // FIXME
3062 : // this should bes based on the closure move-ability
3063 21 : tree var_expr = var->get_tree (expr.get_locus ());
3064 21 : tree val = address_expression (var_expr, expr.get_locus ());
3065 21 : vals.push_back (val);
3066 : }
3067 : else
3068 0 : rust_unreachable ();
3069 : }
3070 :
3071 61 : translated = Backend::constructor_expression (compiled_closure_tyty, false,
3072 : vals, -1, expr.get_locus ());
3073 61 : }
3074 :
3075 : tree
3076 61 : CompileExpr::generate_closure_function (HIR::ClosureExpr &expr,
3077 : TyTy::ClosureType &closure_tyty,
3078 : tree compiled_closure_tyty)
3079 : {
3080 61 : TyTy::FnType *fn_tyty = nullptr;
3081 61 : tree compiled_fn_type
3082 61 : = generate_closure_fntype (expr, closure_tyty, compiled_closure_tyty,
3083 : &fn_tyty);
3084 61 : if (compiled_fn_type == error_mark_node)
3085 : return error_mark_node;
3086 :
3087 61 : const Resolver::CanonicalPath &parent_canonical_path
3088 61 : = closure_tyty.get_ident ().path;
3089 :
3090 61 : tl::optional<NodeId> nid = ctx->get_mappings ().lookup_hir_to_node (
3091 61 : expr.get_mappings ().get_hirid ());
3092 61 : rust_assert (nid.has_value ());
3093 61 : auto node_id = nid.value ();
3094 :
3095 61 : Resolver::CanonicalPath path = parent_canonical_path.append (
3096 61 : Resolver::CanonicalPath::new_seg (node_id, "{{closure}}"));
3097 :
3098 61 : std::string ir_symbol_name = path.get ();
3099 61 : std::string asm_name = ctx->mangle_item (&closure_tyty, path);
3100 :
3101 61 : unsigned int flags = 0;
3102 61 : tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name, asm_name,
3103 : flags, expr.get_locus ());
3104 :
3105 : // insert into the context
3106 61 : ctx->insert_function_decl (fn_tyty, fndecl);
3107 61 : ctx->insert_closure_decl (&closure_tyty, fndecl);
3108 :
3109 : // setup the parameters
3110 61 : std::vector<Bvariable *> param_vars;
3111 :
3112 : // closure self
3113 61 : Bvariable *self_param
3114 61 : = Backend::parameter_variable (fndecl, "$closure", compiled_closure_tyty,
3115 61 : expr.get_locus ());
3116 61 : DECL_ARTIFICIAL (self_param->get_decl ()) = 1;
3117 61 : param_vars.push_back (self_param);
3118 :
3119 : // push a new context
3120 61 : ctx->push_closure_context (expr.get_mappings ().get_hirid ());
3121 :
3122 : // setup the implicit argument captures
3123 61 : size_t idx = 0;
3124 82 : for (const auto &capture : closure_tyty.get_captures ())
3125 : {
3126 : // lookup the HirId
3127 21 : if (auto hid = ctx->get_mappings ().lookup_node_to_hir (capture))
3128 : {
3129 : // get the assessor
3130 21 : tree binding = Backend::struct_field_expression (
3131 : self_param->get_tree (expr.get_locus ()), idx, expr.get_locus ());
3132 21 : tree indirection = indirect_expression (binding, expr.get_locus ());
3133 :
3134 : // insert bindings
3135 21 : ctx->insert_closure_binding (*hid, indirection);
3136 :
3137 : // continue
3138 21 : idx++;
3139 : }
3140 : else
3141 0 : rust_unreachable ();
3142 : }
3143 :
3144 : // args tuple
3145 61 : tree args_type
3146 61 : = TyTyResolveCompile::compile (ctx, &closure_tyty.get_parameters ());
3147 61 : Bvariable *args_param
3148 61 : = Backend::parameter_variable (fndecl, "args", args_type,
3149 61 : expr.get_locus ());
3150 61 : param_vars.push_back (args_param);
3151 :
3152 : // setup the implicit mappings for the arguments. Since argument passing to
3153 : // closure functions is done via passing a tuple but the closure body expects
3154 : // just normal arguments this means we need to destructure them similar to
3155 : // what we do in MatchExpr's. This means when we have a closure-param of a we
3156 : // actually setup the destructure to take from the args tuple
3157 :
3158 61 : tree args_param_expr = args_param->get_tree (expr.get_locus ());
3159 61 : size_t i = 0;
3160 120 : for (auto &closure_param : expr.get_params ())
3161 : {
3162 59 : tree compiled_param_var
3163 59 : = Backend::struct_field_expression (args_param_expr, i,
3164 : closure_param.get_locus ());
3165 :
3166 59 : CompilePatternBindings::Compile (closure_param.get_pattern (),
3167 : compiled_param_var, ctx);
3168 59 : i++;
3169 : }
3170 :
3171 61 : if (!Backend::function_set_parameters (fndecl, param_vars))
3172 : {
3173 0 : ctx->pop_closure_context ();
3174 0 : return error_mark_node;
3175 : }
3176 :
3177 : // lookup locals
3178 61 : HIR::Expr &function_body = expr.get_expr ();
3179 61 : bool is_block_expr
3180 61 : = function_body.get_expression_type () == HIR::Expr::ExprType::Block;
3181 :
3182 61 : if (is_block_expr)
3183 : {
3184 52 : auto body_mappings = function_body.get_mappings ();
3185 52 : auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
3186 :
3187 52 : auto candidate
3188 52 : = nr_ctx.get_underlying ().values.to_rib (body_mappings.get_nodeid ());
3189 :
3190 52 : rust_assert (candidate.has_value ());
3191 : }
3192 :
3193 61 : tree enclosing_scope = NULL_TREE;
3194 61 : location_t start_location = function_body.get_locus ();
3195 61 : location_t end_location = function_body.get_locus ();
3196 61 : if (is_block_expr)
3197 : {
3198 52 : auto &body = static_cast<HIR::BlockExpr &> (function_body);
3199 52 : start_location = body.get_locus ();
3200 52 : end_location = body.get_end_locus ();
3201 : }
3202 :
3203 61 : tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/,
3204 : start_location, end_location);
3205 61 : ctx->push_block (code_block);
3206 :
3207 61 : TyTy::BaseType *tyret = &closure_tyty.get_result_type ();
3208 61 : Bvariable *return_address = nullptr;
3209 :
3210 61 : tree return_type = TyTyResolveCompile::compile (ctx, tyret);
3211 61 : bool address_is_taken = false;
3212 61 : tree ret_var_stmt = NULL_TREE;
3213 :
3214 61 : return_address
3215 61 : = Backend::temporary_variable (fndecl, code_block, return_type, NULL,
3216 : address_is_taken, expr.get_locus (),
3217 : &ret_var_stmt);
3218 :
3219 61 : ctx->add_statement (ret_var_stmt);
3220 :
3221 61 : ctx->push_fn (fndecl, return_address, tyret);
3222 :
3223 61 : if (is_block_expr)
3224 : {
3225 52 : auto &body = static_cast<HIR::BlockExpr &> (function_body);
3226 52 : compile_function_body (fndecl, body, tyret);
3227 : }
3228 : else
3229 : {
3230 9 : tree value = CompileExpr::Compile (function_body, ctx);
3231 9 : tree return_expr
3232 9 : = Backend::return_statement (fndecl, value, function_body.get_locus ());
3233 9 : ctx->add_statement (return_expr);
3234 : }
3235 :
3236 61 : tree cleanup = CompileDrop (ctx).build_current_scope_drop_cleanup ();
3237 61 : tree bind_tree
3238 61 : = ctx->pop_block_with_cleanup (cleanup, function_body.get_locus ());
3239 :
3240 61 : gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
3241 61 : DECL_SAVED_TREE (fndecl) = bind_tree;
3242 :
3243 61 : ctx->pop_closure_context ();
3244 61 : ctx->pop_fn ();
3245 61 : ctx->push_function (fndecl);
3246 :
3247 61 : return fndecl;
3248 61 : }
3249 :
3250 : tree
3251 61 : CompileExpr::generate_closure_fntype (HIR::ClosureExpr &expr,
3252 : const TyTy::ClosureType &closure_tyty,
3253 : tree compiled_closure_tyty,
3254 : TyTy::FnType **fn_tyty)
3255 : {
3256 : // grab the specified_bound
3257 61 : rust_assert (closure_tyty.num_specified_bounds () == 1);
3258 61 : const TyTy::TypeBoundPredicate &predicate
3259 61 : = *closure_tyty.get_specified_bounds ().begin ();
3260 :
3261 : // FnOnce::Output is normalized on demand by normalize_projection's closure
3262 : // special-case
3263 :
3264 : // the function signature is based on the trait bound that the closure
3265 : // implements which is determined at the type resolution time
3266 : //
3267 : // https://github.com/rust-lang/rust/blob/7807a694c2f079fd3f395821bcc357eee8650071/library/core/src/ops/function.rs#L54-L71
3268 :
3269 61 : TyTy::TypeBoundPredicateItem item = TyTy::TypeBoundPredicateItem::error ();
3270 61 : if (predicate.get_name ().compare ("FnOnce") == 0)
3271 : {
3272 122 : item = predicate.lookup_associated_item ("call_once").value ();
3273 : }
3274 0 : else if (predicate.get_name ().compare ("FnMut") == 0)
3275 : {
3276 0 : item = predicate.lookup_associated_item ("call_mut").value ();
3277 : }
3278 0 : else if (predicate.get_name ().compare ("Fn") == 0)
3279 : {
3280 0 : item = predicate.lookup_associated_item ("call").value ();
3281 : }
3282 : else
3283 : {
3284 : // FIXME error message?
3285 0 : rust_unreachable ();
3286 : return error_mark_node;
3287 : }
3288 :
3289 61 : rust_assert (!item.is_error ());
3290 :
3291 61 : TyTy::BaseType *item_tyty = item.get_tyty_for_receiver (&closure_tyty);
3292 61 : rust_assert (item_tyty->get_kind () == TyTy::TypeKind::FNDEF);
3293 61 : *fn_tyty = static_cast<TyTy::FnType *> (item_tyty);
3294 61 : return TyTyResolveCompile::compile (ctx, item_tyty);
3295 61 : }
3296 :
3297 : bool
3298 11422 : CompileExpr::generate_possible_fn_trait_call (HIR::CallExpr &expr,
3299 : tree receiver, tree *result)
3300 : {
3301 11422 : TyTy::FnType *fn_sig = nullptr;
3302 11422 : bool found_overload = ctx->get_tyctx ()->lookup_operator_overload (
3303 11422 : expr.get_mappings ().get_hirid (), &fn_sig);
3304 11422 : if (!found_overload)
3305 : return false;
3306 :
3307 60 : auto id = fn_sig->get_ty_ref ();
3308 60 : auto dId = fn_sig->get_id ();
3309 :
3310 60 : tree function = error_mark_node;
3311 60 : bool found_closure = ctx->lookup_function_decl (id, &function, dId, fn_sig);
3312 60 : if (!found_closure)
3313 : {
3314 : // something went wrong we still return true as this was meant to be an fn
3315 : // trait call
3316 0 : *result = error_mark_node;
3317 0 : return true;
3318 : }
3319 :
3320 : // need to apply any autoderef's to the self argument
3321 60 : HIR::Expr &fnexpr = expr.get_fnexpr ();
3322 60 : HirId autoderef_mappings_id = fnexpr.get_mappings ().get_hirid ();
3323 60 : std::vector<Resolver::Adjustment> *adjustments = nullptr;
3324 60 : bool ok = ctx->get_tyctx ()->lookup_autoderef_mappings (autoderef_mappings_id,
3325 : &adjustments);
3326 60 : rust_assert (ok);
3327 :
3328 : // apply adjustments for the fn call
3329 60 : tree self = resolve_adjustments (*adjustments, receiver, expr.get_locus ());
3330 :
3331 : // resolve the arguments
3332 60 : std::vector<tree> tuple_arg_vals;
3333 120 : for (auto &argument : expr.get_arguments ())
3334 : {
3335 60 : auto rvalue = CompileExpr::Compile (*argument, ctx);
3336 60 : tuple_arg_vals.push_back (rvalue);
3337 : }
3338 :
3339 : // this is always the 2nd argument in the function signature
3340 60 : tree fnty = TREE_TYPE (function);
3341 60 : tree fn_arg_tys = TYPE_ARG_TYPES (fnty);
3342 60 : tree tuple_args_tyty_chain = TREE_CHAIN (fn_arg_tys);
3343 60 : tree tuple_args_tyty = TREE_VALUE (tuple_args_tyty_chain);
3344 :
3345 60 : tree tuple_args
3346 60 : = Backend::constructor_expression (tuple_args_tyty, false, tuple_arg_vals,
3347 60 : -1, expr.get_locus ());
3348 :
3349 : // args are always self, and the tuple of the args we are passing where
3350 : // self is the path of the call-expr in this case the fn_address
3351 60 : std::vector<tree> args;
3352 60 : args.push_back (self);
3353 60 : args.push_back (tuple_args);
3354 :
3355 60 : tree call_address = address_expression (function, expr.get_locus ());
3356 60 : *result
3357 60 : = Backend::call_expression (call_address, args, nullptr /* static chain ?*/,
3358 : expr.get_locus ());
3359 60 : return true;
3360 60 : }
3361 :
3362 : tree
3363 3 : CompileExpr::construct_block_label (HIR::BlockExpr &expr)
3364 : {
3365 3 : if (expr.has_label ())
3366 : {
3367 3 : fncontext fnctx = ctx->peek_fn ();
3368 3 : HIR::LoopLabel &label = expr.get_label ();
3369 3 : std::string label_name = label.get_lifetime ().get_name ();
3370 3 : HirId label_id = label.get_lifetime ().get_mappings ().get_hirid ();
3371 3 : tree label_decl
3372 3 : = Backend::label (fnctx.fndecl, label_name, label.get_locus ());
3373 3 : tree label_expr = Backend::label_definition_statement (label_decl);
3374 3 : ctx->insert_break_label (label_id, label_decl);
3375 3 : return label_expr;
3376 3 : }
3377 : return NULL_TREE;
3378 : }
3379 :
3380 : tree
3381 0 : CompileExpr::lookup_label (NodeId to_be_resolved)
3382 : {
3383 0 : HirId ref = resolve_nodeid (to_be_resolved, Resolver2_0::Namespace::Labels);
3384 0 : tree label = NULL_TREE;
3385 0 : rust_assert (ctx->lookup_label_decl (ref, &label)
3386 : && "failed to lookup a label");
3387 0 : return label;
3388 : }
3389 :
3390 : Bvariable *
3391 5 : CompileExpr::lookup_label_temp_var (NodeId to_be_resolved)
3392 : {
3393 : // TODO: Not sure that this temp var should have been inserted in the Labels
3394 : // namespace? Why not values?
3395 5 : HirId ref = resolve_nodeid (to_be_resolved, Resolver2_0::Namespace::Labels);
3396 5 : Bvariable *ltemp = nullptr;
3397 5 : rust_assert (ctx->lookup_var_decl (ref, <emp)
3398 : && "failed to lookup a temp var");
3399 5 : return ltemp;
3400 : }
3401 :
3402 : HirId
3403 10 : CompileExpr::resolve_nodeid (NodeId to_be_resolved, Resolver2_0::Namespace ns)
3404 : {
3405 10 : auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
3406 :
3407 10 : NodeId resolved_node_id;
3408 10 : resolved_node_id = nr_ctx.lookup (to_be_resolved, ns).value ();
3409 :
3410 10 : HirId ref
3411 10 : = ctx->get_mappings ().lookup_node_to_hir (resolved_node_id).value ();
3412 10 : return ref;
3413 : }
3414 :
3415 : std::pair<tree, tree>
3416 244 : CompileExpr::construct_loop_labels (tl::optional<HIR::LoopLabel> opt_loop_label)
3417 : {
3418 244 : fncontext fnctx = ctx->peek_fn ();
3419 244 : tree break_label_decl = NULL_TREE;
3420 244 : tree break_label_expr = NULL_TREE;
3421 244 : tree continue_label_decl = NULL_TREE;
3422 244 : tree continue_label_expr = NULL_TREE;
3423 244 : location_t label_locus = UNKNOWN_LOCATION;
3424 244 : tl::optional<std::string> continue_label_name = tl::nullopt;
3425 244 : tl::optional<std::string> break_label_name = tl::nullopt;
3426 244 : tl::optional<HirId> label_hirid = tl::nullopt;
3427 244 : if (opt_loop_label.has_value ())
3428 : {
3429 51 : label_locus = opt_loop_label.value ().get_locus ();
3430 51 : HIR::LoopLabel &loop_label = opt_loop_label.value ();
3431 51 : std::string label_name = loop_label.get_lifetime ().get_name ();
3432 51 : continue_label_name = label_name + "_continue";
3433 51 : break_label_name = label_name + "_break";
3434 51 : label_hirid = loop_label.get_lifetime ().get_mappings ().get_hirid ();
3435 51 : }
3436 244 : continue_label_decl
3437 244 : = Backend::label (fnctx.fndecl, continue_label_name, label_locus);
3438 244 : continue_label_expr
3439 244 : = Backend::label_definition_statement (continue_label_decl);
3440 244 : break_label_decl
3441 244 : = Backend::label (fnctx.fndecl, break_label_name, label_locus);
3442 244 : break_label_expr = Backend::label_definition_statement (break_label_decl);
3443 244 : if (label_hirid.has_value ())
3444 : {
3445 51 : ctx->insert_continue_label (label_hirid.value (), continue_label_decl);
3446 51 : ctx->insert_break_label (label_hirid.value (), break_label_decl);
3447 : }
3448 244 : ctx->push_loop_begin_label (continue_label_decl);
3449 244 : ctx->push_loop_end_label (break_label_decl);
3450 244 : return std::make_pair (continue_label_expr, break_label_expr);
3451 244 : }
3452 :
3453 : } // namespace Compile
3454 : } // namespace Rust
|