diff options
author | Araq <rumpf_a@web.de> | 2013-08-22 08:38:47 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-08-22 08:38:47 +0200 |
commit | 6f1fc1b5ba7f74fde21467f5f0bfd294ad9292f3 (patch) | |
tree | 1bc09471b81b6b0b1a9830e4d0858a21cb248a78 | |
parent | 50403afb5c8d49f2d9046498ea714251a3e4ad90 (diff) | |
download | Nim-6f1fc1b5ba7f74fde21467f5f0bfd294ad9292f3.tar.gz |
fixed and documented computedGoto pragma
-rw-r--r-- | compiler/ccgstmts.nim | 5 | ||||
-rw-r--r-- | compiler/nimsets.nim | 27 | ||||
-rw-r--r-- | compiler/vm.nim | 1 | ||||
-rw-r--r-- | compiler/vmgen.nim | 42 | ||||
-rw-r--r-- | doc/manual.txt | 45 | ||||
-rw-r--r-- | doc/nimrodc.txt | 2 | ||||
-rw-r--r-- | tests/compile/tcomputedgoto.nim | 5 | ||||
-rw-r--r-- | web/news.txt | 2 |
8 files changed, 94 insertions, 35 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 4d52e3aab..01c734524 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -322,6 +322,7 @@ proc genComputedGoto(p: BProc; n: PNode) = gotoArray.appf("&&TMP$#};$n", (id+arraySize).toRope) line(p, cpsLocals, gotoArray) + for j in 0 .. casePos-1: genStmts(p, n.sons[j]) let caseStmt = n.sons[casePos] var a: TLoc initLocExpr(p, caseStmt.sons[0], a) @@ -329,6 +330,7 @@ proc genComputedGoto(p: BProc; n: PNode) = lineF(p, cpsStmts, "goto *$#[$#];$n", tmp, a.rdLoc) for i in 1 .. <caseStmt.len: + startBlock(p) let it = caseStmt.sons[i] for j in 0 .. it.len-2: if it.sons[j].kind == nkRange: @@ -336,12 +338,13 @@ proc genComputedGoto(p: BProc; n: PNode) = 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]) + for j in 0 .. casePos-1: genStmts(p, n.sons[j]) var a: TLoc initLocExpr(p, caseStmt.sons[0], a) lineF(p, cpsStmts, "goto *$#[$#];$n", tmp, a.rdLoc) + endBlock(p) proc genWhileStmt(p: BProc, t: PNode) = # we don't generate labels here as for example GCC would produce diff --git a/compiler/nimsets.nim b/compiler/nimsets.nim index f874ccdca..34f79e14b 100644 --- a/compiler/nimsets.nim +++ b/compiler/nimsets.nim @@ -117,32 +117,17 @@ proc ToTreeSet(s: TBitSet, settype: PType, info: TLineInfo): PNode = e = b Inc(e) -type - TSetOP = enum - soUnion, soDiff, soSymDiff, soIntersect - -proc nodeSetOp(a, b: PNode, op: TSetOp): PNode = +template nodeSetOp(a, b: PNode, op: expr) {.dirty.} = var x, y: TBitSet toBitSet(a, x) toBitSet(b, y) - case op - of soUnion: BitSetUnion(x, y) - of soDiff: BitSetDiff(x, y) - of soSymDiff: BitSetSymDiff(x, y) - of soIntersect: BitSetIntersect(x, y) + op(x, y) result = toTreeSet(x, a.typ, a.info) -proc unionSets(a, b: PNode): PNode = - result = nodeSetOp(a, b, soUnion) - -proc diffSets(a, b: PNode): PNode = - result = nodeSetOp(a, b, soDiff) - -proc intersectSets(a, b: PNode): PNode = - result = nodeSetOp(a, b, soIntersect) - -proc symdiffSets(a, b: PNode): PNode = - result = nodeSetOp(a, b, soSymDiff) +proc unionSets(a, b: PNode): PNode = nodeSetOp(a, b, BitSetUnion) +proc diffSets(a, b: PNode): PNode = nodeSetOp(a, b, BitSetDiff) +proc intersectSets(a, b: PNode): PNode = nodeSetOp(a, b, BitSetIntersect) +proc symdiffSets(a, b: PNode): PNode = nodeSetOp(a, b, BitSetSymDiff) proc containsSets(a, b: PNode): bool = var x, y: TBitSet diff --git a/compiler/vm.nim b/compiler/vm.nim index b02de405e..c0ce047ea 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -352,7 +352,6 @@ proc execute(c: PCtx, start: int) = if not inSet(regs[ra], regs[rb]): addSon(regs[ra], copyTree(regs[rb])) of opcExcl: decodeB(nkCurly) - # XXX arg we need types here :-( var b = newNodeIT(nkCurly, regs[rb].info, regs[rb].typ) addSon(b, regs[rb]) var r = diffSets(regs[ra], b) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index f7df31c0c..fc356018a 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -439,6 +439,22 @@ proc genBinaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) = c.freeTemp(tmp) c.freeTemp(tmp2) +proc genSetType(c: PCtx; n: PNode; dest: TRegister) = + let t = skipTypes(n.typ, abstractInst) + if t.kind == tySet: + c.gABx(n, opcSetType, dest, c.genType(t)) + +proc genBinarySet(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) = + let + tmp = c.genx(n.sons[1]) + tmp2 = c.genx(n.sons[2]) + if dest < 0: dest = c.getTemp(n.typ) + c.genSetType(n.sons[1], tmp) + c.genSetType(n.sons[2], tmp2) + c.gABC(n, opc, dest, tmp, tmp2) + c.freeTemp(tmp) + c.freeTemp(tmp2) + proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) = let dest = c.genx(n.sons[1]) @@ -488,6 +504,13 @@ proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) = c.gABx(n, opc, 0, genType(c, n.typ)) c.freeTemp(tmp) +proc genCard(c: PCtx; n: PNode; dest: var TDest) = + let tmp = c.genx(n.sons[1]) + if dest < 0: dest = c.getTemp(n.typ) + c.genSetType(n.sons[1], tmp) + c.gABC(n, opc, dest, tmp) + c.freeTemp(tmp) + proc genMagic(c: PCtx; n: PNode; dest: var TDest) = let m = n.sons[0].sym.magic case m @@ -532,10 +555,11 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) = unused(n, dest) var d = c.genx(n.sons[1]) var tmp = c.genx(n.sons[2]) + c.genSetType(n.sons[1], d) c.gABC(n, if m == mIncl: opcIncl else: opcExcl, d, tmp) c.freeTemp(d) c.freeTemp(tmp) - of mCard: genUnaryABC(c, n, dest, opcCard) + of mCard: genCard(c, n, dest) of mMulI, mMulI64: genBinaryABC(c, n, dest, opcMulInt) of mDivI, mDivI64: genBinaryABC(c, n, dest, opcDivInt) of mModI, mModI64: genBinaryABC(c, n, dest, opcModInt) @@ -580,15 +604,15 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) = of mEqStr: genBinaryABC(c, n, dest, opcEqStr) of mLeStr: genBinaryABC(c, n, dest, opcLeStr) of mLtStr: genBinaryABC(c, n, dest, opcLtStr) - of mEqSet: genBinaryABC(c, n, dest, opcEqSet) - of mLeSet: genBinaryABC(c, n, dest, opcLeSet) - of mLtSet: genBinaryABC(c, n, dest, opcLtSet) - of mMulSet: genBinaryABC(c, n, dest, opcMulSet) - of mPlusSet: genBinaryABC(c, n, dest, opcPlusSet) - of mMinusSet: genBinaryABC(c, n, dest, opcMinusSet) - of mSymDiffSet: genBinaryABC(c, n, dest, opcSymdiffSet) + of mEqSet: genBinarySet(c, n, dest, opcEqSet) + of mLeSet: genBinarySet(c, n, dest, opcLeSet) + of mLtSet: genBinarySet(c, n, dest, opcLtSet) + of mMulSet: genBinarySet(c, n, dest, opcMulSet) + of mPlusSet: genBinarySet(c, n, dest, opcPlusSet) + of mMinusSet: genBinarySet(c, n, dest, opcMinusSet) + of mSymDiffSet: genBinarySet(c, n, dest, opcSymdiffSet) of mConStrStr: genVarargsABC(c, n, dest, opcConcatStr) - of mInSet: genBinaryABC(c, n, dest, opcContainsSet) + of mInSet: genBinarySet(c, n, dest, opcContainsSet) of mRepr: genUnaryABC(c, n, dest, opcRepr) of mExit: unused(n, dest) diff --git a/doc/manual.txt b/doc/manual.txt index 5fdc5a884..d2fc7e5c9 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -4561,6 +4561,51 @@ tested against via linear scanning. If put into the last branch of the whole ``case`` statement, the whole ``case`` statement uses linear scanning. +computedGoto pragma +------------------- +The `computedGoto`:idx: pragma can be used to tell the compiler how to +compile a Nimrod `case`:idx: in a ``while true`` statement. +Syntactically it has to be used as a statement inside the loop: + +.. code-block:: nimrod + + type + MyEnum = enum + enumA, enumB, enumC, enumD, enumE + + proc vm() = + var instructions: array [0..100, MyEnum] + instructions[2] = enumC + instructions[3] = enumD + instructions[4] = enumA + instructions[5] = enumD + instructions[6] = enumC + instructions[7] = enumA + instructions[8] = enumB + + instructions[12] = enumE + var pc = 0 + while true: + {.computedGoto.} + let instr = instructions[pc] + case instr + of enumA: + echo "yeah A" + of enumC, enumD: + echo "yeah CD" + of enumB: + echo "yeah B" + of enumE: + break + inc(pc) + + vm() + +As the example shows ``computedGoto`` is mostly useful for interpreters. If +the underlying backend (C compiler) does not support the computed goto +extension the pragma is simply ignored. + + unroll pragma ------------- The `unroll`:idx: pragma can be used to tell the compiler that it should unroll diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt index 5e2bfb09b..dd320019f 100644 --- a/doc/nimrodc.txt +++ b/doc/nimrodc.txt @@ -488,7 +488,7 @@ in C/C++). Nimrod idetools integration -======================= +=========================== Nimrod provides language integration with external IDEs through the idetools command. See the documentation of `idetools <idetools.html>`_ diff --git a/tests/compile/tcomputedgoto.nim b/tests/compile/tcomputedgoto.nim index 661f70743..2c3b4bbd4 100644 --- a/tests/compile/tcomputedgoto.nim +++ b/tests/compile/tcomputedgoto.nim @@ -31,7 +31,8 @@ proc vm() = var pc = 0 while true: {.computedGoto.} - case instructions[pc] + let instr = instructions[pc] + case instr of enumA: echo "yeah A" of enumC, enumD: @@ -39,7 +40,7 @@ proc vm() = of enumB: echo "yeah B" of enumE: - return + break inc(pc) vm() diff --git a/web/news.txt b/web/news.txt index 56919d56c..896cf9941 100644 --- a/web/news.txt +++ b/web/news.txt @@ -37,6 +37,8 @@ Compiler Additions - The compiler now enforces the ``not nil`` constraint. - The compiler now supports a ``codegenDecl`` pragma for even more control over the generated code. +- The compiler now supports a ``computedGoto`` pragma to support very fast + dispatching for interpreters and the like. Language Additions |