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 | |
parent | 16d82c82e37cfdc17b063e32f042e85b5d1122e2 (diff) | |
download | Nim-eb6225ad8ce0f0d7e7ca834045ed71c2fc457745.tar.gz |
fixes #9276 (#9317)
-rwxr-xr-x[-rw-r--r--] | bin/nim-gdb | 0 | ||||
-rw-r--r-- | compiler/ccgstmts.nim | 83 | ||||
-rw-r--r-- | koch.nim | 7 | ||||
-rw-r--r-- | tests/casestmt/tcomputedgoto.nim | 9 | ||||
-rw-r--r-- | tools/nim-gdb.py | 19 |
5 files changed, 84 insertions, 34 deletions
diff --git a/bin/nim-gdb b/bin/nim-gdb index e7b41094d..e7b41094d 100644..100755 --- a/bin/nim-gdb +++ b/bin/nim-gdb 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) diff --git a/koch.nim b/koch.nim index a77f5cc3a..8e84ac5fa 100644 --- a/koch.nim +++ b/koch.nim @@ -407,13 +407,14 @@ proc temp(args: string) = result[1].add " " & quoteShell(args[i]) inc i - var output = "compiler" / "nim".exe - var finalDest = "bin" / "nim_temp".exe + let d = getAppDir() + var output = d / "compiler" / "nim".exe + var finalDest = d / "bin" / "nim_temp".exe # 125 is the magic number to tell git bisect to skip the current # commit. let (bootArgs, programArgs) = splitArgs(args) let nimexec = findNim() - exec(nimexec & " c -d:debug --debugger:native " & bootArgs & " compiler" / "nim", 125) + exec(nimexec & " c -d:debug --debugger:native " & bootArgs & " " & (d / "compiler" / "nim"), 125) copyExe(output, finalDest) if programArgs.len > 0: exec(finalDest & " " & programArgs) diff --git a/tests/casestmt/tcomputedgoto.nim b/tests/casestmt/tcomputedgoto.nim index 58ef3caa4..f7603dac3 100644 --- a/tests/casestmt/tcomputedgoto.nim +++ b/tests/casestmt/tcomputedgoto.nim @@ -1,16 +1,22 @@ discard """ output: ''' yeah A enumB +uneven yeah A enumB yeah CD enumD +uneven yeah CD enumE yeah A enumB +uneven yeah CD enumE yeah CD enumD +uneven yeah A enumB yeah B enumC +uneven yeah A enumB yeah A enumB +uneven yeah A enumB ''' """ @@ -47,4 +53,7 @@ proc vm() = of enumLast: discard inc(pc) + if pc mod 2 == 1: + echo "uneven" + vm() diff --git a/tools/nim-gdb.py b/tools/nim-gdb.py index b98dc96fe..1a0d89fcb 100644 --- a/tools/nim-gdb.py +++ b/tools/nim-gdb.py @@ -209,6 +209,25 @@ class NimStringPrinter: else: return "" +class NimRopePrinter: + pattern = re.compile(r'^tyObject_RopeObj_OFzf0kSiPTcNreUIeJgWVA \*$') + + def __init__(self, val): + self.val = val + + def display_hint(self): + return 'string' + + def to_string(self): + if self.val: + left = NimRopePrinter(self.val["left"]).to_string() + data = NimStringPrinter(self.val["data"]).to_string() + right = NimRopePrinter(self.val["right"]).to_string() + return left + data + right + else: + return "" + + ################################################################################ # proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} = |