harec

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

commit ca87307666e26afeb337c89259f900a34ac09eb3
parent c9ca244381beb97ce49c08eb7c1dacbcb8c79f67
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sat, 24 Jul 2021 09:37:05 +0200

gen: implement automatic dereference

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

Diffstat:
Msrc/gen.c | 26+++++++++++++++++++++++++-
Atests/904-deref.ha | 18++++++++++++++++++
Mtests/configure | 4+++-
3 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/src/gen.c b/src/gen.c @@ -161,6 +161,24 @@ gen_copy(struct gen_context *ctx, store_temp(ctx, dest, &value); } +static void +auto_deref(struct gen_context *ctx, struct gen_temp *val) +{ + const struct type *type = val->type; + struct qbe_value qval = {0}; + qval_temp(ctx, &qval, val); + while (type_dealias(type)->storage == STORAGE_POINTER) { + type = type_dealias(type)->pointer.referent; + // XXX: On some obsolete architectures, uintptr and pointer are + // not necessarily the same representation. + pushi(ctx->current, &qval, + load_for_type(ctx, &builtin_type_uintptr), + &qval, NULL); + } + val->type = type; + val->indirect = true; +} + static void gen_expr(struct gen_context *ctx, const struct expression *expr, const struct gen_temp *out); @@ -200,15 +218,19 @@ gen_address_field(struct gen_context *ctx, struct gen_temp *temp, const struct expression *object = access->_struct; assert(object->type == EXPR_ACCESS); // TODO: Other cases? + pushc(ctx->current, "XXX"); + struct gen_temp base = {0}; struct qbe_value qbase = {0}, field = {0}, offset = {0}; gen_access_address(ctx, &base, object); + auto_deref(ctx, &base); qval_temp(ctx, &qbase, &base); gen_qtemp(ctx, &field, ctx->arch.ptr, "field.%d"); constl(&offset, access->field->offset); pushi(ctx->current, &field, Q_ADD, &qbase, &offset, NULL); temp->name = field.name; temp->type = access->field->type; + temp->indirect = true; } static void @@ -217,12 +239,14 @@ gen_address_index(struct gen_context *ctx, struct gen_temp *temp, { assert(access->type == ACCESS_INDEX); - const struct type *atype = access->array->result; + const struct type *atype = type_dereference(access->array->result); + assert(atype->storage == STORAGE_ARRAY); const struct expression *object = access->array; assert(object->type == EXPR_ACCESS); // TODO: Other cases? struct gen_temp base = {0}; gen_access_address(ctx, &base, object); + auto_deref(ctx, &base); struct gen_temp index = {0}; gen_direct(ctx, &index, &builtin_type_size, "index.%d"); diff --git a/tests/904-deref.ha b/tests/904-deref.ha @@ -0,0 +1,18 @@ +type coords = struct { x: int, y: int }; + +export fn main() int = { + let a = coords { x = 10, y = 20 }; + let b = &a; + let c = &b; + assert(a.x == 10); + assert(b.x == 10); + assert(c.x == 10); + + let x = [1, 3, 3, 7]; + let y = &x; + let z = &y; + assert(x[2] == 3); + assert(y[2] == 3); + assert(z[2] == 3); + return 0; +}; diff --git a/tests/configure b/tests/configure @@ -6,7 +6,9 @@ tests() { for t in \ 900-basics \ 901-primitives \ - 902-arithm + 902-arithm \ + 903-call \ + 904-deref do cat <<EOF tests/$t: tests/$t.ha