summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorandri lim <jangko128@gmail.com>2018-08-07 23:41:30 +0700
committerAndreas Rumpf <rumpf_a@web.de>2018-08-07 18:41:30 +0200
commit4d5cce9882d554ada9cf737d63e40880d88ba170 (patch)
tree7c71118c55f00ff6542e047a751b2ad7af6cb71d
parent9b9cfa7306d696961cc6fd590ca72c08f66bdcb3 (diff)
downloadNim-4d5cce9882d554ada9cf737d63e40880d88ba170.tar.gz
fixes #6255, add `system.ashr` arithmetic right shift (#8547)
-rw-r--r--changelog.md3
-rw-r--r--compiler/ast.nim2
-rw-r--r--compiler/ccgexprs.nim2
-rw-r--r--compiler/condsyms.nim1
-rw-r--r--compiler/jsgen.nim1
-rw-r--r--compiler/semfold.nim8
-rw-r--r--compiler/sigmatch.nim4
-rw-r--r--compiler/vm.nim3
-rw-r--r--compiler/vmdef.nim3
-rw-r--r--compiler/vmgen.nim1
-rw-r--r--lib/system.nim17
-rw-r--r--tests/arithm/tashr.nim46
-rw-r--r--tests/concepts/t3330.nim12
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