summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xlib/nimbase.h12
-rwxr-xr-xlib/system.nim57
-rwxr-xr-xlib/system/excpt.nim48
-rwxr-xr-xlib/system/gc.nim45
-rwxr-xr-xlib/system/systhread.nim46
-rwxr-xr-xrod/ast.nim9
-rwxr-xr-xrod/ccgstmts.nim59
-rwxr-xr-xrod/cgen.nim2
-rwxr-xr-xrod/commands.nim48
-rwxr-xr-xrod/rodread.nim86
-rwxr-xr-xrod/rodwrite.nim32
-rwxr-xr-xrod/semfold.nim8
-rw-r--r--tests/accept/run/tcontinuexc.nim21
-rwxr-xr-xtests/accept/run/toverflw2.nim5
-rwxr-xr-xtinyc/config_edited.h5
-rwxr-xr-xtodo.txt4
-rwxr-xr-xtools/buildsh.tmpl3
-rwxr-xr-xweb/news.txt4
18 files changed, 329 insertions, 165 deletions
diff --git a/lib/nimbase.h b/lib/nimbase.h
index 01c3ece20..983bb112d 100755
--- a/lib/nimbase.h
+++ b/lib/nimbase.h
@@ -177,10 +177,6 @@ __TINYC__
 **
 **  Fortunately the ISO C99 specifications define the functions lrint, lrintf,
 **  llrint and llrintf which fix this problem as a side effect.
