Skip to content

Commit 98ddf74

Browse files
Polygonalrphilberty
authored andcommitted
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 <[email protected]>
1 parent 5dc8c4d commit 98ddf74

File tree

6 files changed

+127
-2
lines changed

6 files changed

+127
-2
lines changed

gcc/rust/backend/rust-compile-pattern.cc

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,53 @@ CompilePatternCheckExpr::visit (HIR::IdentifierPattern &pattern)
514514
}
515515
}
516516

517+
void
518+
CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern)
519+
{
520+
check_expr = boolean_true_node;
521+
522+
// lookup the type
523+
TyTy::BaseType *lookup = nullptr;
524+
bool ok
525+
= ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (),
526+
&lookup);
527+
rust_assert (ok);
528+
529+
// pattern must either be ArrayType or SliceType, should be already confirmed
530+
// by type checking
531+
rust_assert (lookup->get_kind () == TyTy::TypeKind::ARRAY
532+
|| lookup->get_kind () == TyTy::TypeKind::SLICE);
533+
534+
size_t array_element_index = 0;
535+
switch (lookup->get_kind ())
536+
{
537+
case TyTy::TypeKind::ARRAY:
538+
for (auto &pattern_member : pattern.get_items ())
539+
{
540+
tree array_index_tree
541+
= Backend::size_constant_expression (array_element_index++);
542+
tree element_expr
543+
= Backend::array_index_expression (match_scrutinee_expr,
544+
array_index_tree,
545+
pattern.get_locus ());
546+
tree check_expr_sub
547+
= CompilePatternCheckExpr::Compile (*pattern_member, element_expr,
548+
ctx);
549+
check_expr = Backend::arithmetic_or_logical_expression (
550+
ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
551+
check_expr_sub, pattern.get_locus ());
552+
}
553+
break;
554+
case TyTy::TypeKind::SLICE:
555+
rust_sorry_at (
556+
pattern.get_locus (),
557+
"SlicePattern matching against slices are not yet supported");
558+
break;
559+
default:
560+
rust_unreachable ();
561+
}
562+
}
563+
517564
// setup the bindings
518565

519566
void
@@ -837,6 +884,44 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern)
837884
}
838885
}
839886

887+
void
888+
CompilePatternBindings::visit (HIR::SlicePattern &pattern)
889+
{
890+
// lookup the type
891+
TyTy::BaseType *lookup = nullptr;
892+
bool ok
893+
= ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (),
894+
&lookup);
895+
rust_assert (ok);
896+
897+
rust_assert (lookup->get_kind () == TyTy::TypeKind::ARRAY
898+
|| lookup->get_kind () == TyTy::TypeKind::SLICE);
899+
900+
size_t array_element_index = 0;
901+
switch (lookup->get_kind ())
902+
{
903+
case TyTy::TypeKind::ARRAY:
904+
for (auto &pattern_member : pattern.get_items ())
905+
{
906+
tree array_index_tree
907+
= Backend::size_constant_expression (array_element_index++);
908+
tree element_expr
909+
= Backend::array_index_expression (match_scrutinee_expr,
910+
array_index_tree,
911+
pattern.get_locus ());
912+
CompilePatternBindings::Compile (*pattern_member, element_expr, ctx);
913+
}
914+
break;
915+
case TyTy::TypeKind::SLICE:
916+
rust_sorry_at (
917+
pattern.get_locus (),
918+
"SlicePattern matching against slices are not yet supported");
919+
break;
920+
default:
921+
rust_unreachable ();
922+
}
923+
}
924+
840925
//
841926

842927
void

gcc/rust/backend/rust-compile-pattern.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class CompilePatternCheckExpr : public HIRCompileBase,
4646
void visit (HIR::TupleStructPattern &) override;
4747
void visit (HIR::TuplePattern &) override;
4848
void visit (HIR::IdentifierPattern &) override;
49+
void visit (HIR::SlicePattern &) override;
4950

5051
// Always succeeds
5152
void visit (HIR::WildcardPattern &) override
@@ -55,7 +56,6 @@ class CompilePatternCheckExpr : public HIRCompileBase,
5556

5657
// Empty visit for unused Pattern HIR nodes.
5758
void visit (HIR::QualifiedPathInExpression &) override {}
58-
void visit (HIR::SlicePattern &) override {}
5959

6060
CompilePatternCheckExpr (Context *ctx, tree match_scrutinee_expr)
6161
: HIRCompileBase (ctx), match_scrutinee_expr (match_scrutinee_expr),
@@ -95,14 +95,14 @@ class CompilePatternBindings : public HIRCompileBase,
9595
void visit (HIR::ReferencePattern &pattern) override;
9696
void visit (HIR::IdentifierPattern &) override;
9797
void visit (HIR::TuplePattern &pattern) override;
98+
void visit (HIR::SlicePattern &) override;
9899

99100
// Empty visit for unused Pattern HIR nodes.
100101
void visit (HIR::AltPattern &) override {}
101102
void visit (HIR::LiteralPattern &) override {}
102103
void visit (HIR::PathInExpression &) override {}
103104
void visit (HIR::QualifiedPathInExpression &) override {}
104105
void visit (HIR::RangePattern &) override {}
105-
void visit (HIR::SlicePattern &) override {}
106106
void visit (HIR::WildcardPattern &) override {}
107107

108108
protected:

gcc/rust/rust-backend.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ tree char_constant_expression (char c);
176176
// Get a char literal
177177
tree wchar_constant_expression (wchar_t c);
178178

179+
// Get a size literal
180+
tree size_constant_expression (size_t val);
181+
179182
// Return an expression for the boolean value VAL.
180183
tree boolean_constant_expression (bool val);
181184

gcc/rust/rust-gcc.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,12 @@ char_constant_expression (char c)
818818
return build_int_cst (char_type_node, c);
819819
}
820820

821+
tree
822+
size_constant_expression (size_t val)
823+
{
824+
return size_int (val);
825+
}
826+
821827
// Make a constant boolean expression.
822828

823829
tree
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn main() {
2+
let a = [0, 1];
3+
4+
match a {
5+
[0, 1] => {},
6+
_ => {}
7+
}
8+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// { dg-output "correct\r*" }
2+
extern "C" {
3+
fn puts(s: *const i8);
4+
}
5+
6+
fn main() -> i32 {
7+
let a = [0, 1];
8+
let mut ret = 1;
9+
10+
match a {
11+
[0, 0] => {
12+
/* should not take this path */
13+
unsafe { puts("wrong\0" as *const str as *const i8) }
14+
},
15+
[0, b] => {
16+
ret -= b;
17+
unsafe { puts("correct\0" as *const str as *const i8) }
18+
},
19+
_ => {}
20+
}
21+
22+
ret
23+
}

0 commit comments

Comments
 (0)