harec

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

commit 8aa724d3d94bcd6f9fdc68934f8a1da97e3b5480
parent 1077f85ed77bcfcd98d50281f37fb7e8f61e29fa
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri,  6 Aug 2021 14:58:14 +0200

gen: implement casting from tagged unions

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

Diffstat:
Msrc/gen.c | 17+++++++++++++++--
Mtests/910-tagged.ha | 8++++++++
2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/src/gen.c b/src/gen.c @@ -544,8 +544,6 @@ gen_expr_cast(struct gen_context *ctx, const struct expression *expr) return out; } - assert(type_dealias(from)->storage != STORAGE_TAGGED); // TODO - if (type_dealias(to)->storage == type_dealias(from)->storage && to->size == from->size) { struct gen_value value = gen_expr(ctx, expr->cast.value); @@ -554,13 +552,28 @@ gen_expr_cast(struct gen_context *ctx, const struct expression *expr) } // Special cases + if (type_dealias(from)->storage == STORAGE_TAGGED) { + // Cast from tagged union + struct gen_value value = gen_expr(ctx, expr->cast.value); + struct qbe_value base = mkcopy(ctx, &value, ".%d"); + struct qbe_value align = constl(from->align); + pushi(ctx->current, &base, Q_ADD, &base, &align, NULL); + struct gen_value storage = (struct gen_value){ + .kind = GV_TEMP, + .type = to, + .name = base.name, + }; + return gen_load(ctx, storage); + } switch (type_dealias(to)->storage) { case STORAGE_POINTER: if (type_dealias(from)->storage == STORAGE_SLICE) { + // Cast slice to pointer assert(0); // TODO } break; case STORAGE_VOID: + // Cast to void gen_expr(ctx, expr->cast.value); // Side-effects return gv_void; default: break; diff --git a/tests/910-tagged.ha b/tests/910-tagged.ha @@ -63,8 +63,16 @@ fn subsetcast() void = { assert(p.data.i == 1337); }; +fn castout() void = { + let x: (int | void) = 1337; + let y = x: int; + assert(y == 1337); + // XXX: We can probably expand this +}; + export fn main() int = { membercast(); subsetcast(); + castout(); return 0; };