harec

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

commit 8c31e681ffbeb80bcb45e631ba91cf43525bb39b
parent daa1a18c4fd26564453b1802f97ad10d1ab7a4c7
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri, 15 Jan 2021 11:31:52 -0500

type store: initialize tagged union types

Diffstat:
Minclude/types.h | 6++++++
Msrc/type_store.c | 93++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/types.c | 8+++++++-
3 files changed, 105 insertions(+), 2 deletions(-)

diff --git a/include/types.h b/include/types.h @@ -102,6 +102,11 @@ struct type_struct_union { struct struct_field *fields; }; +struct type_tagged_union { + const struct type *type; + struct type_tagged_union *next; +}; + enum type_flags { TYPE_CONST = 1 << 0, }; @@ -117,6 +122,7 @@ struct type { struct type_func func; struct type_pointer pointer; struct type_struct_union struct_union; + struct type_tagged_union tagged; }; }; diff --git a/src/type_store.c b/src/type_store.c @@ -351,6 +351,96 @@ struct_init_from_atype(struct type_store *store, enum type_storage storage, } } +static size_t +sum_atagged_memb(const struct ast_tagged_union_type *u) +{ + size_t nmemb = 0; + for (; u; u = u->next) { + if (u->type->storage == TYPE_STORAGE_TAGGED_UNION) { + nmemb += sum_atagged_memb(&u->type->tagged_union); + } else { + ++nmemb; + } + } + return nmemb; +} + +static void +collect_atagged_memb(struct type_store *store, + struct type_tagged_union **ta, + const struct ast_tagged_union_type *atu, + size_t *i) +{ + for (; atu; atu = atu->next) { + if (atu->type->storage == TYPE_STORAGE_TAGGED_UNION) { + collect_atagged_memb(store, ta, atu, i); + continue; + } + struct type_tagged_union *tu; + ta[*i] = tu = xcalloc(1, sizeof(struct type_tagged_union)); + tu->type = type_store_lookup_atype(store, atu->type); + *i += 1; + } +} + +static int +tagged_cmp(const void *ptr_a, const void *ptr_b) +{ + const struct type_tagged_union **a = + (const struct type_tagged_union **)ptr_a; + const struct type_tagged_union **b = + (const struct type_tagged_union **)ptr_b; + return (*a)->type->id < (*b)->type->id ? -1 + : (*a)->type->id > (*b)->type->id ? 1 : 0; +} + +static void +tagged_init_from_atype(struct type_store *store, + struct type *type, const struct ast_type *atype) +{ + size_t nmemb = sum_atagged_memb(&atype->tagged_union); + struct type_tagged_union **tu = + xcalloc(nmemb, sizeof(struct type_tagged_union *)); + size_t i = 0; + collect_atagged_memb(store, tu, &atype->tagged_union, &i); + + // Prune duplicates + for (i = 1; i < nmemb; ++i) + for (size_t j = 0; j < i; ++j) { + if (tu[j]->type->id == tu[i]->type->id) { + assert(0); // TODO: prune + } + } + + // Sort by ID + qsort(tu, nmemb, sizeof(tu[0]), tagged_cmp); + + // First one free + type->tagged = *tu[0]; + free(tu[0]); + + type->size = type->tagged.type->size; + type->align = type->tagged.type->align; + + struct type_tagged_union **next = &type->tagged.next; + for (size_t i = 1; i < nmemb; ++i) { + if (tu[i]->type->size > type->size) { + type->size = tu[i]->type->size; + } + if (tu[i]->type->align > type->align) { + type->align = tu[i]->type->align; + } + + *next = tu[i]; + next = &tu[i]->next; + } + + type->size += builtin_type_size.size; + if (builtin_type_size.align > type->align) { + type->align = builtin_type_size.align; + } +} + static void type_init_from_atype(struct type_store *store, struct type *type, @@ -450,7 +540,8 @@ type_init_from_atype(struct type_store *store, &atype->struct_union); break; case TYPE_STORAGE_TAGGED_UNION: - assert(0); // TODO + tagged_init_from_atype(store, type, atype); + break; } } diff --git a/src/types.c b/src/types.c @@ -306,7 +306,13 @@ type_hash(const struct type *type) } break; case TYPE_STORAGE_TAGGED_UNION: - assert(0); // TODO + // Invariant: subtypes must be sorted by ID and must not include + // any other tagged union types, nor any duplicates. + for (const struct type_tagged_union *tu = &type->tagged; + tu; tu = tu->next) { + hash = fnv1a_u64(hash, type_hash(tu->type)); + } + break; } return hash; }