summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorautumngray <simon.werbeck@gmail.com>2024-08-27 14:03:56 +0200
committerGitHub <noreply@github.com>2024-08-27 14:03:56 +0200
commit540b414c861c44be9011336ee5fb1cd6f0d6da44 (patch)
treedd8b17ec4d8433648416a8292c6cbc3f148038e1 /compiler
parentf09c549d42f477866bfa72a902d6b43f85959e8f (diff)
downloadNim-540b414c861c44be9011336ee5fb1cd6f0d6da44.tar.gz
fixes #23925; VM generates wrong cast for negative enum values (#23951)
Follow up of #23927 which solves the build error.

This is still only a partial fix as it doesn't take into account
unordered enums. I'll make a separate issue for those.

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
Diffstat (limited to 'compiler')
-rw-r--r--compiler/vmgen.nim18
1 files changed, 12 insertions, 6 deletions
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 4abaed920..1879245ab 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -900,9 +900,15 @@ proc genCard(c: PCtx; n: PNode; dest: var TDest) =
   c.freeTemp(tmp)
 
 proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) =
+  template isSigned(typ: PType): bool {.dirty.} =
+    typ.kind == tyEnum and firstOrd(c.config, typ) < 0 or
+    typ.kind in {tyInt..tyInt64}
+  template isUnsigned(typ: PType): bool {.dirty.} =
+    typ.kind == tyEnum and firstOrd(c.config, typ) >= 0 or
+    typ.kind in {tyUInt..tyUInt64, tyChar, tyBool}
+
   const allowedIntegers = {tyInt..tyInt64, tyUInt..tyUInt64, tyChar, tyEnum, tyBool}
-  var signedIntegers = {tyInt..tyInt64}
-  var unsignedIntegers = {tyUInt..tyUInt64, tyChar, tyEnum, tyBool}
+
   let src = n[1].typ.skipTypes(abstractRange)#.kind
   let dst = n[0].typ.skipTypes(abstractRange)#.kind
   let srcSize = getSize(c.config, src)
@@ -914,12 +920,12 @@ proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) =
     if dest < 0: dest = c.getTemp(n[0].typ)
     c.gABC(n, opcAsgnInt, dest, tmp)
     if dstSize != sizeof(BiggestInt): # don't do anything on biggest int types
-      if dst.kind in signedIntegers: # we need to do sign extensions
+      if isSigned(dst): # we need to do sign extensions
         if dstSize <= srcSize:
           # Sign extension can be omitted when the size increases.
           c.gABC(n, opcSignExtend, dest, TRegister(dstSize*8))
-      elif dst.kind in unsignedIntegers:
-        if src.kind in signedIntegers or dstSize < srcSize:
+      elif isUnsigned(dst):
+        if isSigned(src) or dstSize < srcSize:
           # Cast from signed to unsigned always needs narrowing. Cast
           # from unsigned to unsigned only needs narrowing when target
           # is smaller than source.
@@ -947,7 +953,7 @@ proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) =
     if dest < 0: dest = c.getTemp(n[0].typ)
     if src.kind == tyFloat32:
       c.gABC(n, opcCastFloatToInt32, dest, tmp)
-      if dst.kind in unsignedIntegers:
+      if isUnsigned(dst):
         # integers are sign extended by default.
         # since there is no opcCastFloatToUInt32, narrowing should do the trick.
         c.gABC(n, opcNarrowU, dest, TRegister(32))