threads compile again; attempt to fix serious code gen issue (except + return)

This commit is contained in:
Araq 2011-12-03 19:22:01 +01:00
commit 728328eec2
4 changed files with 25 additions and 17 deletions

View file

@ -117,7 +117,7 @@ proc genIfStmt(p: BProc, n: PNode) =
else: internalError(n.info, "genIfStmt()") else: internalError(n.info, "genIfStmt()")
if sonsLen(n) > 1: fixLabel(p, Lend) if sonsLen(n) > 1: fixLabel(p, Lend)
proc popSafePoints(p: BProc, howMany: int) = proc blockLeaveActions(p: BProc, howMany: int) =
var L = p.nestedTryStmts.len var L = p.nestedTryStmts.len
# danger of endless recursion! we workaround this here by a temp stack # danger of endless recursion! we workaround this here by a temp stack
var stack: seq[PNode] var stack: seq[PNode]
@ -134,10 +134,12 @@ proc popSafePoints(p: BProc, howMany: int) =
# push old elements again: # push old elements again:
for i in countdown(howMany-1, 0): for i in countdown(howMany-1, 0):
p.nestedTryStmts.add(stack[i]) p.nestedTryStmts.add(stack[i])
for i in countdown(p.popCurrExc-1, 0):
appcg(p, cpsStmts, "#popCurrentException();$n", [])
proc genReturnStmt(p: BProc, t: PNode) = proc genReturnStmt(p: BProc, t: PNode) =
p.beforeRetNeeded = true p.beforeRetNeeded = true
popSafePoints(p, min(1, p.nestedTryStmts.len)) blockLeaveActions(p, min(1, p.nestedTryStmts.len))
genLineDir(p, t) genLineDir(p, t)
if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0]) if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])
appff(p.s[cpsStmts], "goto BeforeRet;$n", "br label %BeforeRet$n", []) 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) assert(sym.loc.k == locOther)
idx = sym.loc.a idx = sym.loc.a
p.blocks[idx].id = abs(p.blocks[idx].id) # label is used 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) genLineDir(p, t)
appf(p.s[cpsStmts], "goto LA$1;$n", [toRope(p.blocks[idx].id)]) 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) add(p.nestedTryStmts, t)
genStmts(p, t.sons[0]) genStmts(p, t.sons[0])
appcg(p, cpsStmts, "#popSafePoint();$n} else {$n#popSafePoint();$n") appcg(p, cpsStmts, "#popSafePoint();$n} else {$n#popSafePoint();$n")
discard pop(p.nestedTryStmts)
var i = 1 var i = 1
while (i < length) and (t.sons[i].kind == nkExceptBranch): while (i < length) and (t.sons[i].kind == nkExceptBranch):
var blen = sonsLen(t.sons[i]) var blen = sonsLen(t.sons[i])
if blen == 1: if blen == 1:
# general except section: # general except section:
if i > 1: appf(p.s[cpsStmts], "else {$n") if i > 1: appf(p.s[cpsStmts], "else {$n")
inc p.popCurrExc
genStmts(p, t.sons[i].sons[0]) genStmts(p, t.sons[i].sons[0])
dec p.popCurrExc
appcg(p, cpsStmts, "$1.status = 0;#popCurrentException();$n", [safePoint]) appcg(p, cpsStmts, "$1.status = 0;#popCurrentException();$n", [safePoint])
if i > 1: appf(p.s[cpsStmts], "}$n") if i > 1: appf(p.s[cpsStmts], "}$n")
else: else:
inc p.popCurrExc
var orExpr: PRope = nil var orExpr: PRope = nil
for j in countup(0, blen - 2): for j in countup(0, blen - 2):
assert(t.sons[i].sons[j].kind == nkType) assert(t.sons[i].sons[j].kind == nkType)
@ -530,12 +536,12 @@ proc genTryStmt(p: BProc, t: PNode) =
if i > 1: app(p.s[cpsStmts], "else ") if i > 1: app(p.s[cpsStmts], "else ")
appf(p.s[cpsStmts], "if ($1) {$n", [orExpr]) 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: # code to clear the exception:
appcg(p, cpsStmts, "$1.status = 0;#popCurrentException();}$n", appcg(p, cpsStmts, "$1.status = 0;#popCurrentException();}$n",
[safePoint]) [safePoint])
inc(i) inc(i)
appf(p.s[cpsStmts], "}$n") # end of if statement appf(p.s[cpsStmts], "}$n") # end of if statement
discard pop(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]) genStmts(p, t.sons[i].sons[0])
appcg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint]) appcg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint])

View file

@ -60,6 +60,8 @@ type
ThreadVarAccessed*: bool # true if the proc already accessed some threadvar ThreadVarAccessed*: bool # true if the proc already accessed some threadvar
nestedTryStmts*: seq[PNode] # in how many nested try statements we are nestedTryStmts*: seq[PNode] # in how many nested try statements we are
# (the vars must be volatile then) # (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 labels*: Natural # for generating unique labels in the C proc
blocks*: seq[TBlock] # nested blocks blocks*: seq[TBlock] # nested blocks
options*: TOptions # options that should be used for code options*: TOptions # options that should be used for code

View file

@ -62,14 +62,14 @@ proc storeAux(dest, src: Pointer, n: ptr TNimNode, t: PRawChannel,
n.typ.size) n.typ.size)
var m = selectBranch(src, n) var m = selectBranch(src, n)
if m != nil: storeAux(dest, src, m, t, mode) 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, proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
mode: TLoadStoreMode) = mode: TLoadStoreMode) =
var var
d = cast[TAddress](dest) d = cast[TAddress](dest)
s = cast[TAddress](src) s = cast[TAddress](src)
sysAssert(mt != nil) sysAssert(mt != nil, "mt == nil")
case mt.Kind case mt.Kind
of tyString: of tyString:
if mode == mStore: if mode == mStore:
@ -100,7 +100,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
else: else:
unsureAsgnRef(x, nil) unsureAsgnRef(x, nil)
else: else:
sysAssert(dest != nil) sysAssert(dest != nil, "dest == nil")
if mode == mStore: if mode == mStore:
x[] = Alloc(t.region, seq.len *% mt.base.size +% GenericSeqSize) x[] = Alloc(t.region, seq.len *% mt.base.size +% GenericSeqSize)
else: else:

View file

@ -221,7 +221,7 @@ when not defined(useNimRtl):
t.prev = nil t.prev = nil
t.next = threadList t.next = threadList
if threadList != nil: if threadList != nil:
sysAssert(threadList.prev == nil) sysAssert(threadList.prev == nil, "threadList.prev == nil")
threadList.prev = t threadList.prev = t
threadList = t threadList = t
ReleaseSys(HeapLock) ReleaseSys(HeapLock)
@ -315,7 +315,7 @@ proc joinThreads*[TArg](t: openArray[TThread[TArg]]) =
## waits for every thread in `t` to finish. ## waits for every thread in `t` to finish.
when hostOS == "windows": when hostOS == "windows":
var a: array[0..255, TSysThread] 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 for i in 0..t.high: a[i] = t[i].sys
discard WaitForMultipleObjects(t.len, cast[ptr TSysThread](addr(a)), 1, -1) discard WaitForMultipleObjects(t.len, cast[ptr TSysThread](addr(a)), 1, -1)
else: else: