https://gcc.gnu.org/g:e80e577df7ca410eac549da61f9a9fd702dc55ea

commit r16-2960-ge80e577df7ca410eac549da61f9a9fd702dc55ea
Author: Yap Zhi Heng <yapz...@gmail.com>
Date:   Wed Jul 23 08:24:18 2025 +0800

    gccrs: Implement compilation for SlicePattern against SliceType scrutinee
    
    006t.original output from compiling 
testsuite/rust/compile/match-slicepattern-slice.rs:
    
    ...
      RUSTTMP.3 = slice;
      if (RUSTTMP.3.len == 1 && *(RUSTTMP.3.data + 0 * 4) == 1)
        {
          {
                    struct () RUSTTMP.4;
            {
    
            }
            goto <D.129>;
          }
        }
      if (RUSTTMP.3.len == 2 && *(RUSTTMP.3.data + 1 * 4) == 2)
        {
          {
                    struct () RUSTTMP.5;
            {
    
            }
            goto <D.129>;
          }
        }
      if (1)
        {
          {
                    struct () RUSTTMP.6;
            {
    
            }
            goto <D.129>;
          }
        }
      <D.129>:;
    ...
    
    gcc/rust/ChangeLog:
    
            * rust-backend.h: New slice_index_expression function.
            * rust-gcc.cc: Implementation of slice_index_expression to generate 
tree node for
                    accessing slice elements.
            * backend/rust-compile-pattern.cc: Implement SlicePattern check 
expression & binding
                    compilation against SliceType scrutinee.
    
    Signed-off-by: Yap Zhi Heng <yapz...@gmail.com>

Diff:
---
 gcc/rust/backend/rust-compile-pattern.cc           | 50 +++++++++++++++++++++-
 gcc/rust/rust-backend.h                            |  4 ++
 gcc/rust/rust-gcc.cc                               | 28 ++++++++++++
 .../rust/compile/match-slicepattern-slice.rs       | 10 +++++
 .../execute/torture/match-slicepattern-slice-1.rs  | 24 +++++++++++
 5 files changed, 114 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-pattern.cc 
b/gcc/rust/backend/rust-compile-pattern.cc
index e00de4f467f3..fe6592174382 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -555,7 +555,38 @@ CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern)
     case TyTy::TypeKind::SLICE:
       rust_sorry_at (
        pattern.get_locus (),
-       "SlicePattern matching against slices are not yet supported");
+       "SlicePattern matching against non-ref slices are not yet supported");
+      break;
+    case TyTy::TypeKind::REF:
+      {
+       rust_assert (RS_DST_FLAG_P (TREE_TYPE (match_scrutinee_expr)));
+       tree size_field
+         = Backend::struct_field_expression (match_scrutinee_expr, 1,
+                                             pattern.get_locus ());
+
+       // First compare the size
+       check_expr = Backend::comparison_expression (
+         ComparisonOperator::EQUAL, size_field,
+         build_int_cst (size_type_node, pattern.get_items ().size ()),
+         pattern.get_locus ());
+
+       // Then compare each element in the slice pattern
+       for (auto &pattern_member : pattern.get_items ())
+         {
+           tree slice_index_tree
+             = Backend::size_constant_expression (array_element_index++);
+           tree element_expr
+             = Backend::slice_index_expression (match_scrutinee_expr,
+                                                slice_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;
     default:
       rust_unreachable ();
@@ -917,8 +948,23 @@ CompilePatternBindings::visit (HIR::SlicePattern &pattern)
     case TyTy::TypeKind::SLICE:
       rust_sorry_at (
        pattern.get_locus (),
-       "SlicePattern matching against slices are not yet supported");
+       "SlicePattern matching against non-ref slices are not yet supported");
       break;
+    case TyTy::TypeKind::REF:
+      {
+       for (auto &pattern_member : pattern.get_items ())
+         {
+           tree slice_index_tree
+             = Backend::size_constant_expression (array_element_index++);
+           tree element_expr
+             = Backend::slice_index_expression (match_scrutinee_expr,
+                                                slice_index_tree,
+                                                pattern.get_locus ());
+           CompilePatternBindings::Compile (*pattern_member, element_expr,
+                                            ctx);
+         }
+       break;
+      }
     default:
       rust_unreachable ();
     }
diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h
index 8a77d96de835..205eb2b71465 100644
--- a/gcc/rust/rust-backend.h
+++ b/gcc/rust/rust-backend.h
@@ -245,6 +245,10 @@ tree array_initializer (tree, tree, tree, tree, tree, tree 
*, location_t);
 // fixed-length array, not a slice.
 tree array_index_expression (tree array, tree index, location_t);
 
+// Return an expresison for SLICE[INDEX] as an l-value.  SLICE is represented
+// with a DST.
+tree slice_index_expression (tree slice, tree index, location_t);
+
 // Create an expression for a call to FN with ARGS, taking place within
 // caller CALLER.
 tree call_expression (tree fn, const std::vector<tree> &args, tree 
static_chain,
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index c5fda5c7a9ca..0f9ccfb9c81a 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -1504,6 +1504,34 @@ array_index_expression (tree array_tree, tree 
index_tree, location_t location)
   return ret;
 }
 
+// Return an expression representing SLICE[INDEX]
+
+tree
+slice_index_expression (tree slice_tree, tree index_tree, location_t location)
+{
+  if (error_operand_p (slice_tree) || error_operand_p (index_tree))
+    return error_mark_node;
+
+  // A slice is created in TyTyResolvecompile::create_slice_type_record
+  // For example:
+  //   &[i32] is turned directly into a struct { i32* data, usize len };
+  //   [i32] is also turned into struct { i32* data, usize len }
+
+  // it should have RS_DST_FLAG set to 1
+  rust_assert (RS_DST_FLAG_P (TREE_TYPE (slice_tree)));
+
+  tree data_field = struct_field_expression (slice_tree, 0, location);
+  tree data_field_deref = build_fold_indirect_ref_loc (location, data_field);
+
+  tree element_type = TREE_TYPE (data_field_deref);
+  tree data_pointer = TREE_OPERAND (data_field_deref, 0);
+  rust_assert (POINTER_TYPE_P (TREE_TYPE (data_pointer)));
+  tree data_offset_expr
+    = Rust::pointer_offset_expression (data_pointer, index_tree, location);
+
+  return build1_loc (location, INDIRECT_REF, element_type, data_offset_expr);
+}
+
 // Create an expression for a call to FN_EXPR with FN_ARGS.
 tree
 call_expression (tree fn, const std::vector<tree> &fn_args, tree chain_expr,
diff --git a/gcc/testsuite/rust/compile/match-slicepattern-slice.rs 
b/gcc/testsuite/rust/compile/match-slicepattern-slice.rs
new file mode 100644
index 000000000000..cc33d938c7be
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-slicepattern-slice.rs
@@ -0,0 +1,10 @@
+fn main() {
+    let arr = [1, 2];
+    let slice: &[i32] = &arr;
+
+    match slice {
+        [1] => {},
+        [_, 2] => {},
+        _ => {}
+    }
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/execute/torture/match-slicepattern-slice-1.rs 
b/gcc/testsuite/rust/execute/torture/match-slicepattern-slice-1.rs
new file mode 100644
index 000000000000..3ed0b644fb7e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match-slicepattern-slice-1.rs
@@ -0,0 +1,24 @@
+// { dg-output "correct\r*" }
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn main() -> i32 {
+    let arr = [0, 1];
+    let a: &[i32] = &arr;
+    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