harec

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

commit d4bd9749de1ea29690b9f9d4d9c6a04c69da05bc
parent 1ee3a9573c990bc15544be8cbcb7ca2879c439cb
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu,  5 Aug 2021 15:44:56 +0200

gen: implement subtype tagged casts

Just one of two cases is implemented here; the second requires more
work.

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

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

diff --git a/src/gen.c b/src/gen.c @@ -124,7 +124,9 @@ gen_store(struct gen_context *ctx, gen_copy_aligned(ctx, object, value); return; case STORAGE_TAGGED: - assert(0); // TODO + // TODO: We can be smarter in this case + gen_copy_aligned(ctx, object, value); + return; case STORAGE_UNION: gen_copy_memcpy(ctx, object, value); return; @@ -463,10 +465,23 @@ gen_expr_cast_at(struct gen_context *ctx, return; } - // Cast to tagged union const struct type *subtype = tagged_select_subtype(to, from); - assert(subtype); // TODO: Casting between incompatible tagged unions + assert(subtype || tagged_subset_compat(to, from)); + if (!subtype && to->align == from->align) { + // Case 1: from is a union whose members are a subset of to, and + // the alignment matches, so we can just interpret values of + // type 'from' as if it were of type 'to' + struct gen_value out2 = out; + out2.type = from; + gen_expr_at(ctx, expr->cast.value, out2); + return; + } else if (!subtype) { + // Case 2: alignment mismatch, so (much) more work is required. + assert(0); // TODO + return; + } + // Case 3: from is a member of to struct qbe_value qout = mkqval(ctx, &out); struct qbe_value id = constw(subtype->id); enum qbe_instr store = store_for_type(ctx, &builtin_type_uint); diff --git a/tests/910-tagged.ha b/tests/910-tagged.ha @@ -1,4 +1,4 @@ -fn totagged() void = { +fn membercast() void = { // Simple case let x: (int | void) = void; let p = &x: *struct { @@ -33,11 +33,28 @@ fn totagged() void = { }; assert(p.id == 4119164483); assert(p.data == 1337z); +}; + +fn subsetcast() void = { + // Equal alignment + let x: (size | void) = 1337z; + let y: (size | int | void) = x; + let p = &y: *struct { + tag: uint, + data: union { + z: size, + i: int, + }, + }; + assert(p.tag == 4119164483); + assert(p.data.z == 1337z); - // TODO: More cases + // Disjoint alignment + // TODO }; export fn main() int = { - totagged(); + membercast(); + subsetcast(); return 0; };