diff options
author | Araq <rumpf_a@web.de> | 2018-03-30 02:32:29 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2018-03-30 02:32:29 +0200 |
commit | a9691aeef513ea20a9b1735f37172a1bd66a80dd (patch) | |
tree | 2d0de165d9907a3a8a4b56cea5bb33a3fb201465 /compiler | |
parent | 9de05ec3e04e8a2321b29896fe9fa7db4c6e65f3 (diff) | |
parent | 325d76b56a5b26ba2d5ce065574eb6ef736eb179 (diff) | |
download | Nim-a9691aeef513ea20a9b1735f37172a1bd66a80dd.tar.gz |
Merge branch 'devel' of github.com:nim-lang/Nim into devel
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ccgstmts.nim | 40 | ||||
-rw-r--r-- | compiler/cgendata.nim | 9 |
2 files changed, 23 insertions, 26 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 8a54708ee..f6c4204e8 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -37,6 +37,10 @@ proc isAssignedImmediately(n: PNode): bool {.inline.} = return false result = true +proc inExceptBlockLen(p: BProc): int = + for x in p.nestedTryStmts: + if x.inExcept: result.inc + proc genVarTuple(p: BProc, n: PNode) = var tup, field: TLoc if n.kind != nkVarTuple: internalError(n.info, "genVarTuple") @@ -96,7 +100,7 @@ proc startBlock(p: BProc, start: FormatStr = "{$n", setLen(p.blocks, result + 1) p.blocks[result].id = p.labels p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16 - p.blocks[result].nestedExceptStmts = p.inExceptBlock.int16 + p.blocks[result].nestedExceptStmts = p.inExceptBlockLen.int16 proc assignLabel(b: var TBlock): Rope {.inline.} = b.label = "LA" & b.id.rope @@ -344,26 +348,22 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) = # Called by return and break stmts. # Deals with issues faced when jumping out of try/except/finally stmts, - var stack: seq[PNode] - newSeq(stack, 0) + var stack = newSeq[tuple[n: PNode, inExcept: bool]](0) - var alreadyPoppedCnt = p.inExceptBlock for i in countup(1, howManyTrys): + let tryStmt = p.nestedTryStmts.pop if not p.module.compileToCpp or optNoCppExceptions in gGlobalOptions: # Pop safe points generated by try - if alreadyPoppedCnt > 0: - dec alreadyPoppedCnt - else: + if not tryStmt.inExcept: linefmt(p, cpsStmts, "#popSafePoint();$n") # Pop this try-stmt of the list of nested trys # so we don't infinite recurse on it in the next step. - var tryStmt = p.nestedTryStmts.pop stack.add(tryStmt) # Find finally-stmt for this try-stmt # and generate a copy of its sons - var finallyStmt = lastSon(tryStmt) + var finallyStmt = lastSon(tryStmt.n) if finallyStmt.kind == nkFinally: genStmts(p, finallyStmt.sons[0]) @@ -384,7 +384,7 @@ proc genReturnStmt(p: BProc, t: PNode) = if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0]) blockLeaveActions(p, howManyTrys = p.nestedTryStmts.len, - howManyExcepts = p.inExceptBlock) + howManyExcepts = p.inExceptBlockLen) if (p.finallySafePoints.len > 0): # If we're in a finally block, and we came here by exception # consume it before we return. @@ -567,15 +567,15 @@ proc genBreakStmt(p: BProc, t: PNode) = let label = assignLabel(p.blocks[idx]) blockLeaveActions(p, p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts, - p.inExceptBlock - p.blocks[idx].nestedExceptStmts) + p.inExceptBlockLen - p.blocks[idx].nestedExceptStmts) genLineDir(p, t) lineF(p, cpsStmts, "goto $1;$n", [label]) proc genRaiseStmt(p: BProc, t: PNode) = - if p.inExceptBlock > 0 and p.inExceptBlock == p.nestedTryStmts.len: + if p.nestedTryStmts.len > 0 and p.nestedTryStmts[^1].inExcept: # if the current try stmt have a finally block, # we must execute it before reraising - var finallyBlock = p.nestedTryStmts[p.nestedTryStmts.len - 1].lastSon + var finallyBlock = p.nestedTryStmts[^1].n[^1] if finallyBlock.kind == nkFinally: genSimpleBlock(p, finallyBlock.sons[0]) if t.sons[0].kind != nkEmpty: @@ -812,14 +812,14 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = let end_label = getLabel(p) discard cgsym(p.module, "Exception") - add(p.nestedTryStmts, t) + add(p.nestedTryStmts, (t, false)) startBlock(p, "try {$n") expr(p, t[0], d) endBlock(p) var catchAllPresent = false - inc p.inExceptBlock + p.nestedTryStmts[^1].inExcept = true for i in 1..<t.len: if t[i].kind != nkExceptBranch: break @@ -839,6 +839,8 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = genExceptBranchBody(t[i][^1]) # exception handler body will duplicated for every type endBlock(p) + discard pop(p.nestedTryStmts) + if not catchAllPresent and t[^1].kind == nkFinally: # finally requires catch all presence startBlock(p, "catch (...) {$n") @@ -846,9 +848,6 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = line(p, cpsStmts, ~"throw;$n") endBlock(p) - dec p.inExceptBlock - discard pop(p.nestedTryStmts) - if t[^1].kind == nkFinally: genSimpleBlock(p, t[^1][0]) @@ -902,7 +901,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) = linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint) startBlock(p, "if ($1.status == 0) {$n", [safePoint]) var length = sonsLen(t) - add(p.nestedTryStmts, t) + add(p.nestedTryStmts, (t, false)) expr(p, t.sons[0], d) linefmt(p, cpsStmts, "#popSafePoint();$n") endBlock(p) @@ -910,7 +909,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) = linefmt(p, cpsStmts, "#popSafePoint();$n") if optStackTrace in p.options: linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR_);$n") - inc p.inExceptBlock + p.nestedTryStmts[^1].inExcept = true var i = 1 while (i < length) and (t.sons[i].kind == nkExceptBranch): # bug #4230: avoid false sharing between branches: @@ -941,7 +940,6 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) = linefmt(p, cpsStmts, "#popCurrentException();$n") endBlock(p) inc(i) - dec p.inExceptBlock discard pop(p.nestedTryStmts) endBlock(p) # end of else block if i < length and t.sons[i].kind == nkFinally: diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index 0f8fa760e..efa346934 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -70,11 +70,10 @@ type threadVarAccessed*: bool # true if the proc already accessed some threadvar lastLineInfo*: TLineInfo # to avoid generating excessive 'nimln' statements currLineInfo*: TLineInfo # AST codegen will make this superfluous - nestedTryStmts*: seq[PNode] # in how many nested try statements we are - # (the vars must be volatile then) - inExceptBlock*: int # are we currently inside an except block? - # leaving such scopes by raise or by return must - # execute any applicable finally blocks + nestedTryStmts*: seq[tuple[n: PNode, inExcept: bool]] + # in how many nested try statements we are + # (the vars must be volatile then) + # bool is true when are in the except part of a try block finallySafePoints*: seq[Rope] # For correctly cleaning up exceptions when # using return in finally statements labels*: Natural # for generating unique labels in the C proc |