harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit e745c6f48fa18ee3b4b7a46771575d567cd9f15a
parent e4e051ebd818de9f2d4ea66f657366a999edeeb5
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri,  2 Jul 2021 14:37:31 -0400

gen: basic array support

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Msrc/gen.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/qtype.c | 4++++
2 files changed, 77 insertions(+), 2 deletions(-)

diff --git a/src/gen.c b/src/gen.c @@ -98,6 +98,45 @@ binding_lookup(struct gen_context *ctx, const struct scope_object *obj) abort(); // Invariant } +static void +gen_copy_memcpy(struct gen_context *ctx, + const struct gen_temp *dest, + const struct gen_temp *src) +{ + struct qbe_value rtfunc = {0}, size = {0}; + rtfunc.kind = QV_GLOBAL; + rtfunc.name = strdup("rt.memcpy"); + rtfunc.type = &qbe_long; + constl(&size, dest->type->size); + struct qbe_value dtemp = { + .kind = QV_TEMPORARY, + .type = ctx->arch.ptr, + .name = dest->name, + }, stemp = { + .kind = QV_TEMPORARY, + .type = ctx->arch.ptr, + .name = src->name, + }; + pushi(ctx->current, NULL, Q_CALL, &rtfunc, + &dtemp, &stemp, &size, NULL); +} + +static void +gen_copy_array(struct gen_context *ctx, + const struct gen_temp *dest, + const struct gen_temp *src) +{ + const struct type *atype = type_dealias(dest->type); + assert(atype->storage == STORAGE_ARRAY); + assert(atype->array.length != SIZE_UNDEFINED); + if (atype->array.length > 8) { + gen_copy_memcpy(ctx, dest, src); + return; + } + // TODO: Generate more efficient approach + gen_copy_memcpy(ctx, dest, src); +} + // Generates a copy operation from one gen temporary to another. For primitive // types this is a load+store operation; for aggregate types this may emit more // complex code or a memcpy. @@ -127,9 +166,11 @@ gen_copy(struct gen_context *ctx, case STORAGE_U8: case STORAGE_UINT: case STORAGE_UINTPTR: - // fallthrough + // Implemented below break; case STORAGE_ARRAY: + gen_copy_array(ctx, dest, src); + return; case STORAGE_FUNCTION: case STORAGE_POINTER: case STORAGE_SLICE: @@ -257,6 +298,33 @@ gen_expr_binding(struct gen_context *ctx, } static void +gen_expr_const_array(struct gen_context *ctx, + const struct type *atype, + const struct array_constant *expr, + const struct gen_temp *out) +{ + assert(!expr->expand); // TODO + + struct qbe_value base = {0}, ptr = {0}, membsz = {0}; + qval_temp(ctx, &base, out); + gen_qtemp(ctx, &ptr, ctx->arch.ptr, "offset.%d"); + constl(&membsz, atype->array.members->size); + pushi(ctx->current, &ptr, Q_COPY, &base, NULL); + + for (const struct array_constant *ac = expr; ac; ac = ac->next) { + struct gen_temp temp = { + .type = atype->array.members, + .name = ptr.name, + }; + gen_expr(ctx, ac->value, &temp); + + if (ac->next) { + pushi(ctx->current, &ptr, Q_ADD, &ptr, &membsz, NULL); + } + } +} + +static void gen_expr_constant(struct gen_context *ctx, const struct expression *expr, const struct gen_temp *out) @@ -309,9 +377,12 @@ gen_expr_constant(struct gen_context *ctx, abort(); } break; + case STORAGE_ARRAY: + gen_expr_const_array(ctx, type_dealias(expr->result), + constexpr->array, out); + return; case STORAGE_UINTPTR: case STORAGE_POINTER: - case STORAGE_ARRAY: case STORAGE_NULL: case STORAGE_SLICE: case STORAGE_STRING: diff --git a/src/qtype.c b/src/qtype.c @@ -39,6 +39,10 @@ aggregate_lookup(struct gen_context *ctx, const struct type *type) struct qbe_field *field = &def->type.fields; switch (type->storage) { case STORAGE_ARRAY: + assert(type->array.length != SIZE_UNDEFINED); + field->count = type->array.length; + field->type = qtype_lookup(ctx, type->array.members, true); + break; case STORAGE_STRING: assert(0); // TODO case STORAGE_STRUCT: