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