summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xcompiler/ccgstmts.nim18
-rw-r--r--compiler/cgendata.nim2
-rwxr-xr-xlib/system/channels.nim18
-rwxr-xr-xlib/system/threads.nim4
4 files changed, 25 insertions, 17 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index da9a05188..a994f27f3 100755
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -117,7 +117,7 @@ proc genIfStmt(p: BProc, n: PNode) =
     else: internalError(n.info, "genIfStmt()")
   if sonsLen(n) > 1: fixLabel(p, Lend)
   
-proc popSafePoints(p: BProc, howMany: int) = 
+proc blockLeaveActions(p: BProc, howMany: int) = 
   var L = p.nestedTryStmts.len
   # danger of endless recursion! we workaround this here by a temp stack
   var stack: seq[PNode]
@@ -134,10 +134,12 @@ proc popSafePoints(p: BProc, howMany: int) =
   # push old elements again:
   for i in countdown(howMany-1, 0): 
     p.nestedTryStmts.add(stack[i])
+  for i in countdown(p.popCurrExc-1, 0):
+    appcg(p, cpsStmts, "#popCurrentException();$n", [])
 
 proc genReturnStmt(p: BProc, t: PNode) = 
   p.beforeRetNeeded = true
-  popSafePoints(p, min(1, p.nestedTryStmts.len))
+  blockLeaveActions(p, min(1, p.nestedTryStmts.len))
   genLineDir(p, t)
   if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])
   appff(p.s[cpsStmts], "goto BeforeRet;$n", "br label %BeforeRet$n", [])
@@ -196,7 +198,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
-  popSafePoints(p, p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts)
+  blockLeaveActions(p, p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts)
   genLineDir(p, t)
   appf(p.s[cpsStmts], "goto LA$1;$n", [toRope(p.blocks[idx].id)])
 
@@ -510,16 +512,20 @@ proc genTryStmt(p: BProc, t: PNode) =
   add(p.nestedTryStmts, t)
   genStmts(p, t.sons[0])
   appcg(p, cpsStmts, "#popSafePoint();$n} else {$n#popSafePoint();$n")
+  discard pop(p.nestedTryStmts)
   var i = 1
   while (i < length) and (t.sons[i].kind == nkExceptBranch): 
     var blen = sonsLen(t.sons[i])
     if blen == 1: 
       # general except section:
       if i > 1: appf(p.s[cpsStmts], "else {$n")
+      inc p.popCurrExc
       genStmts(p, t.sons[i].sons[0])
+      dec p.popCurrExc
       appcg(p, cpsStmts, "$1.status = 0;#popCurrentException();$n", [safePoint])
       if i > 1: appf(p.s[cpsStmts], "}$n")
-    else: 
+    else:
+      inc p.popCurrExc
       var orExpr: PRope = nil
       for j in countup(0, blen - 2): 
         assert(t.sons[i].sons[j].kind == nkType)
@@ -529,13 +535,13 @@ proc genTryStmt(p: BProc, t: PNode) =
               [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]) 
+      genStmts(p, t.sons[i].sons[blen-1])
+      dec p.popCurrExc
       # code to clear the exception:
       appcg(p, cpsStmts, "$1.status = 0;#popCurrentException();}$n",
            [safePoint])
     inc(i)
   appf(p.s[cpsStmts], "}$n") # end of if statement
-  discard pop(p.nestedTryStmts)
   if i < length and t.sons[i].kind == nkFinally: 
     genStmts(p, t.sons[i].sons[0])
   appcg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint])
diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim
index 260032f3e..54e1f5d1a 100644
--- a/compiler/cgendata.nim
+++ b/compiler/cgendata.nim
@@ -60,6 +60,8 @@ type
     ThreadVarAccessed*: bool  # true if the proc already accessed some threadvar
     nestedTryStmts*: seq[PNode] # in how many nested try statements we are
                                 # (the vars must be volatile then)
+    popCurrExc*: Natural      # how often to emit 'popCurrentException()'
+                              # before 'break'|'return'
     labels*: Natural          # for generating unique labels in the C proc
     blocks*: seq[TBlock]      # nested blocks
     options*: TOptions        # options that should be used for code
diff --git a/lib/system/channels.nim b/lib/system/channels.nim
index c2456c9c1..4a37bcc14 100755
--- a/lib/system/channels.nim
+++ b/lib/system/channels.nim
@@ -25,7 +25,7 @@ type
     ready: bool

     region: TMemRegion

   PRawChannel = ptr TRawChannel

-  TLoadStoreMode = enum mStore, mLoad
+  TLoadStoreMode = enum mStore, mLoad

   TChannel*[TMsg] = TRawChannel ## a channel for thread communication

 

 const ChannelDeadMask = -2

@@ -45,7 +45,7 @@ proc deinitRawChannel(p: pointer) =
   deinitSys(c.lock)

   deinitSysCond(c.cond)

 

-proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel, 
+proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel, 

               mode: TLoadStoreMode)

 proc storeAux(dest, src: Pointer, n: ptr TNimNode, t: PRawChannel,

               mode: TLoadStoreMode) =

@@ -62,14 +62,14 @@ proc storeAux(dest, src: Pointer, n: ptr TNimNode, t: PRawChannel,
             n.typ.size)

     var m = selectBranch(src, n)

     if m != nil: storeAux(dest, src, m, t, mode)

-  of nkNone: sysAssert(false)

+  of nkNone: sysAssert(false, "storeAux")

 

 proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel, 

               mode: TLoadStoreMode) =

   var

     d = cast[TAddress](dest)

     s = cast[TAddress](src)

-  sysAssert(mt != nil)

+  sysAssert(mt != nil, "mt == nil")

   case mt.Kind

   of tyString:

     if mode == mStore:

@@ -100,7 +100,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
       else:

         unsureAsgnRef(x, nil)

     else:

-      sysAssert(dest != nil)

+      sysAssert(dest != nil, "dest == nil")

       if mode == mStore:

         x[] = Alloc(t.region, seq.len *% mt.base.size +% GenericSeqSize)

       else:

@@ -140,8 +140,8 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
       if mode == mStore:

         x[] = Alloc(t.region, mt.base.size)

       else:

-        # XXX we should use the dynamic type here too, but that is not stored
-        # in the inbox at all --> use source[]'s object type? but how? we need
+        # XXX we should use the dynamic type here too, but that is not stored

+        # in the inbox at all --> use source[]'s object type? but how? we need

         # a tyRef to the object!

         var obj = newObj(mt.base, mt.base.size)

         unsureAsgnRef(x, obj)

@@ -237,8 +237,8 @@ proc close*[TMsg](c: var TChannel[TMsg]) =
   deinitRawChannel(addr(c))

 

 proc ready*[TMsg](c: var TChannel[TMsg]): bool =

-  ## returns true iff some thread is waiting on the channel `c` for
+  ## returns true iff some thread is waiting on the channel `c` for

   ## new messages.

   var q = cast[PRawChannel](addr(c))

   result = q.ready

-
+

diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index 7c26cf8ee..08184acce 100755
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -221,7 +221,7 @@ when not defined(useNimRtl):
       t.prev = nil
       t.next = threadList
       if threadList != nil: 
-        sysAssert(threadList.prev == nil)
+        sysAssert(threadList.prev == nil, "threadList.prev == nil")
         threadList.prev = t
       threadList = t
       ReleaseSys(HeapLock)
@@ -315,7 +315,7 @@ proc joinThreads*[TArg](t: openArray[TThread[TArg]]) =
   ## waits for every thread in `t` to finish.
   when hostOS == "windows":
     var a: array[0..255, TSysThread]
-    sysAssert a.len >= t.len
+    sysAssert a.len >= t.len, "a.len >= t.len"
     for i in 0..t.high: a[i] = t[i].sys
     discard WaitForMultipleObjects(t.len, cast[ptr TSysThread](addr(a)), 1, -1)
   else: