commit 8978c6eae3accde2f7fc75204a9e18958e12c360
parent e6e8f8824d2d9eb8388e5580ae630c1bcadac90e
Author: Eyal Sawady <ecs@d2evs.net>
Date: Tue, 12 Jan 2021 12:02:07 -0500
Implement logical AND and logical OR
Diffstat:
3 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/src/gen.c b/src/gen.c
@@ -527,6 +527,35 @@ gen_expr_binarithm(struct gen_context *ctx,
const struct qbe_type *etype = qtype_for_type(ctx, expr->result, false);
assert(ltype == rtype); // TODO: Type promotion
+ if (expr->binarithm.op == BIN_LAND || expr->binarithm.op == BIN_LOR) {
+ struct qbe_statement rlabel = {0}, slabel = {0};
+ struct qbe_value rbranch = {0}, sbranch = {0}, result = {0};
+ rbranch.kind = QV_LABEL;
+ rbranch.name = strdup(genl(&rlabel, &ctx->id, "rvalue.%d"));
+ sbranch.kind = QV_LABEL;
+ sbranch.name = strdup(genl(&slabel, &ctx->id, "short_circuit.%d"));
+ gen_temp(ctx, &result, etype, "result.%d");
+
+ gen_expression(ctx, expr->binarithm.lvalue, &result);
+ if (expr->binarithm.op == BIN_LAND) {
+ pushi(ctx->current, NULL, Q_JNZ, &result, &rbranch,
+ &sbranch, NULL);
+ } else {
+ pushi(ctx->current, NULL, Q_JNZ, &result, &sbranch,
+ &rbranch, NULL);
+ }
+
+ push(&ctx->current->body, &rlabel);
+ gen_expression(ctx, expr->binarithm.rvalue, &result);
+ if (!expr->binarithm.rvalue->terminates) {
+ pushi(ctx->current, NULL, Q_JMP, &sbranch, NULL);
+ }
+
+ push(&ctx->current->body, &slabel);
+ gen_store(ctx, out, &result);
+ return;
+ }
+
struct qbe_value lvalue = {0}, rvalue = {0}, result = {0};
gen_temp(ctx, &lvalue, ltype, "lvalue.%d");
gen_temp(ctx, &rvalue, rtype, "rvalue.%d");
diff --git a/tests/10-binarithms.ha b/tests/10-binarithms.ha
@@ -0,0 +1,35 @@
+
+fn error() bool = {
+ abort();
+ return false;
+};
+
+fn set(x: *int) bool = {
+ *x = 42;
+ return true;
+};
+
+fn andor() void = {
+ assert((false || false) == false);
+ assert((false || true) == true);
+ assert((true || false) == true);
+ assert((true || true) == true);
+ assert((true || error()) == true);
+ let x = 0;
+ assert((false || set(&x)) == true);
+ assert(x == 42);
+
+ assert((false && false) == false);
+ assert((false && true) == false);
+ assert((true && false) == false);
+ assert((true && true) == true);
+ assert((false && error()) == false);
+ x = 0;
+ assert((true && set(&x)) == true);
+ assert(x == 42);
+};
+
+export fn main() void = {
+ // TODO: other binarithms
+ andor();
+};
diff --git a/tests/configure b/tests/configure
@@ -12,7 +12,8 @@ tests() {
06-structs \
07-aliases \
08-slices \
- 09-funcs
+ 09-funcs \
+ 10-binarithms
do
cat <<EOF
tests/$t: libhart.a tests/$t.ha