harec

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

commit e03bafbc84892e59bc7054b5433083d88def7298
parent 4ba09b87472e233e2a2d7858fcd4f723a8553a67
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sat, 31 Jul 2021 19:35:46 +0200

gen: binding expressions

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

Diffstat:
Minclude/gen.h | 14++++++++++----
Minclude/qbe.h | 6+-----
Msrc/gen.c | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/genutil.c | 8++++++++
Msrc/qbe.c | 43+++++++------------------------------------
5 files changed, 77 insertions(+), 45 deletions(-)

diff --git a/include/gen.h b/include/gen.h @@ -13,6 +13,11 @@ enum fixed_aborts { ABORT_STATIC_EXCEEDED = 3, }; +struct gen_arch { + const struct qbe_type *ptr; + const struct qbe_type *sz; +}; + enum gen_value_kind { GV_CONST, GV_GLOBAL, @@ -31,9 +36,9 @@ struct gen_value { }; }; -struct gen_arch { - const struct qbe_type *ptr; - const struct qbe_type *sz; +struct gen_binding { + struct gen_value value; + struct gen_binding *next; }; struct gen_context { @@ -46,7 +51,7 @@ struct gen_context { struct qbe_func *current; const struct type *functype; - const char *end; + struct gen_binding *bindings; }; struct unit; @@ -58,6 +63,7 @@ void gen(const struct unit *unit, // genutil.c char *gen_name(struct gen_context *ctx, const char *fmt); struct qbe_value mkqval(struct gen_context *ctx, struct gen_value *value); +struct qbe_value mklval(struct gen_context *ctx, struct gen_value *value); // qinstr.c enum qbe_instr alloc_for_align(size_t align); diff --git a/include/qbe.h b/include/qbe.h @@ -262,10 +262,6 @@ void push(struct qbe_statements *stmts, struct qbe_statement *stmt); struct qbe_value *qval_dup(const struct qbe_value *val); -void constw(struct qbe_value *val, uint32_t l); -void constl(struct qbe_value *val, uint64_t l); -void consts(struct qbe_value *val, float l); -void constd(struct qbe_value *val, double l); -void const_void(struct qbe_value *val); +struct qbe_value constl(uint64_t l); #endif diff --git a/src/gen.c b/src/gen.c @@ -13,10 +13,59 @@ static const struct gen_value gv_void = { .type = &builtin_type_void, }; +static void +gen_store(struct gen_context *ctx, + struct gen_value object, + struct gen_value value) +{ + 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 qbe_value qobj = mkqval(ctx, &object), + qval = mkqval(ctx, &value); + enum qbe_instr qi = store_for_type(ctx, object.type); + pushi(ctx->current, NULL, qi, &qval, &qobj, NULL); +} + static struct gen_value gen_expr(struct gen_context *ctx, const struct expression *expr); static struct gen_value +gen_expr_binding(struct gen_context *ctx, const struct expression *expr) +{ + for (const struct expression_binding *binding = &expr->binding; + binding; binding = binding->next) { + const struct type *type = binding->initializer->result; + struct gen_binding *gb = xcalloc(1, sizeof(struct gen_binding)); + gb->value.kind = GV_TEMP; + gb->value.type = type; + gb->value.name = gen_name(ctx, "binding.%d"); + gb->next = ctx->bindings; + ctx->bindings = gb; + + struct qbe_value qv = mklval(ctx, &gb->value); + struct qbe_value sz = constl(type->size); + enum qbe_instr qi = alloc_for_align(type->align); + pushprei(ctx->current, &qv, qi, &sz, NULL); + + struct gen_value init = gen_expr(ctx, binding->initializer); + gen_store(ctx, gb->value, init); + } + return gv_void; +} + +static struct gen_value gen_expr_const(struct gen_context *ctx, const struct expression *expr) { struct gen_value val = { @@ -102,7 +151,9 @@ gen_expr(struct gen_context *ctx, const struct expression *expr) case EXPR_ASSERT: case EXPR_ASSIGN: case EXPR_BINARITHM: + assert(0); // TODO case EXPR_BINDING: + return gen_expr_binding(ctx, expr); case EXPR_BREAK: case EXPR_CALL: case EXPR_CAST: diff --git a/src/genutil.c b/src/genutil.c @@ -35,3 +35,11 @@ mkqval(struct gen_context *ctx, struct gen_value *value) qval.type = qtype_lookup(ctx, value->type, true); return qval; } + +struct qbe_value +mklval(struct gen_context *ctx, struct gen_value *value) +{ + struct qbe_value qval = mkqval(ctx, value); + qval.type = ctx->arch.ptr; + return qval; +} diff --git a/src/qbe.c b/src/qbe.c @@ -265,41 +265,12 @@ pushc(struct qbe_func *func, const char *fmt, ...) push(&func->body, &stmt); } -void -constw(struct qbe_value *val, uint32_t w) -{ - val->kind = QV_CONST; - val->type = &qbe_word; - val->wval = w; -} - -void -constl(struct qbe_value *val, uint64_t l) -{ - val->kind = QV_CONST; - val->type = &qbe_long; - val->lval = l; -} - -void -consts(struct qbe_value *val, float s) -{ - val->kind = QV_CONST; - val->type = &qbe_single; - val->sval = s; -} - -void -constd(struct qbe_value *val, double d) -{ - val->kind = QV_CONST; - val->type = &qbe_double; - val->dval = d; -} - -void -const_void(struct qbe_value *val) +struct qbe_value +constl(uint64_t l) { - val->kind = QV_CONST; - val->type = &qbe_void; + return (struct qbe_value){ + .kind = QV_CONST, + .type = &qbe_long, + .lval = l, + }; }