Skip to content

Commit

Permalink
fixes #6255, add system.ashr arithmetic right shift (#8547)
Browse files Browse the repository at this point in the history
  • Loading branch information
jangko authored and Araq committed Aug 7, 2018
1 parent 9b9cfa7 commit 4d5cce9
Show file tree
Hide file tree
Showing 13 changed files with 93 additions and 10 deletions.
3 changes: 2 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@
- ``parseOct`` and ``parseBin`` in parseutils now also support the ``maxLen`` argument similar to ``parseHexInt``
- Added the proc ``flush`` for memory mapped files.
- Added the ``MemMapFileStream``.
- Added ``macros.copyLineInfo`` to copy lineInfo from other node
- Added ``macros.copyLineInfo`` to copy lineInfo from other node.
- Added ``system.ashr`` an arithmetic right shift for integers.

### Library changes

Expand Down
2 changes: 1 addition & 1 deletion compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ type
mAddI, mSubI, mMulI, mDivI, mModI,
mSucc, mPred,
mAddF64, mSubF64, mMulF64, mDivF64,
mShrI, mShlI, mBitandI, mBitorI, mBitxorI,
mShrI, mShlI, mAshrI, mBitandI, mBitorI, mBitxorI,
mMinI, mMaxI,
mMinF64, mMaxF64,
mAddU, mSubU, mMulU, mDivU, mModU,
Expand Down
2 changes: 1 addition & 1 deletion compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -552,9 +552,9 @@ proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
"(($4)($1) - ($4)($2))", # SubF64
"(($4)($1) * ($4)($2))", # MulF64
"(($4)($1) / ($4)($2))", # DivF64

"($4)((NU$5)($1) >> (NU$3)($2))", # ShrI
"($4)((NU$3)($1) << (NU$3)($2))", # ShlI
"($4)((NI$3)($1) >> (NU$3)($2))", # AshrI
"($4)($1 & $2)", # BitandI
"($4)($1 | $2)", # BitorI
"($4)($1 ^ $2)", # BitxorI
Expand Down
1 change: 1 addition & 0 deletions compiler/condsyms.nim
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,4 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimNotNil")
defineSymbol("nimVmExportFixed")
defineSymbol("nimIncrSeqV3")
defineSymbol("nimAshr")
1 change: 1 addition & 0 deletions compiler/jsgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
["", "", "($1 / $2)", "($1 / $2)"], # DivF64
["", "", "", ""], # ShrI
["", "", "($1 << $2)", "($1 << $2)"], # ShlI
["", "", "($1 >> $2)", "($1 >> $2)"], # AshrI
["", "", "($1 & $2)", "($1 & $2)"], # BitandI
["", "", "($1 | $2)", "($1 | $2)"], # BitorI
["", "", "($1 ^ $2)", "($1 ^ $2)"], # BitxorI
Expand Down
8 changes: 8 additions & 0 deletions compiler/semfold.nim
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,14 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
of tyInt64, tyInt, tyUInt..tyUInt64:
result = newIntNodeT(`shr`(getInt(a), getInt(b)), n, g)
else: internalError(g.config, n.info, "constant folding for shr")
of mAshrI:
case skipTypes(n.typ, abstractRange).kind
of tyInt8: result = newIntNodeT(ashr(int8(getInt(a)), int8(getInt(b))), n, g)
of tyInt16: result = newIntNodeT(ashr(int16(getInt(a)), int16(getInt(b))), n, g)
of tyInt32: result = newIntNodeT(ashr(int32(getInt(a)), int32(getInt(b))), n, g)
of tyInt64, tyInt:
result = newIntNodeT(ashr(getInt(a), getInt(b)), n, g)
else: internalError(g.config, n.info, "constant folding for ashr")
of mDivI: result = foldDiv(getInt(a), getInt(b), n, g)
of mModI: result = foldMod(getInt(a), getInt(b), n, g)
of mAddF64: result = newFloatNodeT(getFloat(a) + getFloat(b), n, g)
Expand Down
4 changes: 4 additions & 0 deletions compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,10 @@ proc inferStaticParam*(c: var TCandidate, lhs: PNode, rhs: BiggestInt): bool =
if lhs[2].kind == nkIntLit:
return inferStaticParam(c, lhs[1], rhs shl lhs[2].intVal)

of mAshrI:
if lhs[2].kind == nkIntLit:
return inferStaticParam(c, lhs[1], ashr(rhs, lhs[2].intVal))

of mUnaryMinusI:
return inferStaticParam(c, lhs[1], -rhs)

Expand Down
3 changes: 3 additions & 0 deletions compiler/vm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of opcShlInt:
decodeBC(rkInt)
regs[ra].intVal = regs[rb].intVal shl regs[rc].intVal
of opcAshrInt:
decodeBC(rkInt)
regs[ra].intVal = ashr(regs[rb].intVal, regs[rc].intVal)
of opcBitandInt:
decodeBC(rkInt)
regs[ra].intVal = regs[rb].intVal and regs[rc].intVal
Expand Down
3 changes: 2 additions & 1 deletion compiler/vmdef.nim
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ type
opcLenStr,