-**
-**  On Unix-like systems, the configure process should have detected the
-**  presence of these functions. If they weren't found we have to replace them
-**  here with a standard C cast.
 */
 
 /*
@@ -444,4 +440,12 @@ __declspec(naked) int __fastcall NimXadd(volatile int* pNum, int val) {
 }
 #endif
 
+#ifdef __GNUC__
+#  define likely(x) __builtin_expect(x, 1)
+#  define unlikely(x) __builtin_expect(x, 0)
+#else
+#  define likely(x) (x)
+#  define unlikely(x) (x)
+#endif
+
 #endif
diff --git a/lib/system.nim b/lib/system.nim
index 0152ebf23..0b2959266 100755
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -144,6 +144,7 @@ type
   E_Base* {.compilerproc.} = object of TObject ## base exception class;
                                                ## each exception has to
                                                ## inherit from `E_Base`.
+    parent: ref E_Base        ## parent exception (can be used as a stack)
     name: cstring             ## The exception's name is its Nimrod identifier.
                               ## This field is filled automatically in the
                               ## ``raise`` statement.
@@ -717,6 +718,22 @@ const
     ## a string that describes the application type. Possible values:
     ## "console", "gui", "lib".
   
+proc compileOption*(option: string): bool {.
+  magic: "CompileOption", noSideEffect.}
+  ## can be used to determine a on|off compile-time option. Example:
+  ##
+  ## .. code-block:: nimrod
+  ## when compileOption("floatchecks"): 
+  ##   echo "compiled with floating point NaN and Inf checks"
+  
+proc compileOption*(option, arg: string): bool {.
+  magic: "CompileOptionArg", noSideEffect.}
+  ## can be used to determine an enum compile-time option. Example:
+  ##
+  ## .. code-block:: nimrod
+  ## when compileOption("opt", "size") and compileOption("gc", "boehm"): 
+  ##   echo "compiled with optimization for size and uses Boehm's GC"
+  
 include "system/inclrtl"
 include "system/cgprocs"
 
@@ -961,14 +978,6 @@ proc getRefcount*[T](x: ref T): int {.importc: "getRefcount", noSideEffect.}
 
 #proc writeStackTrace() {.export: "writeStackTrace".}
 
-when not defined(NimrodVM):
-  proc getCurrentExceptionMsg*(): string {.exportc.}
-    ## retrieves the error message that was attached to the current
-    ## exception; if there is none, "" is returned.
-  
-  proc getCurrentException*(): ref E_Base
-    ## retrieves the current exception; if there is none, nil is returned.
-
 # new constants:
 const
   inf* {.magic: "Inf".} = 1.0 / 0.0
@@ -1168,15 +1177,6 @@ proc each*[T](data: var openArray[T], op: proc (x: var T)) =
   ## `op` to every item in `data`.
   for i in 0..data.len-1: op(data[i])
 
-
-# ----------------- FPU ------------------------------------------------------
-
-#proc disableFPUExceptions*()
-# disables all floating point unit exceptions
-
-#proc enableFPUExceptions*()
-# enables all floating point unit exceptions
-
 # ----------------- GC interface ---------------------------------------------
 
 proc GC_disable*() {.rtl.}
@@ -1577,14 +1577,15 @@ when not defined(EcmaScript) and not defined(NimrodVM):
   include "system/assign"
   include "system/repr"
 
-  # we have to implement it here after gentostr for the cstrToNimStrDummy proc
-  proc getCurrentExceptionMsg(): string =
-    if excHandler == nil: return ""
-    return $excHandler.exc.msg
+  proc getCurrentException*(): ref E_Base {.compilerRtl, inl.} =
+    ## retrieves the current exception; if there is none, nil is returned.
+    result = currException
 
-  proc getCurrentException(): ref E_Base = 
-    if excHandler != nil: 
-      result = excHandler.exc
+  proc getCurrentExceptionMsg*(): string {.inline.} =
+    ## retrieves the error message that was attached to the current
+    ## exception; if there is none, "" is returned.
+    var e = getCurrentException()
+    return if e == nil: "" else: e.msg
 
   {.push stack_trace: off.}
   when defined(endb):
@@ -1594,6 +1595,14 @@ when not defined(EcmaScript) and not defined(NimrodVM):
     include "system/profiler"
   {.pop.} # stacktrace
 
+  proc likely*(val: bool): bool {.importc: "likely", nodecl, nosideeffect.}
+    ## can be used to mark a condition to be likely. This is a hint for the 
+    ## optimizer.
+  
+  proc unlikely*(val: bool): bool {.importc: "unlikely", nodecl, nosideeffect.}
+    ## can be used to mark a condition to be unlikely. This is a hint for the 
+    ## optimizer.
+
 elif defined(ecmaScript):
   include "system/ecmasys"
 elif defined(NimrodVM):
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index d8bdf2a9f..c473c42f0 100755
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -20,9 +20,6 @@ else:
   proc writeToStdErr(msg: CString) =
     discard MessageBoxA(0, msg, nil, 0)
 
-proc raiseException(e: ref E_Base, ename: CString) {.compilerproc.}
-proc reraiseException() {.compilerproc.}
-
 proc registerSignalHandler() {.compilerproc.}
 
 proc chckIndx(i, a, b: int): int {.inline, compilerproc.}
@@ -34,20 +31,29 @@ type
   PSafePoint = ptr TSafePoint
   TSafePoint {.compilerproc, final.} = object
     prev: PSafePoint # points to next safe point ON THE STACK
-    exc: ref E_Base
     status: int
+    exc: ref E_Base  # XXX only needed for bootstrapping
     context: C_JmpBuf
 
 var
   excHandler {.compilerproc.}: PSafePoint = nil
     # list of exception handlers
     # a global variable for the root of all try blocks
+  currException: ref E_Base
 
-proc reraiseException() =
-  if excHandler == nil:
-    raise newException(ENoExceptionToReraise, "no exception to reraise")
-  else:
-    c_longjmp(excHandler.context, 1)
+proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} = 
+  s.prev = excHandler
+  excHandler = s
+
+proc popSafePoint {.compilerRtl, inl.} =
+  excHandler = excHandler.prev
+
+proc pushCurrentException(e: ref E_Base) {.compilerRtl, inl.} = 
+  e.parent = currException
+  currException = e
+
+proc popCurrentException {.compilerRtl, inl.} =
+  currException = currException.parent
 
 type
   PFrame = ptr TFrame
@@ -114,13 +120,17 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
     add(s, stackTraceNewLine)
 
 proc rawWriteStackTrace(s: var string) =
-  if framePtr == nil:
-    add(s, "No stack traceback available")
-    add(s, stackTraceNewLine)
+  when compileOption("stacktrace") or compileOption("linetrace"):
+    if framePtr == nil:
+      add(s, "No stack traceback available")
+      add(s, stackTraceNewLine)
+    else:
+      add(s, "Traceback (most recent call last)")
+      add(s, stackTraceNewLine)
+      auxWriteStackTrace(framePtr, s)
   else:
-    add(s, "Traceback (most recent call last)")
+    add(s, "No stack traceback available")
     add(s, stackTraceNewLine)
-    auxWriteStackTrace(framePtr, s)
 
 proc quitOrDebug() {.inline.} =
   when not defined(endb):
@@ -128,11 +138,11 @@ proc quitOrDebug() {.inline.} =
   else:
     endbStep() # call the debugger
 
-proc raiseException(e: ref E_Base, ename: CString) =
+proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
   GC_disable() # a bad thing is an error in the GC while raising an exception
   e.name = ename
   if excHandler != nil:
-    excHandler.exc = e
+    pushCurrentException(e)
     c_longjmp(excHandler.context, 1)
   else:
     if not isNil(buf):
@@ -152,6 +162,12 @@ proc raiseException(e: ref E_Base, ename: CString) =
     quitOrDebug()
   GC_enable()
 
+proc reraiseException() {.compilerRtl.} =
+  if currException == nil:
+    raise newException(ENoExceptionToReraise, "no exception to reraise")
+  else:
+    raiseException(currException, currException.name)
+
 var
   gAssertionFailed: ref EAssertionFailed
 
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index cd803d70a..0c403b4bc 100755
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -61,6 +61,8 @@ type
     decStack: TCellSeq       # cells in the stack that are to decref again
     cycleRoots: TCellSet
     tempStack: TCellSeq      # temporary stack for recursion elimination
+    cycleRootsLock: TSysLock
+    zctLock: TSysLock
     stat: TGcStat
 
 var
@@ -68,12 +70,22 @@ var
   gch: TGcHeap
   cycleThreshold: int = InitialCycleThreshold
   recGcLock: int = 0
-    # we use a lock to prevend the garbage collector to be triggered in a
+    # we use a lock to prevent the garbage collector to be triggered in a
     # finalizer; the collector should not call itself this way! Thus every
     # object allocated by a finalizer will not trigger a garbage collection.
     # This is wasteful but safe. This is a lock against recursive garbage
     # collection, not a lock for threads!
 
+proc lock(gch: var TGcHeap) {.inline.} = 
+  if isMultiThreaded: 
+    Lock(gch.zctLock)
+    lock(gch.cycleRootsLock)
+
+proc unlock(gch: var TGcHeap) {.inline.} = 
+  if isMultiThreaded: 
+    unlock(gch.zctLock)
+    unlock(gch.cycleRootsLock)
+
 proc addZCT(s: var TCellSeq, c: PCell) {.noinline.} =
   if (c.refcount and rcZct) == 0:
     c.refcount = c.refcount and not colorMask or rcZct
@@ -159,7 +171,7 @@ when traceGC:
     for c in elements(states[csAllocated]):
       inc(e)
       if c in states[csZctFreed]: inc(z)
-      elif c in states[csCycFreed]: inc(z)
+      elif c in states[csCycFreed]: inc(y)
       else: writeCell("leak", c)
     cfprintf(cstdout, "Allocations: %ld; ZCT freed: %ld; CYC freed: %ld\n",
              e, z, y)
@@ -190,25 +202,28 @@ proc prepareDealloc(cell: PCell) =
 
 proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} = 
   # we MUST access gch as a global here, because this crosses DLL boundaries!
+  if isMultiThreaded: Lock(gch.cycleRootsLock)
   incl(gch.cycleRoots, c)
+  if isMultiThreaded: Unlock(gch.cycleRootsLock)
 
 proc rtlAddZCT(c: PCell) {.rtl, inl.} =
   # we MUST access gch as a global here, because this crosses DLL boundaries!
+  if isMultiThreaded: Lock(gch.zctLock)
   addZCT(gch.zct, c)
+  if isMultiThreaded: Unlock(gch.zctLock)
 
 proc decRef(c: PCell) {.inline.} =
   when stressGC:
     if c.refcount <% rcIncrement:
       writeCell("broken cell", c)
   assert(c.refcount >=% rcIncrement)
-  c.refcount = c.refcount -% rcIncrement
-  if c.refcount <% rcIncrement:
+  if atomicDec(c.refcount, rcIncrement) <% rcIncrement:
     rtlAddZCT(c)
   elif canBeCycleRoot(c):
     rtlAddCycleRoot(c) 
 
 proc incRef(c: PCell) {.inline.} = 
-  c.refcount = c.refcount +% rcIncrement
+  discard atomicInc(c.refcount, rcIncrement)
   if canBeCycleRoot(c):
     rtlAddCycleRoot(c)
 
@@ -228,11 +243,10 @@ proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerProc, inline.} =
   # cycle is possible.
   if src != nil: 
     var c = usrToCell(src)
-    c.refcount = c.refcount +% rcIncrement
+    discard atomicInc(c.refcount, rcIncrement)
   if dest^ != nil: 
     var c = usrToCell(dest^)
-    c.refcount = c.refcount -% rcIncrement
-    if c.refcount <% rcIncrement:
+    if atomicDec(c.refcount, rcIncrement) <% rcIncrement:
       rtlAddZCT(c)
   dest^ = src
 
@@ -260,6 +274,8 @@ proc initGC() =
     init(gch.tempStack)
     Init(gch.cycleRoots)
     Init(gch.decStack)
+    InitLock(gch.cycleRootsLock)
+    InitLock(gch.zctLock)
     new(gOutOfMem) # reserve space for the EOutOfMemory exception here!
 
 proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
@@ -310,6 +326,7 @@ proc checkCollection {.inline.} =
 
 proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
   # generates a new object and sets its reference counter to 0
+  lock(gch)
   assert(typ.kind in {tyRef, tyString, tySequence})
   checkCollection()
   var res = cast[PCell](rawAlloc(allocator, size + sizeof(TCell)))
@@ -337,15 +354,18 @@ proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
         break addToZCT
     add(gch.zct, res)
   when logGC: writeCell("new cell", res)
-  gcTrace(res, csAllocated)
+  gcTrace(res, csAllocated)  
+  unlock(gch)
   result = cellToUsr(res)
 
 proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
+  # `newObj` already uses locks, so no need for them here.
   result = newObj(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize))
   cast[PGenericSeq](result).len = len
   cast[PGenericSeq](result).space = len
 
 proc growObj(old: pointer, newsize: int): pointer {.rtl.} =
+  lock(gch)
   checkCollection()
   var ol = usrToCell(old)
   assert(ol.typ != nil)
@@ -383,6 +403,7 @@ proc growObj(old: pointer, newsize: int): pointer {.rtl.} =
   else:
     assert(ol.typ != nil)
     zeroMem(ol, sizeof(TCell))
+  unlock(gch)
   result = cellToUsr(res)
 
 # ---------------- cycle collector -------------------------------------------
@@ -632,9 +653,9 @@ proc collectCT(gch: var TGcHeap) =
     unmarkStackAndRegisters(gch)
 
 when not defined(useNimRtl):
-  proc GC_disable() = inc(recGcLock)
+  proc GC_disable() = discard atomicInc(recGcLock, 1)
   proc GC_enable() =
-    if recGcLock > 0: dec(recGcLock)
+    if recGcLock > 0: discard atomicDec(recGcLock, 1)
 
   proc GC_setStrategy(strategy: TGC_Strategy) =
     case strategy
@@ -651,10 +672,12 @@ when not defined(useNimRtl):
     # set to the max value to suppress the cycle detector
 
   proc GC_fullCollect() =
+    lock(gch)
     var oldThreshold = cycleThreshold
     cycleThreshold = 0 # forces cycle collection
     collectCT(gch)
     cycleThreshold = oldThreshold
+    unlock(gch)
 
   proc GC_getStatistics(): string =
     GC_disable()
diff --git a/lib/system/systhread.nim b/lib/system/systhread.nim
index 58482ac65..583cd2a43 100755
--- a/lib/system/systhread.nim
+++ b/lib/system/systhread.nim
@@ -15,6 +15,10 @@ when defined(gcc) or defined(llvm_gcc):
 elif defined(vcc):
   proc sync_add_and_fetch(p: var int, val: int): int {.
     importc: "NimXadd", nodecl.}
+else:
+  proc sync_add_and_fetch(p: var int, val: int): int {.inline.} =
+    inc(p, val)
+    result = p
 
 const
   isMultiThreaded* = true
@@ -37,12 +41,51 @@ proc atomicDec(memLoc: var int, x: int): int =
     dec(memLoc, x)
     result = memLoc  
   
+when defined(Windows):
+  type 
+    THandle = int
+    TSysLock {.final, pure.} = object # CRITICAL_SECTION in WinApi
+      DebugInfo: pointer
+      LockCount: int32
+      RecursionCount: int32
+      OwningThread: int
+      LockSemaphore: int
+      Reserved: int32
+  
+  proc InitLock(L: var TSysLock) {.stdcall,
+    dynlib: "kernel32", importc: "InitializeCriticalSection".}
+  proc Lock(L: var TSysLock) {.stdcall,
+    dynlib: "kernel32", importc: "EnterCriticalSection".}
+  proc Unlock(L: var TSysLock) {.stdcall,
+    dynlib: "kernel32", importc: "LeaveCriticalSection".}
+
+  proc CreateThread(lpThreadAttributes: Pointer, dwStackSize: int32,
+                     lpStartAddress: pointer, lpParameter: Pointer,
+                     dwCreationFlags: int32, lpThreadId: var int32): THandle {.
+    stdcall, dynlib: "kernel32", importc: "CreateThread".}
+
+  
+else:
+  type
+    TSysLock {.importc: "pthread_mutex_t", header: "<sys/types.h>".} = int
+    TSysThread {.importc: "pthread_t", header: "<sys/types.h>".} = int
+
+  proc InitLock(L: var TSysLock, attr: pointer = nil) {.
+    importc: "pthread_mutex_init", header: "<pthread.h>".}
+  proc Lock(L: var TSysLock) {.
+    importc: "pthread_mutex_lock", header: "<pthread.h>".}
+  proc Unlock(L: var TSysLock) {.
+    importc: "pthread_mutex_unlock", header: "<pthread.h>".}
+  
+  
 type
   TThread* {.final, pure.} = object
+    id: int
     next: ptr TThread
-  TThreadFunc* = proc (closure: pointer)
+  TThreadFunc* = proc (closure: pointer) {.cdecl.}
   
 proc createThread*(t: var TThread, fn: TThreadFunc) = 
+  
   nil
   
 proc destroyThread*(t: var TThread) =
@@ -50,4 +93,3 @@ proc destroyThread*(t: var TThread) =
 
 
 
-
diff --git a/rod/ast.nim b/rod/ast.nim
index 5b5676495..a2d35044e 100755
--- a/rod/ast.nim
+++ b/rod/ast.nim
@@ -31,8 +31,8 @@ type
 
 const 
   CallingConvToStr*: array[TCallingConvention, string] = ["", "stdcall", 
-    "cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "closure", 
-    "noconv"]
+    "cdecl", "safecall", "syscall", "inline", "noinline", "fastcall",
+    "closure", "noconv"]
 
 type 
   TNodeKind* = enum # order is extremely important, because ranges are used
@@ -329,8 +329,9 @@ type
     mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc, 
     mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor, 
     mNimrodMinor, mNimrodPatch, mCpuEndian, mHostOS, mHostCPU, mAppType, 
-    mNaN, mInf, 
-    mNegInf, mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, mNKind, 
+    mNaN, mInf, mNegInf, 
+    mCompileOption, mCompileOptionArg,
+    mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, mNKind, 
     mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal, 
     mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, 
     mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mIdentToStr, 
diff --git a/rod/ccgstmts.nim b/rod/ccgstmts.nim
index 88deb7f12..e60648184 100755
--- a/rod/ccgstmts.nim
+++ b/rod/ccgstmts.nim
@@ -27,21 +27,15 @@ proc genLineDir(p: BProc, t: PNode) =
     appf(p.s[cpsStmts], "F.line = $1;F.filename = $2;$n", 
         [toRope(line), makeCString(toFilename(t.info).extractFilename)])
 
-proc finishTryStmt(p: BProc, howMany: int) = 
+proc popSafePoints(p: BProc, howMany: int) = 
   for i in countup(1, howMany): 
-    inc(p.labels, 3)
-    appff(p.s[cpsStmts], "excHandler = excHandler->prev;$n", 
-        "%LOC$1 = load %TSafePoint** @excHandler$n" &
-        "%LOC$2 = getelementptr %TSafePoint* %LOC$1, %NI 0$n" &
-        "%LOC$3 = load %TSafePoint** %LOC$2$n" &
-        "store %TSafePoint* %LOC$3, %TSafePoint** @excHandler$n", 
-          [toRope(p.labels), toRope(p.labels - 1), toRope(p.labels - 2)])
+    appcg(p, cpsStmts, "#popSafePoint();$n", [])
 
 proc genReturnStmt(p: BProc, t: PNode) = 
   p.beforeRetNeeded = true
   genLineDir(p, t)
   if (t.sons[0] != nil): genStmts(p, t.sons[0])
-  finishTryStmt(p, p.nestedTryStmts)
+  popSafePoints(p, p.nestedTryStmts)
   appff(p.s[cpsStmts], "goto BeforeRet;$n", "br label %BeforeRet$n", [])
 
 proc genVarTuple(p: BProc, n: PNode) = 
@@ -202,7 +196,7 @@ proc genBreakStmt(p: BProc, t: PNode) =
     assert(sym.loc.k == locOther)
     idx = sym.loc.a
   p.blocks[idx].id = abs(p.blocks[idx].id) # label is used
-  finishTryStmt(p, p.nestedTryStmts - p.blocks[idx].nestedTryStmts)
+  popSafePoints(p, p.nestedTryStmts - p.blocks[idx].nestedTryStmts)
   appf(p.s[cpsStmts], "goto LA$1;$n", [toRope(p.blocks[idx].id)])
 
 proc genAsmStmt(p: BProc, t: PNode) = 
@@ -477,7 +471,7 @@ proc genTryStmtCpp(p: BProc, t: PNode) =
   #      {
   #         case DIVIDE_BY_ZERO:
   #           tmpRethrow = false;
-  #           printf('Division by Zero\n');
+  #           printf("Division by Zero\n");
   #         break;
   #      default: // used for general except!
   #         generalExceptPart();
@@ -526,8 +520,8 @@ proc genTryStmtCpp(p: BProc, t: PNode) =
     inc(i)
   if t.sons[1].kind == nkExceptBranch: 
     app(p.s[cpsStmts], "}}" & tnl) # end of catch-switch statement
+  popSafePoints(p, p.nestedTryStmts)
   dec(p.nestedTryStmts)
-  app(p.s[cpsStmts], "excHandler = excHandler->prev;" & tnl)
   if (i < length) and (t.sons[i].kind == nkFinally): 
     genStmts(p, t.sons[i].sons[0])
   if rethrowFlag != nil: 
@@ -536,38 +530,39 @@ proc genTryStmtCpp(p: BProc, t: PNode) =
 proc genTryStmt(p: BProc, t: PNode) = 
   # code to generate:
   #
-  #  sp.prev = excHandler;
-  #  excHandler = &sp;
+  #  TSafePoint sp;
+  #  pushSafePoint(&sp);
   #  sp.status = setjmp(sp.context);
   #  if (sp.status == 0) {
   #    myDiv(4, 9);
+  #    popSafePoint();
   #  } else {
+  #    popSafePoint();
   #    /* except DivisionByZero: */
   #    if (sp.status == DivisionByZero) {
   #      printf('Division by Zero\n');
