summary refs log tree commit diff stats
path: root/lib/system
diff options
context:
space:
mode:
Diffstat (limited to 'lib/system')
-rw-r--r--lib/system/atomics.nim20
-rw-r--r--lib/system/endb.nim2
-rw-r--r--lib/system/excpt.nim85
-rw-r--r--lib/system/gc2.nim2
-rw-r--r--lib/system/sysspawn.nim4
-rw-r--r--lib/system/sysstr.nim61
6 files changed, 114 insertions, 60 deletions
diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim
index 8c3801687..afc435638 100644
--- a/lib/system/atomics.nim
+++ b/lib/system/atomics.nim
@@ -213,12 +213,20 @@ proc atomicDec*(memLoc: var int, x: int = 1): int =
     result = memLoc
 
 when defined(vcc):
-  proc interlockedCompareExchange64(p: pointer; exchange, comparand: int64): int64
-    {.importc: "_InterlockedCompareExchange64", header: "<intrin.h>".}
-  proc interlockedCompareExchange32(p: pointer; exchange, comparand: int32): int32
-    {.importc: "_InterlockedCompareExchange", header: "<intrin.h>".}
-  proc interlockedCompareExchange8(p: pointer; exchange, comparand: byte): byte
-    {.importc: "_InterlockedCompareExchange64", header: "<intrin.h>".}
+  when defined(cpp):
+    proc interlockedCompareExchange64(p: pointer; exchange, comparand: int64): int64
+      {.importcpp: "_InterlockedCompareExchange64(static_cast<NI64 volatile *>(#), #, #)", header: "<intrin.h>".}
+    proc interlockedCompareExchange32(p: pointer; exchange, comparand: int32): int32
+      {.importcpp: "_InterlockedCompareExchange(static_cast<NI volatile *>(#), #, #)", header: "<intrin.h>".}
+    proc interlockedCompareExchange8(p: pointer; exchange, comparand: byte): byte
+      {.importcpp: "_InterlockedCompareExchange8(static_cast<char volatile *>(#), #, #)", header: "<intrin.h>".}
+  else:
+    proc interlockedCompareExchange64(p: pointer; exchange, comparand: int64): int64
+      {.importc: "_InterlockedCompareExchange64", header: "<intrin.h>".}
+    proc interlockedCompareExchange32(p: pointer; exchange, comparand: int32): int32
+      {.importc: "_InterlockedCompareExchange", header: "<intrin.h>".}
+    proc interlockedCompareExchange8(p: pointer; exchange, comparand: byte): byte
+      {.importc: "_InterlockedCompareExchange8", header: "<intrin.h>".}
 
   proc cas*[T: bool|int|ptr](p: ptr T; oldValue, newValue: T): bool =
     when sizeof(T) == 8:
diff --git a/lib/system/endb.nim b/lib/system/endb.nim
index 35d8f25c4..d51ae29df 100644
--- a/lib/system/endb.nim
+++ b/lib/system/endb.nim
@@ -370,7 +370,7 @@ proc commandPrompt() =
     if dbgUser.len == 0: dbgUser.len = oldLen
     # now look what we have to do:
     var i = scanWord(addr dbgUser.data, dbgTemp, 0)
-    template `?`(x: expr): expr = dbgTemp == cstring(x)
+    template `?`(x: untyped): untyped = dbgTemp == cstring(x)
     if ?"s" or ?"step":
       dbgState = dbStepInto
       again = false
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index 9e02d6824..70c18ae21 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -155,6 +155,52 @@ when not hasThreadSupport:
   var
     tempFrames: array[0..127, PFrame] # should not be alloc'd on stack
 
