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