opcIncl, opcInclRange, opcExcl, opcCard, opcMulInt, opcDivInt, opcModInt,
opcAddFloat, opcSubFloat, opcMulFloat, opcDivFloat, opcShrInt, opcShlInt,
opcAddFloat, opcSubFloat, opcMulFloat, opcDivFloat,
opcShrInt, opcShlInt, opcAshrInt,
opcBitandInt, opcBitorInt, opcBitxorInt, opcAddu, opcSubu, opcMulu,
opcDivu, opcModu, opcEqInt, opcLeInt, opcLtInt, opcEqFloat,
opcLeFloat, opcLtFloat, opcLeu, opcLtu,
Expand Down
1 change: 1 addition & 0 deletions compiler/vmgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -939,6 +939,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
c.freeTemp(tmp2)

of mShlI: genBinaryABCnarrowU(c, n, dest, opcShlInt)
of mAshrI: genBinaryABCnarrow(c, n, dest, opcAshrInt)
of mBitandI: genBinaryABCnarrowU(c, n, dest, opcBitandInt)
of mBitorI: genBinaryABCnarrowU(c, n, dest, opcBitorInt)
of mBitxorI: genBinaryABCnarrowU(c, n, dest, opcBitxorInt)
Expand Down
17 changes: 17 additions & 0 deletions lib/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,23 @@ else:
proc `shl`*(x, y: int32): int32 {.magic: "ShlI", noSideEffect.}
proc `shl`*(x, y: int64): int64 {.magic: "ShlI", noSideEffect.}

when defined(nimAshr):
proc ashr*(x: int, y: SomeInteger): int {.magic: "AshrI", noSideEffect.}
proc ashr*(x: int8, y: SomeInteger): int8 {.magic: "AshrI", noSideEffect.}
proc ashr*(x: int16, y: SomeInteger): int16 {.magic: "AshrI", noSideEffect.}
proc ashr*(x: int32, y: SomeInteger): int32 {.magic: "AshrI", noSideEffect.}
proc ashr*(x: int64, y: SomeInteger): int64 {.magic: "AshrI", noSideEffect.}
## Shifts right by pushing copies of the leftmost bit in from the left,
## and let the rightmost bits fall off.
##
## .. code-block:: Nim
## 0b0001_0000'i8 shr 2 == 0b0000_0100'i8
## 0b1000_0000'i8 shr 8 == 0b1111_1111'i8
## 0b1000_0000'i8 shr 1 == 0b1100_0000'i8
else:
# used for bootstrapping the compiler
proc ashr*[T](x: T, y: SomeInteger): T = discard

proc `and`*(x, y: int): int {.magic: "BitandI", noSideEffect.}
proc `and`*(x, y: int8): int8 {.magic: "BitandI", noSideEffect.}
proc `and`*(x, y: int16): int16 {.magic: "BitandI", noSideEffect.}
Expand Down
46 changes: 46 additions & 0 deletions tests/arithm/tashr.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
discard """
output: ''''''
targets: '''c js'''
"""

# issue #6255, feature request
# arithmetic right shift

var x1 = -123'i8
var x2 = -123'i16
var x3 = -123'i32
var x4 = -123'i64
var x5 = -123

block codegen_test:
doAssert ashr(x1, 1) == -62
doAssert ashr(x2, 1) == -62
doAssert ashr(x3, 1) == -62
doAssert ashr(x4, 1) == -62
doAssert ashr(x5, 1) == -62

block semfold_test:
doAssert ashr(-123'i8 , 1) == -62
doAssert ashr(-123'i16, 1) == -62
doAssert ashr(-123'i32, 1) == -62
doAssert ashr(-123'i64, 1) == -62
doAssert ashr(-123 , 1) == -62

static: # VM test
doAssert ashr(-123'i8 , 1) == -62
doAssert ashr(-123'i16, 1) == -62
doAssert ashr(-123'i32, 1) == -62
doAssert ashr(-123'i64, 1) == -62
doAssert ashr(-123 , 1) == -62

var y1 = -123'i8
var y2 = -123'i16
var y3 = -123'i32
var y4 = -123'i64
var y5 = -123

doAssert ashr(y1, 1) == -62
doAssert ashr(y2, 1) == -62
doAssert ashr(y3, 1) == -62
doAssert ashr(y4, 1) == -62
doAssert ashr(y5, 1) == -62
12 changes: 6 additions & 6 deletions tests/concepts/t3330.nim
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,11 @@ proc add(result: var string; x: float)
first type mismatch at position: 1
required type: var string
but expression 'k' is of type: Alias
proc add(x: var string; y: cstring)
first type mismatch at position: 1
required type: var string
but expression 'k' is of type: Alias
proc add(x: var string; y: char)
proc add(x: var string; y: string)
first type mismatch at position: 1
required type: var string
but expression 'k' is of type: Alias
proc add(x: var string; y: string)
proc add(x: var string; y: cstring)
first type mismatch at position: 1
required type: var string
but expression 'k' is of type: Alias
Expand All @@ -33,6 +29,10 @@ proc add(result: var string; x: int64)
first type mismatch at position: 1
required type: var string
but expression 'k' is of type: Alias
proc add(x: var string; y: char)
first type mismatch at position: 1
required type: var string
but expression 'k' is of type: Alias
t3330.nim(48, 8) template/generic instantiation from here
t3330.nim(55, 6) Foo: 'bar.value' cannot be assigned to
Expand Down

0 comments on commit 4d5cce9

Please sign in to comment.