harec

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

commit 7fd0e10f6eedd57fbd089297678d72c2f050d29e
parent a4321b7134e3144f4ebf9169c3c0eaec27058f36
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri, 25 Dec 2020 14:15:48 -0500

Implement logical arithmetic

Diffstat:
Minclude/gen.h | 3++-
Msrc/check.c | 8++++----
Msrc/gen.c | 8++++----
Msrc/parse.c | 2++
Msrc/qinstr.c | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
5 files changed, 99 insertions(+), 16 deletions(-)

diff --git a/include/gen.h b/include/gen.h @@ -40,6 +40,7 @@ bool type_is_aggregate(const struct type *type); enum qbe_instr alloc_for_align(size_t align); enum qbe_instr store_for_type(enum qbe_stype stype); enum qbe_instr load_for_type(enum qbe_stype stype, bool is_signed); -enum qbe_instr binarithm_for_op(enum binarithm_operator op); +enum qbe_instr binarithm_for_op(enum binarithm_operator op, + const struct qbe_type *type, bool is_signed); #endif diff --git a/src/check.c b/src/check.c @@ -133,10 +133,10 @@ check_expr_binarithm(struct context *ctx, case BIN_LOR: case BIN_LXOR: case BIN_NEQUAL: - expect(lvalue->result == &builtin_type_bool - && rvalue->result == &builtin_type_bool, - "Logical expressions must have boolean operands"); - assert(0); // TODO + // TODO: Promotion, comparibility rules + assert(lvalue->result->storage == rvalue->result->storage); + expr->result = &builtin_type_bool; + break; } } diff --git a/src/gen.c b/src/gen.c @@ -271,8 +271,6 @@ gen_binarithm(struct gen_context *ctx, const struct qbe_type *etype = qtype_for_type(ctx, expr->result, false); assert(etype == ltype && ltype == rtype); // TODO: Type promotion - assert(expr->result != &builtin_type_bool); // TODO: Logical arithmetic - struct qbe_value lvalue = {0}, rvalue = {0}, result = {0}; gen_temp(ctx, &lvalue, ltype, "lvalue.%d"); gen_temp(ctx, &rvalue, rtype, "rvalue.%d"); @@ -281,8 +279,10 @@ gen_binarithm(struct gen_context *ctx, gen_expression(ctx, expr->binarithm.lvalue, &lvalue); gen_expression(ctx, expr->binarithm.rvalue, &rvalue); - pushi(ctx->current, &result, binarithm_for_op(expr->binarithm.op), - &lvalue, &rvalue, NULL); + pushi(ctx->current, &result, + binarithm_for_op(expr->binarithm.op, ltype, + type_is_signed(expr->binarithm.lvalue->result)), + &lvalue, &rvalue, NULL); gen_store(ctx, out, &result); } diff --git a/src/parse.c b/src/parse.c @@ -766,6 +766,8 @@ binop_for_token(enum lexical_token tok) return BIN_LOR; case T_LAND: return BIN_LAND; + case T_LXOR: + return BIN_LXOR; case T_BOR: return BIN_BOR; case T_BXOR: diff --git a/src/qinstr.c b/src/qinstr.c @@ -65,9 +65,12 @@ load_for_type(enum qbe_stype stype, bool is_signed) } enum qbe_instr -binarithm_for_op(enum binarithm_operator op) +binarithm_for_op(enum binarithm_operator op, + const struct qbe_type *type, bool is_signed) { - // TODO: udiv et al + // TODO: NaN, udiv et al + enum qbe_stype stype = type->stype; + assert(stype != Q__AGGREGATE && stype != Q__VOID); switch (op) { case BIN_PLUS: return Q_ADD; @@ -89,16 +92,93 @@ binarithm_for_op(enum binarithm_operator op) return Q_SHL; case BIN_RSHIFT: return Q_SHR; + case BIN_LEQUAL: + switch (stype) { + case Q_WORD: + return Q_CEQW; + case Q_LONG: + return Q_CEQL; + case Q_SINGLE: + return Q_CEQS; + case Q_DOUBLE: + return Q_CEQD; + default: + assert(0); + } + break; + case BIN_NEQUAL: + case BIN_LXOR: + switch (stype) { + case Q_WORD: + return Q_CNEW; + case Q_LONG: + return Q_CNEL; + case Q_SINGLE: + return Q_CNES; + case Q_DOUBLE: + return Q_CNED; + default: + assert(0); + } + break; case BIN_GREATER: + switch (stype) { + case Q_WORD: + return is_signed ? Q_CSGTW : Q_CUGTW; + case Q_LONG: + return is_signed ? Q_CSGTL : Q_CUGTL; + case Q_SINGLE: + return Q_CGTS; + case Q_DOUBLE: + return Q_CGTD; + default: + assert(0); + } case BIN_GREATEREQ: - case BIN_LAND: - case BIN_LEQUAL: + switch (stype) { + case Q_WORD: + return is_signed ? Q_CSGEW : Q_CUGEW; + case Q_LONG: + return is_signed ? Q_CSGEL : Q_CUGEL; + case Q_SINGLE: + return Q_CGES; + case Q_DOUBLE: + return Q_CGED; + default: + assert(0); + } + break; case BIN_LESS: + switch (stype) { + case Q_WORD: + return is_signed ? Q_CSLTW : Q_CULTW; + case Q_LONG: + return is_signed ? Q_CSLTL : Q_CULTL; + case Q_SINGLE: + return Q_CLTS; + case Q_DOUBLE: + return Q_CLTD; + default: + assert(0); + } + break; case BIN_LESSEQ: + switch (stype) { + case Q_WORD: + return is_signed ? Q_CSLEW : Q_CULEW; + case Q_LONG: + return is_signed ? Q_CSLEL : Q_CULEL; + case Q_SINGLE: + return Q_CLES; + case Q_DOUBLE: + return Q_CLED; + default: + assert(0); + } + break; + case BIN_LAND: case BIN_LOR: - case BIN_LXOR: - case BIN_NEQUAL: - assert(0); // Invariant + assert(0); // Handled elsewhere to address short circuiting } assert(0); // Unreachable }