diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2010-08-01 14:49:54 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2010-08-01 14:49:54 +0200 |
commit | 03724c2952e4eea4d9e16f5b4eccec862a1ba21c (patch) | |
tree | e456ae6e514beae649defcc5596d40fd42f62f66 | |
parent | ff02ce2d50d8a4b445f9fba6076527c3db62425c (diff) | |
download | Nim-03724c2952e4eea4d9e16f5b4eccec862a1ba21c.tar.gz |
before stack init change
-rwxr-xr-x | lib/pure/strutils.nim | 2 | ||||
-rwxr-xr-x | lib/system.nim | 10 | ||||
-rw-r--r-- | lib/system/cgprocs.nim | 12 | ||||
-rwxr-xr-x | lib/system/dyncalls.nim | 40 | ||||
-rwxr-xr-x | lib/system/gc.nim | 29 | ||||
-rwxr-xr-x | lib/system/inclrtl.nim | 2 | ||||
-rwxr-xr-x | lib/system/mmdisp.nim | 10 | ||||
-rwxr-xr-x | rod/astalgo.nim | 8 | ||||
-rwxr-xr-x | rod/ccgstmts.nim | 6 | ||||
-rwxr-xr-x | rod/cgen.nim | 21 | ||||
-rwxr-xr-x | rod/passaux.nim | 7 | ||||
-rwxr-xr-x | todo.txt | 1 | ||||
-rwxr-xr-x | web/news.txt | 4 |
13 files changed, 94 insertions, 58 deletions
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index ee56deab3..9e8798043 100755 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -385,8 +385,6 @@ proc intToStr(x: int, minchars: int = 1): string = if x < 0: result = '-' & result -proc toString[Ty](x: Ty): string = return $x - proc toOctal(c: char): string = result = newString(3) var val = ord(c) diff --git a/lib/system.nim b/lib/system.nim index fec31eba0..abad660f1 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -666,7 +666,8 @@ proc `&` * (x: char, y: string): string {. proc add*(x: var string, y: char) {.magic: "AppendStrCh", noSideEffect.} proc add*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.} - + +include "system/inclrtl" include "system/cgprocs" when not defined(ECMAScript): @@ -824,8 +825,6 @@ const ## a string that describes the application type. Possible values: ## "console", "gui", "lib". -include "system/inclrtl" - proc toFloat*(i: int): float {. magic: "ToFloat", noSideEffect, importc: "toFloat".} ## converts an integer `i` into a ``float``. If the conversion @@ -1305,12 +1304,17 @@ when not defined(EcmaScript) and not defined(NimrodVM): proc initGC() + proc initStackBottom() {.inline.} = + var locals: array[0..7, int] + setStackBottom(addr(locals)) + var strDesc: TNimType strDesc.size = sizeof(string) strDesc.kind = tyString strDesc.flags = {ntfAcyclic} + initStackBottom() initGC() # BUGFIX: need to be called here! {.push stack_trace: off.} diff --git a/lib/system/cgprocs.nim b/lib/system/cgprocs.nim index 40aca033b..99f802910 100644 --- a/lib/system/cgprocs.nim +++ b/lib/system/cgprocs.nim @@ -11,4 +11,16 @@ proc addChar(s: NimString, c: char): NimString {.compilerProc.} +type + TLibHandle = pointer # private type + TProcAddr = pointer # libary loading and loading of procs: + +proc nimLoadLibrary(path: string): TLibHandle {.compilerproc.} +proc nimUnloadLibrary(lib: TLibHandle) {.compilerproc.} +proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr {.compilerproc.} + +proc nimLoadLibraryError(path: string) {.compilerproc, noinline.} + +proc setStackBottom(theStackBottom: pointer) {.compilerRtl.} + diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim index cb665c5cb..d7be3d6ef 100755 --- a/lib/system/dyncalls.nim +++ b/lib/system/dyncalls.nim @@ -12,24 +12,28 @@ # However, the interface has been designed to take platform differences into # account and been ported to all major platforms. -type - TLibHandle = pointer # private type - TProcAddr = pointer # libary loading and loading of procs: - const NilLibHandle: TLibHandle = nil -proc nimLoadLibrary(path: string): TLibHandle {.compilerproc.} -proc nimUnloadLibrary(lib: TLibHandle) {.compilerproc.} -proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr {.compilerproc.} - -proc nimLoadLibraryError(path: string) {.compilerproc, noinline.} = - when true: - # carefully written to avoid memory allocation: - stdout.write("could not load: ") - quit(path) - else: - raise newException(EInvalidLibrary, "could not load: " & path) +proc rawWrite(f: TFile, s: string) = + # we cannot throw an exception here! + discard writeBuffer(f, cstring(s), s.len) + +proc nimLoadLibraryError(path: string) = + # carefully written to avoid memory allocation: + #stdout.write("could not load: ") + #quit(path) + stdout.rawWrite("could not load: ") + stdout.rawWrite(path) + stdout.rawWrite("\n") + quit(1) + +proc ProcAddrError(name: cstring) {.noinline.} = + # carefully written to avoid memory allocation: + stdout.rawWrite("could not import: ") + stdout.write(name) + stdout.rawWrite("\n") + quit(1) # this code was inspired from Lua's source code: # Lua - An Extensible Extension Language @@ -65,7 +69,7 @@ when defined(posix): proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr = result = dlsym(lib, name) - if result == nil: nimLoadLibraryError($name) + if result == nil: ProcAddrError(name) elif defined(windows) or defined(dos): # @@ -90,7 +94,7 @@ elif defined(windows) or defined(dos): proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr = result = GetProcAddress(cast[THINSTANCE](lib), name) - if result == nil: nimLoadLibraryError($name) + if result == nil: ProcAddrError(name) elif defined(mac): # @@ -126,7 +130,7 @@ elif defined(mac): nss: NSSymbol nss = NSLookupSymbolInModule(NSModule(lib), name) result = TProcAddr(NSAddressOfSymbol(nss)) - if result == nil: nimLoadLibraryError($name) + if result == nil: ProcAddrError(name) else: {.error: "no implementation for dyncalls".} diff --git a/lib/system/gc.nim b/lib/system/gc.nim index f21f5bc01..d1a3e8273 100755 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -214,11 +214,6 @@ proc prepareDealloc(cell: PCell) = (cast[TFinalizer](cell.typ.finalizer))(cellToUsr(cell)) dec(recGcLock) -proc setStackBottom(theStackBottom: pointer) {.compilerRtl.} = - # the first init must be the one that defines the stack bottom: - if stackBottom == nil: - stackBottom = theStackBottom - proc PossibleRoot(gch: var TGcHeap, c: PCell) {.inline.} = if canbeCycleRoot(c): incl(gch.cycleRoots, c) @@ -367,7 +362,7 @@ proc newSeq(typ: PNimType, len: int): pointer = cast[PGenericSeq](result).len = len cast[PGenericSeq](result).space = len -proc growObj(old: pointer, newsize: int): pointer = +proc growObj(old: pointer, newsize: int): pointer {.rtl.} = checkCollection() var ol = usrToCell(old) assert(ol.typ != nil) @@ -487,6 +482,25 @@ proc markThreadStacks(gch: var TGcHeap) = # ----------------- stack management -------------------------------------- # inspired from Smart Eiffel +when defined(sparc): + const stackIncreases = false +elif defined(hppa) or defined(hp9000) or defined(hp9000s300) or + defined(hp9000s700) or defined(hp9000s800) or defined(hp9000s820): + const stackIncreases = true +else: + const stackIncreases = false + +proc setStackBottom(theStackBottom: pointer) = + # the first init must be the one that defines the stack bottom: + if stackBottom == nil: stackBottom = theStackBottom + else: + var a = cast[TAddress](theStackBottom) + var b = cast[TAddress](stackBottom) + when stackIncreases: + stackBottom = cast[pointer](min(a, b)) + else: + stackBottom = cast[pointer](max(a, b)) + proc stackSize(): int {.noinline.} = var stackTop: array[0..1, pointer] result = abs(cast[int](addr(stackTop[0])) - cast[int](stackBottom)) @@ -518,8 +532,7 @@ when defined(sparc): # For SPARC architecture. elif defined(ELATE): {.error: "stack marking code is to be written for this architecture".} -elif defined(hppa) or defined(hp9000) or defined(hp9000s300) or - defined(hp9000s700) or defined(hp9000s800) or defined(hp9000s820): +elif stackIncreases: # --------------------------------------------------------------------------- # Generic code for architectures where addresses increase as the stack grows. # --------------------------------------------------------------------------- diff --git a/lib/system/inclrtl.nim b/lib/system/inclrtl.nim index 28965b4b1..3db6a77ca 100755 --- a/lib/system/inclrtl.nim +++ b/lib/system/inclrtl.nim @@ -21,7 +21,7 @@ when defined(createNimRtl): when defined(useNimRtl): {.error: "Cannot create and use nimrtl at the same time!".} elif appType != "lib": - {.error: "nimrtl must be build as a library!".} + {.error: "nimrtl must be built as a library!".} when defined(createNimRtl): # NOTE: compilerproc cannot make use of name mangling! diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim index ff61ea1fe..f0685c5c3 100755 --- a/lib/system/mmdisp.nim +++ b/lib/system/mmdisp.nim @@ -117,7 +117,7 @@ when defined(boehmgc): proc growObj(old: pointer, newsize: int): pointer = result = realloc(old, newsize) - proc setStackBottom(theStackBottom: pointer) {.compilerproc.} = nil + proc setStackBottom(theStackBottom: pointer) = nil proc nimGCref(p: pointer) {.compilerproc, inline.} = nil proc nimGCunref(p: pointer) {.compilerproc, inline.} = nil @@ -175,7 +175,7 @@ elif defined(nogc): proc growObj(old: pointer, newsize: int): pointer = result = realloc(old, newsize) - proc setStackBottom(theStackBottom: pointer) {.compilerproc.} = nil + proc setStackBottom(theStackBottom: pointer) = nil proc nimGCref(p: pointer) {.compilerproc, inline.} = nil proc nimGCunref(p: pointer) {.compilerproc, inline.} = nil @@ -194,12 +194,6 @@ elif defined(useNimRtl): proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} proc growObj(old: pointer, newsize: int): pointer {.rtl.} - proc setStackBottom(theStackBottom: pointer) {.compilerProc, inline.} = - # This happens before setStackBottom has been loaded by dlsym(), so - # we simply provide a dummy implemenation here for the code gen. No - # harm is done by this. - nil - proc nimGCref(p: pointer) {.compilerRtl.} proc nimGCunref(p: pointer) {.compilerRtl.} diff --git a/rod/astalgo.nim b/rod/astalgo.nim index 1b4572b2b..f3e573d84 100755 --- a/rod/astalgo.nim +++ b/rod/astalgo.nim @@ -284,7 +284,8 @@ proc symToYamlAux(n: PSym, marker: var TIntSet, indent: int, flagsToStr(n.options), toRope("position"), toRope(n.position)]) -proc typeToYamlAux(n: PType, marker: var TIntSet, indent: int, maxRecDepth: int): PRope = +proc typeToYamlAux(n: PType, marker: var TIntSet, indent: int, + maxRecDepth: int): PRope = if n == nil: result = toRope("null") elif intSetContainsOrIncl(marker, n.id): @@ -417,7 +418,10 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope = appf(result, "$n$1}", [spaces(indent)]) proc debug(n: PSym) = - writeln(stdout, ropeToStr(ropef("$1_$2", [toRope(n.name.s), toRope(n.id)]))) + #writeln(stdout, ropeToStr(symToYaml(n, 0, 1))) + writeln(stdout, ropeToStr(ropef("$1_$2: $3, $4", [ + toRope(n.name.s), toRope(n.id), flagsToStr(n.flags), + flagsToStr(n.loc.flags)]))) proc debug(n: PType) = writeln(stdout, ropeToStr(debugType(n))) diff --git a/rod/ccgstmts.nim b/rod/ccgstmts.nim index 9171b5fb8..348615cce 100755 --- a/rod/ccgstmts.nim +++ b/rod/ccgstmts.nim @@ -715,10 +715,12 @@ proc genStmts(p: BProc, t: PNode) = of nkProcDef, nkMethodDef, nkConverterDef: if (t.sons[genericParamsPos] == nil): prc = t.sons[namePos].sym - if not (optDeadCodeElim in gGlobalOptions) and - not (sfDeadCodeElim in getModule(prc).flags) or + if (optDeadCodeElim notin gGlobalOptions and + sfDeadCodeElim notin getModule(prc).flags) or ({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or + (sfExportc in prc.flags and lfExportLib in prc.loc.flags) or (prc.kind == skMethod): + # we have not only the header: if (t.sons[codePos] != nil) or (lfDynamicLib in prc.loc.flags): genProc(p.module, prc) else: internalError(t.info, "genStmts(" & $t.kind & ')') diff --git a/rod/cgen.nim b/rod/cgen.nim index dd1878465..b5cf04b58 100755 --- a/rod/cgen.nim +++ b/rod/cgen.nim @@ -399,7 +399,7 @@ proc loadDynamicLib(m: BModule, lib: PLib) = lib.generated = true var tmp = getGlobalTempName() assert(lib.name == nil) - lib.name = tmp # BUGFIX: useMagic has awful side-effects + lib.name = tmp # BUGFIX: cgsym has awful side-effects appf(m.s[cfsVars], "static void* $1;$n", [tmp]) if lib.path.kind in {nkStrLit..nkTripleStrLit}: var s: TStringSeq = @[] @@ -437,14 +437,14 @@ proc SymInDynamicLib(m: BModule, sym: PSym) = var lib = sym.annex var extname = sym.loc.r loadDynamicLib(m, lib) - discard cgsym(m, "nimGetProcAddr") + #discard cgsym(m, "nimGetProcAddr") if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect) var tmp = mangleDynLibProc(sym) sym.loc.r = tmp # from now on we only need the internal name sym.typ.sym = nil # generate a new name inc(m.labels, 2) - appf(m.s[cfsDynLibInit], - "$1 = ($2) nimGetProcAddr($3, $4);$n", + appcg(m, m.s[cfsDynLibInit], + "$1 = ($2) #nimGetProcAddr($3, $4);$n", [tmp, getTypeDesc(m, sym.typ), lib.name, cstringLit(m, m.s[cfsDynLibInit], ropeToStr(extname))]) appff(m.s[cfsVars], "$2 $1;$n", @@ -458,7 +458,7 @@ proc cgsym(m: BModule, name: string): PRope = of skProc, skMethod, skConverter: genProc(m, sym) of skVar: genVarPrototype(m, sym) of skType: discard getTypeDesc(m, sym.typ) - else: InternalError("useMagic: " & name) + else: InternalError("cgsym: " & name) else: # we used to exclude the system module from this check, but for DLL # generation support this sloppyness leads to hard to detect bugs, so @@ -700,10 +700,10 @@ proc getFileHeader(cfilenoext: string): PRope = proc genMainProc(m: BModule) = const - CommonMainBody = " setStackBottom(dummy);$n" & " nim__datInit();$n" & + CommonMainBody = " #setStackBottom(dummy);$n" & " nim__datInit();$n" & " systemInit();$n" & "$1" & "$2" CommonMainBodyLLVM = " %MOC$3 = bitcast [8 x %NI]* %dummy to i8*$n" & - " call void @setStackBottom(i8* %MOC$3)$n" & + " call void @#setStackBottom(i8* %MOC$3)$n" & " call void @nim__datInit()$n" & " call void systemInit()$n" & "$1" & "$2" PosixNimMain = "int cmdCount;$n" & "char** cmdLine;$n" & "char** gEnv;$n" & @@ -744,7 +744,6 @@ proc genMainProc(m: BModule) = " i8* %lpvReserved) {$n" & " call void @NimMain()$n" & " ret i32 1$n" & "}$n" var nimMain, otherMain: TFormatStr - discard cgsym(m, "setStackBottom") if (platform.targetOS == osWindows) and (gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}): if optGenGuiApp in gGlobalOptions: @@ -771,8 +770,10 @@ proc genMainProc(m: BModule) = otherMain = PosixCMain if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint") inc(m.labels) - appf(m.s[cfsProcs], nimMain, [gBreakpoints, mainModInit, toRope(m.labels)]) - if not (optNoMain in gGlobalOptions): appf(m.s[cfsProcs], otherMain, []) + appcg(m, m.s[cfsProcs], nimMain, [ + gBreakpoints, mainModInit, toRope(m.labels)]) + if not (optNoMain in gGlobalOptions): + appcg(m, m.s[cfsProcs], otherMain, []) proc getInitName(m: PSym): PRope = result = ropeff("$1Init", "@$1Init", [toRope(m.name.s)]) diff --git a/rod/passaux.nim b/rod/passaux.nim index 0fc5226d1..d687dba08 100755 --- a/rod/passaux.nim +++ b/rod/passaux.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2008 Andreas Rumpf +# (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -33,8 +33,9 @@ proc verbosePass(): TPass = proc cleanUp(c: PPassContext, n: PNode): PNode = var s: PSym - result = n # we cannot clean up if dead code elimination is activated - if (optDeadCodeElim in gGlobalOptions): return + result = n + # we cannot clean up if dead code elimination is activated + if optDeadCodeElim in gGlobalOptions: return case n.kind of nkStmtList: for i in countup(0, sonsLen(n) - 1): discard cleanup(c, n.sons[i]) diff --git a/todo.txt b/todo.txt index 496caab4e..470661be1 100755 --- a/todo.txt +++ b/todo.txt @@ -1,7 +1,6 @@ For version 0.8.10 ================== -- more robust boot strap process! - support for generation of dynamic libraries - fix exception handling - fix implicit generic routines diff --git a/web/news.txt b/web/news.txt index b7f02b5ac..f70bb5bdd 100755 --- a/web/news.txt +++ b/web/news.txt @@ -34,6 +34,10 @@ Changes affecting backwards compatibility - Removed ``strutils.splitLinesSeq``. - Removed ``strutils.splitSeq``. - Removed ``strutils.toString``. +- If a DLL cannot be loaded (via the ``dynlib`` pragma) ``EInvalidLibrary`` + is not raised anymore. Instead ``system.quit()`` is called. This is because + raising an exception requires heap allocations. However the memory manager + might be contained in the DLL that failed to load. Additions |