From c85e4b4d2411e60af7387dec663ea62b03743eab Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 19 Nov 2023 20:25:45 +0200 Subject: add implicit ret to void functions --- include/ek/ast.h | 1 + include/ek/ops.h | 1 + src/actualize.c | 5 +++++ src/asm.c | 22 +++++++++++++++++----- src/ops.c | 17 +++++++++++++++++ 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/include/ek/ast.h b/include/ek/ast.h index d36860f..e078f59 100644 --- a/include/ek/ast.h +++ b/include/ek/ast.h @@ -22,6 +22,7 @@ #define AST_CAST(x) x->_cast #define AST_PROC(x) x->_proc #define AST_VAR(x) x->_var +#define AST_RETURN(x) x->_return #define AST_STRUCT(x) x->_struct #define AST_ENUM(x) x->_enum #define AST_CALL(x) x->_call diff --git a/include/ek/ops.h b/include/ek/ops.h index e913d37..0d9d433 100644 --- a/include/ek/ops.h +++ b/include/ek/ops.h @@ -27,6 +27,7 @@ enum opcode { OP_LDT, OP_STW, OP_LDW, + OP_RET, OP_MV, /* kind of meta op, will be realized as either load/store or register move */ OP_LABEL, OP_COMMENT, diff --git a/src/actualize.c b/src/actualize.c index ab72589..694eca9 100644 --- a/src/actualize.c +++ b/src/actualize.c @@ -683,6 +683,11 @@ static int actualize_proc(struct act_state *state, "no return with non-void return type"); ret = -1; } + /* add 'implicit' return */ + struct ast_node *body = AST_PROC(actual).body; + struct ast_node *r = gen_return(NULL); + r->scope = body->scope; + ast_append(AST_BLOCK(body).body, r); } else if (ast_block_last(actual->_proc.body)->node_type != AST_RETURN) { /* TODO: something more sophisticated than this */ diff --git a/src/asm.c b/src/asm.c index 4102265..e2076f5 100644 --- a/src/asm.c +++ b/src/asm.c @@ -57,6 +57,17 @@ static int print_stt(struct op *op, FILE *f) return 0; } +static int print_ret(struct op *op, FILE *f) +{ + /* technically speaking ret takes a number of inputs, but they should be + * marshaled into registers with moves etc. so don't worry about them + * here */ + fprintf(f, "jalr x0, 0(x21)\n"); + /* eventually add in proper ret alias to assembly language once I go + * through calling conventions etc. */ + return 0; +} + static int print_op(struct op *op, FILE *f) { int ret = 0; @@ -66,6 +77,7 @@ static int print_op(struct op *op, FILE *f) case OP_LI: ret = print_li(op, f); break; case OP_MV: ret = print_mv(op, f); break; case OP_STT: ret = print_stt(op, f); break; + case OP_RET: ret = print_ret(op, f); break; default: abort(); } @@ -77,7 +89,11 @@ int print_asm(struct ops *ops, const char *output) FILE *f = fopen(output, "w"); /* main should probably be mangled here as well */ - fprintf(f, "jal x0, main\n"); + fprintf(f, "jal x21, main\n"); + /* tell simulator to turn off (very much temp) */ + fprintf(f, "li x1, 3\n"); + fprintf(f, "csrrw mpower, x0, x1\n"); + int ret = 0; struct op *op = ops->base; while (op) { @@ -87,10 +103,6 @@ int print_asm(struct ops *ops, const char *output) op = op->next; } - /* tell simulator to turn off (very much temp) */ - fprintf(f, "li x1, 3\n"); - fprintf(f, "csrrw mpower, x0, x1\n"); - fclose(f); return ret; } diff --git a/src/ops.c b/src/ops.c index 625f0cf..9562035 100644 --- a/src/ops.c +++ b/src/ops.c @@ -252,6 +252,21 @@ static int lower_id(struct ast_node *n, struct ops *ops) return 0; } +static int lower_ret(struct ast_node *n, struct ops *ops) +{ + if (AST_RETURN(n).expr) { + int ret = lower_op(AST_RETURN(n).expr, ops); + if (ret) + return ret; + } + + struct op *op = append_op(ops, OP_RET); + if (AST_RETURN(n).expr) + set_reg(&op->inputs, HEAD_OUTPUTS(ops).reg); + + return 0; +} + static int lower_op(struct ast_node *n, struct ops *ops) { int ret = 0; @@ -264,6 +279,7 @@ static int lower_op(struct ast_node *n, struct ops *ops) case AST_ASSIGN: ret = lower_assign(n, ops); break; case AST_UNOP: ret = lower_unop(n, ops); break; case AST_ID: ret = lower_id(n, ops); break; + case AST_RETURN: ret = lower_ret(n, ops); break; default: semantic_error(n->scope->fctx, n, "unimplemented lowering"); return -1; @@ -316,6 +332,7 @@ static void print_op(struct op *op) case OP_LDT: printf("ldt"); break; case OP_STW: printf("stw"); break; case OP_LDW: printf("ldw"); break; + case OP_RET: printf("ret"); break; case OP_MV: printf("mv"); break; default: printf("unimp"); break; } -- cgit v1.3