aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYap Zhi Heng <yapzhhg@gmail.com>2025-07-23 08:24:18 +0800
committerArthur Cohen <arthur.cohen@embecosm.com>2025-08-05 16:36:58 +0200
commite80e577df7ca410eac549da61f9a9fd702dc55ea (patch)
tree6c65976ebc9f32f7688d73867941d7dcbb763079
parent495765758a3c434c6767610f377cace4bba8ff1c (diff)
downloadgcc-e80e577df7ca410eac549da61f9a9fd702dc55ea.zip
gcc-e80e577df7ca410eac549da61f9a9fd702dc55ea.tar.gz
gcc-e80e577df7ca410eac549da61f9a9fd702dc55ea.tar.bz2
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 <yapzhhg@gmail.com>
-rw-r--r--gcc/rust/backend/rust-compile-pattern.cc50
-rw-r--r--gcc/rust/rust-backend.h4
-rw-r--r--gcc/rust/rust-gcc.cc28
-rw-r--r--gcc/testsuite/rust/compile/match-slicepattern-slice.rs10
-rw-r--r--gcc/testsuite/rust/execute/torture/match-slicepattern-slice-1.rs24
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 e00de4f..fe65921 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 8a77d96..205eb2b 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 c5fda5c..0f9ccfb 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 0000000..cc33d93
--- /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 0000000..3ed0b644
--- /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
+}