From: Zhi Heng <[email protected]>
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 <[email protected]>
---
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