aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-compile-pattern.cc
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-04-20 08:33:46 +0000
committerGitHub <noreply@github.com>2022-04-20 08:33:46 +0000
commit14dbac9a8bbc7f3cf37679e91ea56e449a64bde7 (patch)
tree37c16bbb73f388b0c9851f3a945b03c545a8ec50 /gcc/rust/backend/rust-compile-pattern.cc
parentdc57f4ced0d168be911ca22db81fe9526e2d70a8 (diff)
parentc3a3e1053f41819d1f6ff8fa68bcd4aca9fc5f80 (diff)
downloadgcc-14dbac9a8bbc7f3cf37679e91ea56e449a64bde7.zip
gcc-14dbac9a8bbc7f3cf37679e91ea56e449a64bde7.tar.gz
gcc-14dbac9a8bbc7f3cf37679e91ea56e449a64bde7.tar.bz2
Merge #1138
1138: Support pattern bindings within function signitures r=philberty a=philberty This reuses our code to handle match-arms within MatchExpressions, we resolve the pattern's type's and implicitly create types for that binding. For code-generation we create a tmp var name for the name of the parameter which is the base type and for the destructuring we reuse the same match arm code to generate the implicit bindings to the parts of the structure ```c __attribute__((cdecl)) i32 test::pattern_as_arg (const struct test::Pattern RSTPRM.0) { i32 RUSTTMP.1; return RSTPRM.0.0; } ``` Fixes #995 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc/rust/backend/rust-compile-pattern.cc')
-rw-r--r--gcc/rust/backend/rust-compile-pattern.cc111
1 files changed, 72 insertions, 39 deletions
diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc
index d715c7c..393fbd5 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -20,6 +20,8 @@
#include "rust-compile-expr.h"
#include "rust-constexpr.h"
+#include "print-tree.h"
+
namespace Rust {
namespace Compile {
@@ -92,18 +94,20 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern)
// this must be an enum
rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
- rust_assert (adt->is_enum ());
+ rust_assert (adt->number_of_variants () > 0);
- // lookup the variant
- HirId variant_id;
- ok = ctx->get_tyctx ()->lookup_variant_definition (
- pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
- rust_assert (ok);
+ int variant_index = 0;
+ TyTy::VariantDef *variant = adt->get_variants ().at (0);
+ if (adt->is_enum ())
+ {
+ HirId variant_id = UNKNOWN_HIRID;
+ bool ok = ctx->get_tyctx ()->lookup_variant_definition (
+ pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
+ rust_assert (ok);
- int variant_index = -1;
- TyTy::VariantDef *variant = nullptr;
- ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
- rust_assert (ok);
+ ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
+ rust_assert (ok);
+ }
rust_assert (variant->get_variant_type ()
== TyTy::VariantDef::VariantType::TUPLE);
@@ -124,20 +128,37 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern)
rust_assert (items_no_range.get_patterns ().size ()
== variant->num_fields ());
- // we are offsetting by + 1 here since the first field in the record
- // is always the discriminator
- size_t tuple_field_index = 1;
- for (auto &pattern : items_no_range.get_patterns ())
+ if (adt->is_enum ())
+ {
+ // we are offsetting by + 1 here since the first field in the record
+ // is always the discriminator
+ size_t tuple_field_index = 1;
+ for (auto &pattern : items_no_range.get_patterns ())
+ {
+ tree variant_accessor
+ = ctx->get_backend ()->struct_field_expression (
+ match_scrutinee_expr, variant_index, pattern->get_locus ());
+
+ tree binding = ctx->get_backend ()->struct_field_expression (
+ variant_accessor, tuple_field_index++, pattern->get_locus ());
+
+ ctx->insert_pattern_binding (
+ pattern->get_pattern_mappings ().get_hirid (), binding);
+ }
+ }
+ else
{
- tree variant_accessor
- = ctx->get_backend ()->struct_field_expression (
- match_scrutinee_expr, variant_index, pattern->get_locus ());
+ size_t tuple_field_index = 0;
+ for (auto &pattern : items_no_range.get_patterns ())
+ {
+ tree variant_accessor = match_scrutinee_expr;
- tree binding = ctx->get_backend ()->struct_field_expression (
- variant_accessor, tuple_field_index++, pattern->get_locus ());
+ tree binding = ctx->get_backend ()->struct_field_expression (
+ variant_accessor, tuple_field_index++, pattern->get_locus ());
- ctx->insert_pattern_binding (
- pattern->get_pattern_mappings ().get_hirid (), binding);
+ ctx->insert_pattern_binding (
+ pattern->get_pattern_mappings ().get_hirid (), binding);
+ }
}
}
break;
@@ -156,18 +177,20 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern)
// this must be an enum
rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
- rust_assert (adt->is_enum ());
+ rust_assert (adt->number_of_variants () > 0);
- // lookup the variant
- HirId variant_id;
- ok = ctx->get_tyctx ()->lookup_variant_definition (
- pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
- rust_assert (ok);
+ int variant_index = 0;
+ TyTy::VariantDef *variant = adt->get_variants ().at (0);
+ if (adt->is_enum ())
+ {
+ HirId variant_id = UNKNOWN_HIRID;
+ bool ok = ctx->get_tyctx ()->lookup_variant_definition (
+ pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
+ rust_assert (ok);
- int variant_index = -1;
- TyTy::VariantDef *variant = nullptr;
- ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
- rust_assert (ok);
+ ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
+ rust_assert (ok);
+ }
rust_assert (variant->get_variant_type ()
== TyTy::VariantDef::VariantType::STRUCT);
@@ -193,19 +216,29 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern)
HIR::StructPatternFieldIdent &ident
= static_cast<HIR::StructPatternFieldIdent &> (*field.get ());
- tree variant_accessor
- = ctx->get_backend ()->struct_field_expression (
- match_scrutinee_expr, variant_index, ident.get_locus ());
-
size_t offs = 0;
ok
= variant->lookup_field (ident.get_identifier (), nullptr, &offs);
rust_assert (ok);
- // we are offsetting by + 1 here since the first field in the record
- // is always the discriminator
- tree binding = ctx->get_backend ()->struct_field_expression (
- variant_accessor, offs + 1, ident.get_locus ());
+ tree binding = error_mark_node;
+ if (adt->is_enum ())
+ {
+ tree variant_accessor
+ = ctx->get_backend ()->struct_field_expression (
+ match_scrutinee_expr, variant_index, ident.get_locus ());
+
+ // we are offsetting by + 1 here since the first field in the
+ // record is always the discriminator
+ binding = ctx->get_backend ()->struct_field_expression (
+ variant_accessor, offs + 1, ident.get_locus ());
+ }
+ else
+ {
+ tree variant_accessor = match_scrutinee_expr;
+ binding = ctx->get_backend ()->struct_field_expression (
+ variant_accessor, offs, ident.get_locus ());
+ }
ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (),
binding);