harec

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

commit 6b506fe9fe1333efa974b2206a307d7647c47735
parent f6faaf8fd1cb78e62eae69ae5e618cb4ea4b1654
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sat,  3 Jul 2021 10:57:16 -0400

gen: implement function parameters

We still need to fully validate the direct/indirect distinction.

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

Diffstat:
Minclude/gen.h | 3++-
Msrc/gen.c | 53+++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/qtype.c | 44++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 91 insertions(+), 9 deletions(-)

diff --git a/include/gen.h b/include/gen.h @@ -64,6 +64,7 @@ enum qbe_instr load_for_type(struct gen_context *ctx, const struct type *type); // qtype.c const struct qbe_type *qtype_lookup(struct gen_context *ctx, - const struct type *type, bool xtype); + const struct type *type, bool xtype); +bool type_is_aggregate(const struct type *type); #endif diff --git a/src/gen.c b/src/gen.c @@ -88,16 +88,21 @@ load_temp(struct gen_context *ctx, out->kind = QV_TEMPORARY; if (qtype->stype == Q__AGGREGATE) { + assert(temp->indirect); out->name = temp->name; out->type = ctx->arch.ptr; } else { out->name = gen_name(ctx, "load.%d"); out->type = qtype; - struct qbe_value addr; - qval_temp(ctx, &addr, temp); - enum qbe_instr instr = load_for_type(ctx, temp->type); - pushi(ctx->current, out, instr, &addr, NULL); + struct qbe_value src; + qval_temp(ctx, &src, temp); + if (temp->indirect) { + enum qbe_instr instr = load_for_type(ctx, temp->type); + pushi(ctx->current, out, instr, &src, NULL); + } else { + pushi(ctx->current, out, Q_COPY, &src, NULL); + } } } @@ -208,8 +213,12 @@ gen_copy(struct gen_context *ctx, load_temp(ctx, &value, src); qval_temp(ctx, &dtemp, dest); - enum qbe_instr instr = store_for_type(ctx, dtype); - pushi(ctx->current, NULL, instr, &value, &dtemp, NULL); + if (dest->indirect) { + enum qbe_instr instr = store_for_type(ctx, dtype); + pushi(ctx->current, NULL, instr, &value, &dtemp, NULL); + } else { + pushi(ctx->current, &dtemp, Q_COPY, &value, NULL); + } } static void gen_expr(struct gen_context *ctx, @@ -223,6 +232,7 @@ gen_address_object(struct gen_context *ctx, struct gen_temp *temp, const struct scope_object *obj) { const struct gen_binding *binding = binding_lookup(ctx, obj); + assert(binding->temp.indirect); *temp = binding->temp; } @@ -624,8 +634,35 @@ gen_function_decl(struct gen_context *ctx, const struct declaration *decl) qdef->func.returns = &qbe_void; } - // TODO: Allocate parameters - assert(!func->scope->objects); + struct qbe_func_param *param, **next = &qdef->func.params; + struct scope_object *obj = decl->func.scope->objects; + while (obj) { + param = *next = xcalloc(1, sizeof(struct qbe_func_param)); + assert(!obj->ident.ns); // Invariant + param->name = strdup(obj->ident.name); + param->type = qtype_lookup(ctx, obj->type, false); + + struct gen_binding *gb = xcalloc(1, sizeof(struct gen_binding)); + if (type_is_aggregate(obj->type)) { + gb->temp.name = strdup(param->name); + gb->temp.type = obj->type; + gb->temp.indirect = true; + } else { + alloc_temp(ctx, &gb->temp, obj->type, "parameter.%d"); + struct gen_temp temp = { + .name = param->name, + .type = obj->type, + .indirect = false, + }; + gen_copy(ctx, &gb->temp, &temp); + } + gb->object = obj; + gb->next = ctx->bindings; + ctx->bindings = gb; + + obj = obj->lnext; + next = &param->next; + } pushl(&qdef->func, &ctx->id, "body.%d"); gen_expr(ctx, func->body, ctx->rval); diff --git a/src/qtype.c b/src/qtype.c @@ -163,3 +163,47 @@ const struct qbe_type *qtype_lookup( } abort(); // Invariant } + +bool +type_is_aggregate(const struct type *type) +{ + switch (type->storage) { + case STORAGE_BOOL: + case STORAGE_CHAR: + case STORAGE_ENUM: + case STORAGE_F32: + case STORAGE_F64: + case STORAGE_I16: + case STORAGE_I32: + case STORAGE_I64: + case STORAGE_I8: + case STORAGE_INT: + case STORAGE_POINTER: + case STORAGE_NULL: + case STORAGE_RUNE: + case STORAGE_SIZE: + case STORAGE_U16: + case STORAGE_U32: + case STORAGE_U64: + case STORAGE_U8: + case STORAGE_UINT: + case STORAGE_UINTPTR: + case STORAGE_VOID: + return false; + case STORAGE_ALIAS: + return type_is_aggregate(type->alias.type); + case STORAGE_ARRAY: + case STORAGE_SLICE: + case STORAGE_STRING: + case STORAGE_STRUCT: + case STORAGE_TAGGED: + case STORAGE_TUPLE: + case STORAGE_UNION: + case STORAGE_FUNCTION: + return true; + case STORAGE_FCONST: + case STORAGE_ICONST: + assert(0); // Lowered in check + } + assert(0); // Unreachable +}