computed goto now works; some progress on the new VM

This commit is contained in:
Araq 2013-10-25 13:30:34 +02:00
commit 6ea538cec3
5 changed files with 53 additions and 23 deletions

View file

@ -323,7 +323,19 @@ proc genComputedGoto(p: BProc; n: PNode) =
gotoArray.appf("&&TMP$#};$n", (id+arraySize).toRope) gotoArray.appf("&&TMP$#};$n", (id+arraySize).toRope)
line(p, cpsLocals, gotoArray) 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]) for j in 0 .. casePos-1: genStmts(p, n.sons[j])
let tailA = p.blocks[topBlock].sections[cpsStmts]
p.blocks[topBlock].sections[cpsStmts] = oldBody.con(tailA)
let caseStmt = n.sons[casePos] let caseStmt = n.sons[casePos]
var a: TLoc var a: TLoc
initLocExpr(p, caseStmt.sons[0], a) initLocExpr(p, caseStmt.sons[0], a)
@ -340,8 +352,11 @@ proc genComputedGoto(p: BProc; n: PNode) =
let val = getOrdValue(it.sons[j]) let val = getOrdValue(it.sons[j])
lineF(p, cpsStmts, "TMP$#:$n", intLiteral(val+id+1)) lineF(p, cpsStmts, "TMP$#:$n", intLiteral(val+id+1))
genStmts(p, it.lastSon) genStmts(p, it.lastSon)
for j in casePos+1 .. <n.len: genStmts(p, n.sons[j]) #for j in casePos+1 .. <n.len: genStmts(p, n.sons[j]) # tailB
for j in 0 .. casePos-1: genStmts(p, n.sons[j]) #for j in 0 .. casePos-1: genStmts(p, n.sons[j]) # tailA
app(p.s(cpsStmts), tailB)
app(p.s(cpsStmts), tailA)
var a: TLoc var a: TLoc
initLocExpr(p, caseStmt.sons[0], a) initLocExpr(p, caseStmt.sons[0], a)
lineF(p, cpsStmts, "goto *$#[$#];$n", tmp, a.rdLoc) lineF(p, cpsStmts, "goto *$#[$#];$n", tmp, a.rdLoc)

View file

@ -10,8 +10,10 @@
## This file implements the new evaluation engine for Nimrod code. ## This file implements the new evaluation engine for Nimrod code.
## An instruction is 1-2 int32s in memory, it is a register based VM. ## An instruction is 1-2 int32s in memory, it is a register based VM.
import ast except getstr
import import
strutils, ast, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned, strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned,
parser, vmdeps, idents, trees, renderer parser, vmdeps, idents, trees, renderer
from semfold import leValueConv, ordinalValToString from semfold import leValueConv, ordinalValToString
@ -131,7 +133,7 @@ proc asgnComplex(x, y: PNode) =
for i in countup(0, sonsLen(y) - 1): addSon(x, y.sons[i]) for i in countup(0, sonsLen(y) - 1): addSon(x, y.sons[i])
template getstr(a: expr): expr = template getstr(a: expr): expr =
(if a.kind == nkStrLit: a.strVal else: $chr(int(a.intVal))) (if a.kind in {nkStrLit..nkTripleStrLit}: a.strVal else: $chr(int(a.intVal)))
proc pushSafePoint(f: PStackFrame; pc: int) = proc pushSafePoint(f: PStackFrame; pc: int) =
if f.safePoints.isNil: f.safePoints = @[] if f.safePoints.isNil: f.safePoints = @[]
@ -669,8 +671,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
of opcSetLenStr: of opcSetLenStr:
decodeB(nkStrLit) decodeB(nkStrLit)
regs[ra].strVal.setLen(regs[rb].getOrdValue.int) regs[ra].strVal.setLen(regs[rb].getOrdValue.int)
of opcOf:
decodeBC(nkIntLit)
regs[ra].intVal = ord(inheritanceDiff(regs[rb].typ, regs[rc].typ) >= 0)
of opcSetLenSeq, of opcSetLenSeq,
opcSwap, opcIsNil, opcOf, opcSwap, opcIsNil,
opcCast, opcReset: opcCast, opcReset:
internalError(c.debug[pc], "too implement") internalError(c.debug[pc], "too implement")
of opcNBindSym: of opcNBindSym:
@ -868,6 +873,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
regs[ra].strVal = typ.typeToString(preferExported) regs[ra].strVal = typ.typeToString(preferExported)
inc pc inc pc
proc fixType(result, n: PNode) {.inline.} =
# XXX do it deeply for complex values
if result.typ.isNil: result.typ = n.typ
proc execute(c: PCtx, start: int): PNode = proc execute(c: PCtx, start: int): PNode =
var tos = PStackFrame(prc: nil, comesFrom: 0, next: nil) var tos = PStackFrame(prc: nil, comesFrom: 0, next: nil)
newSeq(tos.slots, c.prc.maxSlots) newSeq(tos.slots, c.prc.maxSlots)
@ -885,6 +894,7 @@ proc evalExpr*(c: PCtx, n: PNode): PNode =
let start = genExpr(c, n) let start = genExpr(c, n)
assert c.code[start].opcode != opcEof assert c.code[start].opcode != opcEof
result = execute(c, start) result = execute(c, start)
fixType(result, n)
# for now we share the 'globals' environment. XXX Coming soon: An API for # for now we share the 'globals' environment. XXX Coming soon: An API for
# storing&loading the 'globals' environment to get what a component system # storing&loading the 'globals' environment to get what a component system
@ -928,6 +938,7 @@ proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
newSeq(tos.slots, c.prc.maxSlots) newSeq(tos.slots, c.prc.maxSlots)
for i in 0 .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty) for i in 0 .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
result = rawExecute(c, start, tos) result = rawExecute(c, start, tos)
fixType(result, n)
proc evalConstExpr*(module: PSym, e: PNode): PNode = proc evalConstExpr*(module: PSym, e: PNode): PNode =
result = evalConstExprAux(module, nil, e, emConst) result = evalConstExprAux(module, nil, e, emConst)

