harec

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

commit e976c86b2efc493c69053ff13cb68d124503d76c
parent e9acfa8ee777ea3290553af54079c79c8ff4e62e
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun, 26 Sep 2021 10:41:31 +0200

gen: implement tagged union reflection

Diffstat:
Msrc/gen.c | 42++++++++++++++++++++++++++++++++++++++++++
Mtests/34-reflect.ha | 27+++++++++++++++++++++++++++
2 files changed, 69 insertions(+), 0 deletions(-)

diff --git a/src/gen.c b/src/gen.c @@ -3702,6 +3702,48 @@ gen_type_info(struct gen_context *ctx, item->value = constl(len); break; case STORAGE_TAGGED: + *repr_name = "tagged"; + item->value = constw(type_hash(&repr)); + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + + item->type = QD_ZEROED; + item->zeroed = 4; + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + + def = xcalloc(1, sizeof(struct qbe_def)); + def->name = gen_name(ctx, "sldata.%d"); + def->kind = Q_DATA; + subitem = &def->data.items; + for (const struct type_tagged_union *tu = &type->tagged; + tu; tu = tu->next) { + ref = mktyperef(ctx, tu->type); + subitem->type = QD_VALUE; + subitem->value.kind = QV_GLOBAL; + subitem->value.type = &qbe_long; + subitem->value.name = ref.name; + if (tu->next) { + subitem->next = xcalloc(1, sizeof(struct qbe_data_item)); + subitem = subitem->next; + } + ++len; + } + qbe_append_def(ctx->out, def); + + item->type = QD_VALUE; + item->value.kind = QV_GLOBAL; + item->value.type = &qbe_long; + item->value.name = strdup(def->name); + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + item->type = QD_VALUE; + item->value = constl(len); + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + item->type = QD_VALUE; + item->value = constl(len); + break; case STORAGE_TUPLE: // XXX: Temporary code to make sure code in the wild builds // while we flesh out these types diff --git a/tests/34-reflect.ha b/tests/34-reflect.ha @@ -166,6 +166,32 @@ fn struct_union() void = { assert(su.fields[2].offs == 8); }; +fn tagged() void = { + let ty = types::reflect(type((int | uint | void))); + assert(ty.sz == size(uint) * 2); + assert(ty.al == size(uint)); + let ta = ty.repr as types::tagged; + assert(len(ta) == 3); + // The order of fields in a tagged union type is not consistent with + // their AST ordering, so we don't expect specific types at specific + // indicies. It is consistently ordered (based on type ID), but the type + // IDs change whenever the ABI changes and I don't feel like updating + // this every time. + let _i = false, _u = false, _v = false; + for (let i = 0z; i < len(ta); i += 1) { + if (ta[i] == type(int)) { + _i = true; + }; + if (ta[i] == type(uint)) { + _u = true; + }; + if (ta[i] == type(void)) { + _v = true; + }; + }; + assert(_i && _u && _v); +}; + export fn main() void = { builtins(); aliases(); @@ -175,4 +201,5 @@ export fn main() void = { pointers(); functions(); struct_union(); + tagged(); };