From 728328eec2064ed2086b230c09db063268d064fd Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 3 Dec 2011 19:22:01 +0100 Subject: threads compile again; attempt to fix serious code gen issue (except + return) --- compiler/ccgstmts.nim | 18 ++++++++++++------ compiler/cgendata.nim | 2 ++ lib/system/channels.nim | 18 +++++++++--------- lib/system/threads.nim | 4 ++-- 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: -- cgit 1.4.1-2-gfad0