commit 1e2b6a1c399039c995448b35543a0bb0d31095d5
parent a8f7752df0f0c42e2311ec85240dde16491d808b
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 2 Feb 2021 21:36:18 -0500
gen: implement freeing strings
Diffstat:
2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/src/gen.c b/src/gen.c
@@ -563,6 +563,7 @@ gen_expr_alloc(struct gen_context *ctx,
{
assert(expr->type == EXPR_ALLOC);
struct qbe_value val = {0}, rtfunc = {0};
+ const struct type *type = type_dealias(expr->alloc.expr->result);
switch (expr->alloc.kind) {
case AKIND_ALLOC:
gen_alloc(ctx, expr, out);
@@ -570,15 +571,17 @@ gen_expr_alloc(struct gen_context *ctx,
case AKIND_APPEND:
assert(0); // TODO
case AKIND_FREE:
- gen_temp(ctx, &val,
- qtype_for_type(ctx, expr->alloc.expr->result, true),
- "free.%d");
- if (type_dealias(expr->alloc.expr->result)->storage == TYPE_STORAGE_SLICE) {
- qval_address(&val);
+ if (type->storage == TYPE_STORAGE_SLICE
+ || type->storage == TYPE_STORAGE_STRING) {
+ alloc_temp(ctx, &val, type, "free.%d");
+ val.type = &qbe_long;
gen_expression(ctx, expr->alloc.expr, &val);
val.type = &qbe_long;
pushi(ctx->current, &val, Q_LOADL, &val, NULL);
} else {
+ gen_temp(ctx, &val,
+ qtype_for_type(ctx, expr->alloc.expr->result, false),
+ "free.%d");
gen_expression(ctx, expr->alloc.expr, &val);
}
rtfunc.kind = QV_GLOBAL;
@@ -2383,6 +2386,9 @@ gen_data_item(struct gen_context *ctx, struct expression *expr,
for (struct struct_constant *f = constant->_struct;
f; f = f->next) {
gen_data_item(ctx, f->value, item);
+ while (item->next) {
+ item = item->next;
+ }
if (f->next) {
const struct struct_field *f1 = f->field;
const struct struct_field *f2 = f->next->field;
diff --git a/tests/17-alloc.ha b/tests/17-alloc.ha
@@ -60,6 +60,17 @@ fn slice() void = {
free(x);
};
+fn string() void = {
+ let x = struct {
+ data: *[3]int = alloc(*[3]int, [1, 2, 3]),
+ length: size = 3z,
+ capacity: size = 3z,
+ };
+ let y = *(&x: *str);
+ assert(len(y) == 3z);
+ free(y);
+};
+
export fn main() void = {
assignment();
allocation();