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
+}

Reply via email to