harec

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

commit 06c6349a933e1968ea1d74eaac3fcba36330dbc3
parent 3ed43ec2b1fe4a3e843ac728f5148c4d0b4639c9
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Sat, 17 Apr 2021 15:06:03 -0400

Rework type promotion

Diffstat:
Msrc/check.c | 113+++++++++++++++++++++++++++++++++++++++++--------------------------------------
1 file changed, 58 insertions(+), 55 deletions(-)

diff --git a/src/check.c b/src/check.c @@ -527,44 +527,52 @@ check_expr_assign(struct context *ctx, static const struct type * type_promote(struct type_store *store, - const struct type *_a, - const struct type *_b) + const struct type *a, + const struct type *b) { - bool is_const = (_a->flags & TYPE_CONST) || (_b->flags & TYPE_CONST); - const struct type *a = type_store_lookup_with_flags(store, _a, 0); - const struct type *b = type_store_lookup_with_flags(store, _b, 0); + // Note: we must return either a, b, or NULL + // TODO: There are likely some improperly handled edge cases around type + // flags, both here and in the spec + const struct type *da = type_store_lookup_with_flags(store, a, 0); + const struct type *db = type_store_lookup_with_flags(store, b, 0); - if (a->storage == STORAGE_ALIAS) { - return a == b || a->alias.type == b ? _b : NULL; + if (da == db) { + const struct type *base = type_store_lookup_with_flags(store, a, + a->flags | b->flags); + assert(base == a || base == b); + return base; } - if (b->storage == STORAGE_ALIAS) { - return a == b || a == b->alias.type ? _a : NULL; + + if (a->storage == STORAGE_ALIAS && b->storage == STORAGE_ALIAS) { + return NULL; } - const struct type *base = a == b ? a : NULL; + da = type_dealias(da); + db = type_dealias(db); + + if (da == db) { + return a->storage == STORAGE_ALIAS ? a : b; + } - switch (a->storage) { + switch (da->storage) { case STORAGE_ARRAY: - if (a->array.length == SIZE_UNDEFINED && a->array.members) { - base = b; - break; + if (da->array.length == SIZE_UNDEFINED && da->array.members) { + return b; } - if (b->array.length == SIZE_UNDEFINED && b->array.members) { - base = a; - break; + if (db->array.length == SIZE_UNDEFINED && db->array.members) { + return a; } - break; + return NULL; case STORAGE_I8: case STORAGE_I16: case STORAGE_I32: case STORAGE_I64: case STORAGE_INT: - if (!type_is_integer(b) || !type_is_signed(b) - || b->size == a->size) { - break; + if (!type_is_integer(db) || !type_is_signed(db) + || db->size == da->size) { + return NULL; } - base = a->size > b->size ? a : b; - break; + return da->size > db->size ? a : b; case STORAGE_U32: case STORAGE_U16: case STORAGE_U64: @@ -572,40 +580,40 @@ type_promote(struct type_store *store, case STORAGE_SIZE: case STORAGE_U8: case STORAGE_CHAR: - if (!type_is_integer(b) || type_is_signed(b) - || b->size == a->size) { - break; + if (!type_is_integer(db) || type_is_signed(db) + || db->size == da->size) { + return NULL; } - base = a->size > b->size ? a : b; - break; + return da->size > db->size ? a : b; case STORAGE_F32: case STORAGE_F64: - if (!type_is_float(b) || b->size == a->size) { - break; + if (!type_is_float(db) || db->size == da->size) { + return NULL; } - base = a->size > b->size ? a : b; - break; + return da->size > db->size ? a : b; case STORAGE_POINTER: - if (b->storage == STORAGE_NULL) { - base = a; - break; + if (db->storage == STORAGE_NULL) { + return a; } - if (b->storage != STORAGE_POINTER) { - break; + if (db->storage != STORAGE_POINTER) { + return NULL; } - base = type_promote(store, a->pointer.referent, - b->pointer.referent); - if (base) { - base = type_store_lookup_pointer(store, base, - a->pointer.flags | b->pointer.flags); + const struct type *r = type_promote(store, da->pointer.referent, + db->pointer.referent); + if (r == da->pointer.referent) { + return a; } - break; + if (r == db->pointer.referent) { + return b; + } + assert(r == NULL); + return NULL; case STORAGE_NULL: - if (b->storage == STORAGE_POINTER - || b->storage == STORAGE_NULL) { - base = b; + assert(db->storage != STORAGE_NULL); + if (db->storage == STORAGE_POINTER) { + return b; } - break; + return NULL; // Cannot be promoted case STORAGE_BOOL: case STORAGE_ENUM: @@ -619,21 +627,16 @@ type_promote(struct type_store *store, case STORAGE_UINTPTR: case STORAGE_UNION: case STORAGE_VOID: - break; + return NULL; // Handled above case STORAGE_ALIAS: - break; + assert(0); // Invariant case STORAGE_FCONST: case STORAGE_ICONST: assert(0); } - - if (is_const && base) { - base = type_store_lookup_with_flags(store, base, - base->flags | TYPE_CONST); - } - return base; + assert(0); } static bool