commit 34c063ebdda44768262a2ecae2cb3b4f320f8c8b
parent 70cd7548e3cea3bf2b326c1328879912de348d99
Author: Drew DeVault <sir@cmpwn.com>
Date: Thu, 8 Jul 2021 17:02:21 -0400
gen: emit memcpy for initializing large arrays
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
2 files changed, 37 insertions(+), 12 deletions(-)
diff --git a/src/gen.c b/src/gen.c
@@ -1599,19 +1599,35 @@ gen_array(struct gen_context *ctx,
}
pushc(ctx->current, "expanding array to length %zd", type->array.length);
- struct qbe_value last = {0};
- if (type_is_aggregate(type->array.members)) {
- alloc_temp(ctx, &last, type->array.members, "expand.%d");
- qval_deref(&last);
+ if (type->array.length < 16) {
+ struct qbe_value last = {0};
+ if (type_is_aggregate(type->array.members)) {
+ alloc_temp(ctx, &last, type->array.members, "expand.%d");
+ qval_deref(&last);
+ } else {
+ gen_temp(ctx, &last,
+ qtype_for_type(ctx, type->array.members, false),
+ "expand.%d");
+ }
+ gen_load(ctx, &last, &val, type_is_signed(type->array.members));
+ for (; n < type->array.length; ++n) {
+ pushi(ctx->current, &ptr, Q_ADD, &ptr, &size, NULL);
+ gen_store(ctx, &val, &last);
+ }
} else {
- gen_temp(ctx, &last,
- qtype_for_type(ctx, type->array.members, false),
- "expand.%d");
- }
- gen_load(ctx, &last, &val, type_is_signed(type->array.members));
- for (; n < type->array.length; ++n) {
- pushi(ctx->current, &ptr, Q_ADD, &ptr, &size, NULL);
- gen_store(ctx, &val, &last);
+ struct qbe_value totalsize = {0};
+ constl(&totalsize, (type->array.length - n) * type->array.members->size);
+ struct qbe_value offset = {0};
+ gen_temp(ctx, &offset, &qbe_long, "ptr.%d");
+ pushi(ctx->current, &offset, Q_ADD, &val, &size, NULL);
+ val.type = &qbe_long;
+
+ struct qbe_value rtmemcpy = {0};
+ rtmemcpy.kind = QV_GLOBAL;
+ rtmemcpy.name = strdup("rt.memcpy");
+ rtmemcpy.type = &qbe_long;
+ pushi(ctx->current, NULL, Q_CALL, &rtmemcpy,
+ &offset, &val, &totalsize, NULL);
}
}
diff --git a/tests/01-arrays.ha b/tests/01-arrays.ha
@@ -82,6 +82,15 @@ fn expanded() void = {
for (let i = 0z; i < len(c); i += 1) {
assert(c[i] == expected[i]);
};
+
+ let q: [65535]int = [1, 2, 3...];
+ let expected = [1, 2, 3];
+ for (let i = 0z; i < len(expected); i += 1) {
+ assert(q[i] == expected[i]);
+ };
+ for (let i = 3z; i < len(q); i += 1) {
+ assert(q[i] == 3);
+ };
};
fn extype() void = {