-  #
-  #      /* longjmp(excHandler->context, RangeError); /* raise rangeError */
-  #      sp.status = RangeError; /* if raise; else 0 */
+  #      clearException();
+  #    } else {
+  #      clearException();
   #    }
   #  }
-  #  excHandler = excHandler->prev; /* deactivate this safe point */ 
   #  /* finally: */
   #  printf('fin!\n');
-  #  if (sp.status != 0)
-  #    longjmp(excHandler->context, sp.status);
+  #  if (exception not cleared)
+  #    propagateCurrentException();
   genLineDir(p, t)
   var safePoint = getTempName()
   discard cgsym(p.module, "E_Base")
   appcg(p, cpsLocals, "#TSafePoint $1;$n", [safePoint])
-  appcg(p, cpsStmts, "$1.prev = #excHandler;$n" & "excHandler = &$1;$n" &
-      "$1.status = setjmp($1.context);$n", [safePoint])
+  appcg(p, cpsStmts, "#pushSafePoint(&$1);$n" &
+        "$1.status = setjmp($1.context);$n", [safePoint])
   if optStackTrace in p.Options: 
     app(p.s[cpsStmts], "framePtr = (TFrame*)&F;" & tnl)
   appf(p.s[cpsStmts], "if ($1.status == 0) {$n", [safePoint])
   var length = sonsLen(t)
   inc(p.nestedTryStmts)
   genStmts(p, t.sons[0])
