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