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>
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 ();
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 ();
}
// 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,
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,
--- /dev/null
+fn main() {
+ let arr = [1, 2];
+ let slice: &[i32] = &arr;
+
+ match slice {
+ [1] => {},
+ [_, 2] => {},
+ _ => {}
+ }
+}
\ No newline at end of file
--- /dev/null
+// { 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
+}