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