harec

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

commit 610034a3d7120a3bb79a9c7c97caec98d7caf3b5
parent 19a05fa355486084982a7642e0d880196475b664
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu, 31 Dec 2020 10:04:31 -0500

gen: implement some basic casts

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

diff --git a/src/gen.c b/src/gen.c @@ -273,7 +273,7 @@ gen_expr_access_ident(struct gen_context *ctx, qval_for_object(ctx, &src, obj); if (src.indirect) { gen_loadtemp(ctx, &temp, &src, - qtype_for_type(ctx, obj->type, true), + qtype_for_type(ctx, obj->type, false), type_is_signed(obj->type)); gen_store(ctx, out, &temp); } else { @@ -436,6 +436,27 @@ gen_expr_binding(struct gen_context *ctx, } static void +extend(struct gen_context *ctx, struct qbe_value *v, const struct type *type) +{ + enum qbe_instr op; + switch (type->size) { + case 1: + op = type_is_signed(type) ? Q_EXTSB : Q_EXTUB; + break; + case 2: + op = type_is_signed(type) ? Q_EXTSH : Q_EXTUH; + break; + default: + return; + } + + struct qbe_value temp = {0}; + gen_temp(ctx, &temp, &qbe_word, "ext.%d"); + pushi(ctx->current, &temp, op, v, NULL); + *v = temp; +} + +static void gen_expr_binarithm(struct gen_context *ctx, const struct expression *expr, const struct qbe_value *out) @@ -455,6 +476,20 @@ gen_expr_binarithm(struct gen_context *ctx, gen_expression(ctx, expr->binarithm.lvalue, &lvalue); gen_expression(ctx, expr->binarithm.rvalue, &rvalue); + switch (expr->binarithm.op) { + case BIN_GREATER: + case BIN_GREATEREQ: + case BIN_LEQUAL: + case BIN_LESS: + case BIN_LESSEQ: + case BIN_NEQUAL: + extend(ctx, &lvalue, expr->binarithm.lvalue->result); + extend(ctx, &rvalue, expr->binarithm.rvalue->result); + break; + default: + break; + } + pushi(ctx->current, &result, binarithm_for_op(expr->binarithm.op, ltype, type_is_signed(expr->binarithm.lvalue->result)), @@ -512,6 +547,87 @@ gen_expr_call(struct gen_context *ctx, } static void +gen_expr_cast(struct gen_context *ctx, + const struct expression *expr, + const struct qbe_value *out) +{ + const struct type *to = expr->result, + *from = expr->cast.value->result; + bool is_signed = type_is_signed(from); + + struct qbe_value in = {0}, result = {0}; + gen_temp(ctx, &in, qtype_for_type(ctx, from, false), "cast.in.%d"); + gen_expression(ctx, expr->cast.value, &in); + gen_temp(ctx, &result, qtype_for_type(ctx, to, false), "cast.out.%d"); + + enum qbe_instr op; + switch (to->storage) { + case TYPE_STORAGE_U8: + case TYPE_STORAGE_I8: + case TYPE_STORAGE_I16: + case TYPE_STORAGE_U16: + case TYPE_STORAGE_I32: + case TYPE_STORAGE_U32: + case TYPE_STORAGE_INT: // XXX: ARCH + case TYPE_STORAGE_UINT: // XXX: ARCH + case TYPE_STORAGE_I64: + case TYPE_STORAGE_U64: + case TYPE_STORAGE_UINTPTR: // XXX: ARCH + case TYPE_STORAGE_RUNE: + case TYPE_STORAGE_SIZE: // XXX: ARCH + if (type_is_integer(to) && to->size <= from->size) { + op = Q_COPY; + } else if (type_is_integer(to) && to->size > from->size) { + switch (from->size) { + case 4: + op = is_signed ? Q_EXTSW : Q_EXTUW; + break; + case 2: + op = is_signed ? Q_EXTSH : Q_EXTUH; + break; + case 1: + op = is_signed ? Q_EXTSB : Q_EXTUB; + break; + default: + assert(0); // Invariant + } + } else if (from->storage == TYPE_STORAGE_POINTER) { + assert(to->storage == TYPE_STORAGE_UINTPTR); + op = Q_COPY; + } else if (type_is_float(from)) { + assert(0); // TODO + } else { + assert(0); // Invariant + } + pushi(ctx->current, &result, op, &in, NULL); + break; + case TYPE_STORAGE_F32: + case TYPE_STORAGE_F64: + case TYPE_STORAGE_ALIAS: + case TYPE_STORAGE_STRING: + case TYPE_STORAGE_TAGGED_UNION: + case TYPE_STORAGE_ENUM: + assert(0); // TODO + // Can be implemented with a copy + case TYPE_STORAGE_ARRAY: + case TYPE_STORAGE_SLICE: + case TYPE_STORAGE_CHAR: + case TYPE_STORAGE_NULL: + case TYPE_STORAGE_POINTER: + pushi(ctx->current, &result, Q_COPY, &in, NULL); + break; + case TYPE_STORAGE_BOOL: + case TYPE_STORAGE_FUNCTION: + case TYPE_STORAGE_STRUCT: + case TYPE_STORAGE_UNION: + case TYPE_STORAGE_VOID: + assert(0); // Invariant + } + + gen_store(ctx, out, &result); +} + +static void gen_array(struct gen_context *ctx, const struct expression *expr, const struct qbe_value *out) @@ -859,7 +975,8 @@ gen_expression(struct gen_context *ctx, gen_expr_call(ctx, expr, out); break; case EXPR_CAST: - assert(0); // TODO + gen_expr_cast(ctx, expr, out); + break; case EXPR_CONSTANT: gen_expr_constant(ctx, expr, out); break;