diff options
author | Zhi Heng <yapzhhg@gmail.com> | 2025-06-29 10:44:31 +0800 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2025-08-05 16:36:53 +0200 |
commit | b42078879d758ff25daba406b7eaf9cc5812d0a3 (patch) | |
tree | ca7d93e791182079b2348366e4d070cfd1b6b615 | |
parent | 0803c00cdddb88bf9cfca5ad1958105d66cf04c7 (diff) | |
download | gcc-b42078879d758ff25daba406b7eaf9cc5812d0a3.zip gcc-b42078879d758ff25daba406b7eaf9cc5812d0a3.tar.gz gcc-b42078879d758ff25daba406b7eaf9cc5812d0a3.tar.bz2 |
gccrs: Implement compilation support for TuplePatternItems::RANGED
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 <yapzhhg@gmail.com>
4 files changed, 87 insertions, 2 deletions
diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index cd1c77b..3351bec 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 0000000..5cce3c4 --- /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 0000000..40900a3 --- /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 0000000..2c1418c --- /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 |