aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorYap Zhi Heng <yapzhhg@gmail.com>2025-07-17 22:13:32 +0800
committerArthur Cohen <arthur.cohen@embecosm.com>2025-08-05 16:36:56 +0200
commit39aa96ce9382f455bc071a3aa36f866fef760af1 (patch)
tree30e475314e6b223876c19d2d69aaec48f36d88ae /gcc
parent72eb21fdf97da9613693dfcebe7b3270b133b7f0 (diff)
downloadgcc-39aa96ce9382f455bc071a3aa36f866fef760af1.zip
gcc-39aa96ce9382f455bc071a3aa36f866fef760af1.tar.gz
gcc-39aa96ce9382f455bc071a3aa36f866fef760af1.tar.bz2
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 <yapzhhg@gmail.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/backend/rust-compile-pattern.cc85
-rw-r--r--gcc/rust/backend/rust-compile-pattern.h4
-rw-r--r--gcc/rust/rust-backend.h3
-rw-r--r--gcc/rust/rust-gcc.cc6
-rw-r--r--gcc/testsuite/rust/compile/match-slicepattern-array.rs8
-rw-r--r--gcc/testsuite/rust/execute/torture/match-slicepattern-array-1.rs23
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 3351bec..6d889ba 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 4dd7d55..233799e 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 2d813d9..8a77d96 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 42cdc6c..c5fda5c 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 0000000..e48ca75
--- /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 0000000..95c55d8
--- /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
+}