1 // Copyright (C) 2020-2025 Free Software Foundation, Inc.
3 // This file is part of GCC.
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
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
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/>.
19 #include "rust-compile-expr.h"
20 #include "rust-compile-struct-field-expr.h"
21 #include "rust-compile-pattern.h"
22 #include "rust-compile-resolve-path.h"
23 #include "rust-compile-block.h"
24 #include "rust-compile-implitem.h"
25 #include "rust-constexpr.h"
26 #include "rust-compile-type.h"
28 #include "rust-compile-asm.h"
29 #include "fold-const.h"
32 #include "print-tree.h"
33 #include "rust-system.h"
34 #include "rust-tyty.h"
39 CompileExpr::CompileExpr (Context
*ctx
)
40 : HIRCompileBase (ctx
), translated (error_mark_node
)
44 CompileExpr::Compile (HIR::Expr
&expr
, Context
*ctx
)
46 CompileExpr
compiler (ctx
);
47 expr
.accept_vis (compiler
);
48 return compiler
.translated
;
52 CompileExpr::visit (HIR::TupleIndexExpr
&expr
)
54 HIR::Expr
&tuple_expr
= expr
.get_tuple_expr ();
55 TupleIndex index
= expr
.get_tuple_index ();
57 tree receiver_ref
= CompileExpr::Compile (tuple_expr
, ctx
);
59 TyTy::BaseType
*tuple_expr_ty
= nullptr;
61 = ctx
->get_tyctx ()->lookup_type (tuple_expr
.get_mappings ().get_hirid (),
65 // do we need to add an indirect reference
66 if (tuple_expr_ty
->get_kind () == TyTy::TypeKind::REF
)
68 tree indirect
= indirect_expression (receiver_ref
, expr
.get_locus ());
69 receiver_ref
= indirect
;
73 = Backend::struct_field_expression (receiver_ref
, index
, expr
.get_locus ());
77 CompileExpr::visit (HIR::TupleExpr
&expr
)
81 translated
= unit_expression (expr
.get_locus ());
85 TyTy::BaseType
*tyty
= nullptr;
86 if (!ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (),
89 rust_fatal_error (expr
.get_locus (),
90 "did not resolve type for this TupleExpr");
94 tree tuple_type
= TyTyResolveCompile::compile (ctx
, tyty
);
95 rust_assert (tuple_type
!= nullptr);
97 // this assumes all fields are in order from type resolution
98 std::vector
<tree
> vals
;
99 for (auto &elem
: expr
.get_tuple_elems ())
101 auto e
= CompileExpr::Compile (*elem
, ctx
);
105 translated
= Backend::constructor_expression (tuple_type
, false, vals
, -1,
110 CompileExpr::visit (HIR::ReturnExpr
&expr
)
112 auto fncontext
= ctx
->peek_fn ();
114 tree return_value
= expr
.has_return_expr ()
115 ? CompileExpr::Compile (expr
.get_expr (), ctx
)
116 : unit_expression (expr
.get_locus ());
118 if (expr
.has_return_expr ())
120 HirId id
= expr
.get_mappings ().get_hirid ();
121 location_t rvalue_locus
= expr
.return_expr
->get_locus ();
123 TyTy::BaseType
*expected
= fncontext
.retty
;
124 location_t lvalue_locus
125 = ctx
->get_mappings ().lookup_location (expected
->get_ref ());
127 TyTy::BaseType
*actual
= nullptr;
128 bool ok
= ctx
->get_tyctx ()->lookup_type (
129 expr
.return_expr
->get_mappings ().get_hirid (), &actual
);
132 return_value
= coercion_site (id
, return_value
, actual
, expected
,
133 lvalue_locus
, rvalue_locus
);
136 tree return_stmt
= Backend::return_statement (fncontext
.fndecl
, return_value
,
138 ctx
->add_statement (return_stmt
);
142 CompileExpr::visit (HIR::ArithmeticOrLogicalExpr
&expr
)
144 auto op
= expr
.get_expr_type ();
145 auto lhs
= CompileExpr::Compile (expr
.get_lhs (), ctx
);
146 auto rhs
= CompileExpr::Compile (expr
.get_rhs (), ctx
);
148 // this might be an operator overload situation lets check
149 TyTy::FnType
*fntype
;
150 bool is_op_overload
= ctx
->get_tyctx ()->lookup_operator_overload (
151 expr
.get_mappings ().get_hirid (), &fntype
);
155 = LangItem::OperatorToLangItem (expr
.get_expr_type ());
156 translated
= resolve_operator_overload (
157 lang_item_type
, expr
, lhs
, rhs
, expr
.get_lhs (),
158 tl::optional
<std::reference_wrapper
<HIR::Expr
>> (expr
.get_rhs ()));
162 bool can_generate_overflow_checks
163 = (ctx
->in_fn () && !ctx
->const_context_p ()) && flag_overflow_checks
;
164 if (!can_generate_overflow_checks
)
167 = Backend::arithmetic_or_logical_expression (op
, lhs
, rhs
,
172 auto receiver_tmp
= NULL_TREE
;
174 = Backend::temporary_variable (ctx
->peek_fn ().fndecl
, NULL_TREE
,
175 TREE_TYPE (lhs
), lhs
, true,
176 expr
.get_locus (), &receiver_tmp
);
178 = Backend::arithmetic_or_logical_expression_checked (op
, lhs
, rhs
,
182 ctx
->add_statement (check
);
183 translated
= receiver
->get_tree (expr
.get_locus ());
187 CompileExpr::visit (HIR::CompoundAssignmentExpr
&expr
)
189 auto op
= expr
.get_expr_type ();
190 auto lhs
= CompileExpr::Compile (expr
.get_lhs (), ctx
);
191 auto rhs
= CompileExpr::Compile (expr
.get_rhs (), ctx
);
193 // this might be an operator overload situation lets check
194 TyTy::FnType
*fntype
;
195 bool is_op_overload
= ctx
->get_tyctx ()->lookup_operator_overload (
196 expr
.get_mappings ().get_hirid (), &fntype
);
199 auto lang_item_type
= LangItem::CompoundAssignmentOperatorToLangItem (
200 expr
.get_expr_type ());
201 auto compound_assignment
202 = resolve_operator_overload (lang_item_type
, expr
, lhs
, rhs
,
203 expr
.get_lhs (), expr
.get_rhs ());
204 ctx
->add_statement (compound_assignment
);
209 if (ctx
->in_fn () && !ctx
->const_context_p ())
211 auto tmp
= NULL_TREE
;
213 = Backend::temporary_variable (ctx
->peek_fn ().fndecl
, NULL_TREE
,
214 TREE_TYPE (lhs
), lhs
, true,
215 expr
.get_locus (), &tmp
);
217 = Backend::arithmetic_or_logical_expression_checked (op
, lhs
, rhs
,
220 ctx
->add_statement (check
);
223 = Backend::assignment_statement (lhs
,
224 receiver
->get_tree (expr
.get_locus ()),
230 = Backend::arithmetic_or_logical_expression (op
, lhs
, rhs
,
236 CompileExpr::visit (HIR::NegationExpr
&expr
)
238 auto op
= expr
.get_expr_type ();
240 auto &literal_expr
= expr
.get_expr ();
242 // If it's a negated integer/float literal, we can return early
243 if (op
== NegationOperator::NEGATE
244 && literal_expr
.get_expression_type () == HIR::Expr::ExprType::Lit
)
246 auto &new_literal_expr
= static_cast<HIR::LiteralExpr
&> (literal_expr
);
247 auto lit_type
= new_literal_expr
.get_lit_type ();
248 if (lit_type
== HIR::Literal::LitType::INT
249 || lit_type
== HIR::Literal::LitType::FLOAT
)
251 new_literal_expr
.set_negative ();
252 translated
= CompileExpr::Compile (literal_expr
, ctx
);
257 auto negated_expr
= CompileExpr::Compile (literal_expr
, ctx
);
258 auto location
= expr
.get_locus ();
260 // this might be an operator overload situation lets check
261 TyTy::FnType
*fntype
;
262 bool is_op_overload
= ctx
->get_tyctx ()->lookup_operator_overload (
263 expr
.get_mappings ().get_hirid (), &fntype
);
266 auto lang_item_type
= LangItem::NegationOperatorToLangItem (op
);
268 = resolve_operator_overload (lang_item_type
, expr
, negated_expr
,
269 nullptr, expr
.get_expr (), tl::nullopt
);
273 translated
= Backend::negation_expression (op
, negated_expr
, location
);
277 CompileExpr::visit (HIR::ComparisonExpr
&expr
)
279 auto op
= expr
.get_expr_type ();
280 auto lhs
= CompileExpr::Compile (expr
.get_lhs (), ctx
);
281 auto rhs
= CompileExpr::Compile (expr
.get_rhs (), ctx
);
282 auto location
= expr
.get_locus ();
284 // this might be an operator overload situation lets check
285 TyTy::FnType
*fntype
;
286 bool is_op_overload
= ctx
->get_tyctx ()->lookup_operator_overload (
287 expr
.get_mappings ().get_hirid (), &fntype
);
290 auto seg_name
= LangItem::ComparisonToSegment (expr
.get_expr_type ());
291 auto segment
= HIR::PathIdentSegment (seg_name
);
293 = LangItem::ComparisonToLangItem (expr
.get_expr_type ());
295 rhs
= address_expression (rhs
, EXPR_LOCATION (rhs
));
297 translated
= resolve_operator_overload (
298 lang_item_type
, expr
, lhs
, rhs
, expr
.get_lhs (),
299 tl::optional
<std::reference_wrapper
<HIR::Expr
>> (expr
.get_rhs ()),
304 translated
= Backend::comparison_expression (op
, lhs
, rhs
, location
);
308 CompileExpr::visit (HIR::LazyBooleanExpr
&expr
)
310 auto op
= expr
.get_expr_type ();
311 auto lhs
= CompileExpr::Compile (expr
.get_lhs (), ctx
);
312 auto rhs
= CompileExpr::Compile (expr
.get_rhs (), ctx
);
313 auto location
= expr
.get_locus ();
315 translated
= Backend::lazy_boolean_expression (op
, lhs
, rhs
, location
);
319 CompileExpr::visit (HIR::TypeCastExpr
&expr
)
321 TyTy::BaseType
*type_to_cast_to_ty
= nullptr;
322 if (!ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (),
323 &type_to_cast_to_ty
))
325 translated
= error_mark_node
;
329 TyTy::BaseType
*casted_tyty
= nullptr;
330 if (!ctx
->get_tyctx ()->lookup_type (
331 expr
.get_casted_expr ().get_mappings ().get_hirid (), &casted_tyty
))
333 translated
= error_mark_node
;
337 auto type_to_cast_to
= TyTyResolveCompile::compile (ctx
, type_to_cast_to_ty
);
338 auto casted_expr
= CompileExpr::Compile (expr
.get_casted_expr (), ctx
);
340 std::vector
<Resolver::Adjustment
> *adjustments
= nullptr;
341 bool ok
= ctx
->get_tyctx ()->lookup_cast_autoderef_mappings (
342 expr
.get_mappings ().get_hirid (), &adjustments
);
346 = resolve_adjustements (*adjustments
, casted_expr
, expr
.get_locus ());
350 = type_cast_expression (type_to_cast_to
, casted_expr
, expr
.get_locus ());
354 CompileExpr::visit (HIR::IfExpr
&expr
)
356 auto stmt
= CompileConditionalBlocks::compile (&expr
, ctx
, nullptr);
357 ctx
->add_statement (stmt
);
361 CompileExpr::visit (HIR::InlineAsm
&expr
)
363 CompileAsm
asm_codegen (ctx
);
364 ctx
->add_statement (asm_codegen
.tree_codegen_asm (expr
));
365 // translated = build_asm_expr (0, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE,
366 // NULL_TREE, true, true);
367 // CompileAsm::asm_build_expr (expr);
371 CompileExpr::visit (HIR::LlvmInlineAsm
&expr
)
373 CompileLlvmAsm
asm_codegen (ctx
);
374 ctx
->add_statement (asm_codegen
.tree_codegen_asm (expr
));
378 CompileExpr::visit (HIR::IfExprConseqElse
&expr
)
380 TyTy::BaseType
*if_type
= nullptr;
381 if (!ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (),
384 rust_error_at (expr
.get_locus (),
385 "failed to lookup type of IfExprConseqElse");
389 Bvariable
*tmp
= NULL
;
390 fncontext fnctx
= ctx
->peek_fn ();
391 tree enclosing_scope
= ctx
->peek_enclosing_scope ();
392 tree block_type
= TyTyResolveCompile::compile (ctx
, if_type
);
394 bool is_address_taken
= false;
395 tree ret_var_stmt
= nullptr;
396 tmp
= Backend::temporary_variable (fnctx
.fndecl
, enclosing_scope
, block_type
,
397 NULL
, is_address_taken
, expr
.get_locus (),
399 ctx
->add_statement (ret_var_stmt
);
401 auto stmt
= CompileConditionalBlocks::compile (&expr
, ctx
, tmp
);
402 ctx
->add_statement (stmt
);
404 translated
= Backend::var_expression (tmp
, expr
.get_locus ());
408 CompileExpr::visit (HIR::BlockExpr
&expr
)
410 if (expr
.has_label ())
412 rust_error_at (expr
.get_locus (), "labeled blocks are not supported");
416 TyTy::BaseType
*block_tyty
= nullptr;
417 if (!ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (),
420 rust_error_at (expr
.get_locus (), "failed to lookup type of BlockExpr");
424 Bvariable
*tmp
= NULL
;
425 fncontext fnctx
= ctx
->peek_fn ();
426 tree enclosing_scope
= ctx
->peek_enclosing_scope ();
427 tree block_type
= TyTyResolveCompile::compile (ctx
, block_tyty
);
429 bool is_address_taken
= false;
430 tree ret_var_stmt
= nullptr;
431 tmp
= Backend::temporary_variable (fnctx
.fndecl
, enclosing_scope
, block_type
,
432 NULL
, is_address_taken
, expr
.get_locus (),
434 ctx
->add_statement (ret_var_stmt
);
436 auto block_stmt
= CompileBlock::compile (expr
, ctx
, tmp
);
437 rust_assert (TREE_CODE (block_stmt
) == BIND_EXPR
);
438 ctx
->add_statement (block_stmt
);
440 translated
= Backend::var_expression (tmp
, expr
.get_locus ());
444 CompileExpr::visit (HIR::UnsafeBlockExpr
&expr
)
446 expr
.get_block_expr ().accept_vis (*this);
450 CompileExpr::visit (HIR::StructExprStruct
&struct_expr
)
452 TyTy::BaseType
*tyty
= nullptr;
453 if (!ctx
->get_tyctx ()->lookup_type (struct_expr
.get_mappings ().get_hirid (),
456 rust_error_at (struct_expr
.get_locus (), "unknown type");
460 rust_assert (tyty
->is_unit ());
461 translated
= unit_expression (struct_expr
.get_locus ());
465 CompileExpr::visit (HIR::StructExprStructFields
&struct_expr
)
467 TyTy::BaseType
*tyty
= nullptr;
468 if (!ctx
->get_tyctx ()->lookup_type (struct_expr
.get_mappings ().get_hirid (),
471 rust_error_at (struct_expr
.get_locus (), "unknown type");
476 rust_assert (tyty
->get_kind () == TyTy::TypeKind::ADT
);
477 TyTy::ADTType
*adt
= static_cast<TyTy::ADTType
*> (tyty
);
479 // what variant is it?
480 int union_disriminator
= struct_expr
.union_index
;
481 TyTy::VariantDef
*variant
= nullptr;
482 if (!adt
->is_enum ())
484 rust_assert (adt
->number_of_variants () == 1);
485 variant
= adt
->get_variants ().at (0);
490 bool ok
= ctx
->get_tyctx ()->lookup_variant_definition (
491 struct_expr
.get_struct_name ().get_mappings ().get_hirid (),
496 = adt
->lookup_variant_by_id (variant_id
, &variant
, &union_disriminator
);
501 tree compiled_adt_type
= TyTyResolveCompile::compile (ctx
, tyty
);
503 std::vector
<tree
> arguments
;
504 if (adt
->is_union ())
506 rust_assert (struct_expr
.get_fields ().size () == 1);
508 // assignments are coercion sites so lets convert the rvalue if
510 auto respective_field
= variant
->get_field_at_index (union_disriminator
);
511 auto expected
= respective_field
->get_field_type ();
514 auto &argument
= struct_expr
.get_fields ().at (0);
516 = ctx
->get_mappings ().lookup_location (expected
->get_ty_ref ());
517 auto rvalue_locus
= argument
->get_locus ();
518 auto rvalue
= CompileStructExprField::Compile (*argument
, ctx
);
520 TyTy::BaseType
*actual
= nullptr;
521 bool ok
= ctx
->get_tyctx ()->lookup_type (
522 argument
->get_mappings ().get_hirid (), &actual
);
527 = coercion_site (argument
->get_mappings ().get_hirid (), rvalue
,
528 actual
, expected
, lvalue_locus
, rvalue_locus
);
531 // add it to the list
532 arguments
.push_back (rvalue
);
536 // this assumes all fields are in order from type resolution and if a
537 // base struct was specified those fields are filed via accessors
538 for (size_t i
= 0; i
< struct_expr
.get_fields ().size (); i
++)
540 // assignments are coercion sites so lets convert the rvalue if
542 auto respective_field
= variant
->get_field_at_index (i
);
543 auto expected
= respective_field
->get_field_type ();
546 auto &argument
= struct_expr
.get_fields ().at (i
);
548 = ctx
->get_mappings ().lookup_location (expected
->get_ty_ref ());
549 auto rvalue_locus
= argument
->get_locus ();
550 auto rvalue
= CompileStructExprField::Compile (*argument
, ctx
);
552 TyTy::BaseType
*actual
= nullptr;
553 bool ok
= ctx
->get_tyctx ()->lookup_type (
554 argument
->get_mappings ().get_hirid (), &actual
);
556 // coerce it if required/possible see
557 // compile/torture/struct_base_init_1.rs
561 = coercion_site (argument
->get_mappings ().get_hirid (), rvalue
,
562 actual
, expected
, lvalue_locus
, rvalue_locus
);
565 // add it to the list
566 arguments
.push_back (rvalue
);
570 if (!adt
->is_enum ())
573 = Backend::constructor_expression (compiled_adt_type
, adt
->is_enum (),
574 arguments
, union_disriminator
,
575 struct_expr
.get_locus ());
579 HIR::Expr
&discrim_expr
= variant
->get_discriminant ();
580 tree discrim_expr_node
= CompileExpr::Compile (discrim_expr
, ctx
);
581 tree folded_discrim_expr
= fold_expr (discrim_expr_node
);
582 tree qualifier
= folded_discrim_expr
;
584 tree enum_root_files
= TYPE_FIELDS (compiled_adt_type
);
585 tree payload_root
= DECL_CHAIN (enum_root_files
);
587 tree payload
= Backend::constructor_expression (TREE_TYPE (payload_root
),
588 adt
->is_enum (), arguments
,
590 struct_expr
.get_locus ());
592 std::vector
<tree
> ctor_arguments
= {qualifier
, payload
};
595 = Backend::constructor_expression (compiled_adt_type
, 0, ctor_arguments
, -1,
596 struct_expr
.get_locus ());
600 CompileExpr::visit (HIR::GroupedExpr
&expr
)
602 translated
= CompileExpr::Compile (expr
.get_expr_in_parens (), ctx
);
606 CompileExpr::visit (HIR::FieldAccessExpr
&expr
)
608 HIR::Expr
&receiver_expr
= expr
.get_receiver_expr ();
609 tree receiver_ref
= CompileExpr::Compile (receiver_expr
, ctx
);
611 // resolve the receiver back to ADT type
612 TyTy::BaseType
*receiver
= nullptr;
613 if (!ctx
->get_tyctx ()->lookup_type (
614 expr
.get_receiver_expr ().get_mappings ().get_hirid (), &receiver
))
616 rust_error_at (expr
.get_receiver_expr ().get_locus (),
617 "unresolved type for receiver");
621 size_t field_index
= 0;
622 if (receiver
->get_kind () == TyTy::TypeKind::ADT
)
624 TyTy::ADTType
*adt
= static_cast<TyTy::ADTType
*> (receiver
);
625 rust_assert (!adt
->is_enum ());
626 rust_assert (adt
->number_of_variants () == 1);
628 TyTy::VariantDef
*variant
= adt
->get_variants ().at (0);
629 bool ok
= variant
->lookup_field (expr
.get_field_name ().as_string (),
630 nullptr, &field_index
);
633 else if (receiver
->get_kind () == TyTy::TypeKind::REF
)
635 TyTy::ReferenceType
*r
= static_cast<TyTy::ReferenceType
*> (receiver
);
636 TyTy::BaseType
*b
= r
->get_base ();
637 rust_assert (b
->get_kind () == TyTy::TypeKind::ADT
);
639 TyTy::ADTType
*adt
= static_cast<TyTy::ADTType
*> (b
);
640 rust_assert (!adt
->is_enum ());
641 rust_assert (adt
->number_of_variants () == 1);
643 TyTy::VariantDef
*variant
= adt
->get_variants ().at (0);
644 bool ok
= variant
->lookup_field (expr
.get_field_name ().as_string (),
645 nullptr, &field_index
);
648 tree indirect
= indirect_expression (receiver_ref
, expr
.get_locus ());
649 receiver_ref
= indirect
;
652 translated
= Backend::struct_field_expression (receiver_ref
, field_index
,
657 CompileExpr::visit (HIR::QualifiedPathInExpression
&expr
)
659 translated
= ResolvePathRef::Compile (expr
, ctx
);
663 CompileExpr::visit (HIR::PathInExpression
&expr
)
665 translated
= ResolvePathRef::Compile (expr
, ctx
);
669 CompileExpr::visit (HIR::LoopExpr
&expr
)
671 TyTy::BaseType
*block_tyty
= nullptr;
672 if (!ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (),
675 rust_error_at (expr
.get_locus (), "failed to lookup type of BlockExpr");
679 fncontext fnctx
= ctx
->peek_fn ();
680 tree enclosing_scope
= ctx
->peek_enclosing_scope ();
681 tree block_type
= TyTyResolveCompile::compile (ctx
, block_tyty
);
683 bool is_address_taken
= false;
684 tree ret_var_stmt
= NULL_TREE
;
686 = Backend::temporary_variable (fnctx
.fndecl
, enclosing_scope
, block_type
,
687 NULL
, is_address_taken
, expr
.get_locus (),
689 ctx
->add_statement (ret_var_stmt
);
690 ctx
->push_loop_context (tmp
);
692 if (expr
.has_loop_label ())
694 HIR::LoopLabel
&loop_label
= expr
.get_loop_label ();
696 = Backend::label (fnctx
.fndecl
, loop_label
.get_lifetime ().get_name (),
697 loop_label
.get_locus ());
698 tree label_decl
= Backend::label_definition_statement (label
);
699 ctx
->add_statement (label_decl
);
700 ctx
->insert_label_decl (
701 loop_label
.get_lifetime ().get_mappings ().get_hirid (), label
);
704 tree loop_begin_label
= Backend::label (fnctx
.fndecl
, "", expr
.get_locus ());
705 tree loop_begin_label_decl
706 = Backend::label_definition_statement (loop_begin_label
);
707 ctx
->add_statement (loop_begin_label_decl
);
708 ctx
->push_loop_begin_label (loop_begin_label
);
711 = CompileBlock::compile (expr
.get_loop_block (), ctx
, nullptr);
712 tree loop_expr
= Backend::loop_expression (code_block
, expr
.get_locus ());
713 ctx
->add_statement (loop_expr
);
715 ctx
->pop_loop_context ();
716 translated
= Backend::var_expression (tmp
, expr
.get_locus ());
718 ctx
->pop_loop_begin_label ();
722 CompileExpr::visit (HIR::WhileLoopExpr
&expr
)
724 fncontext fnctx
= ctx
->peek_fn ();
725 if (expr
.has_loop_label ())
727 HIR::LoopLabel
&loop_label
= expr
.get_loop_label ();
729 = Backend::label (fnctx
.fndecl
, loop_label
.get_lifetime ().get_name (),
730 loop_label
.get_locus ());
731 tree label_decl
= Backend::label_definition_statement (label
);
732 ctx
->add_statement (label_decl
);
733 ctx
->insert_label_decl (
734 loop_label
.get_lifetime ().get_mappings ().get_hirid (), label
);
737 std::vector
<Bvariable
*> locals
;
738 location_t start_location
= expr
.get_loop_block ().get_locus ();
739 location_t end_location
= expr
.get_loop_block ().get_locus (); // FIXME
741 tree enclosing_scope
= ctx
->peek_enclosing_scope ();
742 tree loop_block
= Backend::block (fnctx
.fndecl
, enclosing_scope
, locals
,
743 start_location
, end_location
);
744 ctx
->push_block (loop_block
);
746 tree loop_begin_label
= Backend::label (fnctx
.fndecl
, "", expr
.get_locus ());
747 tree loop_begin_label_decl
748 = Backend::label_definition_statement (loop_begin_label
);
749 ctx
->add_statement (loop_begin_label_decl
);
750 ctx
->push_loop_begin_label (loop_begin_label
);
752 tree condition
= CompileExpr::Compile (expr
.get_predicate_expr (), ctx
);
753 tree exit_condition
= fold_build1_loc (expr
.get_locus (), TRUTH_NOT_EXPR
,
754 boolean_type_node
, condition
);
755 tree exit_expr
= Backend::exit_expression (exit_condition
, expr
.get_locus ());
756 ctx
->add_statement (exit_expr
);
759 = CompileBlock::compile (expr
.get_loop_block (), ctx
, nullptr);
760 rust_assert (TREE_CODE (code_block_stmt
) == BIND_EXPR
);
761 ctx
->add_statement (code_block_stmt
);
763 ctx
->pop_loop_begin_label ();
766 tree loop_expr
= Backend::loop_expression (loop_block
, expr
.get_locus ());
767 ctx
->add_statement (loop_expr
);
771 CompileExpr::visit (HIR::BreakExpr
&expr
)
773 if (expr
.has_break_expr ())
775 tree compiled_expr
= CompileExpr::Compile (expr
.get_expr (), ctx
);
777 Bvariable
*loop_result_holder
= ctx
->peek_loop_context ();
778 tree result_reference
779 = Backend::var_expression (loop_result_holder
,
780 expr
.get_expr ().get_locus ());
783 = Backend::assignment_statement (result_reference
, compiled_expr
,
785 ctx
->add_statement (assignment
);
788 if (expr
.has_label ())
790 NodeId resolved_node_id
= UNKNOWN_NODEID
;
791 if (flag_name_resolution_2_0
)
794 = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
797 = nr_ctx
.lookup (expr
.get_label ().get_mappings ().get_nodeid ()))
798 resolved_node_id
= *id
;
802 NodeId tmp
= UNKNOWN_NODEID
;
803 if (ctx
->get_resolver ()->lookup_resolved_label (
804 expr
.get_label ().get_mappings ().get_nodeid (), &tmp
))
805 resolved_node_id
= tmp
;
808 if (resolved_node_id
== UNKNOWN_NODEID
)
811 expr
.get_label ().get_locus (),
812 "failed to resolve compiled label for label %s",
813 expr
.get_label ().get_mappings ().as_string ().c_str ());
817 tl::optional
<HirId
> hid
818 = ctx
->get_mappings ().lookup_node_to_hir (resolved_node_id
);
819 if (!hid
.has_value ())
821 rust_fatal_error (expr
.get_locus (), "reverse lookup label failure");
824 auto ref
= hid
.value ();
826 tree label
= NULL_TREE
;
827 if (!ctx
->lookup_label_decl (ref
, &label
))
829 rust_error_at (expr
.get_label ().get_locus (),
830 "failed to lookup compiled label");
834 tree goto_label
= Backend::goto_statement (label
, expr
.get_locus ());
835 ctx
->add_statement (goto_label
);
840 = Backend::exit_expression (Backend::boolean_constant_expression (true),
842 ctx
->add_statement (exit_expr
);
847 CompileExpr::visit (HIR::ContinueExpr
&expr
)
849 tree label
= ctx
->peek_loop_begin_label ();
850 if (expr
.has_label ())
852 NodeId resolved_node_id
= UNKNOWN_NODEID
;
853 if (flag_name_resolution_2_0
)
856 = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
859 = nr_ctx
.lookup (expr
.get_label ().get_mappings ().get_nodeid ()))
860 resolved_node_id
= *id
;
864 NodeId tmp
= UNKNOWN_NODEID
;
866 if (ctx
->get_resolver ()->lookup_resolved_label (
867 expr
.get_label ().get_mappings ().get_nodeid (), &tmp
))
868 resolved_node_id
= tmp
;
871 if (resolved_node_id
== UNKNOWN_NODEID
)
874 expr
.get_label ().get_locus (),
875 "failed to resolve compiled label for label %s",
876 expr
.get_label ().get_mappings ().as_string ().c_str ());
880 tl::optional
<HirId
> hid
881 = ctx
->get_mappings ().lookup_node_to_hir (resolved_node_id
);
882 if (!hid
.has_value ())
884 rust_fatal_error (expr
.get_locus (), "reverse lookup label failure");
887 auto ref
= hid
.value ();
889 if (!ctx
->lookup_label_decl (ref
, &label
))
891 rust_error_at (expr
.get_label ().get_locus (),
892 "failed to lookup compiled label");
897 translated
= Backend::goto_statement (label
, expr
.get_locus ());
901 CompileExpr::visit (HIR::BorrowExpr
&expr
)
903 tree main_expr
= CompileExpr::Compile (expr
.get_expr (), ctx
);
904 if (RS_DST_FLAG_P (TREE_TYPE (main_expr
)))
906 translated
= main_expr
;
910 TyTy::BaseType
*tyty
= nullptr;
911 if (!ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (),
915 tree expected_type
= TyTyResolveCompile::compile (ctx
, tyty
);
916 translated
= address_expression (main_expr
, expr
.get_locus (), expected_type
);
920 CompileExpr::visit (HIR::DereferenceExpr
&expr
)
922 TyTy::BaseType
*tyty
= nullptr;
923 if (!ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (),
926 rust_fatal_error (expr
.get_locus (),
927 "did not resolve type for this TupleExpr");
931 tree main_expr
= CompileExpr::Compile (expr
.get_expr (), ctx
);
933 // this might be an operator overload situation lets check
934 TyTy::FnType
*fntype
;
935 bool is_op_overload
= ctx
->get_tyctx ()->lookup_operator_overload (
936 expr
.get_mappings ().get_hirid (), &fntype
);
939 auto lang_item_type
= LangItem::Kind::DEREF
;
940 tree operator_overload_call
941 = resolve_operator_overload (lang_item_type
, expr
, main_expr
, nullptr,
942 expr
.get_expr (), tl::nullopt
);
944 // rust deref always returns a reference from this overload then we can
945 // actually do the indirection
946 main_expr
= operator_overload_call
;
949 tree expected_type
= TyTyResolveCompile::compile (ctx
, tyty
);
950 if (RS_DST_FLAG_P (TREE_TYPE (main_expr
)) && RS_DST_FLAG_P (expected_type
))
952 translated
= main_expr
;
956 translated
= indirect_expression (main_expr
, expr
.get_locus ());
960 CompileExpr::visit (HIR::LiteralExpr
&expr
)
962 TyTy::BaseType
*tyty
= nullptr;
963 if (!ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (),
967 switch (expr
.get_lit_type ())
969 case HIR::Literal::BOOL
:
970 translated
= compile_bool_literal (expr
, tyty
);
973 case HIR::Literal::INT
:
974 translated
= compile_integer_literal (expr
, tyty
);
977 case HIR::Literal::FLOAT
:
978 translated
= compile_float_literal (expr
, tyty
);
981 case HIR::Literal::CHAR
:
982 translated
= compile_char_literal (expr
, tyty
);
985 case HIR::Literal::BYTE
:
986 translated
= compile_byte_literal (expr
, tyty
);
989 case HIR::Literal::STRING
:
990 translated
= compile_string_literal (expr
, tyty
);
993 case HIR::Literal::BYTE_STRING
:
994 translated
= compile_byte_string_literal (expr
, tyty
);
1000 CompileExpr::visit (HIR::AssignmentExpr
&expr
)
1002 auto lvalue
= CompileExpr::Compile (expr
.get_lhs (), ctx
);
1003 auto rvalue
= CompileExpr::Compile (expr
.get_rhs (), ctx
);
1005 // assignments are coercion sites so lets convert the rvalue if necessary
1006 TyTy::BaseType
*expected
= nullptr;
1007 TyTy::BaseType
*actual
= nullptr;
1010 ok
= ctx
->get_tyctx ()->lookup_type (
1011 expr
.get_lhs ().get_mappings ().get_hirid (), &expected
);
1014 ok
= ctx
->get_tyctx ()->lookup_type (
1015 expr
.get_rhs ().get_mappings ().get_hirid (), &actual
);
1018 rvalue
= coercion_site (expr
.get_mappings ().get_hirid (), rvalue
, actual
,
1019 expected
, expr
.get_lhs ().get_locus (),
1020 expr
.get_rhs ().get_locus ());
1022 // rust_debug_loc (expr.get_locus (), "XXXXXX assignment");
1023 // debug_tree (rvalue);
1024 // debug_tree (lvalue);
1027 = Backend::assignment_statement (lvalue
, rvalue
, expr
.get_locus ());
1029 ctx
->add_statement (assignment
);
1032 // Helper for CompileExpr::visit (HIR::MatchExpr).
1033 // Check that the scrutinee of EXPR is a valid kind of expression to match on.
1034 // Return the TypeKind of the scrutinee if it is valid, or TyTy::TypeKind::ERROR
1036 static TyTy::TypeKind
1037 check_match_scrutinee (HIR::MatchExpr
&expr
, Context
*ctx
)
1039 TyTy::BaseType
*scrutinee_expr_tyty
= nullptr;
1040 if (!ctx
->get_tyctx ()->lookup_type (
1041 expr
.get_scrutinee_expr ().get_mappings ().get_hirid (),
1042 &scrutinee_expr_tyty
))
1044 return TyTy::TypeKind::ERROR
;
1047 TyTy::TypeKind scrutinee_kind
= scrutinee_expr_tyty
->get_kind ();
1049 if (scrutinee_kind
== TyTy::TypeKind::FLOAT
)
1051 // FIXME: CASE_LABEL_EXPR does not support floating point types.
1052 // Find another way to compile these.
1053 rust_sorry_at (expr
.get_locus (),
1054 "match on floating-point types is not yet supported");
1057 TyTy::BaseType
*expr_tyty
= nullptr;
1058 if (!ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (),
1061 return TyTy::TypeKind::ERROR
;
1064 return scrutinee_kind
;
1068 CompileExpr::visit (HIR::MatchExpr
&expr
)
1070 // https://gcc.gnu.org/onlinedocs/gccint/Basic-Statements.html#Basic-Statements
1072 // SWITCH_ALL_CASES_P is true if the switch includes a default label or the
1073 // case label ranges cover all possible values of the condition expression
1075 TyTy::TypeKind scrutinee_kind
= check_match_scrutinee (expr
, ctx
);
1076 if (scrutinee_kind
== TyTy::TypeKind::ERROR
)
1078 translated
= error_mark_node
;
1082 TyTy::BaseType
*expr_tyty
= nullptr;
1083 if (!ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (),
1086 translated
= error_mark_node
;
1090 // if the result of this expression is meant to be never type then we can
1091 // optimise this away but there is the case where match arms resolve to !
1092 // because of return statements we need to special case this
1093 if (!expr
.has_match_arms () && expr_tyty
->is
<TyTy::NeverType
> ())
1095 translated
= unit_expression (expr
.get_locus ());
1099 fncontext fnctx
= ctx
->peek_fn ();
1100 Bvariable
*tmp
= NULL
;
1101 tree enclosing_scope
= ctx
->peek_enclosing_scope ();
1102 tree block_type
= TyTyResolveCompile::compile (ctx
, expr_tyty
);
1104 bool is_address_taken
= false;
1105 tree ret_var_stmt
= nullptr;
1106 tmp
= Backend::temporary_variable (fnctx
.fndecl
, enclosing_scope
, block_type
,
1107 NULL
, is_address_taken
, expr
.get_locus (),
1109 ctx
->add_statement (ret_var_stmt
);
1111 // lets compile the scrutinee expression
1112 tree match_scrutinee_rval
1113 = CompileExpr::Compile (expr
.get_scrutinee_expr (), ctx
);
1115 Bvariable
*match_scrutinee_tmp_var
1116 = Backend::temporary_variable (fnctx
.fndecl
, enclosing_scope
,
1117 TREE_TYPE (match_scrutinee_rval
), NULL
,
1118 is_address_taken
, expr
.get_locus (),
1120 ctx
->add_statement (ret_var_stmt
);
1122 tree match_scrutinee_expr
= match_scrutinee_tmp_var
->get_tree (
1123 expr
.get_scrutinee_expr ().get_locus ());
1126 = Backend::assignment_statement (match_scrutinee_expr
, match_scrutinee_rval
,
1128 ctx
->add_statement (assignment
);
1130 // setup the end label so the cases can exit properly
1131 tree fndecl
= fnctx
.fndecl
;
1132 location_t end_label_locus
= expr
.get_locus (); // FIXME
1134 = Backend::label (fndecl
, "" /* empty creates an artificial label */,
1136 tree end_label_decl_statement
1137 = Backend::label_definition_statement (end_label
);
1139 for (auto &kase
: expr
.get_match_cases ())
1141 // for now lets just get single pattern's working
1142 HIR::MatchArm
&kase_arm
= kase
.get_arm ();
1143 rust_assert (kase_arm
.get_patterns ().size () > 0);
1145 for (auto &kase_pattern
: kase_arm
.get_patterns ())
1147 // setup the match-arm-body-block
1148 location_t start_location
= UNKNOWN_LOCATION
; // FIXME
1149 location_t end_location
= UNKNOWN_LOCATION
; // FIXME
1150 tree arm_body_block
= Backend::block (fndecl
, enclosing_scope
, {},
1151 start_location
, end_location
);
1153 ctx
->push_block (arm_body_block
);
1155 // setup the bindings for the block
1156 CompilePatternBindings::Compile (*kase_pattern
, match_scrutinee_expr
,
1159 // compile the expr and setup the assignment if required when tmp !=
1161 location_t arm_locus
= kase_arm
.get_locus ();
1162 tree kase_expr_tree
= CompileExpr::Compile (kase
.get_expr (), ctx
);
1163 tree result_reference
= Backend::var_expression (tmp
, arm_locus
);
1165 TyTy::BaseType
*actual
= nullptr;
1166 bool ok
= ctx
->get_tyctx ()->lookup_type (
1167 kase
.get_expr ().get_mappings ().get_hirid (), &actual
);
1171 = coercion_site (kase
.get_expr ().get_mappings ().get_hirid (),
1172 kase_expr_tree
, actual
, expr_tyty
,
1173 expr
.get_locus (), arm_locus
);
1176 = Backend::assignment_statement (result_reference
, coerced_result
,
1178 ctx
->add_statement (assignment
);
1182 = build1_loc (arm_locus
, GOTO_EXPR
, void_type_node
, end_label
);
1183 ctx
->add_statement (goto_end_label
);
1188 = CompilePatternCheckExpr::Compile (*kase_pattern
,
1189 match_scrutinee_expr
, ctx
);
1192 = Backend::if_statement (NULL_TREE
, check_expr
, arm_body_block
,
1193 NULL_TREE
, kase_pattern
->get_locus ());
1195 ctx
->add_statement (check_stmt
);
1199 // setup the switch expression
1200 ctx
->add_statement (end_label_decl_statement
);
1202 translated
= Backend::var_expression (tmp
, expr
.get_locus ());
1206 CompileExpr::visit (HIR::CallExpr
&expr
)
1208 TyTy::BaseType
*tyty
= nullptr;
1209 if (!ctx
->get_tyctx ()->lookup_type (
1210 expr
.get_fnexpr ().get_mappings ().get_hirid (), &tyty
))
1212 rust_error_at (expr
.get_locus (), "unknown type");
1216 // must be a tuple constructor
1217 bool is_adt_ctor
= tyty
->get_kind () == TyTy::TypeKind::ADT
;
1220 rust_assert (tyty
->get_kind () == TyTy::TypeKind::ADT
);
1221 TyTy::ADTType
*adt
= static_cast<TyTy::ADTType
*> (tyty
);
1222 tree compiled_adt_type
= TyTyResolveCompile::compile (ctx
, tyty
);
1224 // what variant is it?
1225 int union_disriminator
= -1;
1226 TyTy::VariantDef
*variant
= nullptr;
1227 if (!adt
->is_enum ())
1229 rust_assert (adt
->number_of_variants () == 1);
1230 variant
= adt
->get_variants ().at (0);
1235 bool ok
= ctx
->get_tyctx ()->lookup_variant_definition (
1236 expr
.get_fnexpr ().get_mappings ().get_hirid (), &variant_id
);
1239 ok
= adt
->lookup_variant_by_id (variant_id
, &variant
,
1240 &union_disriminator
);
1244 // this assumes all fields are in order from type resolution and if a
1245 // base struct was specified those fields are filed via accessors
1246 std::vector
<tree
> arguments
;
1247 for (size_t i
= 0; i
< expr
.num_params (); i
++)
1249 auto &argument
= expr
.get_arguments ().at (i
);
1250 auto rvalue
= CompileExpr::Compile (*argument
, ctx
);
1252 // assignments are coercion sites so lets convert the rvalue if
1254 auto respective_field
= variant
->get_field_at_index (i
);
1255 auto expected
= respective_field
->get_field_type ();
1257 TyTy::BaseType
*actual
= nullptr;
1258 bool ok
= ctx
->get_tyctx ()->lookup_type (
1259 argument
->get_mappings ().get_hirid (), &actual
);
1262 // coerce it if required
1263 location_t lvalue_locus
1264 = ctx
->get_mappings ().lookup_location (expected
->get_ty_ref ());
1265 location_t rvalue_locus
= argument
->get_locus ();
1267 = coercion_site (argument
->get_mappings ().get_hirid (), rvalue
,
1268 actual
, expected
, lvalue_locus
, rvalue_locus
);
1270 // add it to the list
1271 arguments
.push_back (rvalue
);
1274 if (!adt
->is_enum ())
1277 = Backend::constructor_expression (compiled_adt_type
,
1278 adt
->is_enum (), arguments
,
1284 HIR::Expr
&discrim_expr
= variant
->get_discriminant ();
1285 tree discrim_expr_node
= CompileExpr::Compile (discrim_expr
, ctx
);
1286 tree folded_discrim_expr
= fold_expr (discrim_expr_node
);
1287 tree qualifier
= folded_discrim_expr
;
1289 tree enum_root_files
= TYPE_FIELDS (compiled_adt_type
);
1290 tree payload_root
= DECL_CHAIN (enum_root_files
);
1293 = Backend::constructor_expression (TREE_TYPE (payload_root
), true,
1294 {arguments
}, union_disriminator
,
1297 std::vector
<tree
> ctor_arguments
= {qualifier
, payload
};
1298 translated
= Backend::constructor_expression (compiled_adt_type
, false,
1305 auto get_parameter_tyty_at_index
1306 = [] (const TyTy::BaseType
*base
, size_t index
,
1307 TyTy::BaseType
**result
) -> bool {
1308 bool is_fn
= base
->get_kind () == TyTy::TypeKind::FNDEF
1309 || base
->get_kind () == TyTy::TypeKind::FNPTR
;
1310 rust_assert (is_fn
);
1312 if (base
->get_kind () == TyTy::TypeKind::FNPTR
)
1314 const TyTy::FnPtr
*fn
= static_cast<const TyTy::FnPtr
*> (base
);
1315 *result
= fn
->get_param_type_at (index
);
1320 const TyTy::FnType
*fn
= static_cast<const TyTy::FnType
*> (base
);
1321 auto ¶m
= fn
->param_at (index
);
1322 *result
= param
.get_type ();
1327 auto fn_address
= CompileExpr::Compile (expr
.get_fnexpr (), ctx
);
1329 // is this a closure call?
1330 bool possible_trait_call
1331 = generate_possible_fn_trait_call (expr
, fn_address
, &translated
);
1332 if (possible_trait_call
)
1335 bool is_variadic
= false;
1336 size_t required_num_args
= expr
.get_arguments ().size ();
1338 if (tyty
->get_kind () == TyTy::TypeKind::FNDEF
)
1340 const TyTy::FnType
*fn
= static_cast<const TyTy::FnType
*> (tyty
);
1341 required_num_args
= fn
->num_params ();
1342 is_variadic
= fn
->is_variadic ();
1344 else if (tyty
->get_kind () == TyTy::TypeKind::FNPTR
)
1346 const TyTy::FnPtr
*fn
= static_cast<const TyTy::FnPtr
*> (tyty
);
1347 required_num_args
= fn
->num_params ();
1350 std::vector
<tree
> args
;
1351 for (size_t i
= 0; i
< expr
.get_arguments ().size (); i
++)
1353 auto &argument
= expr
.get_arguments ().at (i
);
1354 auto rvalue
= CompileExpr::Compile (*argument
, ctx
);
1356 if (is_variadic
&& i
>= required_num_args
)
1358 args
.push_back (rvalue
);
1362 // assignments are coercion sites so lets convert the rvalue if
1365 TyTy::BaseType
*expected
= nullptr;
1366 ok
= get_parameter_tyty_at_index (tyty
, i
, &expected
);
1369 TyTy::BaseType
*actual
= nullptr;
1370 ok
= ctx
->get_tyctx ()->lookup_type (
1371 argument
->get_mappings ().get_hirid (), &actual
);
1374 // coerce it if required
1375 location_t lvalue_locus
1376 = ctx
->get_mappings ().lookup_location (expected
->get_ty_ref ());
1377 location_t rvalue_locus
= argument
->get_locus ();
1378 rvalue
= coercion_site (argument
->get_mappings ().get_hirid (), rvalue
,
1379 actual
, expected
, lvalue_locus
, rvalue_locus
);
1381 // add it to the list
1382 args
.push_back (rvalue
);
1385 // must be a regular call to a function
1387 = Backend::call_expression (fn_address
, args
, nullptr, expr
.get_locus ());
1391 CompileExpr::visit (HIR::MethodCallExpr
&expr
)
1394 tree self
= CompileExpr::Compile (expr
.get_receiver (), ctx
);
1396 // lookup the expected function type
1397 TyTy::BaseType
*lookup_fntype
= nullptr;
1398 bool ok
= ctx
->get_tyctx ()->lookup_type (
1399 expr
.get_method_name ().get_mappings ().get_hirid (), &lookup_fntype
);
1401 rust_assert (lookup_fntype
->get_kind () == TyTy::TypeKind::FNDEF
);
1402 TyTy::FnType
*fntype
= static_cast<TyTy::FnType
*> (lookup_fntype
);
1404 TyTy::BaseType
*receiver
= nullptr;
1405 ok
= ctx
->get_tyctx ()->lookup_type (
1406 expr
.get_receiver ().get_mappings ().get_hirid (), &receiver
);
1409 bool is_dyn_dispatch
1410 = receiver
->get_root ()->get_kind () == TyTy::TypeKind::DYNAMIC
;
1411 bool is_generic_receiver
= receiver
->get_kind () == TyTy::TypeKind::PARAM
;
1412 if (is_generic_receiver
)
1414 TyTy::ParamType
*p
= static_cast<TyTy::ParamType
*> (receiver
);
1415 receiver
= p
->resolve ();
1418 tree fn_expr
= error_mark_node
;
1419 if (is_dyn_dispatch
)
1421 const TyTy::DynamicObjectType
*dyn
1422 = static_cast<const TyTy::DynamicObjectType
*> (receiver
->get_root ());
1424 = get_fn_addr_from_dyn (dyn
, receiver
, fntype
, self
, expr
.get_locus ());
1425 self
= get_receiver_from_dyn (dyn
, receiver
, fntype
, self
,
1429 // lookup compiled functions since it may have already been compiled
1430 fn_expr
= resolve_method_address (fntype
, receiver
, expr
.get_locus ());
1432 // lookup the autoderef mappings
1433 HirId autoderef_mappings_id
1434 = expr
.get_receiver ().get_mappings ().get_hirid ();
1435 std::vector
<Resolver::Adjustment
> *adjustments
= nullptr;
1436 ok
= ctx
->get_tyctx ()->lookup_autoderef_mappings (autoderef_mappings_id
,
1440 // apply adjustments for the fn call
1441 self
= resolve_adjustements (*adjustments
, self
,
1442 expr
.get_receiver ().get_locus ());
1444 std::vector
<tree
> args
;
1445 args
.push_back (self
); // adjusted self
1448 for (size_t i
= 0; i
< expr
.get_arguments ().size (); i
++)
1450 auto &argument
= expr
.get_arguments ().at (i
);
1451 auto rvalue
= CompileExpr::Compile (*argument
, ctx
);
1453 // assignments are coercion sites so lets convert the rvalue if
1454 // necessary, offset from the already adjusted implicit self
1456 TyTy::BaseType
*expected
= fntype
->param_at (i
+ 1).get_type ();
1458 TyTy::BaseType
*actual
= nullptr;
1459 ok
= ctx
->get_tyctx ()->lookup_type (
1460 argument
->get_mappings ().get_hirid (), &actual
);
1463 // coerce it if required
1464 location_t lvalue_locus
1465 = ctx
->get_mappings ().lookup_location (expected
->get_ty_ref ());
1466 location_t rvalue_locus
= argument
->get_locus ();
1467 rvalue
= coercion_site (argument
->get_mappings ().get_hirid (), rvalue
,
1468 actual
, expected
, lvalue_locus
, rvalue_locus
);
1470 // add it to the list
1471 args
.push_back (rvalue
);
1475 = Backend::call_expression (fn_expr
, args
, nullptr, expr
.get_locus ());
1479 CompileExpr::get_fn_addr_from_dyn (const TyTy::DynamicObjectType
*dyn
,
1480 TyTy::BaseType
*receiver
,
1481 TyTy::FnType
*fntype
, tree receiver_ref
,
1482 location_t expr_locus
)
1485 const Resolver::TraitItemReference
*ref
= nullptr;
1486 for (auto &bound
: dyn
->get_object_items ())
1488 const Resolver::TraitItemReference
*item
= bound
.first
;
1489 auto t
= item
->get_tyty ();
1490 rust_assert (t
->get_kind () == TyTy::TypeKind::FNDEF
);
1491 auto ft
= static_cast<TyTy::FnType
*> (t
);
1493 if (ft
->get_id () == fntype
->get_id ())
1502 return error_mark_node
;
1504 // cast it to the correct fntype
1505 tree expected_fntype
= TyTyResolveCompile::compile (ctx
, fntype
, true);
1506 tree idx
= build_int_cst (size_type_node
, offs
);
1509 = Backend::struct_field_expression (receiver_ref
, 1, expr_locus
);
1510 tree vtable_array_access
1511 = build4_loc (expr_locus
, ARRAY_REF
, TREE_TYPE (TREE_TYPE (vtable_ptr
)),
1512 vtable_ptr
, idx
, NULL_TREE
, NULL_TREE
);
1514 tree vcall
= build3_loc (expr_locus
, OBJ_TYPE_REF
, expected_fntype
,
1515 vtable_array_access
, receiver_ref
, idx
);
1521 CompileExpr::get_receiver_from_dyn (const TyTy::DynamicObjectType
*dyn
,
1522 TyTy::BaseType
*receiver
,
1523 TyTy::FnType
*fntype
, tree receiver_ref
,
1524 location_t expr_locus
)
1526 // access the offs + 1 for the fnptr and offs=0 for the reciever obj
1527 return Backend::struct_field_expression (receiver_ref
, 0, expr_locus
);
1531 CompileExpr::resolve_operator_overload (
1532 LangItem::Kind lang_item_type
, HIR::OperatorExprMeta expr
, tree lhs
, tree rhs
,
1533 HIR::Expr
&lhs_expr
, tl::optional
<std::reference_wrapper
<HIR::Expr
>> rhs_expr
,
1534 HIR::PathIdentSegment specified_segment
)
1536 TyTy::FnType
*fntype
;
1537 bool is_op_overload
= ctx
->get_tyctx ()->lookup_operator_overload (
1538 expr
.get_mappings ().get_hirid (), &fntype
);
1539 rust_assert (is_op_overload
);
1541 TyTy::BaseType
*receiver
= nullptr;
1543 = ctx
->get_tyctx ()->lookup_type (lhs_expr
.get_mappings ().get_hirid (),
1547 bool is_generic_receiver
= receiver
->get_kind () == TyTy::TypeKind::PARAM
;
1548 if (is_generic_receiver
)
1550 TyTy::ParamType
*p
= static_cast<TyTy::ParamType
*> (receiver
);
1551 receiver
= p
->resolve ();
1554 // lookup compiled functions since it may have already been compiled
1555 HIR::PathIdentSegment segment_name
1556 = specified_segment
.is_error ()
1557 ? HIR::PathIdentSegment (LangItem::ToString (lang_item_type
))
1558 : specified_segment
;
1559 tree fn_expr
= resolve_method_address (fntype
, receiver
, expr
.get_locus ());
1561 // lookup the autoderef mappings
1562 std::vector
<Resolver::Adjustment
> *adjustments
= nullptr;
1563 ok
= ctx
->get_tyctx ()->lookup_autoderef_mappings (
1564 expr
.get_lvalue_mappings ().get_hirid (), &adjustments
);
1567 // apply adjustments for the fn call
1568 tree self
= resolve_adjustements (*adjustments
, lhs
, lhs_expr
.get_locus ());
1570 std::vector
<tree
> args
;
1571 args
.push_back (self
); // adjusted self
1572 if (rhs
!= nullptr) // can be null for negation_expr (unary ones)
1573 args
.push_back (rhs
);
1575 return Backend::call_expression (fn_expr
, args
, nullptr, expr
.get_locus ());
1579 CompileExpr::compile_bool_literal (const HIR::LiteralExpr
&expr
,
1580 const TyTy::BaseType
*tyty
)
1582 rust_assert (expr
.get_lit_type () == HIR::Literal::BOOL
);
1584 const auto literal_value
= expr
.get_literal ();
1585 bool bval
= literal_value
.as_string ().compare ("true") == 0;
1586 return Backend::boolean_constant_expression (bval
);
1590 CompileExpr::compile_integer_literal (const HIR::LiteralExpr
&expr
,
1591 const TyTy::BaseType
*tyty
)
1593 rust_assert (expr
.get_lit_type () == HIR::Literal::INT
);
1594 const auto literal_value
= expr
.get_literal ();
1596 tree type
= TyTyResolveCompile::compile (ctx
, tyty
);
1599 if (mpz_init_set_str (ival
, literal_value
.as_string ().c_str (), 10) != 0)
1601 rust_error_at (expr
.get_locus (), "bad number in literal");
1602 return error_mark_node
;
1607 mpz_init (type_min
);
1608 mpz_init (type_max
);
1609 get_type_static_bounds (type
, type_min
, type_max
);
1611 if (expr
.is_negative ())
1613 mpz_neg (ival
, ival
);
1615 if (mpz_cmp (ival
, type_min
) < 0 || mpz_cmp (ival
, type_max
) > 0)
1617 rust_error_at (expr
.get_locus (),
1618 "integer overflows the respective type %qs",
1619 tyty
->get_name ().c_str ());
1620 return error_mark_node
;
1623 tree result
= wide_int_to_tree (type
, wi::from_mpz (type
, ival
, true));
1625 mpz_clear (type_min
);
1626 mpz_clear (type_max
);
1633 CompileExpr::compile_float_literal (const HIR::LiteralExpr
&expr
,
1634 const TyTy::BaseType
*tyty
)
1636 rust_assert (expr
.get_lit_type () == HIR::Literal::FLOAT
);
1637 const auto literal_value
= expr
.get_literal ();
1639 tree type
= TyTyResolveCompile::compile (ctx
, tyty
);
1642 if (mpfr_init_set_str (fval
, literal_value
.as_string ().c_str (), 10,
1646 rust_error_at (expr
.get_locus (), "bad number in literal");
1647 return error_mark_node
;
1651 // see go/gofrontend/expressions.cc:check_float_type
1652 bool real_value_overflow
;
1654 if (mpfr_regular_p (fval
) != 0)
1656 mpfr_exp_t exp
= mpfr_get_exp (fval
);
1661 * By convention, the radix point of the significand is just before the
1662 * first digit (which is always 1 due to normalization), like in the C
1663 * language, but unlike in IEEE 754 (thus, for a given number, the
1664 * exponent values in MPFR and in IEEE 754 differ by 1).
1666 switch (TYPE_PRECISION (type
))
1673 min_exp
= -1024 + 1;
1677 rust_error_at (expr
.get_locus (),
1678 "precision of type %<%s%> not supported",
1679 tyty
->get_name ().c_str ());
1680 return error_mark_node
;
1682 real_value_overflow
= exp
< min_exp
|| exp
> max_exp
;
1686 real_value_overflow
= false;
1690 real_from_mpfr (&r1
, fval
, type
, GMP_RNDN
);
1692 real_convert (&r2
, TYPE_MODE (type
), &r1
);
1694 tree real_value
= build_real (type
, r2
);
1695 if (TREE_OVERFLOW (real_value
) || real_value_overflow
)
1697 rust_error_at (expr
.get_locus (),
1698 "decimal overflows the respective type %qs",
1699 tyty
->get_name ().c_str ());
1700 return error_mark_node
;
1707 CompileExpr::compile_char_literal (const HIR::LiteralExpr
&expr
,
1708 const TyTy::BaseType
*tyty
)
1710 rust_assert (expr
.get_lit_type () == HIR::Literal::CHAR
);
1711 const auto literal_value
= expr
.get_literal ();
1713 // FIXME needs wchar_t
1714 char c
= literal_value
.as_string ().c_str ()[0];
1715 return Backend::wchar_constant_expression (c
);
1719 CompileExpr::compile_byte_literal (const HIR::LiteralExpr
&expr
,
1720 const TyTy::BaseType
*tyty
)
1722 rust_assert (expr
.get_lit_type () == HIR::Literal::BYTE
);
1723 const auto literal_value
= expr
.get_literal ();
1725 tree type
= TyTyResolveCompile::compile (ctx
, tyty
);
1726 char c
= literal_value
.as_string ().c_str ()[0];
1727 return build_int_cst (type
, c
);
1731 CompileExpr::compile_string_literal (const HIR::LiteralExpr
&expr
,
1732 const TyTy::BaseType
*tyty
)
1734 tree fat_pointer
= TyTyResolveCompile::compile (ctx
, tyty
);
1736 rust_assert (expr
.get_lit_type () == HIR::Literal::STRING
);
1737 const auto literal_value
= expr
.get_literal ();
1739 auto base
= Backend::string_constant_expression (literal_value
.as_string ());
1740 tree data
= address_expression (base
, expr
.get_locus ());
1742 TyTy::BaseType
*usize
= nullptr;
1743 bool ok
= ctx
->get_tyctx ()->lookup_builtin ("usize", &usize
);
1745 tree type
= TyTyResolveCompile::compile (ctx
, usize
);
1747 tree size
= build_int_cstu (type
, literal_value
.as_string ().size ());
1749 return Backend::constructor_expression (fat_pointer
, false, {data
, size
}, -1,
1754 CompileExpr::compile_byte_string_literal (const HIR::LiteralExpr
&expr
,
1755 const TyTy::BaseType
*tyty
)
1757 rust_assert (expr
.get_lit_type () == HIR::Literal::BYTE_STRING
);
1759 // the type here is &[ty; capacity]
1760 rust_assert (tyty
->get_kind () == TyTy::TypeKind::REF
);
1761 const auto ref_tyty
= static_cast<const TyTy::ReferenceType
*> (tyty
);
1762 auto base_tyty
= ref_tyty
->get_base ();
1763 rust_assert (base_tyty
->get_kind () == TyTy::TypeKind::ARRAY
);
1764 auto array_tyty
= static_cast<TyTy::ArrayType
*> (base_tyty
);
1766 std::string value_str
= expr
.get_literal ().as_string ();
1767 std::vector
<tree
> vals
;
1768 std::vector
<unsigned long> indexes
;
1769 for (size_t i
= 0; i
< value_str
.size (); i
++)
1771 char b
= value_str
.at (i
);
1772 tree bb
= Backend::char_constant_expression (b
);
1773 vals
.push_back (bb
);
1774 indexes
.push_back (i
);
1777 tree array_type
= TyTyResolveCompile::compile (ctx
, array_tyty
);
1779 = Backend::array_constructor_expression (array_type
, indexes
, vals
,
1782 return address_expression (constructed
, expr
.get_locus ());
1786 CompileExpr::type_cast_expression (tree type_to_cast_to
, tree expr_tree
,
1787 location_t location
)
1789 if (type_to_cast_to
== error_mark_node
|| expr_tree
== error_mark_node
1790 || TREE_TYPE (expr_tree
) == error_mark_node
)
1791 return error_mark_node
;
1793 if (Backend::type_size (type_to_cast_to
) == 0
1794 || TREE_TYPE (expr_tree
) == void_type_node
)
1796 // Do not convert zero-sized types.
1799 else if (TREE_CODE (type_to_cast_to
) == INTEGER_TYPE
)
1801 tree cast
= convert_to_integer (type_to_cast_to
, expr_tree
);
1802 // FIXME check for TREE_OVERFLOW?
1805 else if (TREE_CODE (type_to_cast_to
) == REAL_TYPE
)
1807 tree cast
= convert_to_real (type_to_cast_to
, expr_tree
);
1809 // We might need to check that the tree is MAX val and thusly saturate it
1810 // to inf. we can get the bounds and check the value if its >= or <= to
1811 // the min and max bounds
1813 // https://github.com/Rust-GCC/gccrs/issues/635
1816 else if (TREE_CODE (type_to_cast_to
) == COMPLEX_TYPE
)
1818 return convert_to_complex (type_to_cast_to
, expr_tree
);
1820 else if (TREE_CODE (type_to_cast_to
) == POINTER_TYPE
1821 && TREE_CODE (TREE_TYPE (expr_tree
)) == INTEGER_TYPE
)
1823 return convert_to_pointer (type_to_cast_to
, expr_tree
);
1825 else if (TREE_CODE (type_to_cast_to
) == RECORD_TYPE
1826 || TREE_CODE (type_to_cast_to
) == ARRAY_TYPE
)
1828 return fold_build1_loc (location
, VIEW_CONVERT_EXPR
, type_to_cast_to
,
1831 else if (TREE_CODE (type_to_cast_to
) == POINTER_TYPE
1832 && RS_DST_FLAG (TREE_TYPE (expr_tree
)))
1834 // returning a raw cast using NOP_EXPR seems to resut in an ICE:
1836 // Analyzing compilation unit
1837 // Performing interprocedural optimizations
1838 // <*free_lang_data> {heap 2644k} <visibility> {heap 2644k}
1839 // <build_ssa_passes> {heap 2644k} <opt_local_passes> {heap 2644k}during
1840 // GIMPLE pass: cddce
1841 // In function ‘*T::as_ptr<i32>’:
1842 // rust1: internal compiler error: in propagate_necessity, at
1843 // tree-ssa-dce.cc:984 0x1d5b43e propagate_necessity
1844 // ../../gccrs/gcc/tree-ssa-dce.cc:984
1845 // 0x1d5e180 perform_tree_ssa_dce
1846 // ../../gccrs/gcc/tree-ssa-dce.cc:1876
1847 // 0x1d5e2c8 tree_ssa_cd_dce
1848 // ../../gccrs/gcc/tree-ssa-dce.cc:1920
1849 // 0x1d5e49a execute
1850 // ../../gccrs/gcc/tree-ssa-dce.cc:1992
1852 // this is returning the direct raw pointer of the slice an assumes a very
1854 return Backend::struct_field_expression (expr_tree
, 0, location
);
1857 return fold_convert_loc (location
, type_to_cast_to
, expr_tree
);
1861 CompileExpr::visit (HIR::ArrayExpr
&expr
)
1863 TyTy::BaseType
*tyty
= nullptr;
1864 if (!ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (),
1867 rust_fatal_error (expr
.get_locus (),
1868 "did not resolve type for this array expr");
1872 tree array_type
= TyTyResolveCompile::compile (ctx
, tyty
);
1873 if (TREE_CODE (array_type
) != ARRAY_TYPE
)
1875 translated
= error_mark_node
;
1879 rust_assert (tyty
->get_kind () == TyTy::TypeKind::ARRAY
);
1880 const TyTy::ArrayType
&array_tyty
1881 = static_cast<const TyTy::ArrayType
&> (*tyty
);
1883 HIR::ArrayElems
&elements
= expr
.get_internal_elements ();
1884 switch (elements
.get_array_expr_type ())
1886 case HIR::ArrayElems::ArrayExprType::VALUES
: {
1887 HIR::ArrayElemsValues
&elems
1888 = static_cast<HIR::ArrayElemsValues
&> (elements
);
1890 = array_value_expr (expr
.get_locus (), array_tyty
, array_type
, elems
);
1894 case HIR::ArrayElems::ArrayExprType::COPIED
:
1895 HIR::ArrayElemsCopied
&elems
1896 = static_cast<HIR::ArrayElemsCopied
&> (elements
);
1898 = array_copied_expr (expr
.get_locus (), array_tyty
, array_type
, elems
);
1903 CompileExpr::array_value_expr (location_t expr_locus
,
1904 const TyTy::ArrayType
&array_tyty
,
1905 tree array_type
, HIR::ArrayElemsValues
&elems
)
1907 std::vector
<unsigned long> indexes
;
1908 std::vector
<tree
> constructor
;
1910 for (auto &elem
: elems
.get_values ())
1912 tree translated_expr
= CompileExpr::Compile (*elem
, ctx
);
1913 if (translated_expr
== error_mark_node
)
1915 rich_location
r (line_table
, expr_locus
);
1916 r
.add_fixit_replace (elem
->get_locus (), "not a value");
1917 rust_error_at (r
, ErrorCode::E0423
, "expected value");
1918 return error_mark_node
;
1921 constructor
.push_back (translated_expr
);
1922 indexes
.push_back (i
++);
1925 return Backend::array_constructor_expression (array_type
, indexes
,
1926 constructor
, expr_locus
);
1930 CompileExpr::array_copied_expr (location_t expr_locus
,
1931 const TyTy::ArrayType
&array_tyty
,
1932 tree array_type
, HIR::ArrayElemsCopied
&elems
)
1934 // see gcc/cp/typeck2.cc:1369-1401
1935 gcc_assert (TREE_CODE (array_type
) == ARRAY_TYPE
);
1936 tree domain
= TYPE_DOMAIN (array_type
);
1938 return error_mark_node
;
1940 if (!TREE_CONSTANT (TYPE_MAX_VALUE (domain
)))
1942 rust_error_at (expr_locus
, "non const capacity domain %qT", array_type
);
1943 return error_mark_node
;
1946 ctx
->push_const_context ();
1947 tree capacity_expr
= CompileExpr::Compile (elems
.get_num_copies_expr (), ctx
);
1948 ctx
->pop_const_context ();
1950 if (!TREE_CONSTANT (capacity_expr
))
1952 rust_error_at (expr_locus
, "non const num copies %qT", array_type
);
1953 return error_mark_node
;
1956 // get the compiled value
1957 tree translated_expr
= CompileExpr::Compile (elems
.get_elem_to_copy (), ctx
);
1959 tree max_domain
= TYPE_MAX_VALUE (domain
);
1960 tree min_domain
= TYPE_MIN_VALUE (domain
);
1962 auto max
= wi::to_offset (max_domain
);
1963 auto min
= wi::to_offset (min_domain
);
1964 auto precision
= TYPE_PRECISION (TREE_TYPE (domain
));
1965 auto sign
= TYPE_SIGN (TREE_TYPE (domain
));
1966 unsigned HOST_WIDE_INT len
1967 = wi::ext (max
- min
+ 1, precision
, sign
).to_uhwi ();
1969 // In a const context we must initialize the entire array, which entails
1970 // allocating for each element. If the user wants a huge array, we will OOM
1971 // and die horribly.
1972 if (ctx
->const_context_p ())
1976 std::vector
<unsigned long> indexes
;
1977 std::vector
<tree
> constructor
;
1979 indexes
.reserve (len
);
1980 constructor
.reserve (len
);
1981 for (unsigned HOST_WIDE_INT i
= 0; i
< len
; i
++)
1983 constructor
.push_back (translated_expr
);
1984 indexes
.push_back (idx
++);
1987 return Backend::array_constructor_expression (array_type
, indexes
,
1988 constructor
, expr_locus
);
1993 // Create a new block scope in which to initialize the array
1994 tree fndecl
= NULL_TREE
;
1996 fndecl
= ctx
->peek_fn ().fndecl
;
1998 std::vector
<Bvariable
*> locals
;
1999 tree enclosing_scope
= ctx
->peek_enclosing_scope ();
2000 tree init_block
= Backend::block (fndecl
, enclosing_scope
, locals
,
2001 expr_locus
, expr_locus
);
2002 ctx
->push_block (init_block
);
2005 tree stmts
= Backend::array_initializer (fndecl
, init_block
, array_type
,
2006 capacity_expr
, translated_expr
,
2008 ctx
->add_statement (stmts
);
2010 tree block
= ctx
->pop_block ();
2012 // The result is a compound expression which creates a temporary array,
2013 // initializes all the elements in a loop, and then yeilds the array.
2014 return Backend::compound_expression (block
, tmp
, expr_locus
);
2019 HIRCompileBase::resolve_adjustements (
2020 std::vector
<Resolver::Adjustment
> &adjustments
, tree expression
,
2023 tree e
= expression
;
2024 for (auto &adjustment
: adjustments
)
2026 if (e
== error_mark_node
)
2027 return error_mark_node
;
2029 switch (adjustment
.get_type ())
2031 case Resolver::Adjustment::AdjustmentType::ERROR
:
2032 return error_mark_node
;
2034 case Resolver::Adjustment::AdjustmentType::IMM_REF
:
2035 case Resolver::Adjustment::AdjustmentType::MUT_REF
: {
2036 if (!RS_DST_FLAG (TREE_TYPE (e
)))
2038 e
= address_expression (e
, locus
);
2043 case Resolver::Adjustment::AdjustmentType::DEREF
:
2044 case Resolver::Adjustment::AdjustmentType::DEREF_MUT
:
2045 e
= resolve_deref_adjustment (adjustment
, e
, locus
);
2048 case Resolver::Adjustment::AdjustmentType::INDIRECTION
:
2049 e
= resolve_indirection_adjustment (adjustment
, e
, locus
);
2052 case Resolver::Adjustment::AdjustmentType::UNSIZE
:
2053 e
= resolve_unsized_adjustment (adjustment
, e
, locus
);
2062 HIRCompileBase::resolve_deref_adjustment (Resolver::Adjustment
&adjustment
,
2063 tree expression
, location_t locus
)
2065 rust_assert (adjustment
.is_deref_adjustment ()
2066 || adjustment
.is_deref_mut_adjustment ());
2067 rust_assert (adjustment
.has_operator_overload ());
2069 TyTy::FnType
*lookup
= adjustment
.get_deref_operator_fn ();
2070 TyTy::BaseType
*receiver
= adjustment
.get_actual ();
2071 tree fn_address
= resolve_method_address (lookup
, receiver
, locus
);
2073 // does it need a reference to call
2074 tree adjusted_argument
= expression
;
2075 bool needs_borrow
= adjustment
.get_deref_adjustment_type ()
2076 != Resolver::Adjustment::AdjustmentType::ERROR
;
2079 adjusted_argument
= address_expression (expression
, locus
);
2083 return Backend::call_expression (fn_address
, {adjusted_argument
}, nullptr,
2088 HIRCompileBase::resolve_indirection_adjustment (
2089 Resolver::Adjustment
&adjustment
, tree expression
, location_t locus
)
2091 return indirect_expression (expression
, locus
);
2095 HIRCompileBase::resolve_unsized_adjustment (Resolver::Adjustment
&adjustment
,
2096 tree expression
, location_t locus
)
2099 = adjustment
.get_expected ()->get_kind () == TyTy::TypeKind::SLICE
;
2101 = adjustment
.get_expected ()->get_kind () == TyTy::TypeKind::DYNAMIC
;
2103 // assumes this is an array
2104 tree expr_type
= TREE_TYPE (expression
);
2107 rust_assert (TREE_CODE (expr_type
) == ARRAY_TYPE
);
2108 return resolve_unsized_slice_adjustment (adjustment
, expression
, locus
);
2111 rust_assert (expect_dyn
);
2112 return resolve_unsized_dyn_adjustment (adjustment
, expression
, locus
);
2116 HIRCompileBase::resolve_unsized_slice_adjustment (
2117 Resolver::Adjustment
&adjustment
, tree expression
, location_t locus
)
2119 // assumes this is an array
2120 tree expr_type
= TREE_TYPE (expression
);
2121 rust_assert (TREE_CODE (expr_type
) == ARRAY_TYPE
);
2123 // takes an array and returns a fat-pointer so this becomes a constructor
2125 rust_assert (adjustment
.get_expected ()->get_kind ()
2126 == TyTy::TypeKind::SLICE
);
2128 = TyTyResolveCompile::compile (ctx
, adjustment
.get_expected ());
2130 // make a constructor for this
2131 tree data
= address_expression (expression
, locus
);
2133 // fetch the size from the domain
2134 tree domain
= TYPE_DOMAIN (expr_type
);
2135 unsigned HOST_WIDE_INT array_size
2136 = wi::ext (wi::to_offset (TYPE_MAX_VALUE (domain
))
2137 - wi::to_offset (TYPE_MIN_VALUE (domain
)) + 1,
2138 TYPE_PRECISION (TREE_TYPE (domain
)),
2139 TYPE_SIGN (TREE_TYPE (domain
)))
2141 tree size
= build_int_cstu (size_type_node
, array_size
);
2143 return Backend::constructor_expression (fat_pointer
, false, {data
, size
}, -1,
2148 HIRCompileBase::resolve_unsized_dyn_adjustment (
2149 Resolver::Adjustment
&adjustment
, tree expression
, location_t locus
)
2151 tree rvalue
= expression
;
2152 location_t rvalue_locus
= locus
;
2154 const TyTy::BaseType
*actual
= adjustment
.get_actual ();
2155 const TyTy::BaseType
*expected
= adjustment
.get_expected ();
2157 const TyTy::DynamicObjectType
*dyn
2158 = static_cast<const TyTy::DynamicObjectType
*> (expected
);
2160 rust_debug ("resolve_unsized_dyn_adjustment actual={%s} dyn={%s}",
2161 actual
->debug_str ().c_str (), dyn
->debug_str ().c_str ());
2163 return coerce_to_dyn_object (rvalue
, actual
, dyn
, rvalue_locus
);
2167 CompileExpr::visit (HIR::RangeFromToExpr
&expr
)
2169 tree from
= CompileExpr::Compile (expr
.get_from_expr (), ctx
);
2170 tree to
= CompileExpr::Compile (expr
.get_to_expr (), ctx
);
2171 if (from
== error_mark_node
|| to
== error_mark_node
)
2173 translated
= error_mark_node
;
2177 TyTy::BaseType
*tyty
= nullptr;
2179 = ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (), &tyty
);
2182 tree adt
= TyTyResolveCompile::compile (ctx
, tyty
);
2184 // make the constructor
2185 translated
= Backend::constructor_expression (adt
, false, {from
, to
}, -1,
2190 CompileExpr::visit (HIR::RangeFromExpr
&expr
)
2192 tree from
= CompileExpr::Compile (expr
.get_from_expr (), ctx
);
2193 if (from
== error_mark_node
)
2195 translated
= error_mark_node
;
2199 TyTy::BaseType
*tyty
= nullptr;
2201 = ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (), &tyty
);
2204 tree adt
= TyTyResolveCompile::compile (ctx
, tyty
);
2206 // make the constructor
2207 translated
= Backend::constructor_expression (adt
, false, {from
}, -1,
2212 CompileExpr::visit (HIR::RangeToExpr
&expr
)
2214 tree to
= CompileExpr::Compile (expr
.get_to_expr (), ctx
);
2215 if (to
== error_mark_node
)
2217 translated
= error_mark_node
;
2221 TyTy::BaseType
*tyty
= nullptr;
2223 = ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (), &tyty
);
2226 tree adt
= TyTyResolveCompile::compile (ctx
, tyty
);
2228 // make the constructor
2230 = Backend::constructor_expression (adt
, false, {to
}, -1, expr
.get_locus ());
2234 CompileExpr::visit (HIR::RangeFullExpr
&expr
)
2236 TyTy::BaseType
*tyty
= nullptr;
2238 = ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (), &tyty
);
2241 tree adt
= TyTyResolveCompile::compile (ctx
, tyty
);
2243 = Backend::constructor_expression (adt
, false, {}, -1, expr
.get_locus ());
2247 CompileExpr::visit (HIR::RangeFromToInclExpr
&expr
)
2249 tree from
= CompileExpr::Compile (expr
.get_from_expr (), ctx
);
2250 tree to
= CompileExpr::Compile (expr
.get_to_expr (), ctx
);
2251 if (from
== error_mark_node
|| to
== error_mark_node
)
2253 translated
= error_mark_node
;
2257 TyTy::BaseType
*tyty
= nullptr;
2259 = ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (), &tyty
);
2262 tree adt
= TyTyResolveCompile::compile (ctx
, tyty
);
2264 // make the constructor
2265 translated
= Backend::constructor_expression (adt
, false, {from
, to
}, -1,
2270 CompileExpr::visit (HIR::ArrayIndexExpr
&expr
)
2272 tree array_reference
= CompileExpr::Compile (expr
.get_array_expr (), ctx
);
2273 tree index
= CompileExpr::Compile (expr
.get_index_expr (), ctx
);
2275 // this might be an core::ops::index lang item situation
2276 TyTy::FnType
*fntype
;
2277 bool is_op_overload
= ctx
->get_tyctx ()->lookup_operator_overload (
2278 expr
.get_mappings ().get_hirid (), &fntype
);
2281 auto lang_item_type
= LangItem::Kind::INDEX
;
2282 tree operator_overload_call
2283 = resolve_operator_overload (lang_item_type
, expr
, array_reference
,
2284 index
, expr
.get_array_expr (),
2285 expr
.get_index_expr ());
2287 tree actual_type
= TREE_TYPE (operator_overload_call
);
2288 bool can_indirect
= TYPE_PTR_P (actual_type
) || TYPE_REF_P (actual_type
);
2292 translated
= operator_overload_call
;
2296 // rust deref always returns a reference from this overload then we can
2297 // actually do the indirection
2299 = indirect_expression (operator_overload_call
, expr
.get_locus ());
2303 // lets check if the array is a reference type then we can add an
2304 // indirection if required
2305 TyTy::BaseType
*array_expr_ty
= nullptr;
2306 bool ok
= ctx
->get_tyctx ()->lookup_type (
2307 expr
.get_array_expr ().get_mappings ().get_hirid (), &array_expr_ty
);
2310 // do we need to add an indirect reference
2311 if (array_expr_ty
->get_kind () == TyTy::TypeKind::REF
)
2314 = indirect_expression (array_reference
, expr
.get_locus ());
2317 translated
= Backend::array_index_expression (array_reference
, index
,
2322 CompileExpr::visit (HIR::ClosureExpr
&expr
)
2324 TyTy::BaseType
*closure_expr_ty
= nullptr;
2325 if (!ctx
->get_tyctx ()->lookup_type (expr
.get_mappings ().get_hirid (),
2328 rust_fatal_error (expr
.get_locus (),
2329 "did not resolve type for this ClosureExpr");
2332 rust_assert (closure_expr_ty
->get_kind () == TyTy::TypeKind::CLOSURE
);
2333 TyTy::ClosureType
*closure_tyty
2334 = static_cast<TyTy::ClosureType
*> (closure_expr_ty
);
2335 tree compiled_closure_tyty
= TyTyResolveCompile::compile (ctx
, closure_tyty
);
2337 // generate closure function
2338 generate_closure_function (expr
, *closure_tyty
, compiled_closure_tyty
);
2340 // lets ignore state capture for now we need to instantiate the struct anyway
2341 // then generate the function
2342 std::vector
<tree
> vals
;
2343 for (const auto &capture
: closure_tyty
->get_captures ())
2346 if (auto hid
= ctx
->get_mappings ().lookup_node_to_hir (capture
))
2348 // lookup the var decl
2349 Bvariable
*var
= nullptr;
2350 bool found
= ctx
->lookup_var_decl (*hid
, &var
);
2351 rust_assert (found
);
2354 // this should bes based on the closure move-ability
2355 tree var_expr
= var
->get_tree (expr
.get_locus ());
2356 tree val
= address_expression (var_expr
, expr
.get_locus ());
2357 vals
.push_back (val
);
2360 rust_unreachable ();
2363 translated
= Backend::constructor_expression (compiled_closure_tyty
, false,
2364 vals
, -1, expr
.get_locus ());
2368 CompileExpr::generate_closure_function (HIR::ClosureExpr
&expr
,
2369 TyTy::ClosureType
&closure_tyty
,
2370 tree compiled_closure_tyty
)
2372 TyTy::FnType
*fn_tyty
= nullptr;
2373 tree compiled_fn_type
2374 = generate_closure_fntype (expr
, closure_tyty
, compiled_closure_tyty
,
2376 if (compiled_fn_type
== error_mark_node
)
2377 return error_mark_node
;
2379 const Resolver::CanonicalPath
&parent_canonical_path
2380 = closure_tyty
.get_ident ().path
;
2382 tl::optional
<NodeId
> nid
= ctx
->get_mappings ().lookup_hir_to_node (
2383 expr
.get_mappings ().get_hirid ());
2384 rust_assert (nid
.has_value ());
2385 auto node_id
= nid
.value ();
2387 Resolver::CanonicalPath path
= parent_canonical_path
.append (
2388 Resolver::CanonicalPath::new_seg (node_id
, "{{closure}}"));
2390 std::string ir_symbol_name
= path
.get ();
2391 std::string asm_name
= ctx
->mangle_item (&closure_tyty
, path
);
2393 unsigned int flags
= 0;
2394 tree fndecl
= Backend::function (compiled_fn_type
, ir_symbol_name
, asm_name
,
2395 flags
, expr
.get_locus ());
2397 // insert into the context
2398 ctx
->insert_function_decl (fn_tyty
, fndecl
);
2399 ctx
->insert_closure_decl (&closure_tyty
, fndecl
);
2401 // setup the parameters
2402 std::vector
<Bvariable
*> param_vars
;
2405 Bvariable
*self_param
2406 = Backend::parameter_variable (fndecl
, "$closure", compiled_closure_tyty
,
2408 DECL_ARTIFICIAL (self_param
->get_decl ()) = 1;
2409 param_vars
.push_back (self_param
);
2411 // push a new context
2412 ctx
->push_closure_context (expr
.get_mappings ().get_hirid ());
2414 // setup the implicit argument captures
2416 for (const auto &capture
: closure_tyty
.get_captures ())
2419 if (auto hid
= ctx
->get_mappings ().lookup_node_to_hir (capture
))
2422 tree binding
= Backend::struct_field_expression (
2423 self_param
->get_tree (expr
.get_locus ()), idx
, expr
.get_locus ());
2424 tree indirection
= indirect_expression (binding
, expr
.get_locus ());
2427 ctx
->insert_closure_binding (*hid
, indirection
);
2433 rust_unreachable ();
2438 = TyTyResolveCompile::compile (ctx
, &closure_tyty
.get_parameters ());
2439 Bvariable
*args_param
2440 = Backend::parameter_variable (fndecl
, "args", args_type
,
2442 param_vars
.push_back (args_param
);
2444 // setup the implicit mappings for the arguments. Since argument passing to
2445 // closure functions is done via passing a tuple but the closure body expects
2446 // just normal arguments this means we need to destructure them similar to
2447 // what we do in MatchExpr's. This means when we have a closure-param of a we
2448 // actually setup the destructure to take from the args tuple
2450 tree args_param_expr
= args_param
->get_tree (expr
.get_locus ());
2452 for (auto &closure_param
: expr
.get_params ())
2454 tree compiled_param_var
2455 = Backend::struct_field_expression (args_param_expr
, i
,
2456 closure_param
.get_locus ());
2458 CompilePatternBindings::Compile (closure_param
.get_pattern (),
2459 compiled_param_var
, ctx
);
2463 if (!Backend::function_set_parameters (fndecl
, param_vars
))
2465 ctx
->pop_closure_context ();
2466 return error_mark_node
;
2470 HIR::Expr
&function_body
= expr
.get_expr ();
2472 = function_body
.get_expression_type () == HIR::Expr::ExprType::Block
;
2476 auto body_mappings
= function_body
.get_mappings ();
2477 if (flag_name_resolution_2_0
)
2480 = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
2482 auto candidate
= nr_ctx
.values
.to_rib (body_mappings
.get_nodeid ());
2484 rust_assert (candidate
.has_value ());
2488 Resolver::Rib
*rib
= nullptr;
2490 = ctx
->get_resolver ()->find_name_rib (body_mappings
.get_nodeid (),
2496 tree enclosing_scope
= NULL_TREE
;
2497 location_t start_location
= function_body
.get_locus ();
2498 location_t end_location
= function_body
.get_locus ();
2501 auto &body
= static_cast<HIR::BlockExpr
&> (function_body
);
2502 start_location
= body
.get_locus ();
2503 end_location
= body
.get_end_locus ();
2506 tree code_block
= Backend::block (fndecl
, enclosing_scope
, {} /*locals*/,
2507 start_location
, end_location
);
2508 ctx
->push_block (code_block
);
2510 TyTy::BaseType
*tyret
= &closure_tyty
.get_result_type ();
2511 Bvariable
*return_address
= nullptr;
2513 tree return_type
= TyTyResolveCompile::compile (ctx
, tyret
);
2514 bool address_is_taken
= false;
2515 tree ret_var_stmt
= NULL_TREE
;
2518 = Backend::temporary_variable (fndecl
, code_block
, return_type
, NULL
,
2519 address_is_taken
, expr
.get_locus (),
2522 ctx
->add_statement (ret_var_stmt
);
2524 ctx
->push_fn (fndecl
, return_address
, tyret
);
2528 auto &body
= static_cast<HIR::BlockExpr
&> (function_body
);
2529 compile_function_body (fndecl
, body
, tyret
);
2533 tree value
= CompileExpr::Compile (function_body
, ctx
);
2535 = Backend::return_statement (fndecl
, value
, function_body
.get_locus ());
2536 ctx
->add_statement (return_expr
);
2539 tree bind_tree
= ctx
->pop_block ();
2541 gcc_assert (TREE_CODE (bind_tree
) == BIND_EXPR
);
2542 DECL_SAVED_TREE (fndecl
) = bind_tree
;
2544 ctx
->pop_closure_context ();
2546 ctx
->push_function (fndecl
);
2552 CompileExpr::generate_closure_fntype (HIR::ClosureExpr
&expr
,
2553 const TyTy::ClosureType
&closure_tyty
,
2554 tree compiled_closure_tyty
,
2555 TyTy::FnType
**fn_tyty
)
2557 // grab the specified_bound
2558 rust_assert (closure_tyty
.num_specified_bounds () == 1);
2559 const TyTy::TypeBoundPredicate
&predicate
2560 = *closure_tyty
.get_specified_bounds ().begin ();
2562 // ensure the fn_once_output associated type is set
2563 closure_tyty
.setup_fn_once_output ();
2565 // the function signature is based on the trait bound that the closure
2566 // implements which is determined at the type resolution time
2568 // https://github.com/rust-lang/rust/blob/7807a694c2f079fd3f395821bcc357eee8650071/library/core/src/ops/function.rs#L54-L71
2570 TyTy::TypeBoundPredicateItem item
= TyTy::TypeBoundPredicateItem::error ();
2571 if (predicate
.get_name ().compare ("FnOnce") == 0)
2573 item
= predicate
.lookup_associated_item ("call_once");
2575 else if (predicate
.get_name ().compare ("FnMut") == 0)
2577 item
= predicate
.lookup_associated_item ("call_mut");
2579 else if (predicate
.get_name ().compare ("Fn") == 0)
2581 item
= predicate
.lookup_associated_item ("call");
2585 // FIXME error message?
2586 rust_unreachable ();
2587 return error_mark_node
;
2590 rust_assert (!item
.is_error ());
2592 TyTy::BaseType
*item_tyty
= item
.get_tyty_for_receiver (&closure_tyty
);
2593 rust_assert (item_tyty
->get_kind () == TyTy::TypeKind::FNDEF
);
2594 *fn_tyty
= static_cast<TyTy::FnType
*> (item_tyty
);
2595 return TyTyResolveCompile::compile (ctx
, item_tyty
);
2599 CompileExpr::generate_possible_fn_trait_call (HIR::CallExpr
&expr
,
2600 tree receiver
, tree
*result
)
2602 TyTy::FnType
*fn_sig
= nullptr;
2603 bool found_overload
= ctx
->get_tyctx ()->lookup_operator_overload (
2604 expr
.get_mappings ().get_hirid (), &fn_sig
);
2605 if (!found_overload
)
2608 auto id
= fn_sig
->get_ty_ref ();
2609 auto dId
= fn_sig
->get_id ();
2611 tree function
= error_mark_node
;
2612 bool found_closure
= ctx
->lookup_function_decl (id
, &function
, dId
, fn_sig
);
2615 // something went wrong we still return true as this was meant to be an fn
2617 *result
= error_mark_node
;
2621 // need to apply any autoderef's to the self argument
2622 HIR::Expr
&fnexpr
= expr
.get_fnexpr ();
2623 HirId autoderef_mappings_id
= fnexpr
.get_mappings ().get_hirid ();
2624 std::vector
<Resolver::Adjustment
> *adjustments
= nullptr;
2625 bool ok
= ctx
->get_tyctx ()->lookup_autoderef_mappings (autoderef_mappings_id
,
2629 // apply adjustments for the fn call
2630 tree self
= resolve_adjustements (*adjustments
, receiver
, expr
.get_locus ());
2632 // resolve the arguments
2633 std::vector
<tree
> tuple_arg_vals
;
2634 for (auto &argument
: expr
.get_arguments ())
2636 auto rvalue
= CompileExpr::Compile (*argument
, ctx
);
2637 tuple_arg_vals
.push_back (rvalue
);
2640 // this is always the 2nd argument in the function signature
2641 tree fnty
= TREE_TYPE (function
);
2642 tree fn_arg_tys
= TYPE_ARG_TYPES (fnty
);
2643 tree tuple_args_tyty_chain
= TREE_CHAIN (fn_arg_tys
);
2644 tree tuple_args_tyty
= TREE_VALUE (tuple_args_tyty_chain
);
2647 = Backend::constructor_expression (tuple_args_tyty
, false, tuple_arg_vals
,
2648 -1, expr
.get_locus ());
2650 // args are always self, and the tuple of the args we are passing where
2651 // self is the path of the call-expr in this case the fn_address
2652 std::vector
<tree
> args
;
2653 args
.push_back (self
);
2654 args
.push_back (tuple_args
);
2656 tree call_address
= address_expression (function
, expr
.get_locus ());
2658 = Backend::call_expression (call_address
, args
, nullptr /* static chain ?*/,
2663 } // namespace Compile