summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorArne Döring <arne.doering@gmx.net>2018-10-24 13:10:44 +0200
committerAndreas Rumpf <rumpf_a@web.de>2018-10-24 13:10:44 +0200
commiteb6225ad8ce0f0d7e7ca834045ed71c2fc457745 (patch)
treebfb20f5cc0db718b83ed85e6cffe9705a133ffa2 /compiler
parent16d82c82e37cfdc17b063e32f042e85b5d1122e2 (diff)
downloadNim-eb6225ad8ce0f0d7e7ca834045ed71c2fc457745.tar.gz
fixes #9276 (#9317)
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ccgstmts.nim83
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)