harec

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

commit 2a6711b038d44577cd1aca66ea666260cbecc34b
parent 8376c3d205dffff25aa6294fde4c8e57f39af613
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun, 31 Jan 2021 11:01:14 -0500

gen: rig up new tagged rules

Diffstat:
Minclude/types.h | 4++++
Msrc/gen.c | 32+++++++++++++++++++++-----------
Msrc/types.c | 4++--
3 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/include/types.h b/include/types.h @@ -145,6 +145,10 @@ const struct type *type_dealias(const struct type *type); const struct struct_field *type_get_field( const struct type *type, const char *name); +const struct type *tagged_select_subtype( + const struct type *tagged, const struct type *subtype); +bool tagged_subset_compat(const struct type *to, const struct type *from); + const char *type_storage_unparse(enum type_storage storage); bool type_is_signed(const struct type *type); bool type_is_integer(const struct type *type); diff --git a/src/gen.c b/src/gen.c @@ -916,17 +916,25 @@ gen_cast_to_tagged(struct gen_context *ctx, const struct qbe_value *out, const struct type *from) { + const struct type *tagged = expr->result; + const struct type *subtype = tagged_select_subtype(tagged, from); + struct qbe_value tag = {0}, ptr = {0}, offs = {0}; - gen_temp(ctx, &ptr, &qbe_long, "ptr.%d"); + gen_temp(ctx, &ptr, &qbe_long, "to_tagged.from.%d"); constl(&offs, expr->result->align); - if (type_dealias(from)->storage == TYPE_STORAGE_TAGGED) { + if (!subtype) { + pushc(ctx->current, "to_tagged; no subtype"); gen_expression(ctx, expr->cast.value, &ptr); gen_copy(ctx, out, &ptr); return; - } - constw(&tag, expr->cast.value->result->id); + + pushc(ctx->current, "to_tagged; valid subtype"); + // TODO: check should lower this to multiple casts: + assert(subtype->id == from->id); + + constw(&tag, subtype->id); pushi(ctx->current, &ptr, Q_COPY, out, NULL); pushi(ctx->current, NULL, Q_STOREW, &tag, &ptr, NULL); @@ -1048,19 +1056,21 @@ gen_expr_cast(struct gen_context *ctx, return; } - const struct type *to = type_dealias(expr->result), - *from = type_dealias(expr->cast.value->result); - if (to->storage == from->storage && to->size == from->size) { - gen_expression(ctx, expr->cast.value, out); - return; - } else if (to->storage == TYPE_STORAGE_TAGGED) { + const struct type *to = expr->result, *from = expr->cast.value->result; + if (type_dealias(to)->storage == TYPE_STORAGE_TAGGED) { gen_cast_to_tagged(ctx, expr, out, from); return; - } else if (from->storage == TYPE_STORAGE_TAGGED) { + } else if (type_dealias(from)->storage == TYPE_STORAGE_TAGGED) { gen_cast_from_tagged(ctx, expr, out, to); return; } + to = type_dealias(to), from = type_dealias(from); + if (to->storage == from->storage && to->size == from->size) { + gen_expression(ctx, expr->cast.value, out); + return; + } + bool is_signed = type_is_signed(from); struct qbe_value in = {0}, result = {0}; diff --git a/src/types.c b/src/types.c @@ -346,7 +346,7 @@ strip_flags(const struct type *t, struct type *secondary) return secondary; } -static const struct type * +const struct type * tagged_select_subtype(const struct type *tagged, const struct type *subtype) { tagged = type_dealias(tagged); @@ -375,7 +375,7 @@ tagged_select_subtype(const struct type *tagged, const struct type *subtype) return NULL; } -static bool +bool tagged_subset_compat(const struct type *to, const struct type *from) { // Note: this implementation depends on the invariant that tagged union