Skip to content

Commit

Permalink
fix nim-lang#13513 +% now gives correct values in semfold + VM
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheecour committed Feb 28, 2020
1 parent 986f9fc commit 9be3835
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 11 deletions.
10 changes: 9 additions & 1 deletion compiler/semfold.nim
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,14 @@ proc fitLiteral(c: ConfigRef, n: PNode): PNode {.deprecated: "no substitute".} =
if typ.kind in tyUInt..tyUInt32:
result.intVal = result.intVal and castToInt64(lastOrd(c, typ))

proc castToSizeSigned*(a: BiggestInt, numBits: int): BiggestInt =
# consider moving somewhere more general
if numBits == 8: result = cast[int8](a)
elif numBits == 16: result = cast[int16](a)
elif numBits == 32: result = cast[int32](a)
elif numBits == 64: result = cast[int64](a)
else: doAssert false, $numBits

proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
# b and c may be nil
result = nil
Expand Down Expand Up @@ -297,7 +305,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
of mBitorI, mOr: result = newIntNodeT(bitor(getInt(a), getInt(b)), n, g)
of mBitxorI, mXor: result = newIntNodeT(bitxor(getInt(a), getInt(b)), n, g)
of mAddU:
let val = maskBytes(getInt(a) + getInt(b), int(n.typ.size))
let val = castToSizeSigned(cast[BiggestInt](getInt(a) + getInt(b)), int(n.typ.size)*8)
result = newIntNodeT(val, n, g)
of mSubU:
let val = maskBytes(getInt(a) - getInt(b), int(n.typ.size))
Expand Down
13 changes: 3 additions & 10 deletions compiler/vm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import
vmmarshal, gorgeimpl, lineinfos, tables, btrees, macrocacheimpl,
modulegraphs, sighashes, int128

from semfold import leValueConv, ordinalValToString
from semfold import leValueConv, ordinalValToString, castToSizeSigned
from evaltempl import evalTemplate

const
Expand Down Expand Up @@ -1493,15 +1493,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
stackTrace(c, tos, pc, "unhandled exception: value out of range")
of opcNarrowU:
decodeB(rkInt)
var ret = regs[ra].intVal
ret = ret and ((1'i64 shl rb)-1)
echo0b (rb, ret)
if rb == 8: ret = cast[int8](ret)
elif rb == 16: ret = cast[int16](ret)
elif rb == 32: ret = cast[int32](ret)
elif rb == 64: ret = cast[int64](ret)
else: doAssert false, $rb
regs[ra].intVal = ret
var ret = regs[ra].intVal and ((1'i64 shl rb)-1)
regs[ra].intVal = castToSizeSigned(ret, rb)
of opcSignExtend:
# like opcNarrowS, but no out of range possible
decodeB(rkInt)
Expand Down
20 changes: 20 additions & 0 deletions tests/vm/tarithmetics.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
template testAll(isSemFold: bool) =
block:
template test(T) =
proc fun(): T {.gensym.} =
when isSemFold:
high(T) +% 1
else:
let a = high(T)
a +% 1
const a1 = fun()
let a2 = fun()
doAssert a1 <= high(T)
doAssert $a1 == $a2
doAssert a1 == a2
test(int8)
test(int16)
test(int32)

testAll(true) # will call semfold.nim `of mAddU:`
testAll(false) # will call vm.nim `of opcNarrowU:`

0 comments on commit 9be3835

Please sign in to comment.