commit 1730c7d71a8865c5cdca4752c255c9d65bc674f7
parent ed6140b383e8f9824912b7d7b9bbb38ab8b0e377
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 24 Jan 2021 12:05:21 -0500
gen: fix slicing pointers to objects
Diffstat:
3 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/src/check.c b/src/check.c
@@ -1050,8 +1050,8 @@ check_expr_slice(struct context *ctx,
expect(&aexpr->slice.object->loc, atype,
"Cannot dereference nullable pointer for slicing");
expect(&aexpr->slice.object->loc,
- expr->slice.object->result->storage == TYPE_STORAGE_SLICE ||
- expr->slice.object->result->storage == TYPE_STORAGE_ARRAY,
+ atype->storage == TYPE_STORAGE_SLICE
+ || atype->storage == TYPE_STORAGE_ARRAY,
"Cannot slice non-array, non-slice object");
const struct type *itype;
@@ -1079,8 +1079,7 @@ check_expr_slice(struct context *ctx,
// TODO: Assert that array type has a well-defined length
}
- expr->result = type_store_lookup_slice(ctx->store,
- expr->slice.object->result->array.members);
+ expr->result = type_store_lookup_slice(ctx->store, atype->array.members);
trleave(TR_CHECK, NULL);
}
diff --git a/src/gen.c b/src/gen.c
@@ -1653,13 +1653,21 @@ gen_expr_slice(struct gen_context *ctx,
const struct qbe_value *out)
{
// XXX: ARCH
- struct qbe_value object = {0}, start = {0}, end = {0};
+ struct qbe_value object = {0}, start = {0}, end = {0}, temp = {0};
const struct type *otype = expr->slice.object->result;
- address_object(ctx, expr->slice.object, &object);
+ address_object(ctx, expr->slice.object, &temp);
+ gen_temp(ctx, &object, object.type, "object.%d");
+ object.type = temp.type;
+ pushi(ctx->current, &object, Q_COPY, &temp, NULL);
+ while (otype->storage == TYPE_STORAGE_POINTER) {
+ pushi(ctx->current, &object, Q_LOADL, &object, NULL);
+ otype = type_dereference(otype->pointer.referent);
+ }
+
gen_temp(ctx, &start, &qbe_long, "start.%d");
gen_temp(ctx, &end, &qbe_long, "end.%d");
- struct qbe_value src = {0}, dest = {0}, temp = {0}, offset = {0};
+ struct qbe_value src = {0}, dest = {0}, offset = {0};
gen_temp(ctx, &dest, &qbe_long, "dest.%d");
gen_temp(ctx, &offset, &qbe_long, "offset.%d");
diff --git a/tests/08-slices.ha b/tests/08-slices.ha
@@ -83,6 +83,12 @@ fn slicing() void = {
assert_slice_eq(b[..3], [1, 2, 3]);
assert_slice_eq(b[1..3], [2, 3]);
assert_slice_eq(b[1..], [2, 3, 4, 5]);
+
+ let p = &a;
+ assert_slice_eq(p[..], [1, 2, 3, 4, 5]);
+ assert_slice_eq(p[..3], [1, 2, 3]);
+ assert_slice_eq(p[1..3], [2, 3]);
+ assert_slice_eq(p[1..], [2, 3, 4, 5]);
assert(rt::compile(
"fn test() void = { let x = \"test\"; x[1..3]; };"