harec

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

commit a927ad1e6d57666db87b6294eed6a8bfe2a482fa
parent 932bf67c86c7e9fa04dccd6f4d4fff78db7cc50b
Author: Drew DeVault <sir@cmpwn.com>
Date:   Mon, 28 Dec 2020 10:01:10 -0500

gen: fix various issues with array types

- always treat aggregate values as direct
- update indexing to handle nested aggregates properly
- add code paths to gen_store for various aggregate scenarios

Diffstat:
Mgen.txt | 4++--
Msrc/gen.c | 38+++++++++++++++++++++++++++-----------
2 files changed, 29 insertions(+), 13 deletions(-)

diff --git a/gen.txt b/gen.txt @@ -5,9 +5,9 @@ TODO: - aggregate - aggregate type assignment - nested aggregate types - - binding + - binding ✓ - assignment - - indexing + - indexing ✓ diff --git a/src/gen.c b/src/gen.c @@ -63,6 +63,9 @@ binding_alloc(struct gen_context *ctx, const struct scope_object *obj, { struct gen_binding *binding = xcalloc(1, sizeof(struct gen_binding)); alloc_temp(ctx, val, obj->type, fmt); + if (type_is_aggregate(obj->type)) { + val->indirect = false; + } binding->name = strdup(val->name); binding->object = obj; binding->next = ctx->bindings; @@ -102,7 +105,8 @@ qval_for_object(struct gen_context *ctx, } if (type_is_aggregate(obj->type)) { - val->type = &qbe_aggregate; + val->type = &qbe_aggregate; // TODO: Lookup actual type + val->indirect = false; } else { val->type = &qbe_long; // XXX: ARCH } @@ -136,8 +140,17 @@ gen_store(struct gen_context *ctx, assert(src->type->stype != Q__VOID && dest->type->stype != Q__VOID); // Invariant - assert(src->type->stype != Q__AGGREGATE - && dest->type->stype != Q__AGGREGATE); // TODO: Fuck me + + if (src->type->stype == Q__AGGREGATE) { + assert(!dest->indirect && !src->indirect); + if (dest->type->stype == Q__AGGREGATE) { + assert(0); // TODO: memcpy + } else { + assert(dest->type == &qbe_long); + pushi(ctx->current, dest, Q_COPY, src, NULL); + } + return; + } assert(!src->indirect); if (dest->indirect) { @@ -224,12 +237,15 @@ gen_expr_access_index(struct gen_context *ctx, constl(&temp, atype->array.members->size); pushi(ctx->current, &index, Q_MUL, &index, &temp, NULL); pushi(ctx->current, &obj, Q_ADD, &obj, &index, NULL); - qval_deref(&obj); - - gen_loadtemp(ctx, &temp, &obj, - qtype_for_type(ctx, atype->array.members, true), - type_is_signed(atype->array.members)); - gen_store(ctx, out, &temp); + if (!type_is_aggregate(atype->array.members)) { + qval_deref(&obj); + gen_loadtemp(ctx, &temp, &obj, + qtype_for_type(ctx, atype->array.members, true), + type_is_signed(atype->array.members)); + gen_store(ctx, out, &temp); + } else { + gen_store(ctx, out, &obj); + } } static void @@ -376,14 +392,14 @@ gen_array(struct gen_context *ctx, const struct qbe_value *out) { const struct type *type = expr->result; - assert(out->indirect); // Invariant + assert(!out->indirect); // Invariant assert(!type->array.expandable); // Invariant // XXX: ARCH struct qbe_value ptr = {0}; gen_temp(ctx, &ptr, &qbe_long, "ptr.%d"); pushi(ctx->current, &ptr, Q_COPY, out, NULL); - ptr.indirect = true; + ptr.indirect = !type_is_aggregate(type->array.members); struct qbe_value size = {0}; constl(&size, type->array.members->size);