+const
+  reraisedFromBegin = -10
+  reraisedFromEnd = -100
+
+template reraisedFrom(z): untyped =
+  StackTraceEntry(procname: nil, line: z, filename: nil)
+
+proc auxWriteStackTrace(f: PFrame; s: var seq[StackTraceEntry]) =
+  var
+    it = f
+    i = 0
+  while it != nil:
+    inc(i)
+    it = it.prev
+  var last = i-1
+  if s.isNil:
+    s = newSeq[StackTraceEntry](i)
+  else:
+    last = s.len + i - 1
+    s.setLen(last+1)
+  it = f
+  while it != nil:
+    s[last] = StackTraceEntry(procname: it.procname,
+                              line: it.line,
+                              filename: it.filename)
+    it = it.prev
+    dec last
+
+template addFrameEntry(s, f: untyped) =
+  var oldLen = s.len
+  add(s, f.filename)
+  if f.line > 0:
+    add(s, '(')
+    add(s, $f.line)
+    add(s, ')')
+  for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ')
+  add(s, f.procname)
+  add(s, "\n")
+
+proc `$`(s: seq[StackTraceEntry]): string =
+  result = newStringOfCap(2000)
+  for i in 0 .. s.len-1:
+    if s[i].line == reraisedFromBegin: result.add "[[reraised from:\n"
+    elif s[i].line == reraisedFromEnd: result.add "]]\n"
+    else: addFrameEntry(result, s[i])
+
 proc auxWriteStackTrace(f: PFrame, s: var string) =
   when hasThreadSupport:
     var
@@ -194,17 +240,9 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
     if tempFrames[j] == nil:
       add(s, "(")
       add(s, $skipped)
-      add(s, " calls omitted) ...")
+      add(s, " calls omitted) ...\n")
     else:
-      var oldLen = s.len
-      add(s, tempFrames[j].filename)
-      if tempFrames[j].line > 0:
-        add(s, '(')
-        add(s, $tempFrames[j].line)
-        add(s, ')')
-      for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ')
-      add(s, tempFrames[j].procname)
-    add(s, "\n")
+      addFrameEntry(s, tempFrames[j])
 
 proc stackTraceAvailable*(): bool
 
@@ -221,6 +259,13 @@ when hasSomeStackTrace:
       auxWriteStackTraceWithBacktrace(s)
     else:
       add(s, "No stack traceback available\n")
+
+  proc rawWriteStackTrace(s: var seq[StackTraceEntry]) =
+    when NimStackTrace:
+      auxWriteStackTrace(framePtr, s)
+    else:
+      s = nil
+
   proc stackTraceAvailable(): bool =
     when NimStackTrace:
       if framePtr == nil:
@@ -240,12 +285,6 @@ proc quitOrDebug() {.inline.} =
   else:
     endbStep() # call the debugger
 
-when false:
-  proc rawRaise*(e: ref Exception) =
-    ## undocumented. Do not use.
-    pushCurrentException(e)
-    c_longjmp(excHandler.context, 1)
-
 var onUnhandledException*: (proc (errorMsg: string) {.
   nimcall.}) ## set this error \
   ## handler to override the existing behaviour on an unhandled exception.
@@ -282,7 +321,7 @@ proc raiseExceptionAux(e: ref Exception) =
       when hasSomeStackTrace:
         var buf = newStringOfCap(2000)
         if isNil(e.trace): rawWriteStackTrace(buf)
-        else: add(buf, e.trace)
+        else: add(buf, $e.trace)
         add(buf, "Error: unhandled exception: ")
         if not isNil(e.msg): add(buf, e.msg)
         add(buf, " [")
@@ -318,12 +357,11 @@ proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
   if e.name.isNil: e.name = ename
   when hasSomeStackTrace:
     if e.trace.isNil:
-      e.trace = ""
       rawWriteStackTrace(e.trace)
     elif framePtr != nil:
-      e.trace.add "[[reraised from:\n"
+      e.trace.add reraisedFrom(reraisedFromBegin)
       auxWriteStackTrace(framePtr, e.trace)
-      e.trace.add "]]\n"
+      e.trace.add reraisedFrom(reraisedFromEnd)
   raiseExceptionAux(e)
 
 proc reraiseException() {.compilerRtl.} =
@@ -349,10 +387,15 @@ proc getStackTrace(): string =
 
 proc getStackTrace(e: ref Exception): string =
   if not isNil(e) and not isNil(e.trace):
-    result = e.trace
+    result = $e.trace
   else:
     result = ""
 
+proc getStackTraceEntries*(e: ref Exception): seq[StackTraceEntry] =
+  ## Returns the attached stack trace to the exception ``e`` as
+  ## a ``seq``. This is not yet available for the JS backend.
+  shallowCopy(result, e.trace)
+
 when defined(nimRequiresNimFrame):
   proc stackOverflow() {.noinline.} =
     writeStackTrace()
diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim
index 70bed8740..4ecf3b226 100644
--- a/lib/system/gc2.nim
+++ b/lib/system/gc2.nim
@@ -173,7 +173,7 @@ proc internRefcount(p: pointer): int {.exportc: "getRefcount".} =
 when BitsPerPage mod (sizeof(int)*8) != 0:
   {.error: "(BitsPerPage mod BitsPerUnit) should be zero!".}
 
-template color(c): expr = c.refCount and colorMask
+template color(c): untyped = c.refCount and colorMask
 template setColor(c, col) =
   c.refcount = c.refcount and not colorMask or col
 
diff --git a/lib/system/sysspawn.nim b/lib/system/sysspawn.nim
index a0d10c446..dc2d13578 100644
--- a/lib/system/sysspawn.nim
+++ b/lib/system/sysspawn.nim
@@ -153,12 +153,12 @@ proc preferSpawn*(): bool =
   ## it is not necessary to call this directly; use 'spawnX' instead.
   result = gSomeReady.event
 
-proc spawn*(call: stmt) {.magic: "Spawn".}
+proc spawn*(call: typed) {.magic: "Spawn".}
   ## always spawns a new task, so that the 'call' is never executed on
   ## the calling thread. 'call' has to be proc call 'p(...)' where 'p'
   ## is gcsafe and has 'void' as the return type.
 
-template spawnX*(call: stmt) =
+template spawnX*(call: typed) =
   ## spawns a new task if a CPU core is ready, otherwise executes the
   ## call in the calling thread. Usually it is advised to
   ## use 'spawn' in order to not block the producer for an unknown
diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim
index d9586b00d..3f8e0eff0 100644
--- a/lib/system/sysstr.nim
+++ b/lib/system/sysstr.nim
@@ -322,37 +322,40 @@ proc nimIntToStr(x: int): string {.compilerRtl.} =
   result.add x
 
 proc add*(result: var string; x: float) =
-  var buf: array[0..64, char]
-  when defined(nimNoArrayToCstringConversion):
-    var n: int = c_sprintf(addr buf, "%.16g", x)
+  when nimvm:
+    result.add $x
   else:
-    var n: int = c_sprintf(buf, "%.16g", x)
-  var hasDot = false
-  for i in 0..n-1:
-    if buf[i] == ',':
-      buf[i] = '.'
-      hasDot = true
-    elif buf[i] in {'a'..'z', 'A'..'Z', '.'}:
-      hasDot = true
-  if not hasDot:
-    buf[n] = '.'
-    buf[n+1] = '0'
-    buf[n+2] = '\0'
-  # On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN'
-  # of '-1.#IND' are produced.
-  # We want to get rid of these here:
-  if buf[n-1] in {'n', 'N', 'D', 'd'}:
-    result.add "nan"
-  elif buf[n-1] == 'F':
-    if buf[0] == '-':
-      result.add "-inf"
+    var buf: array[0..64, char]
+    when defined(nimNoArrayToCstringConversion):
+      var n: int = c_sprintf(addr buf, "%.16g", x)
     else:
-      result.add "inf"
-  else:
-    var i = 0
-    while buf[i] != '\0':
-      result.add buf[i]
-      inc i
+      var n: int = c_sprintf(buf, "%.16g", x)
+    var hasDot = false
+    for i in 0..n-1:
+      if buf[i] == ',':
+        buf[i] = '.'
+        hasDot = true
+      elif buf[i] in {'a'..'z', 'A'..'Z', '.'}:
+        hasDot = true
+    if not hasDot:
+      buf[n] = '.'
+      buf[n+1] = '0'
+      buf[n+2] = '\0'
+    # On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN'
+    # of '-1.#IND' are produced.
+    # We want to get rid of these here:
+    if buf[n-1] in {'n', 'N', 'D', 'd'}:
+      result.add "nan"
+    elif buf[n-1] == 'F':
+      if buf[0] == '-':
+        result.add "-inf"
+      else:
+        result.add "inf"
+    else:
+      var i = 0
+      while buf[i] != '\0':
+        result.add buf[i]
+        inc i
 
 proc nimFloatToStr(f: float): string {.compilerproc.} =
   result = newStringOfCap(8)