summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2010-08-01 14:49:54 +0200
committerAndreas Rumpf <rumpf_a@web.de>2010-08-01 14:49:54 +0200
commit03724c2952e4eea4d9e16f5b4eccec862a1ba21c (patch)
treee456ae6e514beae649defcc5596d40fd42f62f66
parentff02ce2d50d8a4b445f9fba6076527c3db62425c (diff)
downloadNim-03724c2952e4eea4d9e16f5b4eccec862a1ba21c.tar.gz
before stack init change
-rwxr-xr-xlib/pure/strutils.nim2
-rwxr-xr-xlib/system.nim10
-rw-r--r--lib/system/cgprocs.nim12
-rwxr-xr-xlib/system/dyncalls.nim40
-rwxr-xr-xlib/system/gc.nim29
-rwxr-xr-xlib/system/inclrtl.nim2
-rwxr-xr-xlib/system/mmdisp.nim10
-rwxr-xr-xrod/astalgo.nim8
-rwxr-xr-xrod/ccgstmts.nim6
-rwxr-xr-xrod/cgen.nim21
-rwxr-xr-xrod/passaux.nim7
-rwxr-xr-xtodo.txt1
-rwxr-xr-xweb/news.txt4
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