Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 Free Software Foundation, Inc.
2 : :
3 : : // This file is part of GCC.
4 : :
5 : : // GCC is free software; you can redistribute it and/or modify it under
6 : : // the terms of the GNU General Public License as published by the Free
7 : : // Software Foundation; either version 3, or (at your option) any later
8 : : // version.
9 : :
10 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : : // for more details.
14 : :
15 : : // You should have received a copy of the GNU General Public License
16 : : // along with GCC; see the file COPYING3. If not see
17 : : // <http://www.gnu.org/licenses/>.
18 : :
19 : : #include "rust-compile-pattern.h"
20 : : #include "rust-compile-expr.h"
21 : : #include "rust-compile-resolve-path.h"
22 : : #include "rust-constexpr.h"
23 : : #include "rust-compile-type.h"
24 : : #include "print-tree.h"
25 : :
26 : : namespace Rust {
27 : : namespace Compile {
28 : :
29 : : void
30 : 294 : CompilePatternCheckExpr::visit (HIR::PathInExpression &pattern)
31 : : {
32 : : // lookup the type
33 : 294 : TyTy::BaseType *lookup = nullptr;
34 : 294 : bool ok
35 : 294 : = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (),
36 : : &lookup);
37 : 294 : rust_assert (ok);
38 : :
39 : : // must be an ADT (?)
40 : 294 : rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
41 : 294 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
42 : :
43 : : // if this isn't an enum, always succeed
44 : 294 : if (!adt->is_enum ())
45 : : {
46 : 0 : check_expr = boolean_true_node;
47 : 0 : return;
48 : : }
49 : :
50 : : // lookup the variant
51 : 294 : HirId variant_id;
52 : 294 : ok = ctx->get_tyctx ()->lookup_variant_definition (
53 : 294 : pattern.get_mappings ().get_hirid (), &variant_id);
54 : 294 : rust_assert (ok);
55 : :
56 : 294 : TyTy::VariantDef *variant = nullptr;
57 : 294 : ok = adt->lookup_variant_by_id (variant_id, &variant);
58 : 294 : rust_assert (ok);
59 : :
60 : : // find discriminant field of scrutinee
61 : 294 : tree scrutinee_expr_qualifier_expr
62 : 294 : = Backend::struct_field_expression (match_scrutinee_expr, 0,
63 : : pattern.get_locus ());
64 : :
65 : : // must be enum
66 : 294 : match_scrutinee_expr = scrutinee_expr_qualifier_expr;
67 : :
68 : 294 : HIR::Expr &discrim_expr = variant->get_discriminant ();
69 : 294 : tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
70 : :
71 : 294 : check_expr
72 : 294 : = Backend::comparison_expression (ComparisonOperator::EQUAL,
73 : : match_scrutinee_expr, discrim_expr_node,
74 : : pattern.get_locus ());
75 : : }
76 : :
77 : : void
78 : 171 : CompilePatternCheckExpr::visit (HIR::LiteralPattern &pattern)
79 : : {
80 : : // Compile the literal
81 : 171 : auto litexpr = std::make_unique<HIR::LiteralExpr> (
82 : 342 : HIR::LiteralExpr (pattern.get_mappings (), pattern.get_literal (),
83 : 342 : pattern.get_locus (), std::vector<AST::Attribute> ()));
84 : :
85 : : // Note: Floating point literals are currently accepted but will likely be
86 : : // forbidden in LiteralPatterns in a future version of Rust.
87 : : // See: https://github.com/rust-lang/rust/issues/41620
88 : : // For now, we cannot compile them anyway as CASE_LABEL_EXPR does not support
89 : : // floating point types.
90 : 171 : if (pattern.get_literal ().get_lit_type () == HIR::Literal::LitType::FLOAT)
91 : : {
92 : 0 : rust_sorry_at (pattern.get_locus (), "floating-point literal in pattern");
93 : : }
94 : :
95 : 171 : tree lit = CompileExpr::Compile (*litexpr, ctx);
96 : :
97 : 171 : check_expr = Backend::comparison_expression (ComparisonOperator::EQUAL,
98 : : match_scrutinee_expr, lit,
99 : 171 : pattern.get_locus ());
100 : 171 : }
101 : :
102 : : static tree
103 : 42 : compile_range_pattern_bound (HIR::RangePatternBound &bound,
104 : : Analysis::NodeMapping mappings, location_t locus,
105 : : Context *ctx)
106 : : {
107 : 42 : tree result = NULL_TREE;
108 : 42 : switch (bound.get_bound_type ())
109 : : {
110 : 21 : case HIR::RangePatternBound::RangePatternBoundType::LITERAL: {
111 : 21 : auto &ref = static_cast<HIR::RangePatternBoundLiteral &> (bound);
112 : :
113 : 63 : HIR::LiteralExpr litexpr (mappings, ref.get_literal (), locus,
114 : 21 : std::vector<AST::Attribute> ());
115 : :
116 : 21 : result = CompileExpr::Compile (litexpr, ctx);
117 : 21 : }
118 : 21 : break;
119 : :
120 : 21 : case HIR::RangePatternBound::RangePatternBoundType::PATH: {
121 : 21 : auto &ref = static_cast<HIR::RangePatternBoundPath &> (bound);
122 : :
123 : 21 : result = ResolvePathRef::Compile (ref.get_path (), ctx);
124 : :
125 : : // If the path resolves to a const expression, fold it.
126 : 21 : result = fold_expr (result);
127 : : }
128 : 21 : break;
129 : :
130 : 0 : case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: {
131 : 0 : auto &ref = static_cast<HIR::RangePatternBoundQualPath &> (bound);
132 : :
133 : 0 : result = ResolvePathRef::Compile (ref.get_qualified_path (), ctx);
134 : :
135 : : // If the path resolves to a const expression, fold it.
136 : 0 : result = fold_expr (result);
137 : : }
138 : : }
139 : :
140 : 42 : return result;
141 : : }
142 : :
143 : : void
144 : 21 : CompilePatternCheckExpr::visit (HIR::RangePattern &pattern)
145 : : {
146 : 21 : tree upper = compile_range_pattern_bound (pattern.get_upper_bound (),
147 : 21 : pattern.get_mappings (),
148 : 21 : pattern.get_locus (), ctx);
149 : 63 : tree lower = compile_range_pattern_bound (pattern.get_lower_bound (),
150 : 21 : pattern.get_mappings (),
151 : 21 : pattern.get_locus (), ctx);
152 : :
153 : 21 : tree check_lower
154 : 21 : = Backend::comparison_expression (ComparisonOperator::GREATER_OR_EQUAL,
155 : : match_scrutinee_expr, lower,
156 : 21 : pattern.get_locus ());
157 : 21 : tree check_upper
158 : 21 : = Backend::comparison_expression (ComparisonOperator::LESS_OR_EQUAL,
159 : : match_scrutinee_expr, upper,
160 : 21 : pattern.get_locus ());
161 : 21 : check_expr = Backend::arithmetic_or_logical_expression (
162 : : ArithmeticOrLogicalOperator::BITWISE_AND, check_lower, check_upper,
163 : 21 : pattern.get_locus ());
164 : 21 : }
165 : :
166 : : void
167 : 37 : CompilePatternCheckExpr::visit (HIR::ReferencePattern &pattern)
168 : : {
169 : 37 : match_scrutinee_expr
170 : 37 : = indirect_expression (match_scrutinee_expr, pattern.get_locus ());
171 : 37 : pattern.get_referenced_pattern ().accept_vis (*this);
172 : 37 : }
173 : :
174 : : void
175 : 2 : CompilePatternCheckExpr::visit (HIR::AltPattern &pattern)
176 : : {
177 : 2 : auto &alts = pattern.get_alts ();
178 : :
179 : 2 : check_expr = CompilePatternCheckExpr::Compile (*alts.at (0),
180 : : match_scrutinee_expr, ctx);
181 : 2 : auto end = alts.end ();
182 : 6 : for (auto i = alts.begin () + 1; i != end; i++)
183 : : {
184 : 4 : tree next_expr
185 : 4 : = CompilePatternCheckExpr::Compile (**i, match_scrutinee_expr, ctx);
186 : 4 : check_expr = Backend::arithmetic_or_logical_expression (
187 : : ArithmeticOrLogicalOperator::BITWISE_OR, check_expr, next_expr,
188 : 4 : (*i)->get_locus ());
189 : : }
190 : 2 : }
191 : :
192 : : void
193 : 54 : CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
194 : : {
195 : : // lookup the type
196 : 54 : TyTy::BaseType *lookup = nullptr;
197 : 54 : bool ok = ctx->get_tyctx ()->lookup_type (
198 : 54 : pattern.get_path ().get_mappings ().get_hirid (), &lookup);
199 : 54 : rust_assert (ok);
200 : :
201 : : // this might be an enum
202 : 54 : rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
203 : 54 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
204 : :
205 : 54 : rust_assert (adt->number_of_variants () > 0);
206 : 54 : TyTy::VariantDef *variant = nullptr;
207 : 54 : if (adt->is_enum ())
208 : : {
209 : : // lookup the variant
210 : 47 : HirId variant_id;
211 : 47 : ok = ctx->get_tyctx ()->lookup_variant_definition (
212 : 47 : pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
213 : 47 : rust_assert (ok);
214 : :
215 : 47 : int variant_index = 0;
216 : 47 : ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
217 : 47 : rust_assert (ok);
218 : :
219 : : // find expected discriminant
220 : : // // need to access qualifier the field, if we use QUAL_UNION_TYPE this
221 : : // // would be DECL_QUALIFIER i think. For now this will just access the
222 : : // // first record field and its respective qualifier because it will
223 : : // // always be set because this is all a big special union
224 : 47 : HIR::Expr &discrim_expr = variant->get_discriminant ();
225 : 47 : tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
226 : :
227 : : // find discriminant field of scrutinee
228 : 47 : tree scrutinee_expr_qualifier_expr
229 : 47 : = Backend::struct_field_expression (match_scrutinee_expr, 0,
230 : 47 : pattern.get_path ().get_locus ());
231 : :
232 : 47 : check_expr
233 : 47 : = Backend::comparison_expression (ComparisonOperator::EQUAL,
234 : : scrutinee_expr_qualifier_expr,
235 : : discrim_expr_node,
236 : 47 : pattern.get_path ().get_locus ());
237 : :
238 : 47 : match_scrutinee_expr = scrutinee_expr_qualifier_expr;
239 : : }
240 : : else
241 : : {
242 : 7 : variant = adt->get_variants ().at (0);
243 : 7 : check_expr = boolean_true_node;
244 : : }
245 : :
246 : 54 : auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
247 : 148 : for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
248 : : {
249 : 94 : switch (field->get_item_type ())
250 : : {
251 : 0 : case HIR::StructPatternField::ItemType::TUPLE_PAT: {
252 : : // TODO
253 : 0 : rust_unreachable ();
254 : : }
255 : 0 : break;
256 : :
257 : 0 : case HIR::StructPatternField::ItemType::IDENT_PAT: {
258 : 0 : HIR::StructPatternFieldIdentPat &ident
259 : 0 : = static_cast<HIR::StructPatternFieldIdentPat &> (*field.get ());
260 : :
261 : 0 : size_t offs = 0;
262 : 0 : ok = variant->lookup_field (ident.get_identifier ().as_string (),
263 : : nullptr, &offs);
264 : 0 : rust_assert (ok);
265 : :
266 : : // we may be offsetting by + 1 here since the first field in the
267 : : // record is always the discriminator
268 : 0 : offs += adt->is_enum ();
269 : 0 : tree field_expr
270 : 0 : = Backend::struct_field_expression (match_scrutinee_expr, offs,
271 : : ident.get_locus ());
272 : :
273 : 0 : tree check_expr_sub
274 : 0 : = CompilePatternCheckExpr::Compile (ident.get_pattern (),
275 : : field_expr, ctx);
276 : 0 : check_expr = Backend::arithmetic_or_logical_expression (
277 : : ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
278 : 0 : check_expr_sub, ident.get_pattern ().get_locus ());
279 : : }
280 : 0 : break;
281 : :
282 : : case HIR::StructPatternField::ItemType::IDENT: {
283 : : // ident pattern always matches - do nothing
284 : : }
285 : : break;
286 : : }
287 : : }
288 : 54 : }
289 : :
290 : : void
291 : 254 : CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern)
292 : : {
293 : : // lookup the type
294 : 254 : TyTy::BaseType *lookup = nullptr;
295 : 254 : bool ok = ctx->get_tyctx ()->lookup_type (
296 : 254 : pattern.get_path ().get_mappings ().get_hirid (), &lookup);
297 : 254 : rust_assert (ok);
298 : :
299 : : // this might be an enum
300 : 254 : rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
301 : 254 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
302 : :
303 : 254 : int variant_index = 0;
304 : 254 : rust_assert (adt->number_of_variants () > 0);
305 : 254 : TyTy::VariantDef *variant = nullptr;
306 : 254 : if (adt->is_enum ())
307 : : {
308 : : // lookup the variant
309 : 254 : HirId variant_id;
310 : 254 : ok = ctx->get_tyctx ()->lookup_variant_definition (
311 : 254 : pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
312 : 254 : rust_assert (ok);
313 : :
314 : 254 : ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
315 : 254 : rust_assert (ok);
316 : :
317 : : // find expected discriminant
318 : 254 : HIR::Expr &discrim_expr = variant->get_discriminant ();
319 : 254 : tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
320 : :
321 : : // find discriminant field of scrutinee
322 : 254 : tree scrutinee_expr_qualifier_expr
323 : 254 : = Backend::struct_field_expression (match_scrutinee_expr, 0,
324 : 254 : pattern.get_path ().get_locus ());
325 : :
326 : 254 : check_expr
327 : 254 : = Backend::comparison_expression (ComparisonOperator::EQUAL,
328 : : scrutinee_expr_qualifier_expr,
329 : : discrim_expr_node,
330 : 254 : pattern.get_path ().get_locus ());
331 : : }
332 : : else
333 : : {
334 : 0 : variant = adt->get_variants ().at (0);
335 : 0 : check_expr = boolean_true_node;
336 : : }
337 : :
338 : 254 : HIR::TupleStructItems &items = pattern.get_items ();
339 : 254 : switch (items.get_item_type ())
340 : : {
341 : 0 : case HIR::TupleStructItems::RANGED: {
342 : : // TODO
343 : 0 : rust_unreachable ();
344 : : }
345 : 254 : break;
346 : :
347 : 254 : case HIR::TupleStructItems::MULTIPLE: {
348 : 254 : HIR::TupleStructItemsNoRange &items_no_range
349 : : = static_cast<HIR::TupleStructItemsNoRange &> (items);
350 : :
351 : 254 : rust_assert (items_no_range.get_patterns ().size ()
352 : : == variant->num_fields ());
353 : :
354 : 254 : size_t tuple_field_index = 0;
355 : 512 : for (auto &pattern : items_no_range.get_patterns ())
356 : : {
357 : : // find payload union field of scrutinee
358 : 258 : tree payload_ref
359 : 258 : = Backend::struct_field_expression (match_scrutinee_expr, 1,
360 : 258 : pattern->get_locus ());
361 : :
362 : 258 : tree variant_ref
363 : 258 : = Backend::struct_field_expression (payload_ref, variant_index,
364 : 258 : pattern->get_locus ());
365 : :
366 : 258 : tree field_expr
367 : 258 : = Backend::struct_field_expression (variant_ref,
368 : : tuple_field_index++,
369 : 258 : pattern->get_locus ());
370 : :
371 : 258 : tree check_expr_sub
372 : 258 : = CompilePatternCheckExpr::Compile (*pattern, field_expr, ctx);
373 : 258 : check_expr = Backend::arithmetic_or_logical_expression (
374 : : ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
375 : 258 : check_expr_sub, pattern->get_locus ());
376 : : }
377 : : }
378 : : break;
379 : : }
380 : 254 : }
381 : :
382 : : void
383 : 25 : CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern)
384 : : {
385 : 25 : check_expr = boolean_true_node;
386 : :
387 : 25 : switch (pattern.get_items ().get_item_type ())
388 : : {
389 : 0 : case HIR::TuplePatternItems::RANGED: {
390 : : // TODO
391 : 0 : gcc_unreachable ();
392 : : }
393 : 25 : break;
394 : :
395 : 25 : case HIR::TuplePatternItems::MULTIPLE: {
396 : 25 : auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
397 : 25 : pattern.get_items ());
398 : 25 : size_t tuple_field_index = 0;
399 : :
400 : 75 : for (auto &pat : items.get_patterns ())
401 : : {
402 : 50 : tree field_expr
403 : 50 : = Backend::struct_field_expression (match_scrutinee_expr,
404 : : tuple_field_index++,
405 : 50 : pat->get_locus ());
406 : :
407 : 50 : tree check_expr_sub
408 : 50 : = CompilePatternCheckExpr::Compile (*pat, field_expr, ctx);
409 : 50 : check_expr = Backend::arithmetic_or_logical_expression (
410 : : ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
411 : 50 : check_expr_sub, pat->get_locus ());
412 : : }
413 : : }
414 : : }
415 : 25 : }
416 : :
417 : : // setup the bindings
418 : :
419 : : void
420 : 268 : CompilePatternBindings::visit (HIR::TupleStructPattern &pattern)
421 : : {
422 : : // lookup the type
423 : 268 : TyTy::BaseType *lookup = nullptr;
424 : 268 : bool ok = ctx->get_tyctx ()->lookup_type (
425 : 268 : pattern.get_path ().get_mappings ().get_hirid (), &lookup);
426 : 268 : rust_assert (ok);
427 : :
428 : : // this must be an enum
429 : 268 : rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
430 : 268 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
431 : 268 : rust_assert (adt->number_of_variants () > 0);
432 : :
433 : 268 : int variant_index = 0;
434 : 268 : TyTy::VariantDef *variant = adt->get_variants ().at (0);
435 : 268 : if (adt->is_enum ())
436 : : {
437 : 254 : HirId variant_id = UNKNOWN_HIRID;
438 : 254 : bool ok = ctx->get_tyctx ()->lookup_variant_definition (
439 : 254 : pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
440 : 254 : rust_assert (ok);
441 : :
442 : 254 : ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
443 : 254 : rust_assert (ok);
444 : : }
445 : :
446 : 268 : rust_assert (variant->get_variant_type ()
447 : : == TyTy::VariantDef::VariantType::TUPLE);
448 : :
449 : 268 : HIR::TupleStructItems &items = pattern.get_items ();
450 : 268 : switch (items.get_item_type ())
451 : : {
452 : 0 : case HIR::TupleStructItems::RANGED: {
453 : : // TODO
454 : 0 : rust_unreachable ();
455 : : }
456 : 268 : break;
457 : :
458 : 268 : case HIR::TupleStructItems::MULTIPLE: {
459 : 268 : HIR::TupleStructItemsNoRange &items_no_range
460 : : = static_cast<HIR::TupleStructItemsNoRange &> (items);
461 : :
462 : 268 : rust_assert (items_no_range.get_patterns ().size ()
463 : : == variant->num_fields ());
464 : :
465 : 268 : if (adt->is_enum ())
466 : : {
467 : 254 : size_t tuple_field_index = 0;
468 : 512 : for (auto &pattern : items_no_range.get_patterns ())
469 : : {
470 : 258 : tree payload_accessor_union
471 : 258 : = Backend::struct_field_expression (match_scrutinee_expr, 1,
472 : 258 : pattern->get_locus ());
473 : :
474 : 258 : tree variant_accessor
475 : 258 : = Backend::struct_field_expression (payload_accessor_union,
476 : : variant_index,
477 : 258 : pattern->get_locus ());
478 : :
479 : 258 : tree binding
480 : 258 : = Backend::struct_field_expression (variant_accessor,
481 : : tuple_field_index++,
482 : 258 : pattern->get_locus ());
483 : :
484 : 258 : CompilePatternBindings::Compile (*pattern, binding, ctx);
485 : : }
486 : : }
487 : : else
488 : : {
489 : 14 : size_t tuple_field_index = 0;
490 : 35 : for (auto &pattern : items_no_range.get_patterns ())
491 : : {
492 : 21 : tree variant_accessor = match_scrutinee_expr;
493 : :
494 : 21 : tree binding
495 : 21 : = Backend::struct_field_expression (variant_accessor,
496 : : tuple_field_index++,
497 : 21 : pattern->get_locus ());
498 : :
499 : 21 : CompilePatternBindings::Compile (*pattern, binding, ctx);
500 : : }
501 : : }
502 : : }
503 : : break;
504 : : }
505 : 268 : }
506 : :
507 : : void
508 : 54 : CompilePatternBindings::visit (HIR::StructPattern &pattern)
509 : : {
510 : : // lookup the type
511 : 54 : TyTy::BaseType *lookup = nullptr;
512 : 54 : bool ok = ctx->get_tyctx ()->lookup_type (
513 : 54 : pattern.get_path ().get_mappings ().get_hirid (), &lookup);
514 : 54 : rust_assert (ok);
515 : :
516 : : // this must be an enum
517 : 54 : rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
518 : 54 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
519 : 54 : rust_assert (adt->number_of_variants () > 0);
520 : :
521 : 54 : int variant_index = 0;
522 : 54 : TyTy::VariantDef *variant = adt->get_variants ().at (0);
523 : 54 : if (adt->is_enum ())
524 : : {
525 : 47 : HirId variant_id = UNKNOWN_HIRID;
526 : 47 : bool ok = ctx->get_tyctx ()->lookup_variant_definition (
527 : 47 : pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
528 : 47 : rust_assert (ok);
529 : :
530 : 47 : ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
531 : 47 : rust_assert (ok);
532 : : }
533 : :
534 : 54 : rust_assert (variant->get_variant_type ()
535 : : == TyTy::VariantDef::VariantType::STRUCT);
536 : :
537 : 54 : auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
538 : 148 : for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
539 : : {
540 : 94 : switch (field->get_item_type ())
541 : : {
542 : 0 : case HIR::StructPatternField::ItemType::TUPLE_PAT: {
543 : : // TODO
544 : 0 : rust_unreachable ();
545 : : }
546 : 0 : break;
547 : :
548 : 0 : case HIR::StructPatternField::ItemType::IDENT_PAT: {
549 : : // TODO
550 : 0 : rust_unreachable ();
551 : : }
552 : 94 : break;
553 : :
554 : 94 : case HIR::StructPatternField::ItemType::IDENT: {
555 : 94 : HIR::StructPatternFieldIdent &ident
556 : 94 : = static_cast<HIR::StructPatternFieldIdent &> (*field.get ());
557 : :
558 : 94 : size_t offs = 0;
559 : 94 : ok = variant->lookup_field (ident.get_identifier ().as_string (),
560 : : nullptr, &offs);
561 : 94 : rust_assert (ok);
562 : :
563 : 94 : tree binding = error_mark_node;
564 : 94 : if (adt->is_enum ())
565 : : {
566 : 80 : tree payload_accessor_union
567 : 80 : = Backend::struct_field_expression (match_scrutinee_expr, 1,
568 : : ident.get_locus ());
569 : :
570 : 80 : tree variant_accessor
571 : 80 : = Backend::struct_field_expression (payload_accessor_union,
572 : : variant_index,
573 : : ident.get_locus ());
574 : :
575 : 80 : binding
576 : 80 : = Backend::struct_field_expression (variant_accessor, offs,
577 : : ident.get_locus ());
578 : : }
579 : : else
580 : : {
581 : 14 : tree variant_accessor = match_scrutinee_expr;
582 : 14 : binding
583 : 14 : = Backend::struct_field_expression (variant_accessor, offs,
584 : : ident.get_locus ());
585 : : }
586 : :
587 : 94 : ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (),
588 : : binding);
589 : : }
590 : 94 : break;
591 : : }
592 : : }
593 : 54 : }
594 : :
595 : : void
596 : 69 : CompilePatternBindings::visit (HIR::ReferencePattern &pattern)
597 : : {
598 : 69 : tree derefed
599 : 69 : = indirect_expression (match_scrutinee_expr, pattern.get_locus ());
600 : :
601 : 69 : CompilePatternBindings::Compile (pattern.get_referenced_pattern (), derefed,
602 : : ctx);
603 : 69 : }
604 : :
605 : : void
606 : 328 : CompilePatternBindings::visit (HIR::IdentifierPattern &pattern)
607 : : {
608 : 328 : if (!pattern.get_is_ref ())
609 : : {
610 : 326 : ctx->insert_pattern_binding (pattern.get_mappings ().get_hirid (),
611 : : match_scrutinee_expr);
612 : 326 : return;
613 : : }
614 : :
615 : 2 : tree ref = address_expression (match_scrutinee_expr,
616 : 2 : EXPR_LOCATION (match_scrutinee_expr));
617 : 2 : ctx->insert_pattern_binding (pattern.get_mappings ().get_hirid (), ref);
618 : : }
619 : :
620 : : void
621 : 27 : CompilePatternBindings::visit (HIR::TuplePattern &pattern)
622 : : {
623 : 27 : rust_assert (pattern.has_tuple_pattern_items ());
624 : :
625 : : // lookup the type
626 : 27 : TyTy::BaseType *ty = nullptr;
627 : 27 : bool ok
628 : 27 : = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (),
629 : : &ty);
630 : 27 : rust_assert (ok);
631 : :
632 : 27 : switch (pattern.get_items ().get_item_type ())
633 : : {
634 : 0 : case HIR::TuplePatternItems::ItemType::RANGED: {
635 : 0 : size_t tuple_idx = 0;
636 : 0 : auto &items
637 : 0 : = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
638 : :
639 : 0 : auto &items_lower = items.get_lower_patterns ();
640 : 0 : auto &items_upper = items.get_upper_patterns ();
641 : :
642 : 0 : for (auto &sub : items_lower)
643 : : {
644 : 0 : TyTy::BaseType *ty_sub = nullptr;
645 : 0 : HirId sub_id = sub->get_mappings ().get_hirid ();
646 : 0 : bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
647 : 0 : rust_assert (ok);
648 : :
649 : 0 : tree sub_init
650 : 0 : = Backend::struct_field_expression (match_scrutinee_expr,
651 : 0 : tuple_idx, sub->get_locus ());
652 : :
653 : 0 : CompilePatternBindings::Compile (*sub.get (), sub_init, ctx);
654 : 0 : tuple_idx++;
655 : : }
656 : :
657 : 0 : rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE);
658 : 0 : tuple_idx = static_cast<TyTy::TupleType &> (*ty).num_fields ()
659 : 0 : - items_upper.size ();
660 : :
661 : 0 : for (auto &sub : items_upper)
662 : : {
663 : 0 : TyTy::BaseType *ty_sub = nullptr;
664 : 0 : HirId sub_id = sub->get_mappings ().get_hirid ();
665 : 0 : bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
666 : 0 : rust_assert (ok);
667 : :
668 : 0 : tree sub_init
669 : 0 : = Backend::struct_field_expression (match_scrutinee_expr,
670 : 0 : tuple_idx, sub->get_locus ());
671 : 0 : CompilePatternBindings::Compile (*sub.get (), sub_init, ctx);
672 : 0 : tuple_idx++;
673 : : }
674 : :
675 : : return;
676 : : }
677 : 27 : case HIR::TuplePatternItems::ItemType::MULTIPLE: {
678 : 27 : size_t tuple_idx = 0;
679 : 27 : auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
680 : 27 : pattern.get_items ());
681 : :
682 : 81 : for (auto &sub : items.get_patterns ())
683 : : {
684 : 54 : TyTy::BaseType *ty_sub = nullptr;
685 : 54 : HirId sub_id = sub->get_mappings ().get_hirid ();
686 : 54 : bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
687 : 54 : rust_assert (ok);
688 : :
689 : 54 : tree sub_init
690 : 54 : = Backend::struct_field_expression (match_scrutinee_expr,
691 : 54 : tuple_idx, sub->get_locus ());
692 : 54 : CompilePatternBindings::Compile (*sub.get (), sub_init, ctx);
693 : 54 : tuple_idx++;
694 : : }
695 : :
696 : : return;
697 : : }
698 : 0 : default: {
699 : 0 : rust_unreachable ();
700 : : }
701 : : }
702 : : }
703 : :
704 : : //
705 : :
706 : : void
707 : 10872 : CompilePatternLet::visit (HIR::IdentifierPattern &pattern)
708 : : {
709 : 10872 : Bvariable *var = nullptr;
710 : 10872 : rust_assert (
711 : : ctx->lookup_var_decl (pattern.get_mappings ().get_hirid (), &var));
712 : :
713 : 10872 : auto fnctx = ctx->peek_fn ();
714 : 10872 : if (ty->is_unit ())
715 : : {
716 : 228 : ctx->add_statement (init_expr);
717 : :
718 : 228 : auto unit_type_init_expr = unit_expression (rval_locus);
719 : 228 : auto s = Backend::init_statement (fnctx.fndecl, var, unit_type_init_expr);
720 : 228 : ctx->add_statement (s);
721 : : }
722 : : else
723 : : {
724 : 10644 : auto s = Backend::init_statement (fnctx.fndecl, var, init_expr);
725 : 10644 : ctx->add_statement (s);
726 : : }
727 : 10872 : }
728 : :
729 : : void
730 : 254 : CompilePatternLet::visit (HIR::WildcardPattern &pattern)
731 : : {
732 : 254 : tree init_stmt = NULL;
733 : 254 : tree stmt_type = TyTyResolveCompile::compile (ctx, ty);
734 : :
735 : 254 : Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE, stmt_type,
736 : 254 : init_expr, false, pattern.get_locus (),
737 : : &init_stmt);
738 : :
739 : 254 : ctx->add_statement (init_stmt);
740 : 254 : }
741 : :
742 : : void
743 : 315 : CompilePatternLet::visit (HIR::TuplePattern &pattern)
744 : : {
745 : 315 : rust_assert (pattern.has_tuple_pattern_items ());
746 : :
747 : 315 : tree tuple_type = TyTyResolveCompile::compile (ctx, ty);
748 : 315 : tree init_stmt;
749 : 315 : Bvariable *tmp_var
750 : 315 : = Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE,
751 : : tuple_type, init_expr, false,
752 : 315 : pattern.get_locus (), &init_stmt);
753 : 315 : tree access_expr = Backend::var_expression (tmp_var, pattern.get_locus ());
754 : 315 : ctx->add_statement (init_stmt);
755 : :
756 : 315 : switch (pattern.get_items ().get_item_type ())
757 : : {
758 : 0 : case HIR::TuplePatternItems::ItemType::RANGED: {
759 : 0 : size_t tuple_idx = 0;
760 : 0 : auto &items
761 : 0 : = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
762 : :
763 : 0 : auto &items_lower = items.get_lower_patterns ();
764 : 0 : auto &items_upper = items.get_upper_patterns ();
765 : :
766 : 0 : for (auto &sub : items_lower)
767 : : {
768 : 0 : TyTy::BaseType *ty_sub = nullptr;
769 : 0 : HirId sub_id = sub->get_mappings ().get_hirid ();
770 : 0 : bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
771 : 0 : rust_assert (ok);
772 : :
773 : 0 : tree sub_init
774 : 0 : = Backend::struct_field_expression (access_expr, tuple_idx,
775 : 0 : sub->get_locus ());
776 : 0 : CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
777 : : rval_locus, ctx);
778 : 0 : tuple_idx++;
779 : : }
780 : :
781 : 0 : rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE);
782 : 0 : tuple_idx = static_cast<TyTy::TupleType &> (*ty).num_fields ()
783 : 0 : - items_upper.size ();
784 : :
785 : 0 : for (auto &sub : items_upper)
786 : : {
787 : 0 : TyTy::BaseType *ty_sub = nullptr;
788 : 0 : HirId sub_id = sub->get_mappings ().get_hirid ();
789 : 0 : bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
790 : 0 : rust_assert (ok);
791 : :
792 : 0 : tree sub_init
793 : 0 : = Backend::struct_field_expression (access_expr, tuple_idx,
794 : 0 : sub->get_locus ());
795 : 0 : CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
796 : : rval_locus, ctx);
797 : 0 : tuple_idx++;
798 : : }
799 : :
800 : : return;
801 : : }
802 : 315 : case HIR::TuplePatternItems::ItemType::MULTIPLE: {
803 : 315 : size_t tuple_idx = 0;
804 : 315 : auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
805 : 315 : pattern.get_items ());
806 : :
807 : 948 : for (auto &sub : items.get_patterns ())
808 : : {
809 : 633 : TyTy::BaseType *ty_sub = nullptr;
810 : 633 : HirId sub_id = sub->get_mappings ().get_hirid ();
811 : 633 : bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
812 : 633 : rust_assert (ok);
813 : :
814 : 633 : tree sub_init
815 : 633 : = Backend::struct_field_expression (access_expr, tuple_idx,
816 : 633 : sub->get_locus ());
817 : 633 : CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
818 : : rval_locus, ctx);
819 : 633 : tuple_idx++;
820 : : }
821 : :
822 : : return;
823 : : }
824 : 0 : default: {
825 : 0 : rust_unreachable ();
826 : : }
827 : : }
828 : : }
829 : :
830 : : } // namespace Compile
831 : : } // namespace Rust
|