commit f9367d93b76faa4de2558027456d58179dacf8d2
parent 7f428e7c869bef3d52d12ccdaf8d7002d4fae9e9
Author: Bor Grošelj Simić <bor.groseljsimic@telemach.net>
Date: Sat, 29 Jan 2022 01:55:05 +0100
gen: unsigned <-> float casts
References: https://todo.sr.ht/~sircmpwn/hare/54
Signed-off-by: Bor Grošelj Simić <bor.groseljsimic@telemach.net>
Diffstat:
4 files changed, 90 insertions(+), 4 deletions(-)
diff --git a/include/qbe.h b/include/qbe.h
@@ -111,6 +111,7 @@ enum qbe_instr {
Q_CUOS,
Q_DIV,
Q_DTOSI,
+ Q_DTOUI,
Q_EXTS,
Q_EXTSB,
Q_EXTSH,
@@ -144,11 +145,14 @@ enum qbe_instr {
Q_STORES,
Q_STOREW,
Q_STOSI,
+ Q_STOUI,
Q_SUB,
Q_SWTOF,
Q_TRUNCD,
Q_UDIV,
+ Q_ULTOF,
Q_UREM,
+ Q_UWTOF,
Q_XOR,
Q_LAST_INSTR,
diff --git a/src/gen.c b/src/gen.c
@@ -1493,7 +1493,11 @@ gen_expr_cast(struct gen_context *ctx, const struct expression *expr)
default: abort(); // Invariant
}
} else {
- assert(0); // TODO
+ switch (fstor) {
+ case STORAGE_F32: op = Q_STOUI; break;
+ case STORAGE_F64: op = Q_DTOUI; break;
+ default: abort(); // Invariant
+ }
}
} else {
abort(); // Invariant
@@ -1530,7 +1534,25 @@ gen_expr_cast(struct gen_context *ctx, const struct expression *expr)
default: abort(); // Invariant
}
} else {
- assert(0); // TODO
+ switch (from->size) {
+ case 1:
+ case 2:
+ intermediate = mktemp(ctx,
+ &builtin_type_i32, "cast.%d");
+ qintermediate = mkqval(ctx, &intermediate);
+ pushi(ctx->current, &qintermediate,
+ from->size == 1? Q_EXTUB : Q_EXTUH,
+ &qvalue, NULL);
+ qvalue = qintermediate;
+ /* fallthrough */
+ case 4:
+ op = Q_UWTOF;
+ break;
+ case 8:
+ op = Q_ULTOF;
+ break;
+ default: abort(); // Invariant
+ }
}
} else {
abort(); // Invariant
diff --git a/src/qbe.c b/src/qbe.c
@@ -86,6 +86,7 @@ const char *qbe_instr[Q_LAST_INSTR] = {
[Q_CUOS] = "cuos",
[Q_DIV] = "div",
[Q_DTOSI] = "dtosi",
+ [Q_DTOUI] = "dtoui",
[Q_EXTS] = "exts",
[Q_EXTSB] = "extsb",
[Q_EXTSH] = "extsh",
@@ -119,11 +120,14 @@ const char *qbe_instr[Q_LAST_INSTR] = {
[Q_STORES] = "stores",
[Q_STOREW] = "storew",
[Q_STOSI] = "stosi",
+ [Q_STOUI] = "stoui",
[Q_SUB] = "sub",
[Q_SWTOF] = "swtof",
[Q_TRUNCD] = "truncd",
[Q_UDIV] = "udiv",
+ [Q_ULTOF] = "ultof",
[Q_UREM] = "urem",
+ [Q_UWTOF] = "uwtof",
[Q_XOR] = "xor",
};
diff --git a/tests/35-floats.ha b/tests/35-floats.ha
@@ -1,4 +1,4 @@
-fn casts() void = {
+fn signed_casts() void = {
let a = 20f64;
let f = a: f32;
assert(f == 20f32);
@@ -52,7 +52,63 @@ fn casts() void = {
assert(f == 20f64);
};
+fn unsigned_casts() void = {
+ let a = 20f64;
+ let f = a: f32;
+ assert(f == 20f32);
+ let i = a: u8;
+ assert(i == 20);
+ let i = a: u16;
+ assert(i == 20);
+ let i = a: u16;
+ assert(i == 20);
+ let i = a: u32;
+ assert(i == 20);
+ let i = a: u64;
+ assert(i == 20);
+
+ let a = 20f32;
+ let f = a: f64;
+ assert(f == 20f64);
+ let i = a: u8;
+ assert(i == 20);
+ let i = a: u16;
+ assert(i == 20);
+ let i = a: u16;
+ assert(i == 20);
+ let i = a: u32;
+ assert(i == 20);
+ let i = a: u64;
+ assert(i == 20);
+
+ let a = 20u8;
+ let f = a: f32;
+ assert(f == 20f32);
+ let f = a: f64;
+ assert(f == 20f64);
+
+ let a = 20u16;
+ let f = a: f32;
+ assert(f == 20f32);
+ let f = a: f64;
+ assert(f == 20f64);
+
+ let a = 20u32;
+ let f = a: f32;
+ assert(f == 20f32);
+ let f = a: f64;
+ assert(f == 20f64);
+
+ let a = 20u64;
+ 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();
+ signed_casts();
+ unsigned_casts();
};