harec

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

commit 6672f420a89e1918ce57392944cfe62b9d741e02
parent e787d8fc64f1d2617263a9fee92b0fc9b000192e
Author: Drew DeVault <sir@cmpwn.com>
Date:   Mon,  9 Aug 2021 13:32:22 +0200

gen: implement simple alloc case

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

Diffstat:
Msrc/gen.c | 30++++++++++++++++++++++++++++++
Mtests/rt.ha | 16++++++++++++++++
2 files changed, 46 insertions(+), 0 deletions(-)

diff --git a/src/gen.c b/src/gen.c @@ -358,6 +358,35 @@ gen_expr_access(struct gen_context *ctx, const struct expression *expr) } static struct gen_value +gen_expr_alloc(struct gen_context *ctx, const struct expression *expr) +{ + if (type_dealias(expr->result)->storage == STORAGE_SLICE) { + assert(0); // TODO + } + assert(expr->alloc.cap == NULL); + + struct qbe_value sz = constl(type_dereference(expr->result)->size); + struct gen_value result = mktemp(ctx, expr->result, ".%d"); + struct qbe_value qresult = mkqval(ctx, &result); + struct qbe_value rtfunc = mkrtfunc(ctx, "rt.malloc"); + pushi(ctx->current, &qresult, Q_CALL, &rtfunc, &sz, NULL); + + if (!(type_dealias(expr->result)->pointer.flags & PTR_NULLABLE)) { + struct qbe_statement linvalid, lvalid; + struct qbe_value binvalid = mklabel(ctx, &linvalid, ".%d"); + struct qbe_value bvalid = mklabel(ctx, &lvalid, ".%d"); + + pushi(ctx->current, NULL, Q_JNZ, &qresult, &bvalid, &binvalid, NULL); + push(&ctx->current->body, &linvalid); + gen_fixed_abort(ctx, expr->loc, ABORT_ALLOC_FAILURE); + push(&ctx->current->body, &lvalid); + } + + gen_expr_at(ctx, expr->alloc.expr, result); + return result; +} + +static struct gen_value gen_expr_assert(struct gen_context *ctx, const struct expression *expr) { assert(expr->assert.message); // Invariant @@ -1792,6 +1821,7 @@ gen_expr(struct gen_context *ctx, const struct expression *expr) case EXPR_ACCESS: return gen_expr_access(ctx, expr); case EXPR_ALLOC: + return gen_expr_alloc(ctx, expr); case EXPR_APPEND: assert(0); // TODO case EXPR_ASSERT: diff --git a/tests/rt.ha b/tests/rt.ha @@ -28,3 +28,19 @@ export @symbol("rt.strcmp") fn strcmp(_a: str, _b: str) bool = { }; return true; }; + +export @symbol("malloc") fn c_malloc(n: size) nullable *void; +export @symbol("free") fn c_free(p: nullable *void) nullable *void; +export @symbol("realloc") fn c_realloc(p: nullable *void, n: size) nullable *void; + +export @symbol("rt.malloc") fn malloc(n: size) nullable *void = { + return c_malloc(n); +}; + +export @symbol("rt.free") fn free_(p: nullable *void) void = { + c_free(p); +}; + +export @symbol("rt.realloc") fn realloc(p: nullable *void, n: size) nullable *void = { + c_realloc(p, n); +};