diff options
author | andri lim <jangko128@gmail.com> | 2018-08-07 23:41:30 +0700 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2018-08-07 18:41:30 +0200 |
commit | 4d5cce9882d554ada9cf737d63e40880d88ba170 (patch) | |
tree | 7c71118c55f00ff6542e047a751b2ad7af6cb71d | |
parent | 9b9cfa7306d696961cc6fd590ca72c08f66bdcb3 (diff) | |
download | Nim-4d5cce9882d554ada9cf737d63e40880d88ba170.tar.gz |
fixes #6255, add `system.ashr` arithmetic right shift (#8547)
-rw-r--r-- | changelog.md | 3 | ||||
-rw-r--r-- | compiler/ast.nim | 2 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 2 | ||||
-rw-r--r-- | compiler/condsyms.nim | 1 | ||||
-rw-r--r-- | compiler/jsgen.nim | 1 | ||||
-rw-r--r-- | compiler/semfold.nim | 8 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 4 | ||||
-rw-r--r-- | compiler/vm.nim | 3 | ||||
-rw-r--r-- | compiler/vmdef.nim | 3 | ||||
-rw-r--r-- | compiler/vmgen.nim | 1 | ||||
-rw-r--r-- | lib/system.nim | 17 | ||||
-rw-r--r-- | tests/arithm/tashr.nim | 46 | ||||
-rw-r--r-- | tests/concepts/t3330.nim | 12 |
13 files changed, 93 insertions, 10 deletions
diff --git a/changelog.md b/changelog.md index 4c19abfc0..c1e7bd09c 100644 --- a/changelog.md +++ b/changelog.md @@ -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 diff --git a/compiler/ast.nim b/compiler/ast.nim index dbf1151a9..ef12e1184 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -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, diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 3bcf2c29b..6803a9478 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -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 diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 9dfe69442..5a62b46ad 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -73,3 +73,4 @@ proc initDefines*(symbols: StringTableRef) = defineSymbol("nimNotNil") defineSymbol("nimVmExportFixed") defineSymbol("nimIncrSeqV3") + defineSymbol("nimAshr") diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index ef54841ae..63100a68d 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -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 diff --git a/compiler/semfold.nim b/compiler/semfold.nim index d2abfac13..a6c185fdc 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -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) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 29f16b808..5afa1b031 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -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) diff --git a/compiler/vm.nim b/compiler/vm.nim index d4b041dea..c49b66b82 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -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 diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index a4489513a..50235c95f 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -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, diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 965c75485..a36f559ca 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -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) diff --git a/lib/system.nim b/lib/system.nim index 94baf7370..53605f9fd 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -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.} diff --git a/tests/arithm/tashr.nim b/tests/arithm/tashr.nim new file mode 100644 index 000000000..aeb3b6843 --- /dev/null +++ b/tests/arithm/tashr.nim @@ -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 diff --git a/tests/concepts/t3330.nim b/tests/concepts/t3330.nim index 78dd876e2..8021db827 100644 --- a/tests/concepts/t3330.nim +++ b/tests/concepts/t3330.nim @@ -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 @@ -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 |