Skip to content

Commit 9914023

Browse files
Polygonalrphilberty
authored andcommitted
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>
1 parent 0fc2084 commit 9914023

File tree

5 files changed

+114
-2
lines changed

5 files changed

+114
-2
lines changed

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

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,38 @@ CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern)
555555
case TyTy::TypeKind::SLICE:
556556
rust_sorry_at (
557557
pattern.get_locus (),
558-
"SlicePattern matching against slices are not yet supported");
558+
"SlicePattern matching against non-ref slices are not yet supported");
559+
break;
560+
case TyTy::TypeKind::REF:
561+
{
562+
rust_assert (RS_DST_FLAG_P (TREE_TYPE (match_scrutinee_expr)));
563+
tree size_field
564+
= Backend::struct_field_expression (match_scrutinee_expr, 1,
565+
pattern.get_locus ());
566+
567+
// First compare the size
568+
check_expr = Backend::comparison_expression (
569+
ComparisonOperator::EQUAL, size_field,
570+
build_int_cst (size_type_node, pattern.get_items ().size ()),
571+
pattern.get_locus ());
572+
573+
// Then compare each element in the slice pattern
574+
for (auto &pattern_member : pattern.get_items ())
575+
{
576+
tree slice_index_tree
577+
= Backend::size_constant_expression (array_element_index++);
578+
tree element_expr
579+
= Backend::slice_index_expression (match_scrutinee_expr,
580+
slice_index_tree,
581+
pattern.get_locus ());
582+
tree check_expr_sub
583+
= CompilePatternCheckExpr::Compile (*pattern_member, element_expr,
584+
ctx);
585+
check_expr = Backend::arithmetic_or_logical_expression (
586+
ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
587+
check_expr_sub, pattern.get_locus ());
588+
}
589+
}
559590
break;
560591
default:
561592
rust_unreachable ();
@@ -917,8 +948,23 @@ CompilePatternBindings::visit (HIR::SlicePattern &pattern)
917948
case TyTy::TypeKind::SLICE:
918949
rust_sorry_at (
919950
pattern.get_locus (),
920-
"SlicePattern matching against slices are not yet supported");
951+
"SlicePattern matching against non-ref slices are not yet supported");
921952
break;
953+
case TyTy::TypeKind::REF:
954+
{
955+
for (auto &pattern_member : pattern.get_items ())
956+
{
957+
tree slice_index_tree
958+
= Backend::size_constant_expression (array_element_index++);
959+
tree element_expr
960+
= Backend::slice_index_expression (match_scrutinee_expr,
961+
slice_index_tree,
962+
pattern.get_locus ());
963+
CompilePatternBindings::Compile (*pattern_member, element_expr,
964+
ctx);
965+
}
966+
break;
967+
}
922968
default:
923969
rust_unreachable ();
924970
}

gcc/rust/rust-backend.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,10 @@ tree array_initializer (tree, tree, tree, tree, tree, tree *, location_t);
245245
// fixed-length array, not a slice.
246246
tree array_index_expression (tree array, tree index, location_t);
247247

248+
// Return an expresison for SLICE[INDEX] as an l-value. SLICE is represented
249+
// with a DST.
250+
tree slice_index_expression (tree slice, tree index, location_t);
251+
248252
// Create an expression for a call to FN with ARGS, taking place within
249253
// caller CALLER.
250254
tree call_expression (tree fn, const std::vector<tree> &args, tree static_chain,

gcc/rust/rust-gcc.cc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,6 +1504,34 @@ array_index_expression (tree array_tree, tree index_tree, location_t location)
15041504
return ret;
15051505
}
15061506

1507+
// Return an expression representing SLICE[INDEX]
1508+
1509+
tree
1510+
slice_index_expression (tree slice_tree, tree index_tree, location_t location)
1511+
{
1512+
if (error_operand_p (slice_tree) || error_operand_p (index_tree))
1513+
return error_mark_node;
1514+
1515+
// A slice is created in TyTyResolvecompile::create_slice_type_record
1516+
// For example:
1517+
// &[i32] is turned directly into a struct { i32* data, usize len };
1518+
// [i32] is also turned into struct { i32* data, usize len }
1519+
1520+
// it should have RS_DST_FLAG set to 1
1521+
rust_assert (RS_DST_FLAG_P (TREE_TYPE (slice_tree)));
1522+
1523+
tree data_field = struct_field_expression (slice_tree, 0, location);
1524+
tree data_field_deref = build_fold_indirect_ref_loc (location, data_field);
1525+
1526+
tree element_type = TREE_TYPE (data_field_deref);
1527+
tree data_pointer = TREE_OPERAND (data_field_deref, 0);
1528+
rust_assert (POINTER_TYPE_P (TREE_TYPE (data_pointer)));
1529+
tree data_offset_expr
1530+
= Rust::pointer_offset_expression (data_pointer, index_tree, location);
1531+
1532+
return build1_loc (location, INDIRECT_REF, element_type, data_offset_expr);
1533+
}
1534+
15071535
// Create an expression for a call to FN_EXPR with FN_ARGS.
15081536
tree
15091537
call_expression (tree fn, const std::vector<tree> &fn_args, tree chain_expr,
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
fn main() {
2+
let arr = [1, 2];
3+
let slice: &[i32] = &arr;
4+
5+
match slice {
6+
[1] => {},
7+
[_, 2] => {},
8+
_ => {}
9+
}
10+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// { dg-output "correct\r*" }
2+
extern "C" {
3+
fn puts(s: *const i8);
4+
}
5+
6+
fn main() -> i32 {
7+
let arr = [0, 1];
8+
let a: &[i32] = &arr;
9+
let mut ret = 1;
10+
11+
match a {
12+
[0, 0] => {
13+
/* should not take this path */
14+
unsafe { puts("wrong\0" as *const str as *const i8) }
15+
},
16+
[0, b] => {
17+
ret -= b;
18+
unsafe { puts("correct\0" as *const str as *const i8) }
19+
},
20+
_ => {}
21+
}
22+
23+
ret
24+
}

0 commit comments

Comments
 (0)