summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authormetagn <metagngn@gmail.com>2023-06-25 01:01:08 +0300
committerGitHub <noreply@github.com>2023-06-25 00:01:08 +0200
commitf718f295df3f6ee5d7fd6fc19e39ac663821b00a (patch)
tree3ed631793cd2d838ad4909afa51770b28864cb14 /compiler
parentc6c85f84db3bd7bd2d1c5823020c7df007f1bb69 (diff)
downloadNim-f718f295df3f6ee5d7fd6fc19e39ac663821b00a.tar.gz
fix VM uint conversion size bug, stricter int gen on JS (#22150)
* fix VM uint conversion bug, stricter int gen on JS

fixes #19929

* fix float -> uint64 conversion too

* no need to mask to source type

* simpler diff with explanation, add test for described issue
Diffstat (limited to 'compiler')
-rw-r--r--compiler/jsgen.nim22
-rw-r--r--compiler/vm.nim10
2 files changed, 23 insertions, 9 deletions
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index ecfc22108..1fbf6c74c 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -2513,10 +2513,12 @@ proc genConv(p: PProc, n: PNode, r: var TCompRes) =
     elif src.kind == tyUInt64:
       r.res = "BigInt.asIntN(64, $1)" % [r.res]
   elif dest.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
-    if fromInt or fromUint:
+    if fromUint or src.kind in {tyBool, tyChar, tyEnum}:
       r.res = "BigInt($1)" % [r.res]
+    elif fromInt: # could be negative
+      r.res = "BigInt.asUintN(64, BigInt($1))" % [r.res]
     elif src.kind in {tyFloat..tyFloat64}:
-      r.res = "BigInt(Math.trunc($1))" % [r.res]
+      r.res = "BigInt.asUintN(64, BigInt(Math.trunc($1)))" % [r.res]
     elif src.kind == tyInt64:
       r.res = "BigInt.asUintN(64, $1)" % [r.res]
   elif toUint or dest.kind in tyFloat..tyFloat64:
@@ -2755,10 +2757,12 @@ proc genCast(p: PProc, n: PNode, r: var TCompRes) =
     elif src.kind == tyUInt64:
       r.res = "BigInt.asIntN(64, $1)" % [r.res]
   elif dest.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
-    if fromInt or fromUint:
+    if fromUint or src.kind in {tyBool, tyChar, tyEnum}:
       r.res = "BigInt($1)" % [r.res]
+    elif fromInt: # could be negative
+      r.res = "BigInt.asUintN(64, BigInt($1))" % [r.res]
     elif src.kind in {tyFloat..tyFloat64}:
-      r.res = "BigInt(Math.trunc($1))" % [r.res]
+      r.res = "BigInt.asUintN(64, BigInt(Math.trunc($1)))" % [r.res]
     elif src.kind == tyInt64:
       r.res = "BigInt.asUintN(64, $1)" % [r.res]
   elif dest.kind in tyFloat..tyFloat64:
@@ -2790,11 +2794,17 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
       if optJsBigInt64 in p.config.globalOptions:
         r.res.add('n')
     of tyInt64:
-      r.res = rope(n.intVal)
+      let wrap = n.intVal < 0 # wrap negative integers with parens
+      if wrap: r.res.add '('
+      r.res.addInt n.intVal
       if optJsBigInt64 in p.config.globalOptions:
         r.res.add('n')
+      if wrap: r.res.add ')'
     else:
-      r.res = rope(n.intVal)
+      let wrap = n.intVal < 0 # wrap negative integers with parens
+      if wrap: r.res.add '('
+      r.res.addInt n.intVal
+      if wrap: r.res.add ')'
     r.kind = resExpr
   of nkNilLit:
     if isEmptyType(n.typ):
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 8b5faabfe..7376ff165 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -443,12 +443,16 @@ proc opConv(c: PCtx; dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType):
       of tyFloat..tyFloat64:
         dest.intVal = int(src.floatVal)
       else:
-        let srcSize = getSize(c.config, styp)
         let destSize = getSize(c.config, desttyp)
-        let srcDist = (sizeof(src.intVal) - srcSize) * 8
         let destDist = (sizeof(dest.intVal) - destSize) * 8
         var value = cast[BiggestUInt](src.intVal)
-        value = (value shl srcDist) shr srcDist
+        when false:
+          # this would make uint64(-5'i8) evaluate to 251
+          # but at runtime, uint64(-5'i8) is 18446744073709551611
+          # so don't do it
+          let srcSize = getSize(c.config, styp)
+          let srcDist = (sizeof(src.intVal) - srcSize) * 8
+          value = (value shl srcDist) shr srcDist
         value = (value shl destDist) shr destDist
         dest.intVal = cast[BiggestInt](value)
     of tyBool: