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