diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2017-09-15 16:08:16 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2017-09-15 16:08:16 +0200 |
commit | 053b0ad6f301ade2d3627abed66a6f48a72aa05b (patch) | |
tree | 7236547fae29334c14693e9f2b0df758875c6c5b | |
parent | 9aeb78e2a86a6a7ab2c4726e634a8fdc7aa91089 (diff) | |
parent | 50ae228e255c0f82a1620657521a27f6b8152b58 (diff) | |
download | Nim-053b0ad6f301ade2d3627abed66a6f48a72aa05b.tar.gz |
Merge branch 'araq' of github.com:nim-lang/Nim into araq
-rw-r--r-- | compiler/ast.nim | 3 | ||||
-rw-r--r-- | compiler/options.nim | 3 | ||||
-rw-r--r-- | compiler/semexprs.nim | 1 | ||||
-rw-r--r-- | compiler/semfold.nim | 130 | ||||
-rw-r--r-- | doc/manual/types.txt | 20 | ||||
-rw-r--r-- | lib/core/macros.nim | 2 | ||||
-rw-r--r-- | lib/pure/md5.nim | 12 | ||||
-rw-r--r-- | lib/pure/securehash.nim | 4 | ||||
-rw-r--r-- | lib/pure/strutils.nim | 2 | ||||
-rw-r--r-- | lib/system.nim | 2 | ||||
-rw-r--r-- | lib/system/excpt.nim | 21 | ||||
-rw-r--r-- | tests/arithm/tsubrange.nim | 13 | ||||
-rw-r--r-- | todo.txt | 1 |
13 files changed, 49 insertions, 165 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 2e6da06c6..0cc4daf22 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -747,6 +747,8 @@ type OnUnknown, # location is unknown (stack, heap or static) OnStatic, # in a static section OnStack, # location is on hardware stack + OnStackShadowDup, # location is on the stack but also replicated + # on the shadow stack OnHeap # location is on heap or global # (reference counting needed) TLocFlags* = set[TLocFlag] @@ -756,6 +758,7 @@ type flags*: TLocFlags # location's flags t*: PType # type of location r*: Rope # rope value of location (code generators) + dup*: Rope # duplicated location for precise stack scans # ---------------- end of backend information ------------------------------ diff --git a/compiler/options.nim b/compiler/options.nim index 9a5a1ae2a..40d56aea5 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -140,12 +140,13 @@ var gEvalExpr* = "" # expression for idetools --eval gLastCmdTime*: float # when caas is enabled, we measure each command gListFullPaths*: bool - isServing*: bool = false + gPreciseStack*: bool = false gNoNimblePath* = false gExperimentalMode*: bool proc importantComments*(): bool {.inline.} = gCmd in {cmdDoc, cmdIdeTools} proc usesNativeGC*(): bool {.inline.} = gSelectedGC >= gcRefc +template preciseStack*(): bool = gPreciseStack template compilationCachePresent*: untyped = {optCaasEnabled, optSymbolFiles} * gGlobalOptions != {} diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 65557658a..74b074f61 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -551,7 +551,6 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode = result = semfold.getConstExpr(c.module, call) if result.isNil: result = n else: return result - result.typ = semfold.getIntervalType(callee.magic, call) block maybeLabelAsStatic: # XXX: temporary work-around needed for tlateboundstatic. diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 84cb0071f..612df1ba3 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -92,26 +92,6 @@ proc pickIntRange(a, b: PType): PType = proc isIntRangeOrLit(t: PType): bool = result = isIntRange(t) or isIntLit(t) -proc pickMinInt(n: PNode): BiggestInt = - if n.kind in {nkIntLit..nkUInt64Lit}: - result = n.intVal - elif isIntLit(n.typ): - result = n.typ.n.intVal - elif isIntRange(n.typ): - result = firstOrd(n.typ) - else: - internalError(n.info, "pickMinInt") - -proc pickMaxInt(n: PNode): BiggestInt = - if n.kind in {nkIntLit..nkUInt64Lit}: - result = n.intVal - elif isIntLit(n.typ): - result = n.typ.n.intVal - elif isIntRange(n.typ): - result = lastOrd(n.typ) - else: - internalError(n.info, "pickMaxInt") - proc makeRange(typ: PType, first, last: BiggestInt): PType = let minA = min(first, last) let maxA = max(first, last) @@ -137,116 +117,6 @@ proc makeRangeF(typ: PType, first, last: BiggestFloat): PType = result.n = n addSonSkipIntLit(result, skipTypes(typ, {tyRange})) -proc getIntervalType*(m: TMagic, n: PNode): PType = - # Nim requires interval arithmetic for ``range`` types. Lots of tedious - # work but the feature is very nice for reducing explicit conversions. - const ordIntLit = {nkIntLit..nkUInt64Lit} - result = n.typ - - template commutativeOp(opr: untyped) = - let a = n.sons[1] - let b = n.sons[2] - if isIntRangeOrLit(a.typ) and isIntRangeOrLit(b.typ): - result = makeRange(pickIntRange(a.typ, b.typ), - opr(pickMinInt(a), pickMinInt(b)), - opr(pickMaxInt(a), pickMaxInt(b))) - - template binaryOp(opr: untyped) = - let a = n.sons[1] - let b = n.sons[2] - if isIntRange(a.typ) and b.kind in {nkIntLit..nkUInt64Lit}: - result = makeRange(a.typ, - opr(pickMinInt(a), pickMinInt(b)), - opr(pickMaxInt(a), pickMaxInt(b))) - - case m - of mUnaryMinusI, mUnaryMinusI64: - let a = n.sons[1].typ - if isIntRange(a): - # (1..3) * (-1) == (-3.. -1) - result = makeRange(a, 0|-|lastOrd(a), 0|-|firstOrd(a)) - of mUnaryMinusF64: - let a = n.sons[1].typ - if isFloatRange(a): - result = makeRangeF(a, -getFloat(a.n.sons[1]), - -getFloat(a.n.sons[0])) - of mAbsF64: - let a = n.sons[1].typ - if isFloatRange(a): - # abs(-5.. 1) == (1..5) - if a.n[0].floatVal <= 0.0: - result = makeRangeF(a, 0.0, abs(getFloat(a.n.sons[0]))) - else: - result = makeRangeF(a, abs(getFloat(a.n.sons[1])), - abs(getFloat(a.n.sons[0]))) - of mAbsI: - let a = n.sons[1].typ - if isIntRange(a): - if a.n[0].intVal <= 0: - result = makeRange(a, 0, `|abs|`(getInt(a.n.sons[0]))) - else: - result = makeRange(a, `|abs|`(getInt(a.n.sons[1])), - `|abs|`(getInt(a.n.sons[0]))) - of mSucc: - let a = n.sons[1].typ - let b = n.sons[2].typ - if isIntRange(a) and isIntLit(b): - # (-5.. 1) + 6 == (-5 + 6)..(-1 + 6) - result = makeRange(a, pickMinInt(n.sons[1]) |+| pickMinInt(n.sons[2]), - pickMaxInt(n.sons[1]) |+| pickMaxInt(n.sons[2])) - of mPred: - let a = n.sons[1].typ - let b = n.sons[2].typ - if isIntRange(a) and isIntLit(b): - result = makeRange(a, pickMinInt(n.sons[1]) |-| pickMinInt(n.sons[2]), - pickMaxInt(n.sons[1]) |-| pickMaxInt(n.sons[2])) - of mAddI, mAddU: - commutativeOp(`|+|`) - of mMulI, mMulU: - commutativeOp(`|*|`) - of mSubI, mSubU: - binaryOp(`|-|`) - of mBitandI: - # since uint64 is still not even valid for 'range' (since it's no ordinal - # yet), we exclude it from the list (see bug #1638) for now: - var a = n.sons[1] - var b = n.sons[2] - # symmetrical: - if b.kind notin ordIntLit: swap(a, b) - if b.kind in ordIntLit: - let x = b.intVal|+|1 - if (x and -x) == x and x >= 0: - result = makeRange(n.typ, 0, b.intVal) - of mModU: - let a = n.sons[1] - let b = n.sons[2] - if b.kind in ordIntLit: - if b.intVal >= 0: - result = makeRange(n.typ, 0, b.intVal-1) - else: - result = makeRange(n.typ, b.intVal+1, 0) - of mModI: - # so ... if you ever wondered about modulo's signedness; this defines it: - let a = n.sons[1] - let b = n.sons[2] - if b.kind in {nkIntLit..nkUInt64Lit}: - if b.intVal >= 0: - result = makeRange(n.typ, -(b.intVal-1), b.intVal-1) - else: - result = makeRange(n.typ, b.intVal+1, -(b.intVal+1)) - of mDivI, mDivU: - binaryOp(`|div|`) - of mMinI: - commutativeOp(min) - of mMaxI: - commutativeOp(max) - else: discard - -discard """ - mShlI, - mShrI, mAddF64, mSubF64, mMulF64, mDivF64, mMaxF64, mMinF64 -""" - proc evalIs(n, a: PNode): PNode = # XXX: This should use the standard isOpImpl internalAssert a.kind == nkSym and a.sym.kind == skType diff --git a/doc/manual/types.txt b/doc/manual/types.txt index e6875f2df..927cda9e1 100644 --- a/doc/manual/types.txt +++ b/doc/manual/types.txt @@ -136,26 +136,6 @@ determined). Assignments from the base type to one of its subrange types A subrange type has the same size as its base type (``int`` in the example). -Nim requires `interval arithmetic`:idx: for subrange types over a set -of built-in operators that involve constants: ``x %% 3`` is of -type ``range[0..2]``. The following built-in operators for integers are -affected by this rule: ``-``, ``+``, ``*``, ``min``, ``max``, ``succ``, -``pred``, ``mod``, ``div``, ``%%``, ``and`` (bitwise ``and``). - -Bitwise ``and`` only produces a ``range`` if one of its operands is a -constant *x* so that (x+1) is a power of two. -(Bitwise ``and`` is then a ``%%`` operation.) - -This means that the following code is accepted: - -.. code-block:: nim - case (x and 3) + 7 - of 7: echo "A" - of 8: echo "B" - of 9: echo "C" - of 10: echo "D" - # note: no ``else`` required as (x and 3) + 7 has the type: range[7..10] - Pre-defined floating point types -------------------------------- diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 3cfefb5c1..e88002c7b 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -669,7 +669,7 @@ proc astGenRepr*(n: NimNode): string {.compileTime, benign.} = t = x result = newString(len) for j in countdown(len-1, 0): - result[j] = HexChars[t and 0xF] + result[j] = HexChars[int(t and 0xF)] t = t shr 4 # handle negative overflow if t == 0 and x < 0: t = -1 diff --git a/lib/pure/md5.nim b/lib/pure/md5.nim index 44b9ed0d4..1ff3a9824 100644 --- a/lib/pure/md5.nim +++ b/lib/pure/md5.nim @@ -78,10 +78,10 @@ proc encode(dest: var MD5Block, src: cstring) = proc decode(dest: var openArray[uint8], src: openArray[uint32]) = var i = 0 for j in 0..high(src): - dest[i] = src[j] and 0xff'u32 - dest[i+1] = src[j] shr 8 and 0xff'u32 - dest[i+2] = src[j] shr 16 and 0xff'u32 - dest[i+3] = src[j] shr 24 and 0xff'u32 + dest[i] = uint8(src[j] and 0xff'u32) + dest[i+1] = uint8(src[j] shr 8 and 0xff'u32) + dest[i+2] = uint8(src[j] shr 16 and 0xff'u32) + dest[i+3] = uint8(src[j] shr 24 and 0xff'u32) inc(i, 4) proc transform(buffer: pointer, state: var MD5State) = @@ -216,8 +216,8 @@ proc `$`*(d: MD5Digest): string = const digits = "0123456789abcdef" result = "" for i in 0..15: - add(result, digits[(d[i] shr 4) and 0xF]) - add(result, digits[d[i] and 0xF]) + add(result, digits[(d[i].int shr 4) and 0xF]) + add(result, digits[d[i].int and 0xF]) proc getMD5*(s: string): string = ## computes an MD5 value of `s` and returns its string representation diff --git a/lib/pure/securehash.nim b/lib/pure/securehash.nim index f141732a7..c19146669 100644 --- a/lib/pure/securehash.nim +++ b/lib/pure/securehash.nim @@ -148,13 +148,13 @@ proc sha1(src: cstring; len: int): Sha1Digest = while lastBlockBytes < endCurrentBlock: var value = uint32(src[lastBlockBytes + currentBlock]) shl - ((3'u32 - (lastBlockBytes and 3)) shl 3) + ((3'u32 - uint32(lastBlockBytes and 3)) shl 3) w[lastBlockBytes shr 2] = w[lastBlockBytes shr 2] or value inc(lastBlockBytes) w[lastBlockBytes shr 2] = w[lastBlockBytes shr 2] or ( - 0x80'u32 shl ((3'u32 - (lastBlockBytes and 3)) shl 3) + 0x80'u32 shl ((3'u32 - uint32(lastBlockBytes and 3)) shl 3) ) if endCurrentBlock >= 56: diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 834e7db6a..2f2b89955 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -887,7 +887,7 @@ proc toHex*(x: BiggestInt, len: Positive): string {.noSideEffect, n = x result = newString(len) for j in countdown(len-1, 0): - result[j] = HexChars[n and 0xF] + result[j] = HexChars[(n and 0xF).int] n = n shr 4 # handle negative overflow if n == 0 and x < 0: n = -1 diff --git a/lib/system.nim b/lib/system.nim index bb99b46f4..f967fb5f5 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1909,7 +1909,7 @@ const NimMinor*: int = 17 ## is the minor number of Nim's version. - NimPatch*: int = 2 + NimPatch*: int = 3 ## is the patch number of Nim's version. NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index cee4e33a5..db4d70613 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -38,20 +38,29 @@ proc chckRange(i, a, b: int): int {.inline, compilerproc, benign.} proc chckRangeF(x, a, b: float): float {.inline, compilerproc, benign.} proc chckNil(p: pointer) {.noinline, compilerproc, benign.} +type + GcFrame = ptr GcFrameHeader + GcFrameHeader {.compilerproc.} = object + len: int + prev: ptr GcFrameHeader + var framePtr {.threadvar.}: PFrame excHandler {.threadvar.}: PSafePoint # list of exception handlers # a global variable for the root of all try blocks currException {.threadvar.}: ref Exception + gcFramePtr {.threadvar.}: GcFrame type - FrameState = tuple[framePtr: PFrame, excHandler: PSafePoint, currException: ref Exception] + FrameState = tuple[gcFramePtr: GcFrame, framePtr: PFrame, + excHandler: PSafePoint, currException: ref Exception] proc getFrameState*(): FrameState {.compilerRtl, inl.} = - return (framePtr, excHandler, currException) + return (gcFramePtr, framePtr, excHandler, currException) proc setFrameState*(state: FrameState) {.compilerRtl, inl.} = + gcFramePtr = state.gcFramePtr framePtr = state.framePtr excHandler = state.excHandler currException = state.currException @@ -64,6 +73,14 @@ proc popFrame {.compilerRtl, inl.} = proc setFrame*(s: PFrame) {.compilerRtl, inl.} = framePtr = s +proc getGcFrame*(): GcFrame {.compilerRtl, inl.} = gcFramePtr +proc popGcFrame*() {.compilerRtl, inl.} = gcFramePtr = gcFramePtr.prev +proc setGcFrame*(s: GcFrame) {.compilerRtl, inl.} = gcFramePtr = s +proc pushGcFrame*(s: GcFrame) {.compilerRtl, inl.} = + s.prev = gcFramePtr + zeroMem(cast[pointer](cast[int](s)+%sizeof(GcFrameHeader)), s.len*sizeof(pointer)) + gcFramePtr = s + proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} = s.hasRaiseAction = false s.prev = excHandler diff --git a/tests/arithm/tsubrange.nim b/tests/arithm/tsubrange.nim new file mode 100644 index 000000000..9d60dbd1a --- /dev/null +++ b/tests/arithm/tsubrange.nim @@ -0,0 +1,13 @@ +discard """ + output: '''1''' +""" + +# bug #5854 +type + n16* = range[0'i16..high(int16)] + +var level: n16 = 1 +let maxLevel: n16 = 1 + +level = min(level + 2, maxLevel) +echo level diff --git a/todo.txt b/todo.txt index 7597c436a..1678c1599 100644 --- a/todo.txt +++ b/todo.txt @@ -1,6 +1,7 @@ version 1.0 battle plan ======================= +- eliminate 'nil' for seqs and strings - make 'not nil' the default (produce warnings instead of errors for a smooth migration path) - case objects needs to be safe and need to support pattern matching |