-  app(p.s[cpsStmts], "} else {" & tnl)
+  appcg(p, cpsStmts, "#popSafePoint();$n} else {$n#popSafePoint();$n")
   var i = 1
   while (i < length) and (t.sons[i].kind == nkExceptBranch): 
     var blen = sonsLen(t.sons[i])
@@ -575,27 +570,27 @@ proc genTryStmt(p: BProc, t: PNode) =
       # general except section:
       if i > 1: app(p.s[cpsStmts], "else {" & tnl)
       genStmts(p, t.sons[i].sons[0])
-      appf(p.s[cpsStmts], "$1.status = 0;$n", [safePoint])
+      appcg(p, cpsStmts, "$1.status = 0;#popCurrentException();$n", [safePoint])
       if i > 1: app(p.s[cpsStmts], '}' & tnl)
     else: 
       var orExpr: PRope = nil
       for j in countup(0, blen - 2): 
         assert(t.sons[i].sons[j].kind == nkType)
         if orExpr != nil: app(orExpr, "||")
-        appf(orExpr, "($1.exc->Sup.m_type == $2)", 
-             [safePoint, genTypeInfo(p.module, t.sons[i].sons[j].typ)])
+        appcg(p.module, orExpr, "#getCurrentException()->Sup.m_type == $1", 
+             [genTypeInfo(p.module, t.sons[i].sons[j].typ)])
       if i > 1: app(p.s[cpsStmts], "else ")
       appf(p.s[cpsStmts], "if ($1) {$n", [orExpr])
