commit 9886c903b7c4e919d70e324ed730ef143c6d0b67
parent b2341bcd39cf7e04969a6bb1ee1c2887ce28a8e6
Author: Bor Grošelj Simić <bor.groseljsimic@telemach.net>
Date: Mon, 24 Jan 2022 05:12:56 +0100
implement {i8,i16} -> floating point casts
Signed-off-by: Bor Grošelj Simić <bor.groseljsimic@telemach.net>
Diffstat:
3 files changed, 78 insertions(+), 3 deletions(-)
diff --git a/src/gen.c b/src/gen.c
@@ -1447,6 +1447,8 @@ gen_expr_cast(struct gen_context *ctx, const struct expression *expr)
struct qbe_value qvalue = mkqval(ctx, &value);
struct gen_value result = mktemp(ctx, expr->result, "cast.%d");
struct qbe_value qresult = mkqval(ctx, &result);
+ struct gen_value intermediate;
+ struct qbe_value qintermediate;
enum qbe_instr op;
bool is_signed = type_is_signed(from);
@@ -1509,8 +1511,22 @@ gen_expr_cast(struct gen_context *ctx, const struct expression *expr)
} else if (type_is_integer(from)) {
if (type_is_signed(from)) {
switch (from->size) {
- case 4: op = Q_SWTOF; break;
- case 8: op = Q_SLTOF; break;
+ case 1:
+ case 2:
+ intermediate = mktemp(ctx,
+ &builtin_type_i32, "cast.%d");
+ qintermediate = mkqval(ctx, &intermediate);
+ pushi(ctx->current, &qintermediate,
+ from->size == 1? Q_EXTSB : Q_EXTSH,
+ &qvalue, NULL);
+ qvalue = qintermediate;
+ /* fallthrough */
+ case 4:
+ op = Q_SWTOF;
+ break;
+ case 8:
+ op = Q_SLTOF;
+ break;
default: abort(); // Invariant
}
} else {
diff --git a/tests/35-floats.ha b/tests/35-floats.ha
@@ -0,0 +1,58 @@
+fn casts() void = {
+ let a = 20f64;
+ let f = a: f32;
+ assert(f == 20f32);
+ let i = a: i8;
+ assert(i == 20);
+ let i = a: i16;
+ assert(i == 20);
+ let i = a: i16;
+ assert(i == 20);
+ let i = a: i32;
+ assert(i == 20);
+ let i = a: i64;
+ assert(i == 20);
+
+ let a = 20f32;
+ let f = a: f64;
+ assert(f == 20f64);
+ let i = a: i8;
+ assert(i == 20);
+ let i = a: i16;
+ assert(i == 20);
+ let i = a: i16;
+ assert(i == 20);
+ let i = a: i32;
+ assert(i == 20);
+ let i = a: i64;
+ assert(i == 20);
+
+ let a = 20i8;
+ let f = a: f32;
+ assert(f == 20f32);
+ let f = a: f64;
+ assert(f == 20f64);
+
+ let a = 20i16;
+ let f = a: f32;
+ assert(f == 20f32);
+ let f = a: f64;
+ assert(f == 20f64);
+
+ let a = 20i32;
+ let f = a: f32;
+ assert(f == 20f32);
+ let f = a: f64;
+ assert(f == 20f64);
+
+ let a = 20i64;
+ let f = a: f32;
+ assert(f == 20f32);
+ let f = a: f64;
+ assert(f == 20f64);
+};
+
+export fn main() void = {
+ // TODO: test parsing, compile-time evaluation
+ casts();
+};
diff --git a/tests/configure b/tests/configure
@@ -37,7 +37,8 @@ tests() {
31-postfix \
32-copy \
33-yield \
- 34-declarations
+ 34-declarations \
+ 35-floats
do
cat <<EOF
tests/$t: libhart.a tests/$t.ha