diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ccgstmts.nim | 61 | ||||
-rw-r--r-- | compiler/condsyms.nim | 2 | ||||
-rw-r--r-- | compiler/msgs.nim | 3 | ||||
-rw-r--r-- | compiler/pragmas.nim | 7 | ||||
-rw-r--r-- | compiler/vm.nim | 6 | ||||
-rw-r--r-- | compiler/wordrecg.nim | 4 |
6 files changed, 71 insertions, 12 deletions
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 .. <n.len: + let it = n.sons[i] + if it.kind == nkCaseStmt: + if lastSon(it).kind != nkOfBranch: + localError(it.info, + "case statement must be exhaustive for computed goto"); return + casePos = i + let aSize = lengthOrd(it.sons[0].typ) + if aSize > 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 .. <caseStmt.len: + let it = caseStmt.sons[i] + for j in 0 .. it.len-2: + if it.sons[j].kind == nkRange: + localError(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)) + for j in 0 .. casePos-1: genStmts(p, n.sons[j]) + genStmts(p, it.lastSon) + for j in casePos+1 .. <n.len: genStmts(p, n.sons[j]) + var a: TLoc + initLocExpr(p, caseStmt.sons[0], a) + lineF(p, cpsStmts, "goto *$#[$#];$n", tmp, a.rdLoc) + proc genWhileStmt(p: BProc, t: PNode) = # we don't generate labels here as for example GCC would produce # significantly worse code @@ -309,7 +360,15 @@ proc genWhileStmt(p: BProc, t: PNode) = 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, t.sons[1]) + var loopBody = t.sons[1] + if loopBody.stmtsContainPragma(wComputedGoto) and + hasComputedGoto in CC[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) + else: + genStmts(p, loopBody) if optProfiler in p.options: # invoke at loop body exit: diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index b8d6a5ce7..21095072b 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -46,7 +46,7 @@ proc InitDefines*() = DefineSymbol("nimmixin") DefineSymbol("nimeffects") DefineSymbol("nimbabel") - DefineSymbol("nimsuperops") + DefineSymbol("nimcomputedgoto") # add platform specific symbols: case targetCPU diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 73481940c..3e5304358 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -774,6 +774,9 @@ proc GlobalError*(info: TLineInfo, arg: string) = proc LocalError*(info: TLineInfo, msg: TMsgKind, arg = "") = liMessage(info, msg, arg, doNothing) +proc LocalError*(info: TLineInfo, arg: string) = + liMessage(info, errGenerated, arg, doNothing) + proc Message*(info: TLineInfo, msg: TMsgKind, arg = "") = liMessage(info, msg, arg, doNothing) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index a11739f95..f185d0f80 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -42,7 +42,7 @@ const wFatal, wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop, wBreakpoint, wWatchpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated, wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, - wLinearScanEnd, wPatterns, wEffects, wNoForward} + wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto} lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wDeprecated, wExtern, wThread, wImportcpp, wImportobjc, wNoStackFrame, @@ -446,9 +446,6 @@ proc PragmaUnroll(c: PContext, n: PNode) = else: invalidPragma(n) -proc PragmaLinearScanEnd(c: PContext, n: PNode) = - noVal(n) - proc PragmaLine(c: PContext, n: PNode) = if n.kind == nkExprColonExpr: n.sons[1] = c.semConstExpr(c, n.sons[1]) @@ -691,7 +688,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, else: sym.typ.callConv = wordToCallConv(k) of wEmit: PragmaEmit(c, it) of wUnroll: PragmaUnroll(c, it) - of wLinearScanEnd: PragmaLinearScanEnd(c, it) + of wLinearScanEnd, wComputedGoto: noVal(it) of wEffects: # is later processed in effect analysis: noVal(it) diff --git a/compiler/vm.nim b/compiler/vm.nim index 37f13990f..b02de405e 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -54,8 +54,8 @@ proc bailOut(c: PCtx; tos: PStackFrame) = stackTrace(c, tos, c.exceptionInstr, errUnhandledExceptionX, c.currentExceptionA.sons[2].strVal) -when not defined(nimHasInterpreterLoop): - {.pragma: interpreterLoop.} +when not defined(nimComputedGoto): + {.pragma: computedGoto.} template inc(pc: ptr TInstr, diff = 1) = inc cast[TAddress](pc), TInstr.sizeof * diff @@ -237,7 +237,7 @@ proc execute(c: PCtx, start: int) = var tos: PStackFrame newSeq(regs, c.prc.maxSlots) while true: - {.interpreterLoop.} + {.computedGoto.} let instr = c.code[pc] let ra = instr.regA #echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index 06607d2a6..a9540269c 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -59,7 +59,7 @@ type wPassc, wPassl, wBorrow, wDiscardable, wFieldChecks, wWatchPoint, wSubsChar, - wAcyclic, wShallow, wUnroll, wLinearScanEnd, + wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, wNoStackFrame, wImplicitStatic, wGlobal, wCodegenDecl, @@ -140,7 +140,7 @@ const "compiletime", "noinit", "passc", "passl", "borrow", "discardable", "fieldchecks", "watchpoint", - "subschar", "acyclic", "shallow", "unroll", "linearscanend", + "subschar", "acyclic", "shallow", "unroll", "linearscanend", "computedgoto", "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit", "nostackframe", "implicitstatic", "global", "codegendecl", |