-      genStmts(p, t.sons[i].sons[blen - 1]) # code to clear the exception:
-      appf(p.s[cpsStmts], "$1.status = 0;}$n", [safePoint])
+      genStmts(p, t.sons[i].sons[blen-1]) 
+      # code to clear the exception:
+      appcg(p, cpsStmts, "$1.status = 0;#popCurrentException();}$n",
+           [safePoint])
     inc(i)
   app(p.s[cpsStmts], '}' & tnl) # end of if statement
-  finishTryStmt(p, p.nestedTryStmts)
   dec(p.nestedTryStmts)
-  if (i < length) and (t.sons[i].kind == nkFinally): 
+  if i < length and t.sons[i].kind == nkFinally: 
     genStmts(p, t.sons[i].sons[0])
-  appcg(p, cpsStmts, "if ($1.status != 0) { " &
-      "#raiseException($1.exc, $1.exc->name); }$n", [safePoint])
+  appcg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint])
 
 var 
   breakPointId: int = 0
diff --git a/rod/cgen.nim b/rod/cgen.nim
index 415eb1a9c..6d39623bb 100755
--- a/rod/cgen.nim
+++ b/rod/cgen.nim
@@ -193,7 +193,7 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: openarray[PRope]): PRope =
         while true: 
           j = (j * 10) + Ord(frmt[i]) - ord('0')
           inc(i)
-          if (i > length + 0 - 1) or not (frmt[i] in {'0'..'9'}): break 
+          if i >= length or not (frmt[i] in {'0'..'9'}): break 
         num = j
         if j > high(args) + 1: 
           internalError("ropes: invalid format string $" & $(j))
diff --git a/rod/commands.nim b/rod/commands.nim
index 706332447..b47bbf1bb 100755
--- a/rod/commands.nim
+++ b/rod/commands.nim
@@ -222,6 +222,54 @@ proc processCompile(filename: string) =
   extccomp.addExternalFileToCompile(found)
   extccomp.addFileToLink(completeCFilePath(trunc, false))
 
+proc testCompileOptionArg*(switch, arg: string, info: TLineInfo): bool = 
+  case whichKeyword(switch)
+  of wGC: 
+    case whichKeyword(arg)
+    of wBoehm: result = contains(gGlobalOptions, optBoehmGC)
+    of wRefc:  result = contains(gGlobalOptions, optRefcGC)
+    of wNone:  result = gGlobalOptions * {optBoehmGC, optRefcGC} == {}
+    else: liMessage(info, errNoneBoehmRefcExpectedButXFound, arg)
+  of wOpt: 
+    case whichKeyword(arg)
+    of wSpeed: result = contains(gOptions, optOptimizeSpeed)
+    of wSize: result = contains(gOptions, optOptimizeSize)
+    of wNone: result = gOptions * {optOptimizeSpeed, optOptimizeSize} == {}
+    else: liMessage(info, errNoneSpeedOrSizeExpectedButXFound, arg)
+  else: InvalidCmdLineOption(passCmd1, switch, info)
+
+proc testCompileOption*(switch: string, info: TLineInfo): bool = 
+  case whichKeyword(switch)
+  of wDebuginfo: result = contains(gGlobalOptions, optCDebug)
+  of wCompileOnly, wC: result = contains(gGlobalOptions, optCompileOnly)
+  of wNoLinking: result = contains(gGlobalOptions, optNoLinking)
+  of wNoMain: result = contains(gGlobalOptions, optNoMain)
+  of wForceBuild, wF: result = contains(gGlobalOptions, optForceFullMake)
+  of wWarnings, wW: result = contains(gOptions, optWarns)
+  of wHints: result = contains(gOptions, optHints)
+  of wCheckpoints: result = contains(gOptions, optCheckpoints)
+  of wStackTrace: result = contains(gOptions, optStackTrace)
+  of wLineTrace: result = contains(gOptions, optLineTrace)
+  of wDebugger: result = contains(gOptions, optEndb)
+  of wProfiler: result = contains(gOptions, optProfiler)
+  of wChecks, wX: result = gOptions * checksOptions == checksOptions
+  of wFloatChecks:
+    result = gOptions * {optNanCheck, optInfCheck} == {optNanCheck, optInfCheck}
+  of wInfChecks: result = contains(gOptions, optInfCheck)
+  of wNanChecks: result = contains(gOptions, optNanCheck)
+  of wObjChecks: result = contains(gOptions, optObjCheck)
+  of wFieldChecks: result = contains(gOptions, optFieldCheck)
+  of wRangeChecks: result = contains(gOptions, optRangeCheck)
+  of wBoundChecks: result = contains(gOptions, optBoundsCheck)
+  of wOverflowChecks: result = contains(gOptions, optOverflowCheck)
+  of wLineDir: result = contains(gOptions, optLineDir)
+  of wAssertions, wA: result = contains(gOptions, optAssert)
+  of wDeadCodeElim: result = contains(gGlobalOptions, optDeadCodeElim)
+  of wRun, wR: result = contains(gGlobalOptions, optRun)
+  of wSymbolFiles: result = contains(gGlobalOptions, optSymbolFiles)
+  of wGenScript: result = contains(gGlobalOptions, optGenScript)
+  else: InvalidCmdLineOption(passCmd1, switch, info)
+
 proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = 
   var 
     theOS: TSystemOS
diff --git a/rod/rodread.nim b/rod/rodread.nim
index ee295d122..3159ec961 100755
--- a/rod/rodread.nim
+++ b/rod/rodread.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -10,10 +10,8 @@
 # This module is responsible for loading of rod files.
 #
 #  Reading and writing binary files are really hard to debug. Therefore we use
