harec

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

commit d5845af7f65f881a400b55dce59181d7a7bd2bd2
parent a2713249b19b81223cac003d65a94bbd597fe19a
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri, 15 Jan 2021 14:05:35 -0500

gen: implement casting to tagged union

Diffstat:
Msrc/gen.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 62 insertions(+), 2 deletions(-)

diff --git a/src/gen.c b/src/gen.c @@ -662,6 +662,58 @@ gen_expr_call(struct gen_context *ctx, } static void +gen_cast_to_tagged(struct gen_context *ctx, + const struct expression *expr, + const struct qbe_value *out, + const struct type *from) +{ + if (from->storage == TYPE_STORAGE_TAGGED_UNION) { + assert(0); // TODO + } + + struct qbe_value tag = {0}, ptr = {0}, offs = {0}; + gen_temp(ctx, &ptr, &qbe_long, "ptr.%d"); + constl(&offs, 8); + constl(&tag, expr->result->id); + pushi(ctx->current, &ptr, Q_COPY, out, NULL); + pushi(ctx->current, NULL, Q_STOREL, &tag, &ptr, NULL); + pushi(ctx->current, &ptr, Q_ADD, &ptr, &offs, NULL); + ptr.type = qtype_for_type(ctx, expr->result, false); + ptr.indirect = type_is_aggregate(expr->cast.value->result); + gen_expression(ctx, expr->cast.value, &ptr); +} + +static void +gen_cast_from_tagged(struct gen_context *ctx, + const struct expression *expr, + const struct qbe_value *out, + const struct type *to) +{ + if (to->storage == TYPE_STORAGE_TAGGED_UNION) { + assert(0); // TODO + } + + // XXX: This has not been fully tested pending rules implementation + struct qbe_value ptr = {0}, offs = {0}, temp = {0}; + gen_temp(ctx, &ptr, + qtype_for_type(ctx, expr->result, false), "tagged.%d"); + gen_expression(ctx, expr->cast.value, &ptr); + + constl(&offs, 8); + pushi(ctx->current, &ptr, Q_ADD, &ptr, &offs, NULL); + ptr.type = qtype_for_type(ctx, expr->result, false); + ptr.indirect = type_is_aggregate(expr->result); + if (ptr.indirect) { + gen_loadtemp(ctx, &temp, &ptr, + qtype_for_type(ctx, expr->result, false), + type_is_signed(expr->result)); + gen_store(ctx, out, &temp); + } else { + gen_store(ctx, out, &ptr); + } +} + +static void gen_expr_cast(struct gen_context *ctx, const struct expression *expr, const struct qbe_value *out) @@ -671,6 +723,12 @@ gen_expr_cast(struct gen_context *ctx, if (to->storage == from->storage) { gen_expression(ctx, expr->cast.value, out); return; + } else if (to->storage == TYPE_STORAGE_TAGGED_UNION) { + gen_cast_to_tagged(ctx, expr, out, from); + return; + } else if (from->storage == TYPE_STORAGE_TAGGED_UNION) { + gen_cast_from_tagged(ctx, expr, out, to); + return; } bool is_signed = type_is_signed(from); @@ -702,7 +760,10 @@ gen_expr_cast(struct gen_context *ctx, } gen_expression(ctx, expr->cast.value, &in); + // Used for various casts enum qbe_instr op; + struct qbe_value ptr = {0}, offs = {0}, len = {0}; + switch (to->storage) { case TYPE_STORAGE_CHAR: case TYPE_STORAGE_U8: @@ -746,7 +807,6 @@ gen_expr_cast(struct gen_context *ctx, break; case TYPE_STORAGE_F32: case TYPE_STORAGE_F64: - case TYPE_STORAGE_TAGGED_UNION: case TYPE_STORAGE_ENUM: assert(0); // TODO case TYPE_STORAGE_ARRAY: @@ -762,7 +822,6 @@ gen_expr_cast(struct gen_context *ctx, break; } // XXX: ARCH - struct qbe_value ptr = {0}, offs = {0}, len = {0}; gen_temp(ctx, &ptr, &qbe_long, "ptr.%d"); constl(&offs, 8); constl(&len, from->array.length); @@ -779,6 +838,7 @@ gen_expr_cast(struct gen_context *ctx, pushi(ctx->current, &result, Q_COPY, &in, NULL); break; case TYPE_STORAGE_ALIAS: + case TYPE_STORAGE_TAGGED_UNION: assert(0); // Handled above case TYPE_STORAGE_BOOL: case TYPE_STORAGE_FUNCTION: