diff options
author | autumngray <simon.werbeck@gmail.com> | 2024-08-27 14:03:56 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-27 14:03:56 +0200 |
commit | 540b414c861c44be9011336ee5fb1cd6f0d6da44 (patch) | |
tree | dd8b17ec4d8433648416a8292c6cbc3f148038e1 /compiler | |
parent | f09c549d42f477866bfa72a902d6b43f85959e8f (diff) | |
download | Nim-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.nim | 18 |
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)) |