-#  a special text format. ROD-files only describe the interface of a module.
-#  Thus they are smaller than the source files most of the time. Even if they
-#  are bigger, they are more efficient to process because symbols are only
-#  loaded on demand.
+#  a special text format. ROD-files are more efficient to process because
+#  symbols are only loaded on demand.
 #  It consists of:
 #
 #  - a header:
@@ -149,10 +147,10 @@ proc decodeBInt(r: PRodReader): biggestInt
 
 proc encode(s: string): PRope = 
   var res = ""
-  for i in countup(0, len(s) + 0 - 1): 
+  for i in countup(0, len(s) - 1): 
     case s[i]
     of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(res, s[i])
-    else: res = res & '\\' & toHex(ord(s[i]), 2)
+    else: add(res, '\\' & toHex(ord(s[i]), 2))
   result = toRope(res)
 
 proc encodeIntAux(str: var string, x: BiggestInt) = 
@@ -191,9 +189,6 @@ proc decodeLineInfo(r: PRodReader, info: var TLineInfo) =
         info = newLineInfo(r.files[decodeInt(r)], info.line, info.col)
 
 proc decodeNode(r: PRodReader, fInfo: TLineInfo): PNode = 
-  var 
-    id: int
-    fl: string
   result = nil
   if r.s[r.pos] == '(': 
     inc(r.pos)
@@ -207,7 +202,7 @@ proc decodeNode(r: PRodReader, fInfo: TLineInfo): PNode =
       result.flags = cast[TNodeFlags](int32(decodeInt(r)))
     if r.s[r.pos] == '^': 
       inc(r.pos)
-      id = decodeInt(r)
+      var id = decodeInt(r)
       result.typ = rrGetType(r, id, result.info)
     case result.kind
     of nkCharLit..nkInt64Lit: 
@@ -217,7 +212,7 @@ proc decodeNode(r: PRodReader, fInfo: TLineInfo): PNode =
     of nkFloatLit..nkFloat64Lit: 
       if r.s[r.pos] == '!': 
         inc(r.pos)
-        fl = decode(r)
+        var fl = decode(r)
         result.floatVal = parseFloat(fl)
     of nkStrLit..nkTripleStrLit: 
       if r.s[r.pos] == '!': 
@@ -228,14 +223,14 @@ proc decodeNode(r: PRodReader, fInfo: TLineInfo): PNode =
     of nkIdent: 
       if r.s[r.pos] == '!': 
         inc(r.pos)
-        fl = decode(r)
+        var fl = decode(r)
         result.ident = getIdent(fl)
       else: 
         internalError(result.info, "decodeNode: nkIdent")
     of nkSym: 
       if r.s[r.pos] == '!': 
         inc(r.pos)
-        id = decodeInt(r)
+        var id = decodeInt(r)
         result.sym = rrGetSym(r, id, result.info)
       else: 
         internalError(result.info, "decodeNode: nkSym")
@@ -282,7 +277,6 @@ proc decodeLoc(r: PRodReader, loc: var TLoc, info: TLineInfo) =
     else: InternalError(info, "decodeLoc " & r.s[r.pos])
   
 proc decodeType(r: PRodReader, info: TLineInfo): PType = 
-  var d: int
   result = nil
   if r.s[r.pos] == '[': 
     inc(r.pos)
@@ -335,7 +329,7 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
       else: InternalError(info, "decodeType ^(" & r.s[r.pos])
       addSon(result, nil)
     else: 
-      d = decodeInt(r)
+      var d = decodeInt(r)
       addSon(result, rrGetType(r, d, info))
 
 proc decodeLib(r: PRodReader, info: TLineInfo): PLib = 
@@ -470,8 +464,8 @@ proc decode(r: PRodReader): string =
     of '\\': 
       inc(i, 3)
       var xi = 0
-      hexChar(r.s[i - 2], xi)
-      hexChar(r.s[i - 1], xi)
+      hexChar(r.s[i-2], xi)
+      hexChar(r.s[i-1], xi)
       add(result, chr(xi))
     of 'a'..'z', 'A'..'Z', '0'..'9', '_': 
       add(result, r.s[i])
@@ -488,7 +482,7 @@ proc skipSection(r: PRodReader) =
     while true: 
       case r.s[r.pos]
       of '\x0A': inc(r.line)
-      of '(':  inc(c)
+      of '(': inc(c)
       of ')': 
         if c == 0: 
           inc(r.pos)
@@ -499,7 +493,7 @@ proc skipSection(r: PRodReader) =
       else: nil
       inc(r.pos)
   else: 
-    InternalError("skipSection " & $(r.line))
+    InternalError("skipSection " & $r.line)
   
 proc rdWord(r: PRodReader): string = 
   result = ""
@@ -530,18 +524,14 @@ proc processInterf(r: PRodReader, module: PSym) =
     IdTablePut(r.syms, s, s)
 
 proc processCompilerProcs(r: PRodReader, module: PSym) = 
-  var 
-    s: PSym
-    w: string
-    key: int
   if r.compilerProcsIdx == 0: InternalError("processCompilerProcs")
   r.pos = r.compilerProcsIdx
   while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'): 
-    w = decode(r)
+    var w = decode(r)
     inc(r.pos)
-    key = decodeInt(r)
+    var key = decodeInt(r)
     inc(r.pos)                # #10
-    s = PSym(IdTableGet(r.syms, key))
+    var s = PSym(IdTableGet(r.syms, key))
     if s == nil: 
       s = newStub(r, w, key)
       s.owner = module
@@ -572,24 +562,25 @@ proc processIndex(r: PRodReader, idx: var TIndex) =
   
 proc processRodFile(r: PRodReader, crc: TCrc32) = 
   var 
-    section, w: string
+    w: string
     d, L, inclCrc: int
   while r.s[r.pos] != '\0': 
-    section = rdWord(r)
+    var section = rdWord(r)
     if r.reason != rrNone: 
       break                   # no need to process this file further
-    if section == "CRC": 
+    case section 
+    of "CRC": 
       inc(r.pos)              # skip ':'
       if int(crc) != decodeInt(r): r.reason = rrCrcChange
-    elif section == "ID": 
+    of "ID": 
       inc(r.pos)              # skip ':'
       r.moduleID = decodeInt(r)
       setID(r.moduleID)
-    elif section == "OPTIONS": 
+    of "OPTIONS": 
       inc(r.pos)              # skip ':'
       r.options = cast[TOptions](int32(decodeInt(r)))
       if options.gOptions != r.options: r.reason = rrOptions
-    elif section == "DEFINES": 
+    of "DEFINES": 
       inc(r.pos)              # skip ':'
       d = 0
       while r.s[r.pos] > '\x0A': 
@@ -599,7 +590,7 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
           r.reason = rrDefines #MessageOut('not defined, but should: ' + w);
         if r.s[r.pos] == ' ': inc(r.pos)
       if (d != countDefinedSymbols()): r.reason = rrDefines
-    elif section == "FILES": 
+    of "FILES": 
       inc(r.pos, 2)           # skip "(\10"
       inc(r.line)
       L = 0
@@ -610,7 +601,7 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
         inc(r.line)
         inc(L)
       if r.s[r.pos] == ')': inc(r.pos)
-    elif section == "INCLUDES": 
+    of "INCLUDES": 
       inc(r.pos, 2)           # skip "(\10"
       inc(r.line)
       while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'): 
@@ -624,7 +615,7 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
           inc(r.pos)
           inc(r.line)
       if r.s[r.pos] == ')': inc(r.pos)
-    elif section == "DEPS": 
+    of "DEPS": 
       inc(r.pos)              # skip ':'
       L = 0
       while (r.s[r.pos] > '\x0A'): 
@@ -632,32 +623,32 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
         r.modDeps[L] = r.files[decodeInt(r)]
         inc(L)
         if r.s[r.pos] == ' ': inc(r.pos)
-    elif section == "INTERF": 
+    of "INTERF": 
       r.interfIdx = r.pos + 2
       skipSection(r)
-    elif section == "COMPILERPROCS": 
+    of "COMPILERPROCS": 
       r.compilerProcsIdx = r.pos + 2
       skipSection(r)
-    elif section == "INDEX": 
+    of "INDEX": 
       processIndex(r, r.index)
-    elif section == "IMPORTS": 
+    of "IMPORTS": 
       processIndex(r, r.imports)
-    elif section == "CONVERTERS": 
+    of "CONVERTERS": 
       r.convertersIdx = r.pos + 1
       skipSection(r)
-    elif section == "DATA": 
+    of "DATA": 
       r.dataIdx = r.pos + 2 # "(\10"
       # We do not read the DATA section here! We read the needed objects on
       # demand.
       skipSection(r)
-    elif section == "INIT": 
+    of "INIT": 
       r.initIdx = r.pos + 2   # "(\10"
       skipSection(r)
-    elif section == "CGEN": 
+    of "CGEN": 
       r.cgenIdx = r.pos + 2
       skipSection(r)
     else: 
-      MessageOut("skipping section: " & $(r.pos))
+      MessageOut("skipping section: " & $r.pos)
       skipSection(r)
     if r.s[r.pos] == '\x0A': 
       inc(r.pos)
