From: Zhi Heng <yapz...@gmail.com>

Example GIMPLE output of the match statement for match-restpattern-tuple-1.rs:

...
RUSTTMP.2 = x;
_1 = RUSTTMP.2.__0;
_2 = _1 == 1;
_3 = RUSTTMP.2.__3;
_4 = _3 == 4;
_5 = _2 & _4;
if (_5 != 0) goto <D.109>; else goto <D.110>;
<D.109>:
{
    {

    }
    goto <D.104>;
}
<D.110>:
if (1 != 0) goto <D.111>; else goto <D.112>;
<D.111>:
{
    {

    }
    goto <D.104>;
}
<D.112>:
<D.104>:
...

gcc/rust/ChangeLog:

        * backend/rust-compile-pattern.cc 
(CompilePatternCheckExpr::visit(TuplePattern)):
                Implement check expression compilation for 
TuplePatternItems::RANGED.

Signed-off-by: Yap Zhi Heng <yapz...@gmail.com>
---
 gcc/rust/backend/rust-compile-pattern.cc      | 46 ++++++++++++++++++-
 .../rust/compile/match-restpattern-tuple-1.rs |  8 ++++
 .../rust/compile/match-restpattern-tuple-2.rs |  8 ++++
 .../torture/match-restpattern-tuple.rs        | 27 +++++++++++
 4 files changed, 87 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/match-restpattern-tuple-1.rs
 create mode 100644 gcc/testsuite/rust/compile/match-restpattern-tuple-2.rs
 create mode 100644 
gcc/testsuite/rust/execute/torture/match-restpattern-tuple.rs

diff --git a/gcc/rust/backend/rust-compile-pattern.cc 
b/gcc/rust/backend/rust-compile-pattern.cc
index cd1c77be5eb..3351becd1d9 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -430,8 +430,50 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern)
     {
     case HIR::TuplePatternItems::RANGED:
       {
-       // TODO
-       gcc_unreachable ();
+       auto &items
+         = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
+       size_t tuple_field_index = 0;
+
+       // lookup the type to find out number of fields
+       TyTy::BaseType *ty = nullptr;
+       bool ok = ctx->get_tyctx ()->lookup_type (
+         pattern.get_mappings ().get_hirid (), &ty);
+       rust_assert (ok);
+       rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE);
+
+       // compile check expr for lower patterns
+       for (auto &pat : items.get_lower_patterns ())
+         {
+           tree field_expr
+             = Backend::struct_field_expression (match_scrutinee_expr,
+                                                 tuple_field_index++,
+                                                 pat->get_locus ());
+
+           tree check_expr_sub
+             = CompilePatternCheckExpr::Compile (*pat, field_expr, ctx);
+           check_expr = Backend::arithmetic_or_logical_expression (
+             ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+             check_expr_sub, pat->get_locus ());
+         }
+
+       // skip the fields that are not checked
+       tuple_field_index = static_cast<TyTy::TupleType &> (*ty).num_fields ()
+                           - items.get_upper_patterns ().size ();
+
+       // compile check expr for upper patterns
+       for (auto &pat : items.get_upper_patterns ())
+         {
+           tree field_expr
+             = Backend::struct_field_expression (match_scrutinee_expr,
+                                                 tuple_field_index++,
+                                                 pat->get_locus ());
+
+           tree check_expr_sub
+             = CompilePatternCheckExpr::Compile (*pat, field_expr, ctx);
+           check_expr = Backend::arithmetic_or_logical_expression (
+             ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+             check_expr_sub, pat->get_locus ());
+         }
       }
       break;
 
diff --git a/gcc/testsuite/rust/compile/match-restpattern-tuple-1.rs 
b/gcc/testsuite/rust/compile/match-restpattern-tuple-1.rs
new file mode 100644
index 00000000000..5cce3c409f0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-restpattern-tuple-1.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let x = (1, 2, 3, 4);
+
+    match x {
+        (1, .., 4) => {},
+        _ => {}
+    }
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/match-restpattern-tuple-2.rs 
b/gcc/testsuite/rust/compile/match-restpattern-tuple-2.rs
new file mode 100644
index 00000000000..40900a36bec
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-restpattern-tuple-2.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let x = (1, 2, 3, 4);
+
+    match x {
+        (1, .., 2, 3, 4, 5) => {}, // { dg-error "expected a tuple with 4 
elements, found one with 5 elements" }
+        _ => {}
+    }
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/execute/torture/match-restpattern-tuple.rs 
b/gcc/testsuite/rust/execute/torture/match-restpattern-tuple.rs
new file mode 100644
index 00000000000..2c1418c551d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match-restpattern-tuple.rs
@@ -0,0 +1,27 @@
+// { dg-output "correct\r*" }
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn main() -> i32 {
+    let x = (1, 2, 3, 4);
+    let mut ret = 1;
+
+    match x {
+        (1, .., 2, 4) => {
+            /* should not take this path */
+            unsafe { puts("wrong\0" as *const str as *const i8) }
+        },
+        (2, ..) => {
+            /* should not take this path */
+            unsafe { puts("wrong\0" as *const str as *const i8) }
+        },
+        (b, .., 4) => { 
+            ret -= b;
+            unsafe { puts("correct\0" as *const str as *const i8) }
+        },
+        _ => {}
+    }
+
+    ret
+}
\ No newline at end of file
-- 
2.49.0

Reply via email to