summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2017-09-15 16:08:16 +0200
committerAndreas Rumpf <rumpf_a@web.de>2017-09-15 16:08:16 +0200
commit053b0ad6f301ade2d3627abed66a6f48a72aa05b (patch)
tree7236547fae29334c14693e9f2b0df758875c6c5b
parent9aeb78e2a86a6a7ab2c4726e634a8fdc7aa91089 (diff)
parent50ae228e255c0f82a1620657521a27f6b8152b58 (diff)
downloadNim-053b0ad6f301ade2d3627abed66a6f48a72aa05b.tar.gz
Merge branch 'araq' of github.com:nim-lang/Nim into araq
-rw-r--r--compiler/ast.nim3
-rw-r--r--compiler/options.nim3
-rw-r--r--compiler/semexprs.nim1
-rw-r--r--compiler/semfold.nim130
-rw-r--r--doc/manual/types.txt20
-rw-r--r--lib/core/macros.nim2
-rw-r--r--lib/pure/md5.nim12
-rw-r--r--lib/pure/securehash.nim4
-rw-r--r--lib/pure/strutils.nim2
-rw-r--r--lib/system.nim2
-rw-r--r--lib/system/excpt.nim21
-rw-r--r--tests/arithm/tsubrange.nim13
-rw-r--r--todo.txt1
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