@@ -686,7 +677,7 @@ proc newRodReader(modfilename: string, crc: TCrc32,
       inc(r.pos)
     if r.s[r.pos] == '\x0A': inc(r.pos)
     if version == FileVersion: 
-      # since ROD files are only for caching, no backwarts compability is
+      # since ROD files are only for caching, no backwarts compatibility is
       # needed
       processRodFile(r, crc)
     else: 
@@ -814,7 +805,8 @@ proc checkDep(filename: string): TReasonForRecompile =
         for i in countup(0, high(r.modDeps)): 
           res = checkDep(r.modDeps[i])
           if res != rrNone: 
-            result = rrModDeps #break // BUGFIX: cannot break here!
+            result = rrModDeps 
+            # we cannot break here, because of side-effects of `checkDep`
   else: 
     result = rrRodDoesNotExist
   if (result != rrNone) and (gVerbosity > 0): 
diff --git a/rod/rodwrite.nim b/rod/rodwrite.nim
index 370ebc314..ea427dce9 100755
--- a/rod/rodwrite.nim
+++ b/rod/rodwrite.nim
@@ -70,8 +70,8 @@ proc fileIdx(w: PRodWriter, filename: string): int =
 
 proc newRodWriter(modfilename: string, crc: TCrc32, module: PSym): PRodWriter = 
   new(result)
-  result.sstack = @ []
-  result.tstack = @ []
+  result.sstack = @[]
+  result.tstack = @[]
   InitIITable(result.index.tab)
   InitIITable(result.imports.tab)
   result.filename = modfilename
@@ -79,7 +79,7 @@ proc newRodWriter(modfilename: string, crc: TCrc32, module: PSym): PRodWriter =
   result.module = module
   result.defines = getDefines()
   result.options = options.gOptions
-  result.files = @ []
+  result.files = @[]
 
 proc addModDep(w: PRodWriter, dep: string) = 
   if w.modDeps != nil: app(w.modDeps, " ")
@@ -284,11 +284,10 @@ proc symStack(w: PRodWriter) =
   setlen(w.sstack, 0)
 
 proc typeStack(w: PRodWriter) = 
-  var i, L: int
-  i = 0
+  var i = 0
   while i < len(w.tstack): 
     if IiTableGet(w.index.tab, w.tstack[i].id) == invalidKey: 
-      L = ropeLen(w.data)
+      var L = ropeLen(w.data)
       addToIndex(w.index, w.tstack[i].id, L)
       app(w.data, encodeType(w, w.tstack[i]))
       app(w.data, rodNL)
@@ -317,9 +316,8 @@ proc addStmt(w: PRodWriter, n: PNode) =
   processStacks(w)
 
 proc writeRod(w: PRodWriter) = 
-  var content: PRope
   processStacks(w)            # write header:
-  content = toRope("NIM:")
+  var content = toRope("NIM:")
   app(content, toRope(FileVersion))
   app(content, rodNL)
   app(content, toRope("ID:"))
@@ -373,43 +371,39 @@ proc writeRod(w: PRodWriter) =
   writeRope(content, completeGeneratedFilePath(changeFileExt(w.filename, "rod")))
 
 proc process(c: PPassContext, n: PNode): PNode = 
-  var 
-    w: PRodWriter
-    a: PNode
-    s: PSym
   result = n
   if c == nil: return 
-  w = PRodWriter(c)
+  var w = PRodWriter(c)
   case n.kind
   of nkStmtList: 
     for i in countup(0, sonsLen(n) - 1): discard process(c, n.sons[i])
   of nkTemplateDef, nkMacroDef: 
-    s = n.sons[namePos].sym
+    var s = n.sons[namePos].sym
     addInterfaceSym(w, s)
   of nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef: 
-    s = n.sons[namePos].sym
+    var s = n.sons[namePos].sym
     if s == nil: InternalError(n.info, "rodwrite.process")
     if (n.sons[codePos] != nil) or (s.magic != mNone) or
         not (sfForward in s.flags): 
       addInterfaceSym(w, s)
   of nkVarSection: 
     for i in countup(0, sonsLen(n) - 1): 
-      a = n.sons[i]
+      var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
       if a.kind != nkIdentDefs: InternalError(a.info, "rodwrite.process")
       addInterfaceSym(w, a.sons[0].sym)
   of nkConstSection: 
     for i in countup(0, sonsLen(n) - 1): 
-      a = n.sons[i]
+      var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
       if a.kind != nkConstDef: InternalError(a.info, "rodwrite.process")
       addInterfaceSym(w, a.sons[0].sym)
   of nkTypeSection: 
     for i in countup(0, sonsLen(n) - 1): 
-      a = n.sons[i]
+      var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
       if a.sons[0].kind != nkSym: InternalError(a.info, "rodwrite.process")
-      s = a.sons[0].sym
+      var s = a.sons[0].sym
       addInterfaceSym(w, s) 
       # this takes care of enum fields too
       # Note: The check for ``s.typ.kind = tyEnum`` is wrong for enum
diff --git a/rod/semfold.nim b/rod/semfold.nim
index a4de04e4f..a447ac66f 100755
--- a/rod/semfold.nim
+++ b/rod/semfold.nim
@@ -12,7 +12,8 @@
 
 import 
   strutils, lists, options, ast, astalgo, trees, treetab, nimsets, times, 
-  nversion, platform, math, msgs, os, condsyms, idents, rnimsyn, types
+  nversion, platform, math, msgs, os, condsyms, idents, rnimsyn, types,
+  commands
 
 proc getConstExpr*(m: PSym, n: PNode): PNode
   # evaluates the constant expression or returns nil if it is no constant
@@ -194,6 +195,11 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
   of mArrToSeq: 
     result = copyTree(a)
     result.typ = n.typ
+  of mCompileOption:
+    result = newIntNodeT(Ord(commands.testCompileOption(getStr(a), n.info)), n)  
+  of mCompileOptionArg:
+    result = newIntNodeT(Ord(
+      testCompileOptionArg(getStr(a), getStr(b), n.info)), n)
   of mNewString, mExit, mInc, ast.mDec, mEcho, mAssert, mSwap, mAppendStrCh, 
      mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq, 
      mNLen..mNError, mEqRef: 
diff --git a/tests/accept/run/tcontinuexc.nim b/tests/accept/run/tcontinuexc.nim
new file mode 100644
index 000000000..97b190e3c
--- /dev/null
+++ b/tests/accept/run/tcontinuexc.nim
@@ -0,0 +1,21 @@
+type
+  ESomething = object of E_Base
+  ESomeOtherErr = object of E_Base
+
+proc genErrors(s: string) =
+  if s == "error!":
+    raise newException(ESomething, "Test")
+  else:
+    raise newException(EsomeotherErr, "bla")
+
+try:
+  for i in 0..3:
+    try:
+      genErrors("error!")
+    except ESomething:
+      echo("Error happened")
+    echo "came here"
+    raise newException(EsomeotherErr, "bla")
+finally:  
+  echo "caught"
+
diff --git a/tests/accept/run/toverflw2.nim b/tests/accept/run/toverflw2.nim
new file mode 100755
index 000000000..b54bda9fa
--- /dev/null
+++ b/tests/accept/run/toverflw2.nim
@@ -0,0 +1,5 @@
+var a : int32 = 2147483647
+var b : int32 = 2147483647
+var c = a + b
+
+
diff --git a/tinyc/config_edited.h b/tinyc/config_edited.h
index ceb34f784..edaf335bb 100755
--- a/tinyc/config_edited.h
+++ b/tinyc/config_edited.h
@@ -6,6 +6,11 @@
 #  define TCC_TARGET_PE   1
 #  define TCC_TARGET_I386

 #  define CONFIG_TCCDIR "."

+#elif defined(__i386__)
+#  define TCC_TARGET_I386
+#  define CONFIG_TCCDIR "/usr/local/lib/tcc"
+#  define GCC_MAJOR 4
+#  define HOST_I386 1
 #else
 #  define TCC_TARGET_X86_64
 #  define CONFIG_TCCDIR "/usr/local/lib/tcc"
diff --git a/todo.txt b/todo.txt
index e752e5862..22529feb6 100755
--- a/todo.txt
+++ b/todo.txt
@@ -1,10 +1,8 @@
 For version 0.8.10
 ==================
 
-- exception propagation across DLLs
-- fix exception handling
 - fix implicit generic routines
-- fix the streams implementation so that they use methods
+- fix the streams implementation so that it uses methods
 
 
 High priority (version 0.9.0)
diff --git a/tools/buildsh.tmpl b/tools/buildsh.tmpl
index f67330514..cdfdbf2c1 100755
--- a/tools/buildsh.tmpl
+++ b/tools/buildsh.tmpl
@@ -33,6 +33,9 @@ case $uos in
   *darwin* ) 
     myos="macosx"
     LINK_FLAGS="$LINK_FLAGS -ldl -lm"
+    if [ `sysctl hw |grep 64bit` = "hw.cpu64bit_capable: 1" ] ; then
+      ucpu="amd64"
+    fi
     ;;
   *aix* )
     myos="aix"
diff --git a/web/news.txt b/web/news.txt
index ec136b66f..e806c23f7 100755
--- a/web/news.txt
+++ b/web/news.txt
@@ -15,9 +15,10 @@ Bugfixes
 - Bugfix: ``system.splitChunk`` still contained code for debug output.
 - Bugfix: ``dialogs.ChooseFileToSave`` uses ``STOCK_SAVE`` instead of 
   ``STOCK_OPEN`` for the GTK backend.
-- Bugfix: ``raise`` within an exception handler did not work.
+- Bugfix: Various bugs concerning exception handling fixed.
 - Bugfix: ``low(somestring)`` crashed the compiler.
 - Bugfix: ``strutils.endsWith`` lacked range checking.
+- Bugfix: Better detection for AMD64 on Mac OS X. 
 
 
 Changes affecting backwards compatibility
@@ -48,6 +49,7 @@ Additions
 - Added ``system.reopen``. 
 - Added ``system.getCurrentException``.
 - Added ``system.appType``.
+- Added ``system.compileOption``. 
 - Added ``times.epochTime`` and ``times.cpuTime``. 
 - Implemented explicit type arguments for generics.
 - Implemented implicit type arguments for generics.