summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorIco Doornekamp <ico@pruts.nl>2020-01-15 11:06:41 +0100
committerAndreas Rumpf <rumpf_a@web.de>2020-01-15 11:06:41 +0100
commit79a326759a5fb49bed60163e48e8e17f3c1ee3a3 (patch)
tree831b77bcd852ad8cdecee71b70c32156a0009beb /lib
parentd31e32743fa3ff7d157632909ae220cc0d34e841 (diff)
downloadNim-79a326759a5fb49bed60163e48e8e17f3c1ee3a3.tar.gz
Added 'ansic' os support for minimal (embedded) targets (#13088)
* os:any implementation
* os:asny: omit flock/funlock calls in echoBinSafe
* Disabled default "unhandled expection" reporting for `--os:any` to reduce
code size. Added unhandledExceptionHook instead which can be used to get
a notification from Nim and handle it from the application.
Diffstat (limited to 'lib')
-rw-r--r--lib/system.nim9
-rw-r--r--lib/system/excpt.nim107
-rw-r--r--lib/system/io.nim4
-rw-r--r--lib/system/mmdisp.nim19
-rw-r--r--lib/system/osalloc.nim11
5 files changed, 80 insertions, 70 deletions
diff --git a/lib/system.nim b/lib/system.nim
index 430069977..1fd7a81a3 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -2096,7 +2096,7 @@ template sysAssert(cond: bool, msg: string) =
 
 const hasAlloc = (hostOS != "standalone" or not defined(nogc)) and not defined(nimscript)
 
-when notJSnotNims and hostOS != "standalone":
+when notJSnotNims and hostOS != "standalone" and hostOS != "any":
   include "system/cgprocs"
 when notJSnotNims and hasAlloc and not defined(nimSeqsV2):
   proc addChar(s: NimString, c: char): NimString {.compilerproc, benign.}
@@ -3395,6 +3395,11 @@ var
     ##
     ## If the handler does not raise an exception, ordinary control flow
     ## continues and the program is terminated.
+  unhandledExceptionHook*: proc (e: ref Exception) {.nimcall, tags: [], benign, raises: [].}
+    ## Set this variable to provide a procedure that should be called
+    ## in case of an `unhandle exception` event. The standard handler
+    ## writes an error message and terminates the program, except when
+    ## using `--os:any`
 
 type
   PFrame* = ptr TFrame  ## Represents a runtime frame of the call stack;
@@ -3745,7 +3750,7 @@ when not defined(JS):
 
 
 when notJSnotNims:
-  when hostOS != "standalone":
+  when hostOS != "standalone" and hostOS != "any":
     include "system/dyncalls"
 
   include "system/sets"
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index 931f3f640..91cf9aa3e 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -210,7 +210,7 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
           # interested in
           enabled = true
 
-when not hasThreadSupport:
+when hasSomeStackTrace and not hasThreadSupport:
   var
     tempFrames: array[0..127, PFrame] # should not be alloc'd on stack
 
@@ -261,52 +261,53 @@ proc `$`(s: seq[StackTraceEntry]): string =
     elif s[i].line == reraisedFromEnd: result.add "]]\n"
     else: addFrameEntry(result, s[i])
 
-proc auxWriteStackTrace(f: PFrame, s: var string) =
-  when hasThreadSupport:
+when hasSomeStackTrace:
+
+  proc auxWriteStackTrace(f: PFrame, s: var string) =
+    when hasThreadSupport:
+      var
+        tempFrames: array[0..127, PFrame] # but better than a threadvar
+    const
+      firstCalls = 32
     var
-      tempFrames: array[0..127, PFrame] # but better than a threadvar
-  const
-    firstCalls = 32
-  var
-    it = f
-    i = 0
-    total = 0
-  # setup long head:
-  while it != nil and i <= high(tempFrames)-firstCalls:
-    tempFrames[i] = it
-    inc(i)
-    inc(total)
-    it = it.prev
-  # go up the stack to count 'total':
-  var b = it
-  while it != nil:
-    inc(total)
-    it = it.prev
-  var skipped = 0
-  if total > len(tempFrames):
-    # skip N
-    skipped = total-i-firstCalls+1
-    for j in 1..skipped:
-      if b != nil: b = b.prev
-    # create '...' entry:
-    tempFrames[i] = nil
-    inc(i)
-  # setup short tail:
-  while b != nil and i <= high(tempFrames):
-    tempFrames[i] = b
-    inc(i)
-    b = b.prev
-  for j in countdown(i-1, 0):
-    if tempFrames[j] == nil:
-      add(s, "(")
-      add(s, $skipped)
-      add(s, " calls omitted) ...\n")
-    else:
-      addFrameEntry(s, tempFrames[j])
+      it = f
+      i = 0
+      total = 0
+    # setup long head:
+    while it != nil and i <= high(tempFrames)-firstCalls:
+      tempFrames[i] = it
+      inc(i)
+      inc(total)
+      it = it.prev
+    # go up the stack to count 'total':
+    var b = it
+    while it != nil:
+      inc(total)
+      it = it.prev
+    var skipped = 0
+    if total > len(tempFrames):
+      # skip N
+      skipped = total-i-firstCalls+1
+      for j in 1..skipped:
+        if b != nil: b = b.prev
+      # create '...' entry:
+      tempFrames[i] = nil
+      inc(i)
+    # setup short tail:
+    while b != nil and i <= high(tempFrames):
+      tempFrames[i] = b
+      inc(i)
+      b = b.prev
+    for j in countdown(i-1, 0):
+      if tempFrames[j] == nil:
+        add(s, "(")
+        add(s, $skipped)
+        add(s, " calls omitted) ...\n")
+      else:
+        addFrameEntry(s, tempFrames[j])
 
-proc stackTraceAvailable*(): bool
+  proc stackTraceAvailable*(): bool
 
-when hasSomeStackTrace:
   proc rawWriteStackTrace(s: var string) =
     when defined(nimStackTraceOverride):
       add(s, "Traceback (most recent call last, using override)\n")
@@ -351,7 +352,7 @@ var onUnhandledException*: (proc (errorMsg: string) {.
   ## The default is to write a stacktrace to ``stderr`` and then call ``quit(1)``.
   ## Unstable API.
 
-proc reportUnhandledError(e: ref Exception) {.nodestroy.} =
+proc reportUnhandledErrorAux(e: ref Exception) {.nodestroy.} =
   when hasSomeStackTrace:
     var buf = newStringOfCap(2000)
     if e.trace.len == 0:
@@ -400,6 +401,14 @@ proc reportUnhandledError(e: ref Exception) {.nodestroy.} =
     else:
       showErrorMessage(tbuf())
 
+proc reportUnhandledError(e: ref Exception) {.nodestroy.} =
+  if unhandledExceptionHook != nil:
+    unhandledExceptionHook(e)
+  when hostOS != "any":
+    reportUnhandledErrorAux(e)
+  else:
+    discard()
+
 proc nimLeaveFinally() {.compilerRtl.} =
   when defined(cpp) and not defined(noCppExceptions):
     {.emit: "throw;".}
@@ -425,14 +434,6 @@ when gotoBasedExceptions:
       currException = nil
       quit(1)
 
-  addQuitProc(proc () {.noconv.} =
-    if currException != nil:
-      reportUnhandledError(currException)
-      # emulate: ``programResult = 1`` via abort() and a nop signal handler.
-      c_signal(SIGABRT, (proc (sign: cint) {.noconv, benign.} = discard))
-      c_abort()
-  )
-
 proc raiseExceptionAux(e: sink(ref Exception)) {.nodestroy.} =
   if localRaiseHook != nil:
     if not localRaiseHook(e): return
diff --git a/lib/system/io.nim b/lib/system/io.nim
index a8f690054..41716f9af 100644
--- a/lib/system/io.nim
+++ b/lib/system/io.nim
@@ -615,7 +615,7 @@ when declared(stdout):
       android_log_print(ANDROID_LOG_VERBOSE, "nim", s)
     else:
       # flockfile deadlocks some versions of Android 5.x.x
-      when not defined(windows) and not defined(android) and not defined(nintendoswitch):
+      when not defined(windows) and not defined(android) and not defined(nintendoswitch) and hostOS != "any":
         proc flockfile(f: File) {.importc, nodecl.}
         proc funlockfile(f: File) {.importc, nodecl.}
         flockfile(stdout)
@@ -629,7 +629,7 @@ when declared(stdout):
       const linefeed = "\n"
       discard c_fwrite(linefeed.cstring, linefeed.len, 1, stdout)
       discard c_fflush(stdout)
-      when not defined(windows) and not defined(android) and not defined(nintendoswitch):
+      when not defined(windows) and not defined(android) and not defined(nintendoswitch) and hostOS != "any":
         funlockfile(stdout)
       when defined(windows) and compileOption("threads"):
         releaseSys echoLock
diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index 8bc8fe28a..faa7813fb 100644
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -354,11 +354,11 @@ elif defined(gogc):
   proc deallocOsPages(r: var MemRegion) {.inline.} = discard
   proc deallocOsPages() {.inline.} = discard
 
-elif defined(nogc) and defined(useMalloc):
+elif (defined(nogc) or defined(gcDestructors)) and defined(useMalloc):
 
   when not defined(useNimRtl):
     proc alloc(size: Natural): pointer =
-      var x = c_malloc(size + sizeof(size))
+      var x = c_malloc (size + sizeof(size)).csize_t
       if x == nil: raiseOutOfMem()
 
       cast[ptr int](x)[] = size
@@ -371,7 +371,7 @@ elif defined(nogc) and defined(useMalloc):
       var x = cast[pointer](cast[int](p) - sizeof(newsize))
       let oldsize = cast[ptr int](x)[]
 
-      x = c_realloc(x, newsize + sizeof(newsize))
+      x = c_realloc(x, (newsize + sizeof(newsize)).csize_t)
 
       if x == nil: raiseOutOfMem()
 
@@ -384,13 +384,13 @@ elif defined(nogc) and defined(useMalloc):
     proc dealloc(p: pointer) = c_free(cast[pointer](cast[int](p) - sizeof(int)))
 
     proc allocShared(size: Natural): pointer =
-      result = c_malloc(size)
+      result = c_malloc(size.csize_t)
       if result == nil: raiseOutOfMem()
     proc allocShared0(size: Natural): pointer =
       result = alloc(size)
       zeroMem(result, size)
     proc reallocShared(p: pointer, newsize: Natural): pointer =
-      result = c_realloc(p, newsize)
+      result = c_realloc(p, newsize.csize_t)
       if result == nil: raiseOutOfMem()
     proc deallocShared(p: pointer) = c_free(p)
 
@@ -400,7 +400,7 @@ elif defined(nogc) and defined(useMalloc):
     proc GC_setStrategy(strategy: GC_Strategy) = discard
     proc GC_enableMarkAndSweep() = discard
     proc GC_disableMarkAndSweep() = discard
-    proc GC_getStatistics(): string = return ""
+    #proc GC_getStatistics(): string = return ""
 
     proc getOccupiedMem(): int = discard
     proc getFreeMem(): int = discard
@@ -410,13 +410,6 @@ elif defined(nogc) and defined(useMalloc):
 
   proc initGC() = discard
 
-  proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
-    result = alloc0(size)
-  proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
-    result = newObj(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize))
-    cast[PGenericSeq](result).len = len
-    cast[PGenericSeq](result).reserved = len
-
   proc newObjNoInit(typ: PNimType, size: int): pointer =
     result = alloc(size)
 
diff --git a/lib/system/osalloc.nim b/lib/system/osalloc.nim
index 85c32e676..28a426e65 100644
--- a/lib/system/osalloc.nim
+++ b/lib/system/osalloc.nim
@@ -295,5 +295,16 @@ elif hostOS == "standalone" or defined(StandaloneHeapSize):
   proc osDeallocPages(p: pointer, size: int) {.inline.} =
     if bumpPointer-size == cast[int](p):
       dec bumpPointer, size
+
+elif hostOS == "any":
+  proc osAllocPages(size: int): pointer {.inline.} =
+    result = c_malloc(size.csize_t)
+
+  proc osTryAllocPages(size: int): pointer {.inline.} =
+    result = c_malloc(size.csize_t)
+
+  proc osDeallocPages(p: pointer, size: int) {.inline.} =
+    c_free(p)
+
 else:
   {.error: "Port memory manager to your platform".}