commit e53dc8299d6493abf22127e2f67d4f27026134de
parent a15c7d28380586cdb938737346c4b80c9cef482a
Author: Drew DeVault <sir@cmpwn.com>
Date: Wed, 3 Feb 2021 17:15:18 -0500
gen: implement string comparisons
Diffstat:
4 files changed, 53 insertions(+), 3 deletions(-)
diff --git a/rt/Makefile b/rt/Makefile
@@ -4,7 +4,8 @@ libhart_srcs+=\
rt/malloc.ha \
rt/memcpy.ha \
rt/memset.ha \
- rt/rtmain.ha
+ rt/rtmain.ha \
+ rt/strcmp.ha
libhart.a: harec $(libhart_srcs) $(libhart_objs) $(rtstart)
@printf 'HAREC\t$@\n'
diff --git a/rt/strcmp.ha b/rt/strcmp.ha
@@ -0,0 +1,18 @@
+type string = struct {
+ data: *[*]u8,
+ length: size,
+ capacity: size,
+};
+
+export fn strcmp(_a: str, _b: str) bool = {
+ if (len(_a) != len(_b)) {
+ return false;
+ };
+ let a = (&_a: *string).data, b = (&_b: *string).data;
+ for (let i = 0z; i < len(_a); i += 1z) {
+ if (a[i] != b[i]) {
+ return false;
+ };
+ };
+ return true;
+};
diff --git a/src/gen.c b/src/gen.c
@@ -788,9 +788,16 @@ gen_expr_binarithm(struct gen_context *ctx,
}
struct qbe_value lvalue = {0}, rvalue = {0}, result = {0};
- gen_temp(ctx, &lvalue, ltype, "lvalue.%d");
- gen_temp(ctx, &rvalue, rtype, "rvalue.%d");
gen_temp(ctx, &result, etype, "result.%d");
+ if (type_is_aggregate(expr->binarithm.lvalue->result)) {
+ alloc_temp(ctx, &lvalue, expr->binarithm.lvalue->result, "lvalue.%d");
+ alloc_temp(ctx, &rvalue, expr->binarithm.lvalue->result, "rvalue.%d");
+ qval_deref(&lvalue);
+ qval_deref(&rvalue);
+ } else {
+ gen_temp(ctx, &lvalue, ltype, "lvalue.%d");
+ gen_temp(ctx, &rvalue, rtype, "rvalue.%d");
+ }
gen_expression(ctx, expr->binarithm.lvalue, &lvalue);
gen_expression(ctx, expr->binarithm.rvalue, &rvalue);
@@ -809,6 +816,23 @@ gen_expr_binarithm(struct gen_context *ctx,
break;
}
+ if (type_dealias(expr->binarithm.lvalue->result)->storage
+ == TYPE_STORAGE_STRING) {
+ struct qbe_value rtfunc = {0};
+ rtfunc.kind = QV_GLOBAL;
+ rtfunc.name = strdup("rt.strcmp");
+ rtfunc.type = &qbe_long;
+ pushi(ctx->current, &result, Q_CALL,
+ &rtfunc, &lvalue, &rvalue, NULL);
+ if (expr->binarithm.op == BIN_NEQUAL) {
+ struct qbe_value temp = {0};
+ constw(&temp, 1);
+ pushi(ctx->current, &result, Q_XOR, &result, &temp, NULL);
+ }
+ gen_store(ctx, out, &result);
+ return;
+ }
+
pushi(ctx->current, &result,
binarithm_for_op(expr->binarithm.op, ltype,
type_is_signed(expr->binarithm.lvalue->result)),
diff --git a/tests/04-strings.ha b/tests/04-strings.ha
@@ -58,9 +58,16 @@ fn concat() void = {
};
};
+fn equality() void = {
+ assert("foo" != "bar");
+ assert("foo" != "foobar");
+ assert("foobar" == "foobar");
+};
+
export fn main() void = {
measurements();
charptr();
storage();
concat();
+ equality();
};