aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-compile-pattern.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/backend/rust-compile-pattern.cc')
-rw-r--r--gcc/rust/backend/rust-compile-pattern.cc331
1 files changed, 290 insertions, 41 deletions
diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc
index 93a5f7c..9e13480 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -26,7 +26,7 @@ namespace Rust {
namespace Compile {
void
-CompilePatternCaseLabelExpr::visit (HIR::PathInExpression &pattern)
+CompilePatternCheckExpr::visit (HIR::PathInExpression &pattern)
{
// lookup the type
TyTy::BaseType *lookup = nullptr;
@@ -36,6 +36,7 @@ CompilePatternCaseLabelExpr::visit (HIR::PathInExpression &pattern)
rust_assert (ok);
// this must be an enum
+ // TODO: might not be
rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
rust_assert (adt->is_enum ());
@@ -50,38 +51,28 @@ CompilePatternCaseLabelExpr::visit (HIR::PathInExpression &pattern)
ok = adt->lookup_variant_by_id (variant_id, &variant);
rust_assert (ok);
- HIR::Expr *discrim_expr = variant->get_discriminant ();
- tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
- tree folded_discrim_expr = fold_expr (discrim_expr_node);
- tree case_low = folded_discrim_expr;
+ // find discriminant field of scrutinee
+ tree scrutinee_record_expr
+ = Backend::struct_field_expression (match_scrutinee_expr, 0,
+ pattern.get_locus ());
+ tree scrutinee_expr_qualifier_expr
+ = Backend::struct_field_expression (scrutinee_record_expr, 0,
+ pattern.get_locus ());
- case_label_expr
- = build_case_label (case_low, NULL_TREE, associated_case_label);
-}
-
-void
-CompilePatternCaseLabelExpr::visit (HIR::StructPattern &pattern)
-{
- CompilePatternCaseLabelExpr::visit (pattern.get_path ());
-}
+ // must be enum
+ match_scrutinee_expr = scrutinee_expr_qualifier_expr;
-void
-CompilePatternCaseLabelExpr::visit (HIR::TupleStructPattern &pattern)
-{
- CompilePatternCaseLabelExpr::visit (pattern.get_path ());
-}
+ HIR::Expr *discrim_expr = variant->get_discriminant ();
+ tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
-void
-CompilePatternCaseLabelExpr::visit (HIR::WildcardPattern &pattern)
-{
- // operand 0 being NULL_TREE signifies this is the default case label see:
- // tree.def for documentation for CASE_LABEL_EXPR
- case_label_expr
- = build_case_label (NULL_TREE, NULL_TREE, associated_case_label);
+ check_expr
+ = Backend::comparison_expression (ComparisonOperator::EQUAL,
+ match_scrutinee_expr, discrim_expr_node,
+ pattern.get_locus ());
}
void
-CompilePatternCaseLabelExpr::visit (HIR::LiteralPattern &pattern)
+CompilePatternCheckExpr::visit (HIR::LiteralPattern &pattern)
{
// Compile the literal
HIR::LiteralExpr *litexpr
@@ -101,18 +92,9 @@ CompilePatternCaseLabelExpr::visit (HIR::LiteralPattern &pattern)
tree lit = CompileExpr::Compile (litexpr, ctx);
- case_label_expr = build_case_label (lit, NULL_TREE, associated_case_label);
-}
-
-void
-CompilePatternCaseLabelExpr::visit (HIR::AltPattern &pattern)
-{
- const auto &alts = pattern.get_alts ();
- for (auto &alt_pattern : alts)
- {
- CompilePatternCaseLabelExpr::Compile (alt_pattern.get (),
- associated_case_label, ctx);
- }
+ check_expr = Backend::comparison_expression (ComparisonOperator::EQUAL,
+ match_scrutinee_expr, lit,
+ pattern.get_locus ());
}
static tree
@@ -161,7 +143,7 @@ compile_range_pattern_bound (HIR::RangePatternBound *bound,
}
void
-CompilePatternCaseLabelExpr::visit (HIR::RangePattern &pattern)
+CompilePatternCheckExpr::visit (HIR::RangePattern &pattern)
{
tree upper = compile_range_pattern_bound (pattern.get_upper_bound ().get (),
pattern.get_mappings (),
@@ -170,7 +152,274 @@ CompilePatternCaseLabelExpr::visit (HIR::RangePattern &pattern)
pattern.get_mappings (),
pattern.get_locus (), ctx);
- case_label_expr = build_case_label (lower, upper, associated_case_label);
+ tree check_lower
+ = Backend::comparison_expression (ComparisonOperator::GREATER_OR_EQUAL,
+ match_scrutinee_expr, lower,
+ pattern.get_locus ());
+ tree check_upper
+ = Backend::comparison_expression (ComparisonOperator::LESS_OR_EQUAL,
+ match_scrutinee_expr, upper,
+ pattern.get_locus ());
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_lower, check_upper,
+ pattern.get_locus ());
+}
+
+void
+CompilePatternCheckExpr::visit (HIR::ReferencePattern &pattern)
+{
+ match_scrutinee_expr
+ = indirect_expression (match_scrutinee_expr, pattern.get_locus ());
+ pattern.get_referenced_pattern ()->accept_vis (*this);
+}
+
+void
+CompilePatternCheckExpr::visit (HIR::AltPattern &pattern)
+{
+ auto &alts = pattern.get_alts ();
+
+ check_expr = CompilePatternCheckExpr::Compile (alts.at (0).get (),
+ match_scrutinee_expr, ctx);
+ auto end = alts.end ();
+ for (auto i = alts.begin () + 1; i != end; i++)
+ {
+ tree next_expr
+ = CompilePatternCheckExpr::Compile (i->get (), match_scrutinee_expr,
+ ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_OR, check_expr, next_expr,
+ (*i)->get_locus ());
+ }
+}
+
+void
+CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
+{
+ // lookup the type
+ TyTy::BaseType *lookup = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_type (
+ pattern.get_path ().get_mappings ().get_hirid (), &lookup);
+ rust_assert (ok);
+
+ // this might be an enum
+ rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
+
+ rust_assert (adt->number_of_variants () > 0);
+ TyTy::VariantDef *variant = nullptr;
+ if (adt->is_enum ())
+ {
+ // 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;
+ ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
+ rust_assert (ok);
+
+ // find expected discriminant
+ // // need to access qualifier the field, if we use QUAL_UNION_TYPE this
+ // // would be DECL_QUALIFIER i think. For now this will just access the
+ // // first record field and its respective qualifier because it will
+ // // always be set because this is all a big special union
+ HIR::Expr *discrim_expr = variant->get_discriminant ();
+ tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
+
+ // find discriminant field of scrutinee
+ tree scrutinee_record_expr
+ = Backend::struct_field_expression (match_scrutinee_expr, variant_index,
+ pattern.get_path ().get_locus ());
+ tree scrutinee_expr_qualifier_expr
+ = Backend::struct_field_expression (scrutinee_record_expr, 0,
+ pattern.get_path ().get_locus ());
+
+ check_expr
+ = Backend::comparison_expression (ComparisonOperator::EQUAL,
+ scrutinee_expr_qualifier_expr,
+ discrim_expr_node,
+ pattern.get_path ().get_locus ());
+
+ match_scrutinee_expr = scrutinee_record_expr;
+ }
+ else
+ {
+ variant = adt->get_variants ().at (0);
+ check_expr = boolean_true_node;
+ }
+
+ auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
+ for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
+ {
+ switch (field->get_item_type ())
+ {
+ case HIR::StructPatternField::ItemType::TUPLE_PAT: {
+ // TODO
+ rust_unreachable ();
+ }
+ break;
+
+ case HIR::StructPatternField::ItemType::IDENT_PAT: {
+ HIR::StructPatternFieldIdentPat &ident
+ = static_cast<HIR::StructPatternFieldIdentPat &> (*field.get ());
+
+ size_t offs = 0;
+ ok = variant->lookup_field (ident.get_identifier ().as_string (),
+ nullptr, &offs);
+ rust_assert (ok);
+
+ // we may be offsetting by + 1 here since the first field in the
+ // record is always the discriminator
+ offs += adt->is_enum ();
+ tree field_expr
+ = Backend::struct_field_expression (match_scrutinee_expr, offs,
+ ident.get_locus ());
+
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (ident.get_pattern ().get (),
+ field_expr, ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, ident.get_pattern ()->get_locus ());
+ }
+ break;
+
+ case HIR::StructPatternField::ItemType::IDENT: {
+ // ident pattern always matches - do nothing
+ }
+ break;
+ }
+ }
+}
+
+void
+CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern)
+{
+ size_t tuple_field_index;
+
+ // lookup the type
+ TyTy::BaseType *lookup = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_type (
+ pattern.get_path ().get_mappings ().get_hirid (), &lookup);
+ rust_assert (ok);
+
+ // this might be an enum
+ rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
+
+ rust_assert (adt->number_of_variants () > 0);
+ TyTy::VariantDef *variant = nullptr;
+ if (adt->is_enum ())
+ {
+ // 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;
+ ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
+ rust_assert (ok);
+
+ // find expected discriminant
+ HIR::Expr *discrim_expr = variant->get_discriminant ();
+ tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
+
+ // find discriminant field of scrutinee
+ tree scrutinee_record_expr
+ = Backend::struct_field_expression (match_scrutinee_expr, variant_index,
+ pattern.get_path ().get_locus ());
+ tree scrutinee_expr_qualifier_expr
+ = Backend::struct_field_expression (scrutinee_record_expr, 0,
+ pattern.get_path ().get_locus ());
+
+ check_expr
+ = Backend::comparison_expression (ComparisonOperator::EQUAL,
+ scrutinee_expr_qualifier_expr,
+ discrim_expr_node,
+ pattern.get_path ().get_locus ());
+
+ match_scrutinee_expr = scrutinee_record_expr;
+ // we are offsetting by + 1 here since the first field in the record
+ // is always the discriminator
+ tuple_field_index = 1;
+ }
+ else
+ {
+ variant = adt->get_variants ().at (0);
+ check_expr = boolean_true_node;
+ tuple_field_index = 0;
+ }
+
+ std::unique_ptr<HIR::TupleStructItems> &items = pattern.get_items ();
+ switch (items->get_item_type ())
+ {
+ case HIR::TupleStructItems::RANGE: {
+ // TODO
+ rust_unreachable ();
+ }
+ break;
+
+ case HIR::TupleStructItems::NO_RANGE: {
+ HIR::TupleStructItemsNoRange &items_no_range
+ = static_cast<HIR::TupleStructItemsNoRange &> (*items.get ());
+
+ rust_assert (items_no_range.get_patterns ().size ()
+ == variant->num_fields ());
+
+ for (auto &pattern : items_no_range.get_patterns ())
+ {
+ tree field_expr
+ = Backend::struct_field_expression (match_scrutinee_expr,
+ tuple_field_index++,
+ pattern->get_locus ());
+
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (pattern.get (), field_expr,
+ ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pattern->get_locus ());
+ }
+ }
+ break;
+ }
+}
+
+void
+CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern)
+{
+ check_expr = boolean_true_node;
+
+ switch (pattern.get_items ()->get_item_type ())
+ {
+ case HIR::TuplePatternItems::RANGED: {
+ // TODO
+ gcc_unreachable ();
+ }
+ break;
+
+ case HIR::TuplePatternItems::MULTIPLE: {
+ auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
+ *pattern.get_items ());
+ size_t tuple_field_index = 0;
+
+ for (auto &pat : items.get_patterns ())
+ {
+ tree field_expr
+ = Backend::struct_field_expression (match_scrutinee_expr,
+ tuple_field_index++,
+ pat->get_locus ());
+
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (pat.get (), field_expr, ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pat->get_locus ());
+ }
+ }
+ }
}
// setup the bindings