diff options
author | Arne Döring <arne.doering@gmx.net> | 2019-05-29 16:48:00 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2019-05-29 16:48:00 +0200 |
commit | 88b5dd33626dcd9a9abfd6c9e316bc6c79eb1b21 (patch) | |
tree | a1e3b51b420c48627ecee0b9f9882e97543244e7 | |
parent | 897e7c90ac148d7a3b63ac9b7f99e464147cfb03 (diff) | |
download | Nim-88b5dd33626dcd9a9abfd6c9e316bc6c79eb1b21.tar.gz |
right shift is now by default sign preserving (#11322)
* right shift is now by default sign preserving * fix hashString and semfold * enable arithmetic shift right globally for CI * fix typo * remove xxx * use oldShiftRight as flag * apply feedback * add changelog entry
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | changelog.md | 4 | ||||
-rw-r--r-- | compiler/bitsets.nim | 20 | ||||
-rw-r--r-- | compiler/ccgutils.nim | 34 | ||||
-rw-r--r-- | compiler/lexer.nim | 13 | ||||
-rw-r--r-- | compiler/semfold.nim | 11 | ||||
-rw-r--r-- | compiler/vm.nim | 16 | ||||
-rw-r--r-- | lib/pure/collections/intsets.nim | 22 | ||||
-rw-r--r-- | lib/pure/hashes.nim | 19 | ||||
-rw-r--r-- | lib/pure/unicode.nim | 132 | ||||
-rw-r--r-- | lib/system.nim | 46 | ||||
-rw-r--r-- | lib/system/alloc.nim | 8 | ||||
-rw-r--r-- | lib/system/cellsets.nim | 38 | ||||
-rw-r--r-- | lib/system/gc.nim | 2 | ||||
-rw-r--r-- | lib/system/strmantle.nim | 12 | ||||
-rw-r--r-- | tests/arithm/tarithm.nim | 8 | ||||
-rw-r--r-- | tests/misc/tints.nim | 8 | ||||
-rw-r--r-- | tests/misc/tvarnums.nim | 4 |
18 files changed, 211 insertions, 187 deletions
diff --git a/.gitignore b/.gitignore index 1da7348fd..a49e10c18 100644 --- a/.gitignore +++ b/.gitignore @@ -82,3 +82,4 @@ megatest.nim /outputExpected.txt /outputGotten.txt +/lib/pure/*.js diff --git a/changelog.md b/changelog.md index b55a92b0f..5197c9fab 100644 --- a/changelog.md +++ b/changelog.md @@ -46,9 +46,13 @@ - A bug allowed `macro foo(): int = 123` to compile even though a macros has to return a `NimNode`. This has been fixed. +- `shr` is now sign preserving. Use `-d:oldShiftRight` to enable old + behavior globally. + - With the exception of `uint` and `uint64`, conversion to unsigned types are now range checked during runtime. + #### Breaking changes in the standard library - `osproc.execProcess` now also takes a `workingDir` parameter. diff --git a/compiler/bitsets.nim b/compiler/bitsets.nim index e0cf33b1d..d03a5915e 100644 --- a/compiler/bitsets.nim +++ b/compiler/bitsets.nim @@ -75,20 +75,20 @@ proc bitSetContains(x, y: TBitSet): bool = const populationCount: array[low(int8)..high(int8), int8] = block: var arr: array[low(int8)..high(int8), int8] - proc countSetBits(x: int8): int8 = + proc countSetBits(x: uint8): uint8 = return - ( x and 0b00000001'i8) + - ((x and 0b00000010'i8) shr 1) + - ((x and 0b00000100'i8) shr 2) + - ((x and 0b00001000'i8) shr 3) + - ((x and 0b00010000'i8) shr 4) + - ((x and 0b00100000'i8) shr 5) + - ((x and 0b01000000'i8) shr 6) + - ((x and 0b10000000'i8) shr 7) + ( x and 0b00000001'u8) + + ((x and 0b00000010'u8) shr 1) + + ((x and 0b00000100'u8) shr 2) + + ((x and 0b00001000'u8) shr 3) + + ((x and 0b00010000'u8) shr 4) + + ((x and 0b00100000'u8) shr 5) + + ((x and 0b01000000'u8) shr 6) + + ((x and 0b10000000'u8) shr 7) for it in low(int8)..high(int8): - arr[it] = countSetBits(it) + arr[it] = cast[int8](countSetBits(cast[uint8](it))) arr diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index c608a8cb0..455012e60 100644 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -28,29 +28,29 @@ proc stmtsContainPragma*(n: PNode, w: TSpecialWord): bool = result = getPragmaStmt(n, w) != nil proc hashString*(conf: ConfigRef; s: string): BiggestInt = - # has to be the same algorithm as system.hashString! + # has to be the same algorithm as strmantle.hashString! if CPU[conf.target.targetCPU].bit == 64: # we have to use the same bitwidth # as the target CPU - var b = 0'i64 + var b = 0'u64 for i in 0 ..< len(s): - b = b +% ord(s[i]) - b = b +% `shl`(b, 10) - b = b xor `shr`(b, 6) - b = b +% `shl`(b, 3) - b = b xor `shr`(b, 11) - b = b +% `shl`(b, 15) - result = b + b = b + uint(s[i]) + b = b + (b shl 10) + b = b xor (b shr 6) + b = b + (b shl 3) + b = b xor (b shr 11) + b = b + (b shl 15) + result = cast[Hash](b) else: - var a = 0'i32 + var a = 0'u32 for i in 0 ..< len(s): - a = a +% ord(s[i]).int32 - a = a +% `shl`(a, 10'i32) - a = a xor `shr`(a, 6'i32) - a = a +% `shl`(a, 3'i32) - a = a xor `shr`(a, 11'i32) - a = a +% `shl`(a, 15'i32) - result = a + a = a + uint32(s[i]) + a = a + (a shl 10) + a = a xor (a shr 6) + a = a + (a shl 3) + a = a xor (a shr 11) + a = a + (a shl 15) + result = cast[Hash](a) template getUniqueType*(key: PType): PType = key diff --git a/compiler/lexer.nim b/compiler/lexer.nim index 52559dad5..7533fb830 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -647,34 +647,35 @@ proc handleDecChars(L: var TLexer, xi: var int) = inc(L.bufpos) proc addUnicodeCodePoint(s: var string, i: int) = + let i = cast[uint](i) # inlined toUTF-8 to avoid unicode and strutils dependencies. let pos = s.len - if i <=% 127: + if i <= 127: s.setLen(pos+1) s[pos+0] = chr(i) - elif i <=% 0x07FF: + elif i <= 0x07FF: s.setLen(pos+2) s[pos+0] = chr((i shr 6) or 0b110_00000) s[pos+1] = chr((i and ones(6)) or 0b10_0000_00) - elif i <=% 0xFFFF: + elif i <= 0xFFFF: s.setLen(pos+3) s[pos+0] = chr(i shr 12 or 0b1110_0000) s[pos+1] = chr(i shr 6 and ones(6) or 0b10_0000_00) s[pos+2] = chr(i and ones(6) or 0b10_0000_00) - elif i <=% 0x001FFFFF: + elif i <= 0x001FFFFF: s.setLen(pos+4) s[pos+0] = chr(i shr 18 or 0b1111_0000) s[pos+1] = chr(i shr 12 and ones(6) or 0b10_0000_00) s[pos+2] = chr(i shr 6 and ones(6) or 0b10_0000_00) s[pos+3] = chr(i and ones(6) or 0b10_0000_00) - elif i <=% 0x03FFFFFF: + elif i <= 0x03FFFFFF: s.setLen(pos+5) s[pos+0] = chr(i shr 24 or 0b111110_00) s[pos+1] = chr(i shr 18 and ones(6) or 0b10_0000_00) s[pos+2] = chr(i shr 12 and ones(6) or 0b10_0000_00) s[pos+3] = chr(i shr 6 and ones(6) or 0b10_0000_00) s[pos+4] = chr(i and ones(6) or 0b10_0000_00) - elif i <=% 0x7FFFFFFF: + elif i <= 0x7FFFFFFF: s.setLen(pos+6) s[pos+0] = chr(i shr 30 or 0b1111110_0) s[pos+1] = chr(i shr 24 and ones(6) or 0b10_0000_00) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index e95184dfd..cb88ee6dd 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -248,13 +248,10 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode = result = doAndFit(newIntNodeT(`shl`(getInt(a), getInt(b)), n, g)) else: internalError(g.config, n.info, "constant folding for shl") of mShrI: - case skipTypes(n.typ, abstractRange).kind - of tyInt8: result = newIntNodeT(int8(getInt(a)) shr int8(getInt(b)), n, g) - of tyInt16: result = newIntNodeT(int16(getInt(a)) shr int16(getInt(b)), n, g) - of tyInt32: result = newIntNodeT(int32(getInt(a)) shr int32(getInt(b)), n, g) - of tyInt64, tyInt, tyUInt..tyUInt64: - result = newIntNodeT(`shr`(getInt(a), getInt(b)), n, g) - else: internalError(g.config, n.info, "constant folding for shr") + let a = cast[uint64](getInt(a)) + let b = cast[uint64](getInt(b)) + let c = cast[BiggestInt](a shr b) + result = newIntNodeT(c, n, g) of mAshrI: case skipTypes(n.typ, abstractRange).kind of tyInt8: result = newIntNodeT(ashr(int8(getInt(a)), int8(getInt(b))), n, g) diff --git a/compiler/vm.nim b/compiler/vm.nim index aa8203a92..4f6208c59 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -421,12 +421,15 @@ proc opConv(c: PCtx; dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): else: let srcDist = (sizeof(src.intVal) - srctyp.size) * 8 let destDist = (sizeof(dest.intVal) - desttyp.size) * 8 + + var value = cast[BiggestUInt](src.intVal) when system.cpuEndian == bigEndian: - dest.intVal = (src.intVal shr srcDist) shl srcDist - dest.intVal = (dest.intVal shr destDist) shl destDist + value = (value shr srcDist) shl srcDist + value = (value shr destDist) shl destDist else: - dest.intVal = (src.intVal shl srcDist) shr srcDist - dest.intVal = (dest.intVal shl destDist) shr destDist + value = (value shl srcDist) shr srcDist + value = (value shl destDist) shr destDist + dest.intVal = cast[BiggestInt](value) of tyFloat..tyFloat64: if dest.kind != rkFloat: myreset(dest); dest.kind = rkFloat @@ -818,7 +821,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = regs[ra].floatVal = regs[rb].floatVal / regs[rc].floatVal of opcShrInt: decodeBC(rkInt) - regs[ra].intVal = regs[rb].intVal shr regs[rc].intVal + let b = cast[uint64](regs[rb].intVal) + let c = cast[uint64](regs[rc].intVal) + let a = cast[int64](b shr c) + regs[ra].intVal = a of opcShlInt: decodeBC(rkInt) regs[ra].intVal = regs[rb].intVal shl regs[rc].intVal diff --git a/lib/pure/collections/intsets.nim b/lib/pure/collections/intsets.nim index 226401b92..fb8b885dc 100644 --- a/lib/pure/collections/intsets.nim +++ b/lib/pure/collections/intsets.nim @@ -23,7 +23,7 @@ import hashes, math type - BitScalar = int + BitScalar = uint const InitIntSetSize = 8 # must be a power of two! @@ -102,8 +102,8 @@ proc intSetPut(t: var IntSet, key: int): PTrunk = proc bitincl(s: var IntSet, key: int) {.inline.} = var t = intSetPut(s, `shr`(key, TrunkShift)) var u = key and TrunkMask - t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or - `shl`(1, u and IntMask) + t.bits[u shr IntShift] = t.bits[u shr IntShift] or + (BitScalar(1) shl (u and IntMask)) proc exclImpl(s: var IntSet, key: int) = if s.elems <= s.a.len: @@ -113,11 +113,11 @@ proc exclImpl(s: var IntSet, key: int) = dec s.elems return else: - var t = intSetGet(s, `shr`(key, TrunkShift)) + var t = intSetGet(s, key shr TrunkShift) if t != nil: var u = key and TrunkMask - t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] and - not `shl`(1, u and IntMask) + t.bits[u shr IntShift] = t.bits[u shr IntShift] and + not(BitScalar(1) shl (u and IntMask)) template dollarImpl(): untyped = result = "{" @@ -137,7 +137,7 @@ iterator items*(s: IntSet): int {.inline.} = while r != nil: var i = 0 while i <= high(r.bits): - var w = r.bits[i] + var w: uint = r.bits[i] # taking a copy of r.bits[i] here is correct, because # modifying operations are not allowed during traversation var j = 0 @@ -186,7 +186,7 @@ proc contains*(s: IntSet, key: int): bool = var t = intSetGet(s, `shr`(key, TrunkShift)) if t != nil: var u = key and TrunkMask - result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0 + result = (t.bits[u shr IntShift] and (BitScalar(1) shl (u and IntMask))) != 0 else: result = false @@ -268,10 +268,10 @@ proc containsOrIncl*(s: var IntSet, key: int): bool = var t = intSetGet(s, `shr`(key, TrunkShift)) if t != nil: var u = key and TrunkMask - result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0 + result = (t.bits[u shr IntShift] and BitScalar(1) shl (u and IntMask)) != 0 if not result: - t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or - `shl`(1, u and IntMask) + t.bits[u shr IntShift] = t.bits[u shr IntShift] or + (BitScalar(1) shl (u and IntMask)) else: incl(s, key) result = false diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim index 763da523f..df29dc080 100644 --- a/lib/pure/hashes.nim +++ b/lib/pure/hashes.nim @@ -60,17 +60,22 @@ proc `!&`*(h: Hash, val: int): Hash {.inline.} = ## Mixes a hash value `h` with `val` to produce a new hash value. ## ## This is only needed if you need to implement a hash proc for a new datatype. - result = h +% val - result = result +% result shl 10 - result = result xor (result shr 6) + let h = cast[uint](h) + let val = cast[uint](val) + var res = h + val + res = res + res shl 10 + res = res xor (res shr 6) + result = cast[Hash](res) proc `!$`*(h: Hash): Hash {.inline.} = ## Finishes the computation of the hash value. ## ## This is only needed if you need to implement a hash proc for a new datatype. - result = h +% h shl 3 - result = result xor (result shr 11) - result = result +% result shl 15 + let h = cast[uint](h) # Hash is practically unsigned. + var res = h + h shl 3 + res = res xor (res shr 11) + res = res + res shl 15 + result = cast[Hash](res) proc hashData*(data: pointer, size: int): Hash = ## Hashes an array of bytes of size `size`. @@ -105,7 +110,7 @@ proc hash*(x: pointer): Hash {.inline.} = } """ else: - result = (cast[Hash](x)) shr 3 # skip the alignment + result = cast[Hash](cast[uint](x) shr 3) # skip the alignment when not defined(booting): proc hash*[T: proc](x: T): Hash {.inline.} = diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim index f38d89b95..83ec2783a 100644 --- a/lib/pure/unicode.nim +++ b/lib/pure/unicode.nim @@ -48,12 +48,12 @@ proc runeLen*(s: string): int {.rtl, extern: "nuc$1".} = var i = 0 while i < len(s): - if ord(s[i]) <=% 127: inc(i) - elif ord(s[i]) shr 5 == 0b110: inc(i, 2) - elif ord(s[i]) shr 4 == 0b1110: inc(i, 3) - elif ord(s[i]) shr 3 == 0b11110: inc(i, 4) - elif ord(s[i]) shr 2 == 0b111110: inc(i, 5) - elif ord(s[i]) shr 1 == 0b1111110: inc(i, 6) + if uint(s[i]) <= 127: inc(i) + elif uint(s[i]) shr 5 == 0b110: inc(i, 2) + elif uint(s[i]) shr 4 == 0b1110: inc(i, 3) + elif uint(s[i]) shr 3 == 0b11110: inc(i, 4) + elif uint(s[i]) shr 2 == 0b111110: inc(i, 5) + elif uint(s[i]) shr 1 == 0b1111110: inc(i, 6) else: inc i inc(result) @@ -67,12 +67,12 @@ proc runeLenAt*(s: string, i: Natural): int = doAssert a.runeLenAt(0) == 1 doAssert a.runeLenAt(1) == 2 - if ord(s[i]) <=% 127: result = 1 - elif ord(s[i]) shr 5 == 0b110: result = 2 - elif ord(s[i]) shr 4 == 0b1110: result = 3 - elif ord(s[i]) shr 3 == 0b11110: result = 4 - elif ord(s[i]) shr 2 == 0b111110: result = 5 - elif ord(s[i]) shr 1 == 0b1111110: result = 6 + if uint(s[i]) <= 127: result = 1 + elif uint(s[i]) shr 5 == 0b110: result = 2 + elif uint(s[i]) shr 4 == 0b1110: result = 3 + elif uint(s[i]) shr 3 == 0b11110: result = 4 + elif uint(s[i]) shr 2 == 0b111110: result = 5 + elif uint(s[i]) shr 1 == 0b1111110: result = 6 else: result = 1 const replRune = Rune(0xFFFD) @@ -83,76 +83,76 @@ template fastRuneAt*(s: string, i: int, result: untyped, doInc = true) = ## If ``doInc == true`` (default), ``i`` is incremented by the number ## of bytes that have been processed. bind ones - if ord(s[i]) <=% 127: - result = Rune(ord(s[i])) + if uint(s[i]) <= 127: + result = Rune(uint(s[i])) when doInc: inc(i) - elif ord(s[i]) shr 5 == 0b110: - # assert(ord(s[i+1]) shr 6 == 0b10) + elif uint(s[i]) shr 5 == 0b110: + # assert(uint(s[i+1]) shr 6 == 0b10) if i <= s.len - 2: - result = Rune((ord(s[i]) and (ones(5))) shl 6 or - (ord(s[i+1]) and ones(6))) + result = Rune((uint(s[i]) and (ones(5))) shl 6 or + (uint(s[i+1]) and ones(6))) when doInc: inc(i, 2) else: result = replRune when doInc: inc(i) - elif ord(s[i]) shr 4 == 0b1110: - # assert(ord(s[i+1]) shr 6 == 0b10) - # assert(ord(s[i+2]) shr 6 == 0b10) + elif uint(s[i]) shr 4 == 0b1110: + # assert(uint(s[i+1]) shr 6 == 0b10) + # assert(uint(s[i+2]) shr 6 == 0b10) if i <= s.len - 3: - result = Rune((ord(s[i]) and ones(4)) shl 12 or - (ord(s[i+1]) and ones(6)) shl 6 or - (ord(s[i+2]) and ones(6))) + result = Rune((uint(s[i]) and ones(4)) shl 12 or + (uint(s[i+1]) and ones(6)) shl 6 or + (uint(s[i+2]) and ones(6))) when doInc: inc(i, 3) else: result = replRune when doInc: inc(i) - elif ord(s[i]) shr 3 == 0b11110: - # assert(ord(s[i+1]) shr 6 == 0b10) - # assert(ord(s[i+2]) shr 6 == 0b10) - # assert(ord(s[i+3]) shr 6 == 0b10) + elif uint(s[i]) shr 3 == 0b11110: + # assert(uint(s[i+1]) shr 6 == 0b10) + # assert(uint(s[i+2]) shr 6 == 0b10) + # assert(uint(s[i+3]) shr 6 == 0b10) if i <= s.len - 4: - result = Rune((ord(s[i]) and ones(3)) shl 18 or - (ord(s[i+1]) and ones(6)) shl 12 or - (ord(s[i+2]) and ones(6)) shl 6 or - (ord(s[i+3]) and ones(6))) + result = Rune((uint(s[i]) and ones(3)) shl 18 or + (uint(s[i+1]) and ones(6)) shl 12 or + (uint(s[i+2]) and ones(6)) shl 6 or + (uint(s[i+3]) and ones(6))) when doInc: inc(i, 4) else: result = replRune when doInc: inc(i) - elif ord(s[i]) shr 2 == 0b111110: - # assert(ord(s[i+1]) shr 6 == 0b10) - # assert(ord(s[i+2]) shr 6 == 0b10) - # assert(ord(s[i+3]) shr 6 == 0b10) - # assert(ord(s[i+4]) shr 6 == 0b10) + elif uint(s[i]) shr 2 == 0b111110: + # assert(uint(s[i+1]) shr 6 == 0b10) + # assert(uint(s[i+2]) shr 6 == 0b10) + # assert(uint(s[i+3]) shr 6 == 0b10) + # assert(uint(s[i+4]) shr 6 == 0b10) if i <= s.len - 5: - result = Rune((ord(s[i]) and ones(2)) shl 24 or - (ord(s[i+1]) and ones(6)) shl 18 or - (ord(s[i+2]) and ones(6)) shl 12 or - (ord(s[i+3]) and ones(6)) shl 6 or - (ord(s[i+4]) and ones(6))) + result = Rune((uint(s[i]) and ones(2)) shl 24 or + (uint(s[i+1]) and ones(6)) shl 18 or + (uint(s[i+2]) and ones(6)) shl 12 or + (uint(s[i+3]) and ones(6)) shl 6 or + (uint(s[i+4]) and ones(6))) when doInc: inc(i, 5) else: result = replRune when doInc: inc(i) - elif ord(s[i]) shr 1 == 0b1111110: - # assert(ord(s[i+1]) shr 6 == 0b10) - # assert(ord(s[i+2]) shr 6 == 0b10) - # assert(ord(s[i+3]) shr 6 == 0b10) - # assert(ord(s[i+4]) shr 6 == 0b10) - # assert(ord(s[i+5]) shr 6 == 0b10) + elif uint(s[i]) shr 1 == 0b1111110: + # assert(uint(s[i+1]) shr 6 == 0b10) + # assert(uint(s[i+2]) shr 6 == 0b10) + # assert(uint(s[i+3]) shr 6 == 0b10) + # assert(uint(s[i+4]) shr 6 == 0b10) + # assert(uint(s[i+5]) shr 6 == 0b10) if i <= s.len - 6: - result = Rune((ord(s[i]) and ones(1)) shl 30 or - (ord(s[i+1]) and ones(6)) shl 24 or - (ord(s[i+2]) and ones(6)) shl 18 or - (ord(s[i+3]) and ones(6)) shl 12 or - (ord(s[i+4]) and ones(6)) shl 6 or - (ord(s[i+5]) and ones(6))) + result = Rune((uint(s[i]) and ones(1)) shl 30 or + (uint(s[i+1]) and ones(6)) shl 24 or + (uint(s[i+2]) and ones(6)) shl 18 or + (uint(s[i+3]) and ones(6)) shl 12 or + (uint(s[i+4]) and ones(6)) shl 6 or + (uint(s[i+5]) and ones(6))) when doInc: inc(i, 6) else: result = replRune when doInc: inc(i) else: - result = Rune(ord(s[i])) + result = Rune(uint(s[i])) when doInc: inc(i) proc runeAt*(s: string, i: Natural): Rune = @@ -180,20 +180,20 @@ proc validateUTF8*(s: string): int = var i = 0 let L = s.len while i < L: - if ord(s[i]) <=% 127: + if uint(s[i]) <= 127: inc(i) - elif ord(s[i]) shr 5 == 0b110: - if ord(s[i]) < 0xc2: return i # Catch overlong ascii representations. - if i+1 < L and ord(s[i+1]) shr 6 == 0b10: inc(i, 2) + elif uint(s[i]) shr 5 == 0b110: + if uint(s[i]) < 0xc2: return i # Catch overlong ascii representations. + if i+1 < L and uint(s[i+1]) shr 6 == 0b10: inc(i, 2) else: return i - elif ord(s[i]) shr 4 == 0b1110: - if i+2 < L and ord(s[i+1]) shr 6 == 0b10 and ord(s[i+2]) shr 6 == 0b10: + elif uint(s[i]) shr 4 == 0b1110: + if i+2 < L and uint(s[i+1]) shr 6 == 0b10 and uint(s[i+2]) shr 6 == 0b10: inc i, 3 else: return i - elif ord(s[i]) shr 3 == 0b11110: - if i+3 < L and ord(s[i+1]) shr 6 == 0b10 and - ord(s[i+2]) shr 6 == 0b10 and - ord(s[i+3]) shr 6 == 0b10: + elif uint(s[i]) shr 3 == 0b11110: + if i+3 < L and uint(s[i+1]) shr 6 == 0b10 and + uint(s[i+2]) shr 6 == 0b10 and + uint(s[i+3]) shr 6 == 0b10: inc i, 4 else: return i else: @@ -906,7 +906,7 @@ proc lastRune*(s: string; last: int): (Rune, int) = result = (Rune(s[last]), 1) else: var L = 0 - while last-L >= 0 and ord(s[last-L]) shr 6 == 0b10: inc(L) + while last-L >= 0 and uint(s[last-L]) shr 6 == 0b10: inc(L) var r: Rune fastRuneAt(s, last-L, r, false) result = (r, L+1) diff --git a/lib/system.nim b/lib/system.nim index 69ef35256..de5fe3690 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1270,24 +1270,34 @@ else: proc `mod`*(x, y: int64): int64 {.magic: "ModI64", noSideEffect.} when defined(nimNewShiftOps): - proc `shr`*(x: int, y: SomeInteger): int {.magic: "ShrI", noSideEffect.} - ## Computes the `shift right` operation of `x` and `y`, filling - ## vacant bit positions with zeros. - ## - ## **Note**: `Operator precedence <manual.html#syntax-precedence>`_ - ## is different than in *C*. - ## - ## See also: - ## * `ashr proc <#ashr,int,SomeInteger>`_ for arithmetic shift right - ## - ## .. code-block:: Nim - ## 0b0001_0000'i8 shr 2 == 0b0000_0100'i8 - ## 0b1000_0000'i8 shr 8 == 0b0000_0000'i8 - ## 0b0000_0001'i8 shr 1 == 0b0000_0000'i8 - proc `shr`*(x: int8, y: SomeInteger): int8 {.magic: "ShrI", noSideEffect.} - proc `shr`*(x: int16, y: SomeInteger): int16 {.magic: "ShrI", noSideEffect.} - proc `shr`*(x: int32, y: SomeInteger): int32 {.magic: "ShrI", noSideEffect.} - proc `shr`*(x: int64, y: SomeInteger): int64 {.magic: "ShrI", noSideEffect.} + + when defined(oldShiftRight) or not defined(nimAshr): + const shrDepMessage = "`shr` will become sign preserving." + proc `shr`*(x: int, y: SomeInteger): int {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.} + proc `shr`*(x: int8, y: SomeInteger): int8 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.} + proc `shr`*(x: int16, y: SomeInteger): int16 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.} + proc `shr`*(x: int32, y: SomeInteger): int32 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.} + proc `shr`*(x: int64, y: SomeInteger): int64 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.} + else: + proc `shr`*(x: int, y: SomeInteger): int {.magic: "AshrI", noSideEffect.} + ## Computes the `shift right` operation of `x` and `y`, filling + ## vacant bit positions with the sign bit. + ## + ## **Note**: `Operator precedence <manual.html#syntax-precedence>`_ + ## is different than in *C*. + ## + ## See also: + ## * `ashr proc <#ashr,int,SomeInteger>`_ for arithmetic shift right + ## + ## .. code-block:: Nim + ## 0b0001_0000'i8 shr 2 == 0b0000_0100'i8 + ## 0b1000_0000'i8 shr 8 == 0b0000_0000'i8 + ## 0b0000_0001'i8 shr 1 == 0b0000_0000'i8 + proc `shr`*(x: int8, y: SomeInteger): int8 {.magic: "AshrI", noSideEffect.} + proc `shr`*(x: int16, y: SomeInteger): int16 {.magic: "AshrI", noSideEffect.} + proc `shr`*(x: int32, y: SomeInteger): int32 {.magic: "AshrI", noSideEffect.} + proc `shr`*(x: int64, y: SomeInteger): int64 {.magic: "AshrI", noSideEffect.} + proc `shl`*(x: int, y: SomeInteger): int {.magic: "ShlI", noSideEffect.} ## Computes the `shift left` operation of `x` and `y`. diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index d4c686869..47e3318fd 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -38,7 +38,7 @@ type Trunk = object next: PTrunk # all nodes are connected with this pointer key: int # start address at bit 0 - bits: array[0..IntsPerTrunk-1, int] # a bit vector + bits: array[0..IntsPerTrunk-1, uint] # a bit vector TrunkBuckets = array[0..255, PTrunk] IntSet = object @@ -332,21 +332,21 @@ proc contains(s: IntSet, key: int): bool = var t = intSetGet(s, key shr TrunkShift) if t != nil: var u = key and TrunkMask - result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0 + result = (t.bits[u shr IntShift] and (uint(1) shl (u and IntMask))) != 0 else: result = false proc incl(a: var MemRegion, s: var IntSet, key: int) = var t = intSetPut(a, s, key shr TrunkShift) var u = key and TrunkMask - t.bits[u shr IntShift] = t.bits[u shr IntShift] or (1 shl (u and IntMask)) + t.bits[u shr IntShift] = t.bits[u shr IntShift] or (uint(1) shl (u and IntMask)) proc excl(s: var IntSet, key: int) = var t = intSetGet(s, key shr TrunkShift) if t != nil: var u = key and TrunkMask t.bits[u shr IntShift] = t.bits[u shr IntShift] and not - (1 shl (u and IntMask)) + (uint(1) shl (u and IntMask)) iterator elements(t: IntSet): int {.inline.} = # while traversing it is forbidden to change the set! diff --git a/lib/system/cellsets.nim b/lib/system/cellsets.nim index d56de06bb..7712681bc 100644 --- a/lib/system/cellsets.nim +++ b/lib/system/cellsets.nim @@ -27,7 +27,7 @@ type BitIndex = range[0..UnitsPerPage-1] PageDesc {.final, pure.} = object next: PPageDesc # all nodes are connected with this pointer - key: ByteAddress # start address at bit 0 + key: uint # start address at bit 0 bits: array[BitIndex, int] # a bit vector PPageDescArray = ptr UncheckedArray[PPageDesc] @@ -97,7 +97,7 @@ proc nextTry(h, maxHash: int): int {.inline.} = # generates each int in range(maxHash) exactly once (see any text on # random-number generation for proof). -proc cellSetGet(t: CellSet, key: ByteAddress): PPageDesc = +proc cellSetGet(t: CellSet, key: uint): PPageDesc = var h = cast[int](key) and t.max while t.data[h] != nil: if t.data[h].key == key: return t.data[h] @@ -122,7 +122,7 @@ proc cellSetEnlarge(t: var CellSet) = dealloc(t.data) t.data = n -proc cellSetPut(t: var CellSet, key: ByteAddress): PPageDesc = +proc cellSetPut(t: var CellSet, key: uint): PPageDesc = var h = cast[int](key) and t.max while true: var x = t.data[h] @@ -146,33 +146,33 @@ proc cellSetPut(t: var CellSet, key: ByteAddress): PPageDesc = # ---------- slightly higher level procs -------------------------------------- proc contains(s: CellSet, cell: PCell): bool = - var u = cast[ByteAddress](cell) + var u = cast[uint](cell) var t = cellSetGet(s, u shr PageShift) if t != nil: - u = (u %% PageSize) /% MemAlign + u = (u mod PageSize) div MemAlign result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0 else: result = false proc incl(s: var CellSet, cell: PCell) {.noinline.} = - var u = cast[ByteAddress](cell) + var u = cast[uint](cell) var t = cellSetPut(s, u shr PageShift) - u = (u %% PageSize) /% MemAlign + u = (u mod PageSize) div MemAlign t.bits[u shr IntShift] = t.bits[u shr IntShift] or (1 shl (u and IntMask)) proc excl(s: var CellSet, cell: PCell) = - var u = cast[ByteAddress](cell) + var u = cast[uint](cell) var t = cellSetGet(s, u shr PageShift) if t != nil: - u = (u %% PageSize) /% MemAlign + u = (u mod PageSize) div MemAlign t.bits[u shr IntShift] = (t.bits[u shr IntShift] and not (1 shl (u and IntMask))) proc containsOrIncl(s: var CellSet, cell: PCell): bool = - var u = cast[ByteAddress](cell) + var u = cast[uint](cell) var t = cellSetGet(s, u shr PageShift) if t != nil: - u = (u %% PageSize) /% MemAlign + u = (u mod PageSize) div MemAlign result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0 if not result: t.bits[u shr IntShift] = t.bits[u shr IntShift] or @@ -185,15 +185,15 @@ iterator elements(t: CellSet): PCell {.inline.} = # while traversing it is forbidden to add pointers to the tree! var r = t.head while r != nil: - var i = 0 - while i <= high(r.bits): + var i: uint = 0 + while int(i) <= high(r.bits): var w = r.bits[i] # taking a copy of r.bits[i] here is correct, because # modifying operations are not allowed during traversation - var j = 0 + var j: uint = 0 while w != 0: # test all remaining bits for zero if (w and 1) != 0: # the bit is set! yield cast[PCell]((r.key shl PageShift) or - (i shl IntShift +% j) *% MemAlign) + (i shl IntShift + j) * MemAlign) inc(j) w = w shr 1 inc(i) @@ -238,16 +238,16 @@ iterator elementsExcept(t, s: CellSet): PCell {.inline.} = var r = t.head while r != nil: let ss = cellSetGet(s, r.key) - var i = 0 - while i <= high(r.bits): + var i:uint = 0 + while int(i) <= high(r.bits): var w = r.bits[i] if ss != nil: w = w and not ss.bits[i] - var j = 0 + var j:uint = 0 while w != 0: if (w and 1) != 0: yield cast[PCell]((r.key shl PageShift) or - (i shl IntShift +% j) *% MemAlign) + (i shl IntShift + j) * MemAlign) inc(j) w = w shr 1 inc(i) diff --git a/lib/system/gc.nim b/lib/system/gc.nim index db5371156..397708ca3 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -133,7 +133,7 @@ proc extGetCellType(c: pointer): PNimType {.compilerproc.} = result = usrToCell(c).typ proc internRefcount(p: pointer): int {.exportc: "getRefcount".} = - result = int(usrToCell(p).refcount) shr rcShift + result = usrToCell(p).refcount shr rcShift # this that has to equals zero, otherwise we have to round up UnitsPerPage: when BitsPerPage mod (sizeof(int)*8) != 0: diff --git a/lib/system/strmantle.nim b/lib/system/strmantle.nim index 8ff2e0ee0..457e0eab5 100644 --- a/lib/system/strmantle.nim +++ b/lib/system/strmantle.nim @@ -30,15 +30,15 @@ proc eqStrings(a, b: string): bool {.inline, compilerProc.} = proc hashString(s: string): int {.compilerproc.} = # the compiler needs exactly the same hash function! # this used to be used for efficient generation of string case statements - var h = 0 + var h : uint = 0 for i in 0..len(s)-1: - h = h +% ord(s[i]) - h = h +% h shl 10 + h = h + uint(s[i]) + h = h + h shl 10 h = h xor (h shr 6) - h = h +% h shl 3 + h = h + h shl 3 h = h xor (h shr 11) - h = h +% h shl 15 - result = h + h = h + h shl 15 + result = cast[int](h) proc addInt*(result: var string; x: int64) = ## Converts integer to its string representation and appends it to `result`. diff --git a/tests/arithm/tarithm.nim b/tests/arithm/tarithm.nim index 6d857a788..f27174aef 100644 --- a/tests/arithm/tarithm.nim +++ b/tests/arithm/tarithm.nim @@ -150,10 +150,10 @@ block tshr: let VI16 = -8'i16 let VI8 = -8'i8 # doAssert( (VI shr 1) == 9_223_372_036_854_775_804, "Actual: " & $(VI shr 1)) - doAssert( (VI64 shr 1) == 9_223_372_036_854_775_804, "Actual: " & $(VI64 shr 1)) - doAssert( (VI32 shr 1) == 2_147_483_644, "Actual: " & $(VI32 shr 1)) - doAssert( (VI16 shr 1) == 32_764, "Actual: " & $(VI16 shr 1)) - doAssert( (VI8 shr 1) == 124, "Actual: " & $(VI8 shr 1)) + doAssert( (VI64 shr 1) == -4, "Actual: " & $(VI64 shr 1)) + doAssert( (VI32 shr 1) == -4, "Actual: " & $(VI32 shr 1)) + doAssert( (VI16 shr 1) == -4, "Actual: " & $(VI16 shr 1)) + doAssert( (VI8 shr 1) == -4, "Actual: " & $(VI8 shr 1)) T() static: diff --git a/tests/misc/tints.nim b/tests/misc/tints.nim index d5374a543..fa3eb42cb 100644 --- a/tests/misc/tints.nim +++ b/tests/misc/tints.nim @@ -31,13 +31,13 @@ test(`or`, 0xf0f0'i16, 0x0d0d'i16, 0xfdfd'i16) test(`and`, 0xf0f0'i16, 0xfdfd'i16, 0xf0f0'i16) when not defined(js): - test(`shr`, 0xffffffffffffffff'i64, 0x4'i64, 0x0fffffffffffffff'i64) -test(`shr`, 0xffff'i16, 0x4'i16, 0x0fff'i16) -test(`shr`, 0xff'i8, 0x4'i8, 0x0f'i8) + test(`shr`, 0xffffffffffffffff'i64, 0x4'i64, 0xffffffffffffffff'i64) +test(`shr`, 0xffff'i16, 0x4'i16, 0xffff'i16) +test(`shr`, 0xff'i8, 0x4'i8, 0xff'i8) when not defined(js): test(`shr`, 0xffffffff'i64, 0x4'i64, 0x0fffffff'i64) -test(`shr`, 0xffffffff'i32, 0x4'i32, 0x0fffffff'i32) +test(`shr`, 0xffffffff'i32, 0x4'i32, 0xffffffff'i32) when not defined(js): test(`shl`, 0xffffffffffffffff'i64, 0x4'i64, 0xfffffffffffffff0'i64) diff --git a/tests/misc/tvarnums.nim b/tests/misc/tvarnums.nim index 39269b4c0..2aef242e1 100644 --- a/tests/misc/tvarnums.nim +++ b/tests/misc/tvarnums.nim @@ -22,7 +22,7 @@ proc toVarNum(x: int32, b: var TBuffer) = a = abs(x) # first 6 bits: b[0] = toU8(ord(a >% 63'i32) shl 7 or (ord(x < 0'i32) shl 6) or (int(a) and 63)) - a = a shr 6'i32 # skip first 6 bits + a = (a shr 6'i32) and 0x03ffffff # skip first 6 bits var i = 1 while a != 0'i32: b[i] = toU8(ord(a >% 127'i32) shl 7 or (int(a) and 127)) @@ -42,7 +42,7 @@ proc toVarNum64(x: int64, b: var TBuffer) = a = abs(x) # first 6 bits: b[0] = toU8(ord(a >% 63'i64) shl 7 or (ord(x < 0'i64) shl 6) or int(a and 63)) - a = a shr 6 # skip first 6 bits + a = (a shr 6) and 0x03ffffffffffffff # skip first 6 bits var i = 1 while a != 0'i64: b[i] = toU8(ord(a >% 127'i64) shl 7 or int(a and 127)) |