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:
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);
+};