fixes #19198 [backport:1.6] (#19209)

* fixes #19198 [backport:1.6]

* added a test case
This commit is contained in:
Andreas Rumpf 2021-12-04 07:43:20 +01:00 • committed by GitHub
commit f90620fb32
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 16 deletions

View file

@ -434,8 +434,10 @@ proc opConv(c: PCtx; dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType):
of tyFloat..tyFloat64: of tyFloat..tyFloat64:
dest.intVal = int(src.floatVal) dest.intVal = int(src.floatVal)
else: else:
let srcDist = (sizeof(src.intVal) - styp.size) * 8 let srcSize = getSize(c.config, styp)
let destDist = (sizeof(dest.intVal) - desttyp.size) * 8 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) var value = cast[BiggestUInt](src.intVal)
value = (value shl srcDist) shr srcDist value = (value shl srcDist) shr srcDist
value = (value shl destDist) shr destDist value = (value shl destDist) shr destDist

View file

@ -749,18 +749,20 @@ proc genNarrow(c: PCtx; n: PNode; dest: TDest) =
let t = skipTypes(n.typ, abstractVar-{tyTypeDesc}) let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
# uint is uint64 in the VM, we we only need to mask the result for # uint is uint64 in the VM, we we only need to mask the result for
# other unsigned types: # other unsigned types:
if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and t.size < 8): let size = getSize(c.config, t)
c.gABC(n, opcNarrowU, dest, TRegister(t.size*8)) if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and size < 8):
elif t.kind in {tyInt8..tyInt32} or (t.kind == tyInt and t.size < 8): c.gABC(n, opcNarrowU, dest, TRegister(size*8))
c.gABC(n, opcNarrowS, dest, TRegister(t.size*8)) elif t.kind in {tyInt8..tyInt32} or (t.kind == tyInt and size < 8):
c.gABC(n, opcNarrowS, dest, TRegister(size*8))
proc genNarrowU(c: PCtx; n: PNode; dest: TDest) = proc genNarrowU(c: PCtx; n: PNode; dest: TDest) =
let t = skipTypes(n.typ, abstractVar-{tyTypeDesc}) let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
# uint is uint64 in the VM, we we only need to mask the result for # uint is uint64 in the VM, we we only need to mask the result for
# other unsigned types: # other unsigned types:
let size = getSize(c.config, t)
if t.kind in {tyUInt8..tyUInt32, tyInt8..tyInt32} or if t.kind in {tyUInt8..tyUInt32, tyInt8..tyInt32} or
(t.kind in {tyUInt, tyInt} and t.size < 8): (t.kind in {tyUInt, tyInt} and size < 8):
c.gABC(n, opcNarrowU, dest, TRegister(t.size*8)) c.gABC(n, opcNarrowU, dest, TRegister(size*8))
proc genBinaryABCnarrow(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) = proc genBinaryABCnarrow(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
genBinaryABC(c, n, dest, opc) genBinaryABC(c, n, dest, opc)
@ -1088,10 +1090,11 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
genBinaryABC(c, n, dest, opcShlInt) genBinaryABC(c, n, dest, opcShlInt)
# genNarrowU modified # genNarrowU modified
let t = skipTypes(n.typ, abstractVar-{tyTypeDesc}) let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and t.size < 8): let size = getSize(c.config, t)
c.gABC(n, opcNarrowU, dest, TRegister(t.size*8)) if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and size < 8):
elif t.kind in {tyInt8..tyInt32} or (t.kind == tyInt and t.size < 8): c.gABC(n, opcNarrowU, dest, TRegister(size*8))
c.gABC(n, opcSignExtend, dest, TRegister(t.size*8)) elif t.kind in {tyInt8..tyInt32} or (t.kind == tyInt and size < 8):
c.gABC(n, opcSignExtend, dest, TRegister(size*8))
of mAshrI: genBinaryABC(c, n, dest, opcAshrInt) of mAshrI: genBinaryABC(c, n, dest, opcAshrInt)
of mBitandI: genBinaryABC(c, n, dest, opcBitandInt) of mBitandI: genBinaryABC(c, n, dest, opcBitandInt)
of mBitorI: genBinaryABC(c, n, dest, opcBitorInt) of mBitorI: genBinaryABC(c, n, dest, opcBitorInt)
@ -1125,8 +1128,9 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
genUnaryABC(c, n, dest, opcBitnotInt) genUnaryABC(c, n, dest, opcBitnotInt)
#genNarrowU modified, do not narrow signed types #genNarrowU modified, do not narrow signed types
let t = skipTypes(n.typ, abstractVar-{tyTypeDesc}) let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and t.size < 8): let size = getSize(c.config, t)
c.gABC(n, opcNarrowU, dest, TRegister(t.size*8)) if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and size < 8):
c.gABC(n, opcNarrowU, dest, TRegister(size*8))
of mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr: of mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr:
genConv(c, n, n[1], dest) genConv(c, n, n[1], dest)
of mEqStr, mEqCString: genBinaryABC(c, n, dest, opcEqStr) of mEqStr, mEqCString: genBinaryABC(c, n, dest, opcEqStr)

View file

@ -290,10 +290,10 @@ block: # bug #10815
const a = P() const a = P()
doAssert $a == "" doAssert $a == ""
when defined osx: # xxx bug https://github.com/nim-lang/Nim/issues/10815#issuecomment-476380734 when defined osx: # xxx bug https://github.com/nim-lang/Nim/issues/10815#issuecomment-476380734
block: block:
type CharSet {.union.} = object type CharSet {.union.} = object
cs: set[char] cs: set[char]
vs: array[4, uint64] vs: array[4, uint64]
const a = Charset(cs: {'a'..'z'}) const a = Charset(cs: {'a'..'z'})
@ -553,3 +553,22 @@ block: # bug #8015
doAssert $viaProc.table[0] == "(kind: Fixed, cost: 999)" doAssert $viaProc.table[0] == "(kind: Fixed, cost: 999)"
doAssert viaProc.table[1].handler() == 100 doAssert viaProc.table[1].handler() == 100
doAssert viaProc.table[2].handler() == 200 doAssert viaProc.table[2].handler() == 200
# bug #19198
block:
type
Foo[n: static int] = int
block:
static:
let x = int 1
echo x.type # Foo
block:
static:
let x = int 1
let y = x + 1
# Error: unhandled exception: value out of range: -8 notin 0 .. 65535 [RangeDefect]
echo y