harec

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

commit 3b305c020c4e85a92f0818438c9fe516e86f21e8
parent 21fadeeb2d4b70e4f9cad170d1fe7d3acf55b872
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Thu,  3 Jun 2021 17:58:37 -0700

Implement static delete

Signed-off-by: Eyal Sawady <ecs@d2evs.net>

Diffstat:
Minclude/expr.h | 1+
Msrc/check.c | 2+-
Msrc/gen.c | 36+++++++++++++++++++++++++++++++-----
Mtests/22-delete.ha | 4++--
4 files changed, 35 insertions(+), 8 deletions(-)

diff --git a/include/expr.h b/include/expr.h @@ -200,6 +200,7 @@ struct expression_defer { struct expression_delete { struct expression *expr; + bool is_static; }; struct expression_for { diff --git a/src/check.c b/src/check.c @@ -1396,7 +1396,7 @@ check_expr_delete(struct context *ctx, struct errors *errors) { expr->type = EXPR_DELETE; - assert(!aexpr->delete.is_static); // TODO + expr->delete.is_static = aexpr->delete.is_static; expr->result = &builtin_type_void; struct expression *dexpr = expr->delete.expr = xcalloc(1, sizeof(struct expression)); diff --git a/src/gen.c b/src/gen.c @@ -1847,11 +1847,37 @@ gen_expr_delete(struct gen_context *ctx, rtmemcpy.type = &qbe_long; pushi(ctx->current, NULL, Q_CALL, &rtmemcpy, &sptr, &eptr, &len, NULL); - struct qbe_value rtunensure = {0}; - rtunensure.kind = QV_GLOBAL; - rtunensure.name = strdup("rt.unensure"); - rtunensure.type = &qbe_long; - pushi(ctx->current, NULL, Q_CALL, &rtunensure, &object, &membsz, NULL); + if (!expr->delete.is_static) { + struct qbe_value rtunensure = {0}; + rtunensure.kind = QV_GLOBAL; + rtunensure.name = strdup("rt.unensure"); + rtunensure.type = &qbe_long; + pushi(ctx->current, NULL, Q_CALL, &rtunensure, &object, &membsz, NULL); + } else { + struct qbe_value capptr = {0}, cap = {0}; + gen_temp(ctx, &capptr, &qbe_long, "append.capptr.%d"); + constl(&temp, builtin_type_size.size); + pushi(ctx->current, &capptr, Q_ADD, &lenptr, &temp, NULL); + qval_deref(&capptr); + gen_loadtemp(ctx, &cap, &capptr, &qbe_long, false); + + struct qbe_statement validl = {0}, invalidl = {0}; + struct qbe_value bvalid = {0}, binvalid = {0}; + bvalid.kind = QV_LABEL; + bvalid.name = strdup(genl(&validl, &ctx->id, "bounds.valid.%d")); + binvalid.kind = QV_LABEL; + binvalid.name = strdup(genl(&invalidl, &ctx->id, "bounds.invalid.%d")); + + struct qbe_value valid = {0}; + gen_temp(ctx, &valid, &qbe_word, "valid.%d"); + pushi(ctx->current, &valid, Q_CULEL, &newlen, &cap, NULL); + pushi(ctx->current, NULL, Q_JNZ, &valid, &bvalid, &binvalid, NULL); + push(&ctx->current->body, &invalidl); + + gen_fixed_abort(ctx, expr->loc, ABORT_OOB); + + push(&ctx->current->body, &validl); + } } static void diff --git a/tests/22-delete.ha b/tests/22-delete.ha @@ -10,7 +10,7 @@ fn index() void = { assert(len(x) == 4); assert(x[0] == 1 && x[1] == 3 && x[2] == 4 && x[3] == 5); - delete(y[3]); + static delete(y[3]); assert(len(x) == 3); assert(x[0] == 1 && x[1] == 3 && x[2] == 4); free(x); @@ -25,7 +25,7 @@ fn slice() void = { assert(len(x) == 2); assert(x[0] == 4 && x[1] == 5); - delete(y[..]); + static delete(y[..]); assert(len(x) == 0); assert(s.capacity < 5);