harec

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

commit 96f766c0c35c08428a79b75e5945cbcc92d153da
parent ca87307666e26afeb337c89259f900a34ac09eb3
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Sat, 24 Jul 2021 09:37:38 +0200

gen: implement call expressions

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

Diffstat:
Msrc/gen.c | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/genutil.c | 13++++++++++---
2 files changed, 60 insertions(+), 3 deletions(-)

diff --git a/src/gen.c b/src/gen.c @@ -436,6 +436,53 @@ gen_expr_binding(struct gen_context *ctx, } static void +gen_expr_call(struct gen_context *ctx, + const struct expression *expr, + const struct gen_temp *out) +{ + struct gen_temp lvalue = {0}; + gen_direct(ctx, &lvalue, expr->call.lvalue->result, "call.lvalue.%d"); + gen_expr(ctx, expr->call.lvalue, &lvalue); + auto_deref(ctx, &lvalue); + + const struct type *rtype = lvalue.type; + assert(rtype->storage == STORAGE_FUNCTION); + // TODO: Run deferred expressions if rtype->func.flags & FN_NORETURN + struct qbe_statement call = { + .type = Q_INSTR, + .instr = Q_CALL, + }; + struct gen_temp returns = {0}; + if (out) { + // XXX: This is definitely broken on aggregate returns + gen_direct(ctx, &returns, expr->result, "call.returns.%d"); + call.out = xcalloc(1, sizeof(struct qbe_value)); + qval_temp(ctx, call.out, &returns); + } + + struct qbe_arguments *args, **next = &call.args; + struct call_argument *carg = expr->call.args; + args = *next = xcalloc(1, sizeof(struct qbe_arguments)); + qval_temp(ctx, &args->value, &lvalue); + next = &args->next; + while (carg) { + args = *next = xcalloc(1, sizeof(struct qbe_arguments)); + struct gen_temp arg = {0}; + alloc_temp(ctx, &arg, carg->value->result, "call.arg.%d"); + gen_expr(ctx, carg->value, &arg); + qval_temp(ctx, &args->value, &arg); + carg = carg->next; + next = &args->next; + } + + push(&ctx->current->body, &call); + + if (out) { + gen_copy(ctx, out, &returns); + } +} + +static void gen_expr_const_array(struct gen_context *ctx, const struct type *atype, const struct array_constant *expr, @@ -720,7 +767,10 @@ gen_expr(struct gen_context *ctx, break; case EXPR_BREAK: case EXPR_CONTINUE: + assert(0); // TODO case EXPR_CALL: + gen_expr_call(ctx, expr, out); + break; case EXPR_CAST: assert(0); // TODO case EXPR_CONSTANT: diff --git a/src/genutil.c b/src/genutil.c @@ -45,12 +45,19 @@ void gen_direct(struct gen_context *ctx, struct gen_temp *temp, const struct type *type, const char *fmt) { - assert(type->size != 0 && type->size != SIZE_UNDEFINED); + // Functions are a special case: the Hare type system (correctly) states + // that they have an undefined size and storage, but we can assign them + // to qbe temporaries as pointers (=l), so they are suitable for use as + // direct objects. + if (type_dealias(type)->storage != STORAGE_FUNCTION) { + assert(type->size != 0 && type->size != SIZE_UNDEFINED); + const struct qbe_type *qtype = qtype_lookup(ctx, type, false); + assert(qtype->stype != Q__AGGREGATE && qtype->stype != Q__VOID); + } + temp->type = type; temp->name = gen_name(ctx, fmt); temp->indirect = false; - const struct qbe_type *qtype = qtype_lookup(ctx, type, false); - assert(qtype->stype != Q__AGGREGATE && qtype->stype != Q__VOID); } // Emits a qbe copy instruction which makes a working copy of a gen temporary.