View file

@ -32,8 +32,8 @@ proc opSlurp*(file: string, info: TLineInfo, module: PSym): string =
appendToModule(module, newNode(nkIncludeStmt, info, @[ appendToModule(module, newNode(nkIncludeStmt, info, @[
newStrNode(nkStrLit, filename)])) newStrNode(nkStrLit, filename)]))
except EIO: except EIO:
result = ""
LocalError(info, errCannotOpenFile, file) LocalError(info, errCannotOpenFile, file)
result = ""
when false: when false:
proc opExpandToAst*(c: PEvalContext, original: PNode): PNode = proc opExpandToAst*(c: PEvalContext, original: PNode): PNode =

View file

@ -1,16 +1,16 @@
discard """ discard """
output: '''yeah A output: '''yeah A enumB
yeah A yeah A enumB
yeah CD yeah CD enumD
yeah CD yeah CD enumE
yeah A yeah A enumB
yeah CD yeah CD enumE
yeah CD yeah CD enumD
yeah A yeah A enumB
yeah B yeah B enumC
yeah A yeah A enumB
yeah A yeah A enumB
yeah A''' yeah A enumB'''
""" """
type type
@ -32,13 +32,14 @@ proc vm() =
while true: while true:
{.computedGoto.} {.computedGoto.}
let instr = instructions[pc] let instr = instructions[pc]
let ra = instr.succ # instr.regA
case instr case instr
of enumA: of enumA:
echo "yeah A" echo "yeah A ", ra
of enumC, enumD: of enumC, enumD:
echo "yeah CD" echo "yeah CD ", ra
of enumB: of enumB:
echo "yeah B" echo "yeah B ", ra
of enumE: of enumE:
break break
inc(pc) inc(pc)

View file

@ -2,11 +2,12 @@ version 0.9.4
============= =============
- new VM: - new VM:
- get rid of nkIntLit..nkUInt64Lit,
nkFloatLit..nkFloat128Lit, nkStrLit..nkTripleStrLit?
- new VM requires lambda lifting - new VM requires lambda lifting
- codegen for computed goto still wrong
- test and activate the jump optimizer
- implement overflow checking - implement overflow checking
- implement the FFI - implement the FFI
- test and activate the jump optimizer
- make 'bind' default for templates and introduce 'mixin' - make 'bind' default for templates and introduce 'mixin'
- special rule for ``[]=`` - special rule for ``[]=``
@ -20,6 +21,8 @@ version 0.9.4
Bugs Bugs
==== ====
- bug: 'type T = ref T' not recognized as illegal recursion
- bug: type conversions concerning proc types are weird
- compilation of niminst takes way too long. looks like a regression - compilation of niminst takes way too long. looks like a regression
- simple closure iterator doesn't work - simple closure iterator doesn't work
- docgen: sometimes effects are listed twice - docgen: sometimes effects are listed twice