harec

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

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:
Minclude/qbe.h | 4++++
Msrc/gen.c | 26++++++++++++++++++++++++--
Msrc/qbe.c | 4++++
Mtests/35-floats.ha | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
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(); };