diff options
author | Arne Döring <arne.doering@gmx.net> | 2018-10-24 13:10:44 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2018-10-24 13:10:44 +0200 |
commit | eb6225ad8ce0f0d7e7ca834045ed71c2fc457745 (patch) | |
tree | bfb20f5cc0db718b83ed85e6cffe9705a133ffa2 /compiler | |
parent | 16d82c82e37cfdc17b063e32f042e85b5d1122e2 (diff) | |
download | Nim-eb6225ad8ce0f0d7e7ca834045ed71c2fc457745.tar.gz |
fixes #9276 (#9317)
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ccgstmts.nim | 83 |
1 files changed, 52 insertions, 31 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 6c2e8ebc8..907b56dac 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -400,6 +400,16 @@ proc genGotoForCase(p: BProc; caseStmt: PNode) = genStmts(p, it.lastSon) endBlock(p) + +iterator fieldValuePairs(n: PNode): tuple[memberSym, valueSym: PNode] = + assert(n.kind in {nkLetSection, nkVarSection}) + for identDefs in n: + if identDefs.kind == nkIdentDefs: + let valueSym = identDefs[^1] + for i in 0 ..< identDefs.len-2: + let memberSym = identDefs[i] + yield((memberSym: memberSym, valueSym: valueSym)) + proc genComputedGoto(p: BProc; n: PNode) = # first pass: Generate array of computed labels: var casePos = -1 @@ -429,22 +439,12 @@ proc genComputedGoto(p: BProc; n: PNode) = let tmp = "TMP$1_" % [id.rope] var gotoArray = "static void* $#[$#] = {" % [tmp, arraySize.rope] for i in 1..arraySize-1: - gotoArray.addf("&&TMP$#_, ", [(id+i).rope]) - gotoArray.addf("&&TMP$#_};$n", [(id+arraySize).rope]) + gotoArray.addf("&&TMP$#_, ", [rope(id+i)]) + gotoArray.addf("&&TMP$#_};$n", [rope(id+arraySize)]) line(p, cpsLocals, gotoArray) - let topBlock = p.blocks.len-1 - let oldBody = p.blocks[topBlock].sections[cpsStmts] - p.blocks[topBlock].sections[cpsStmts] = nil - - for j in casePos+1 ..< n.len: genStmts(p, n.sons[j]) - let tailB = p.blocks[topBlock].sections[cpsStmts] - - p.blocks[topBlock].sections[cpsStmts] = nil - for j in 0 .. casePos-1: genStmts(p, n.sons[j]) - let tailA = p.blocks[topBlock].sections[cpsStmts] - - p.blocks[topBlock].sections[cpsStmts] = oldBody & tailA + for j in 0 ..< casePos: + genStmts(p, n.sons[j]) let caseStmt = n.sons[casePos] var a: TLoc @@ -459,19 +459,40 @@ proc genComputedGoto(p: BProc; n: PNode) = if it.sons[j].kind == nkRange: localError(p.config, it.info, "range notation not available for computed goto") return + let val = getOrdValue(it.sons[j]) lineF(p, cpsStmts, "TMP$#_:$n", [intLiteral(val+id+1)]) + genStmts(p, it.lastSon) - #for j in casePos+1 ..< n.len: genStmts(p, n.sons[j]) # tailB - #for j in 0 .. casePos-1: genStmts(p, n.sons[j]) # tailA - add(p.s(cpsStmts), tailB) - add(p.s(cpsStmts), tailA) + + for j in casePos+1 ..< n.sons.len: + genStmts(p, n.sons[j]) + + for j in 0 ..< casePos: + # prevent new local declarations + # compile declarations as assignments + let it = n.sons[j] + if it.kind in {nkLetSection, nkVarSection}: + let asgn = copyNode(it) + asgn.kind = nkAsgn + asgn.sons.setLen 2 + for sym, value in it.fieldValuePairs: + if value.kind != nkEmpty: + asgn.sons[0] = sym + asgn.sons[1] = value + genStmts(p, asgn) + else: + genStmts(p, it) var a: TLoc initLocExpr(p, caseStmt.sons[0], a) lineF(p, cpsStmts, "goto *$#[$#];$n", [tmp, a.rdLoc]) endBlock(p) + for j in casePos+1 ..< n.sons.len: + genStmts(p, n.sons[j]) + + proc genWhileStmt(p: BProc, t: PNode) = # we don't generate labels here as for example GCC would produce # significantly worse code @@ -482,26 +503,26 @@ proc genWhileStmt(p: BProc, t: PNode) = genLineDir(p, t) preserveBreakIdx: - p.breakIdx = startBlock(p, "while (1) {$n") - p.blocks[p.breakIdx].isLoop = true - initLocExpr(p, t.sons[0], a) - if (t.sons[0].kind != nkIntLit) or (t.sons[0].intVal == 0): - let label = assignLabel(p.blocks[p.breakIdx]) - lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), label]) var loopBody = t.sons[1] if loopBody.stmtsContainPragma(wComputedGoto) and - hasComputedGoto in CC[p.config.cCompiler].props: - # for closure support weird loop bodies are generated: + hasComputedGoto in CC[p.config.cCompiler].props: + # for closure support weird loop bodies are generated: if loopBody.len == 2 and loopBody.sons[0].kind == nkEmpty: loopBody = loopBody.sons[1] - genComputedGoto(p, loopBody) + genComputedGoto(p, loopBody) # TODO foobar else: + p.breakIdx = startBlock(p, "while (1) {$n") + p.blocks[p.breakIdx].isLoop = true + initLocExpr(p, t.sons[0], a) + if (t.sons[0].kind != nkIntLit) or (t.sons[0].intVal == 0): + let label = assignLabel(p.blocks[p.breakIdx]) + lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), label]) genStmts(p, loopBody) - if optProfiler in p.options: - # invoke at loop body exit: - linefmt(p, cpsStmts, "#nimProfile();$n") - endBlock(p) + if optProfiler in p.options: + # invoke at loop body exit: + linefmt(p, cpsStmts, "#nimProfile();$n") + endBlock(p) dec(p.withinLoop) |