harec

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

commit cb04bf126f6fc918fbb49da08c18ec1f81fa5451
parent e03bafbc84892e59bc7054b5433083d88def7298
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun,  1 Aug 2021 09:33:24 +0200

gen: access expressions

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

Diffstat:
Minclude/gen.h | 1+
Msrc/gen.c | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/include/gen.h b/include/gen.h @@ -37,6 +37,7 @@ struct gen_value { }; struct gen_binding { + const struct scope_object *object; struct gen_value value; struct gen_binding *next; }; diff --git a/src/gen.c b/src/gen.c @@ -38,10 +38,67 @@ gen_store(struct gen_context *ctx, pushi(ctx->current, NULL, qi, &qval, &qobj, NULL); } +static struct gen_value +gen_load(struct gen_context *ctx, struct gen_value object) +{ + switch (type_dealias(object.type)->storage) { + case STORAGE_ARRAY: + case STORAGE_ENUM: + case STORAGE_SLICE: + case STORAGE_STRING: + case STORAGE_STRUCT: + case STORAGE_TAGGED: + case STORAGE_TUPLE: + case STORAGE_UNION: + assert(0); // TODO + default: + break; // no-op + } + + struct gen_value value = { + .kind = GV_TEMP, + .type = object.type, + .name = gen_name(ctx, "load.%d"), + }; + struct qbe_value qobj = mkqval(ctx, &object), + qval = mkqval(ctx, &value); + enum qbe_instr qi = load_for_type(ctx, object.type); + pushi(ctx->current, &qval, qi, &qobj, NULL); + return value; +} + static struct gen_value gen_expr(struct gen_context *ctx, const struct expression *expr); static struct gen_value +gen_access_ident(struct gen_context *ctx, const struct expression *expr) +{ + for (const struct gen_binding *gb = ctx->bindings; gb; gb = gb->next) { + if (gb->object == expr->access.object) { + return gb->value; + } + } + abort(); // Invariant +} + +static struct gen_value +gen_expr_access(struct gen_context *ctx, const struct expression *expr) +{ + struct gen_value addr; + switch (expr->access.type) { + case ACCESS_IDENTIFIER: + addr = gen_access_ident(ctx, expr); + break; + case ACCESS_INDEX: + case ACCESS_FIELD: + case ACCESS_TUPLE: + assert(0); // TODO + } + + return gen_load(ctx, addr); +} + +static struct gen_value gen_expr_binding(struct gen_context *ctx, const struct expression *expr) { for (const struct expression_binding *binding = &expr->binding; @@ -51,6 +108,7 @@ gen_expr_binding(struct gen_context *ctx, const struct expression *expr) gb->value.kind = GV_TEMP; gb->value.type = type; gb->value.name = gen_name(ctx, "binding.%d"); + gb->object = binding->object; gb->next = ctx->bindings; ctx->bindings = gb; @@ -146,6 +204,7 @@ gen_expr(struct gen_context *ctx, const struct expression *expr) { switch (expr->type) { case EXPR_ACCESS: + return gen_expr_access(ctx, expr); case EXPR_ALLOC: case EXPR_APPEND: case EXPR_ASSERT: