summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndrii Riabushenko <cdome@bk.ru>2018-10-24 20:29:51 +0100
committerAndrii Riabushenko <cdome@bk.ru>2018-10-24 20:29:51 +0100
commita54e0703a9de7df522c9f50aa3ef70f30405eddf (patch)
tree960b62bebf97b8159cd4790f391941b3a23ecc4c
parentbd68d3d8f4bffbb2451dee74f1475f12079d8e1e (diff)
downloadNim-a54e0703a9de7df522c9f50aa3ef70f30405eddf.tar.gz
Add test
-rw-r--r--compiler/vm.nim14
-rw-r--r--compiler/vmgen.nim9
-rw-r--r--tests/vm/tcastint.nim47
3 files changed, 60 insertions, 10 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 848cbfcf0..05ee3b90e 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 527c3cf2e..ea0fb35ff 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 7b9ddd7d9..f9d42fc54 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"