computed goto now works; some progress on the new VM
This commit is contained in:
parent
ca12bf76f5
commit
6ea538cec3
5 changed files with 53 additions and 23 deletions
|
|
@ -322,8 +322,20 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
||||||
gotoArray.appf("&&TMP$#, ", (id+i).toRope)
|
gotoArray.appf("&&TMP$#, ", (id+i).toRope)
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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 =
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
7
todo.txt
7
todo.txt
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue