mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-06 13:07:48 +00:00
threads compile again; attempt to fix serious code gen issue (except + return)
This commit is contained in:
@@ -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])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user