From a54e0703a9de7df522c9f50aa3ef70f30405eddf Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Wed, 24 Oct 2018 20:29:51 +0100 Subject: [PATCH] Add test --- compiler/vm.nim | 14 ++++++++----- compiler/vmgen.nim | 9 ++++----- tests/vm/tcastint.nim | 47 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 10 deletions(-) diff --git a/compiler/vm.nim b/compiler/vm.nim index 848cbfcf07..05ee3b90e3 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -489,17 +489,21 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = decodeB(rkFloat) regs[ra].floatVal = regs[rb].floatVal of opcAsgnIntFromFloat32: - decodeB(rkFloat) + let rb = instr.regB + ensureKind(rkInt) regs[ra].intVal = cast[int32](float32(regs[rb].floatVal)) of opcAsgnIntFromFloat64: - decodeB(rkFloat) + let rb = instr.regB + ensureKind(rkInt) regs[ra].intVal = cast[int64](regs[rb].floatVal) of opcAsgnFloat32FromInt: - decodeB(rkInt) + let rb = instr.regB + ensureKind(rkFloat) regs[ra].floatVal = cast[float32](int32(regs[rb].intVal)) of opcAsgnFloat64FromInt: - decodeB(rkInt) - regs[ra].floatVal = cast[float64](int64(regs[rb].intVal)) + let rb = instr.regB + ensureKind(rkFloat) + regs[ra].floatVal = cast[float64](int64(regs[rb].intVal)) of opcAsgnComplex: asgnComplex(regs[ra], regs[instr.regB]) of opcAsgnRef: diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 527c3cf2e8..ea0fb35ff3 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -811,8 +811,7 @@ proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) = c.freeTemp(tmp3) elif src_size == dst_size and src.kind in allowedIntegers and dst.kind in {tyFloat, tyFloat32, tyFloat64}: - - let tmp = c.getTemp(n.sons[1].typ) + let tmp = c.genx(n[1]) if dest < 0: dest = c.getTemp(n[0].typ) if dst.kind == tyFloat32: c.gABC(n, opcAsgnFloat32FromInt, dest, tmp) @@ -821,15 +820,15 @@ proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) = c.freeTemp(tmp) elif src_size == dst_size and src.kind in {tyFloat, tyFloat32, tyFloat64} and - dst.kind in allowedIntegers: - - let tmp = c.getTemp(n.sons[1].typ) + dst.kind in allowedIntegers: + let tmp = c.genx(n[1]) if dest < 0: dest = c.getTemp(n[0].typ) if src.kind == tyFloat32: c.gABC(n, opcAsgnIntFromFloat32, dest, tmp) else: c.gABC(n, opcAsgnIntFromFloat64, dest, tmp) c.freeTemp(tmp) + else: globalError(c.config, n.info, "VM is only allowed to 'cast' between integers and/or floats of same size") diff --git a/tests/vm/tcastint.nim b/tests/vm/tcastint.nim index 7b9ddd7d9f..f9d42fc548 100644 --- a/tests/vm/tcastint.nim +++ b/tests/vm/tcastint.nim @@ -113,8 +113,55 @@ proc test() = doAssert(not compiles(cast[uint32](I8))) doAssert(not compiles(cast[uint64](I8))) + +proc test_float_cast = + + const + exp_bias = 1023'i64 + exp_shift = 52 + exp_mask = 0x7ff'i64 shl exp_shift + mantissa_mask = 0xfffffffffffff'i64 + + let f = 8.0 + let fx = cast[int64](f) + let exponent = ((fx and exp_mask) shr exp_shift) - exp_bias + let mantissa = fx and mantissa_mask + doAssert(exponent == 3, $exponent) + doAssert(mantissa == 0, $mantissa) + + # construct 2^N float, where N is integer + let x = -2'i64 + let xx = (x + exp_bias) shl exp_shift + let xf = cast[float](xx) + doAssert(xf == 0.25, $xf) + +proc test_float32_cast = + + const + exp_bias = 127'i32 + exp_shift = 23 + exp_mask = 0x7f800000'i32 + mantissa_mask = 0x007ffff'i32 + + let f = -0.5'f32 + let fx = cast[int32](f) + let exponent = ((fx and exp_mask) shr exp_shift) - exp_bias + let mantissa = fx and mantissa_mask + doAssert(exponent == -1, $exponent) + doAssert(mantissa == 0, $mantissa) + + # construct 2^N float32 where N is integer + let x = 4'i32 + let xx = (x + exp_bias) shl exp_shift + let xf = cast[float32](xx) + doAssert(xf == 16.0'f32, $xf) + test() +test_float_cast() +test_float32_cast() static: test() + test_float_cast() + test_float32_cast() echo "OK"