diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 1f21b275a..4d52e3aab 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -292,6 +292,57 @@ proc genReturnStmt(p: BProc, t: PNode) = blockLeaveActions(p, min(1, p.nestedTryStmts.len)) lineFF(p, cpsStmts, "goto BeforeRet;$n", "br label %BeforeRet$n", []) +proc genComputedGoto(p: BProc; n: PNode) = + # first pass: Generate array of computed labels: + var casePos = -1 + var arraySize: Int + for i in 0 .. 10_000: + localError(it.info, + "case statement has too many cases for computed goto"); return + arraySize = aSize.int + if firstOrd(it.sons[0].typ) != 0: + localError(it.info, + "case statement has to start at 0 for computed goto"); return + if casePos < 0: + localError(n.info, "no case statement found for computed goto"); return + var id = p.labels+1 + inc p.labels, arraySize+1 + let tmp = ropef("TMP$1", id.toRope) + var gotoArray = ropef("static void* $#[$#] = {", tmp, arraySize.toRope) + for i in 1..arraySize-1: + gotoArray.appf("&&TMP$#, ", (id+i).toRope) + gotoArray.appf("&&TMP$#};$n", (id+arraySize).toRope) + line(p, cpsLocals, gotoArray) + + let caseStmt = n.sons[casePos] + var a: TLoc + initLocExpr(p, caseStmt.sons[0], a) + # first goto: + lineF(p, cpsStmts, "goto *$#[$#];$n", tmp, a.rdLoc) + + for i in 1 ..