https://gcc.gnu.org/g:39aa96ce9382f455bc071a3aa36f866fef760af1
commit r16-2938-g39aa96ce9382f455bc071a3aa36f866fef760af1 Author: Yap Zhi Heng <yapz...@gmail.com> Date: Thu Jul 17 22:13:32 2025 +0800 gccrs: Implement compilation for SlicePattern matching against ArrayType scrutinee Example GIMPLE output from compiling testsuite/rust/compile/match-pattern-array.rs: ... a[0] = 0; a[1] = 1; RUSTTMP.3 = a; _1 = RUSTTMP.3[0]; _2 = _1 == 0; _3 = RUSTTMP.3[1]; _4 = _3 == 1; _5 = _2 & _4; if (_5 != 0) goto <D.122>; else goto <D.123>; <D.122>: { { } } goto <D.117>; } <D.123>: ... gcc/rust/ChangeLog: * rust-backend.h: New size_constant_expression function. * rust-gcc.cc: Implementation of size_constant_expression function to generate tree node for array access. * backend/rust-compile-pattern.h: Remove empty visits for SlicePattern. * backend/rust-compile-pattern.cc: Implement SlicePattern check expression & binding compilation against ArrayType scrutinee. Signed-off-by: Yap Zhi Heng <yapz...@gmail.com> Diff: --- gcc/rust/backend/rust-compile-pattern.cc | 85 ++++++++++++++++++++++ gcc/rust/backend/rust-compile-pattern.h | 4 +- gcc/rust/rust-backend.h | 3 + gcc/rust/rust-gcc.cc | 6 ++ .../rust/compile/match-slicepattern-array.rs | 8 ++ .../execute/torture/match-slicepattern-array-1.rs | 23 ++++++ 6 files changed, 127 insertions(+), 2 deletions(-) diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index 3351becd1d99..6d889baa1992 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -514,6 +514,53 @@ CompilePatternCheckExpr::visit (HIR::IdentifierPattern &pattern) } } +void +CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern) +{ + check_expr = boolean_true_node; + + // lookup the type + TyTy::BaseType *lookup = nullptr; + bool ok + = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (), + &lookup); + rust_assert (ok); + + // pattern must either be ArrayType or SliceType, should be already confirmed + // by type checking + rust_assert (lookup->get_kind () == TyTy::TypeKind::ARRAY + || lookup->get_kind () == TyTy::TypeKind::SLICE); + + size_t array_element_index = 0; + switch (lookup->get_kind ()) + { + case TyTy::TypeKind::ARRAY: + for (auto &pattern_member : pattern.get_items ()) + { + tree array_index_tree + = Backend::size_constant_expression (array_element_index++); + tree element_expr + = Backend::array_index_expression (match_scrutinee_expr, + array_index_tree, + pattern.get_locus ()); + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern_member, element_expr, + ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern.get_locus ()); + } + break; + case TyTy::TypeKind::SLICE: + rust_sorry_at ( + pattern.get_locus (), + "SlicePattern matching against slices are not yet supported"); + break; + default: + rust_unreachable (); + } +} + // setup the bindings void @@ -837,6 +884,44 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern) } } +void +CompilePatternBindings::visit (HIR::SlicePattern &pattern) +{ + // lookup the type + TyTy::BaseType *lookup = nullptr; + bool ok + = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (), + &lookup); + rust_assert (ok); + + rust_assert (lookup->get_kind () == TyTy::TypeKind::ARRAY + || lookup->get_kind () == TyTy::TypeKind::SLICE); + + size_t array_element_index = 0; + switch (lookup->get_kind ()) + { + case TyTy::TypeKind::ARRAY: + for (auto &pattern_member : pattern.get_items ()) + { + tree array_index_tree + = Backend::size_constant_expression (array_element_index++); + tree element_expr + = Backend::array_index_expression (match_scrutinee_expr, + array_index_tree, + pattern.get_locus ()); + CompilePatternBindings::Compile (*pattern_member, element_expr, ctx); + } + break; + case TyTy::TypeKind::SLICE: + rust_sorry_at ( + pattern.get_locus (), + "SlicePattern matching against slices are not yet supported"); + break; + default: + rust_unreachable (); + } +} + // void diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h index 4dd7d559e6eb..233799e21da3 100644 --- a/gcc/rust/backend/rust-compile-pattern.h +++ b/gcc/rust/backend/rust-compile-pattern.h @@ -46,6 +46,7 @@ public: void visit (HIR::TupleStructPattern &) override; void visit (HIR::TuplePattern &) override; void visit (HIR::IdentifierPattern &) override; + void visit (HIR::SlicePattern &) override; // Always succeeds void visit (HIR::WildcardPattern &) override @@ -55,7 +56,6 @@ public: // Empty visit for unused Pattern HIR nodes. void visit (HIR::QualifiedPathInExpression &) override {} - void visit (HIR::SlicePattern &) override {} CompilePatternCheckExpr (Context *ctx, tree match_scrutinee_expr) : HIRCompileBase (ctx), match_scrutinee_expr (match_scrutinee_expr), @@ -95,6 +95,7 @@ public: void visit (HIR::ReferencePattern &pattern) override; void visit (HIR::IdentifierPattern &) override; void visit (HIR::TuplePattern &pattern) override; + void visit (HIR::SlicePattern &) override; // Empty visit for unused Pattern HIR nodes. void visit (HIR::AltPattern &) override {} @@ -102,7 +103,6 @@ public: void visit (HIR::PathInExpression &) override {} void visit (HIR::QualifiedPathInExpression &) override {} void visit (HIR::RangePattern &) override {} - void visit (HIR::SlicePattern &) override {} void visit (HIR::WildcardPattern &) override {} protected: diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 2d813d91efd6..8a77d96de835 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -176,6 +176,9 @@ tree char_constant_expression (char c); // Get a char literal tree wchar_constant_expression (wchar_t c); +// Get a size literal +tree size_constant_expression (size_t val); + // Return an expression for the boolean value VAL. tree boolean_constant_expression (bool val); diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 42cdc6ca7f1c..c5fda5c7a9ca 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -818,6 +818,12 @@ char_constant_expression (char c) return build_int_cst (char_type_node, c); } +tree +size_constant_expression (size_t val) +{ + return size_int (val); +} + // Make a constant boolean expression. tree diff --git a/gcc/testsuite/rust/compile/match-slicepattern-array.rs b/gcc/testsuite/rust/compile/match-slicepattern-array.rs new file mode 100644 index 000000000000..e48ca757f5e0 --- /dev/null +++ b/gcc/testsuite/rust/compile/match-slicepattern-array.rs @@ -0,0 +1,8 @@ +fn main() { + let a = [0, 1]; + + match a { + [0, 1] => {}, + _ => {} + } +} diff --git a/gcc/testsuite/rust/execute/torture/match-slicepattern-array-1.rs b/gcc/testsuite/rust/execute/torture/match-slicepattern-array-1.rs new file mode 100644 index 000000000000..95c55d8f9d5e --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/match-slicepattern-array-1.rs @@ -0,0 +1,23 @@ +// { dg-output "correct\r*" } +extern "C" { + fn puts(s: *const i8); +} + +fn main() -> i32 { + let a = [0, 1]; + let mut ret = 1; + + match a { + [0, 0] => { + /* should not take this path */ + unsafe { puts("wrong\0" as *const str as *const i8) } + }, + [0, b] => { + ret -= b; + unsafe { puts("correct\0" as *const str as *const i8) } + }, + _ => {} + } + + ret +}