commit 74650bc728a53268192bc9794c5ac9a78da12215
parent 15d37ce99f3d0f0822b3bb69c1cbcf1c4b4a42a6
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 2 Feb 2021 11:49:26 -0500
check: lower casts to tagged intermediates
Diffstat:
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/src/check.c b/src/check.c
@@ -45,6 +45,15 @@ lower_implicit_cast(const struct type *to, struct expression *expr)
if (to == expr->result) {
return expr;
}
+
+ if (type_dealias(to)->storage == TYPE_STORAGE_TAGGED) {
+ const struct type *interim =
+ tagged_select_subtype(to, expr->result);
+ if (interim) {
+ expr = lower_implicit_cast(interim, expr);
+ }
+ }
+
struct expression *cast = xcalloc(1, sizeof(struct expression));
cast->type = EXPR_CAST;
cast->result = to;
diff --git a/src/gen.c b/src/gen.c
@@ -881,19 +881,20 @@ gen_cast_to_tagged(struct gen_context *ctx,
const struct type *subtype = tagged_select_subtype(tagged, from);
struct qbe_value tag = {0}, ptr = {0}, offs = {0};
- gen_temp(ctx, &ptr, &qbe_long, "to_tagged.from.%d");
constl(&offs, expr->result->align);
if (!subtype) {
pushc(ctx->current, "to_tagged; no subtype");
+ alloc_temp(ctx, &ptr, tagged, "to_tagged.from.%d");
+ qval_deref(&ptr);
gen_expression(ctx, expr->cast.value, &ptr);
gen_copy(ctx, out, &ptr);
return;
}
+ gen_temp(ctx, &ptr, &qbe_long, "to_tagged.from.%d");
pushc(ctx->current, "to_tagged; valid subtype");
- // TODO: check should lower this to multiple casts:
- assert(subtype->id == from->id);
+ assert(subtype->id == from->id); // Lowered by check
if (out) {
constw(&tag, subtype->id);