harec

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

commit 05f17977b358ab385e0c0043697f05cbff51b672
parent a9eba9f9dadfa1da0a2ea28d7b7e89b10c13065c
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu,  1 Jul 2021 14:01:59 -0400

gen: implement expression list, return

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

Diffstat:
Minclude/gen.h | 2++
Msrc/gen.c | 43++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/include/gen.h b/include/gen.h @@ -27,6 +27,8 @@ struct gen_context { struct type_store *store; struct identifier *ns; struct qbe_func *current; + const struct type *functype; + const char *end; struct gen_temp *rval; struct gen_arch arch; uint64_t id; diff --git a/src/gen.c b/src/gen.c @@ -78,6 +78,9 @@ load_temp(struct gen_context *ctx, } } +static void gen_expr(struct gen_context *ctx, + const struct expression *expr, struct gen_temp *out); + static void gen_expr_constant(struct gen_context *ctx, const struct expression *expr, @@ -144,6 +147,36 @@ gen_expr_constant(struct gen_context *ctx, } static void +gen_expr_list(struct gen_context *ctx, + const struct expression *expr, + struct gen_temp *out) +{ + for (const struct expressions *item = &expr->list.exprs; + item; item = item->next) { + if (!item->next) { + gen_expr(ctx, item->expr, out); + } else { + gen_expr(ctx, item->expr, NULL); + } + } +} + +static void +gen_expr_return(struct gen_context *ctx, + const struct expression *expr, + struct gen_temp *out) +{ + struct qbe_value label = { + .kind = QV_LABEL, + .name = strdup(ctx->end), + }; + if (expr->_return.value) { + gen_expr(ctx, expr->_return.value, ctx->rval); + } + pushi(ctx->current, NULL, Q_JMP, &label, NULL); +} + +static void gen_expr(struct gen_context *ctx, const struct expression *expr, struct gen_temp *out) @@ -170,14 +203,20 @@ gen_expr(struct gen_context *ctx, case EXPR_FREE: case EXPR_IF: case EXPR_INSERT: + assert(0); // TODO case EXPR_LIST: + gen_expr_list(ctx, expr, out); + break; case EXPR_MATCH: case EXPR_MEASURE: assert(0); // TODO case EXPR_PROPAGATE: assert(0); // Lowered in check (XXX: for now...) case EXPR_RETURN: + gen_expr_return(ctx, expr, out); + break; case EXPR_SLICE: + assert(0); // TODO case EXPR_STRUCT: case EXPR_SWITCH: case EXPR_TUPLE: @@ -205,7 +244,9 @@ gen_function_decl(struct gen_context *ctx, const struct declaration *decl) ctx->current = &qdef->func; struct qbe_statement start_label = {0}; + struct qbe_statement end_label = {0}; genl(&start_label, &ctx->id, "start.%d"); + ctx->end = genl(&end_label, &ctx->id, "end.%d"); push(&qdef->func.prelude, &start_label); if (type_dealias(fntype->func.result)->storage != STORAGE_VOID) { @@ -221,7 +262,7 @@ gen_function_decl(struct gen_context *ctx, const struct declaration *decl) pushl(&qdef->func, &ctx->id, "body.%d"); gen_expr(ctx, func->body, ctx->rval); - pushl(&qdef->func, &ctx->id, "end.%d"); + push(&qdef->func.body, &end_label); if (type_dealias(fntype->func.result)->storage != STORAGE_VOID) { struct qbe_value rval = {0}; load_temp(ctx, &rval, ctx->rval);