Skip to content

Commit

Permalink
Added 'ansic' os support for minimal (embedded) targets (#13088)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
zevv authored and Araq committed Jan 15, 2020
1 parent d31e327 commit 79a3267
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 71 deletions.
6 changes: 5 additions & 1 deletion compiler/platform.nim
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osAix, osPalmos, osQnx,
osAmiga, osAtari, osNetware, osMacos, osMacosx, osIos, osHaiku, osAndroid, osVxWorks
osGenode, osJS, osNimVM, osStandalone, osNintendoSwitch
osGenode, osJS, osNimVM, osStandalone, osNintendoSwitch, osAny

type
TInfoOSProp* = enum
Expand Down Expand Up @@ -177,6 +177,10 @@ const
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: ".elf", extSep: ".",
props: {ospNeedsPIC, ospPosix}),
(name: "Any", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {}),
]

type
Expand Down
9 changes: 7 additions & 2 deletions lib/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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.}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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"
Expand Down
107 changes: 54 additions & 53 deletions lib/system/excpt.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;".}
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions lib/system/io.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
19 changes: 6 additions & 13 deletions lib/system/mmdisp.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()

Expand All @@ -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)

Expand All @@ -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
Expand All @@ -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)

Expand Down
11 changes: 11 additions & 0 deletions lib/system/osalloc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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".}

0 comments on commit 79a3267

Please sign in to comment.