new vm: lots of fixes

This commit is contained in:
Araq 2013-07-27 01:28:31 +02:00
commit 27b7ecbbff
3 changed files with 146 additions and 53 deletions

View file

@ -14,16 +14,30 @@ import
trees, intsets, rodread
proc codeListing(c: PCtx, result: var string) =
# first iteration: compute all necessary labels:
var jumpTargets = initIntSet()
for i in 0.. < c.code.len:
let x = c.code[i]
if x.opcode in relativeJumps:
jumpTargets.incl(i+x.regBx-wordExcess)
# for debugging purposes
var i = 0
while i < c.code.len:
if i in c.jumpTargets: result.addf("L$1:\n", i)
if i in jumpTargets: result.addf("L$1:\n", i)
let x = c.code[i]
let opc = opcode(x)
if opc < firstABxInstr:
result.addf("\t$#\tr$#, r$#, r$#", ($opc).substr(3), x.regA,
x.regB, x.regC)
elif opc in relativeJumps:
result.addf("\t$#\tr$#, L$#", ($opc).substr(3), x.regA,
i+x.regBx-wordExcess)
elif opc in {opcLdConst, opcAsgnConst}:
result.addf("\t$#\tr$#, $#", ($opc).substr(3), x.regA,
c.constants[x.regBx-wordExcess].renderTree)
else:
result.addf("\t$#\tr$#, $#", ($opc).substr(3), x.regA, x.regBx-wordExcess)
result.add("\t#")
@ -64,7 +78,7 @@ proc xjmp(c: PCtx; n: PNode; opc: TOpcode; a: TRegister = 0): TPosition =
proc genLabel(c: PCtx): TPosition =
result = TPosition(c.code.len)
c.jumpTargets.incl(c.code.len)
#c.jumpTargets.incl(c.code.len)
proc jmpBack(c: PCtx, n: PNode, opc: TOpcode, p = TPosition(0)) =
let dist = p.int - c.code.len
@ -75,7 +89,7 @@ proc patch(c: PCtx, p: TPosition) =
# patch with current index
let p = p.int
let diff = c.code.len - p
c.jumpTargets.incl(c.code.len)
#c.jumpTargets.incl(c.code.len)
InternalAssert(-0x7fff < diff and diff < 0x7fff)
let oldInstr = c.code[p]
# opcode and regA stay the same:
@ -195,10 +209,11 @@ proc genBlock(c: PCtx; n: PNode; dest: var TDest) =
proc genBreak(c: PCtx; n: PNode) =
let L1 = c.xjmp(n, opcJmp)
if n.sons[0].kind == nkSym:
echo cast[int](n.sons[0].sym)
for i in countdown(c.prc.blocks.len-1, 0):
if c.prc.blocks[i].label == n.sons[0].sym:
c.prc.blocks[i].fixups.add L1
break
return
InternalError(n.info, "cannot find 'break' target")
else:
c.prc.blocks[c.prc.blocks.high].fixups.add L1
@ -365,7 +380,10 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) =
proc genNew(c: PCtx; n: PNode) =
let dest = c.genx(n.sons[1])
c.gABx(n, opcNew, dest, c.genType(n.sons[1].typ.skipTypes(abstractVar)))
# we use the ref's base type here as the VM conflates 'ref object'
# and 'object' since internally we already have a pointer.
c.gABx(n, opcNew, dest,
c.genType(n.sons[1].typ.skipTypes(abstractVar).sons[0]))
c.freeTemp(dest)
proc genNewSeq(c: PCtx; n: PNode) =
@ -382,6 +400,12 @@ proc genUnaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
c.gABC(n, opc, dest, tmp)
c.freeTemp(tmp)
proc genUnaryABI(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
let tmp = c.genx(n.sons[1])
if dest < 0: dest = c.getTemp(n.typ)
c.gABI(n, opc, dest, tmp, 0)
c.freeTemp(tmp)
proc genBinaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
let
tmp = c.genx(n.sons[1])
@ -391,6 +415,13 @@ proc genBinaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
c.freeTemp(tmp)
c.freeTemp(tmp2)
proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
let
dest = c.genx(n.sons[1])
tmp = c.genx(n.sons[2])
c.gABC(n, opc, dest, tmp, 0)
c.freeTemp(tmp)
proc genVarargsABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
if dest < 0: dest = getTemp(c, n.typ)
var x = c.getTempRange(n.len-1, slotTempStr)
@ -465,9 +496,9 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
c.gABC(n, opcNewStr, dest, tmp)
c.freeTemp(tmp)
of mLengthOpenArray, mLengthArray, mLengthSeq:
genUnaryABC(c, n, dest, opcLenSeq)
genUnaryABI(c, n, dest, opcLenSeq)
of mLengthStr:
genUnaryABC(c, n, dest, opcLenStr)
genUnaryABI(c, n, dest, opcLenStr)
of mIncl, mExcl:
unused(n, dest)
var d = c.genx(n.sons[1])
@ -596,9 +627,15 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
var d = c.genx(n.sons[i])
c.gABC(n, opcEcho, d)
c.freeTemp(d)
of mAppendStrCh: InternalError(n.info, "cannot generate code for: " & $m)
of mAppendStrStr: InternalError(n.info, "cannot generate code for: " & $m)
of mAppendSeqElem: InternalError(n.info, "cannot generate code for: " & $m)
of mAppendStrCh:
unused(n, dest)
genBinaryStmt(c, n, opcAddStrCh)
of mAppendStrStr:
unused(n, dest)
genBinaryStmt(c, n, opcAddStrStr)
of mAppendSeqElem:
unused(n, dest)
genBinaryStmt(c, n, opcAddSeqElem)
of mParseExprToAst: InternalError(n.info, "cannot generate code for: " & $m)
of mParseStmtToAst: InternalError(n.info, "cannot generate code for: " & $m)
of mExpandToAst: InternalError(n.info, "cannot generate code for: " & $m)
@ -664,18 +701,18 @@ proc requiresCopy(n: PNode): bool =
else:
result = true
proc unnecessaryIndirection(n: PNode): bool =
proc unneededIndirection(n: PNode): bool =
n.typ.skipTypes(abstractInst).kind == tyRef
proc skipDeref(n: PNode): PNode =
if n.kind in {nkDerefExpr, nkHiddenDeref} and unnecessaryIndirection(n):
if n.kind in {nkDerefExpr, nkHiddenDeref} and unneededIndirection(n.sons[0]):
result = n.sons[0]
else:
result = n
proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
# a nop for certain types
if unnecessaryIndirection(n):
if unneededIndirection(n.sons[0]):
gen(c, n.sons[0], dest)
else:
let tmp = c.genx(n.sons[0])
@ -740,9 +777,11 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
genAsgn(c, dest, ri, requiresCopy)
proc genLit(c: PCtx; n: PNode; dest: var TDest) =
var opc = opcLdConst
if dest < 0: dest = c.getTemp(n.typ)
elif c.prc.slots[dest].kind == slotFixedVar: opc = opcAsgnConst
let lit = genLiteral(c, n)
c.gABx(n, opcLdConst, dest, lit)
c.gABx(n, opc, dest, lit)
proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
let s = n.sym
@ -775,7 +814,10 @@ proc genObjAccess(c: PCtx; n: PNode; dest: var TDest) =
genAccess(c, n, dest, opcLdObj)
proc genArrAccess(c: PCtx; n: PNode; dest: var TDest) =
genAccess(c, n, dest, opcLdArr)
if n.sons[0].typ.skipTypes(abstractVarRange).kind in {tyString, tyCString}:
genAccess(c, n, dest, opcLdStrIdx)
else:
genAccess(c, n, dest, opcLdArr)
proc getNullValue*(typ: PType, info: TLineInfo): PNode
proc getNullValueAux(obj: PNode, result: PNode) =
@ -827,7 +869,8 @@ proc setSlot(c: PCtx; v: PSym) =
# XXX generate type initialization here?
if v.position == 0:
v.position = c.prc.maxSlots
c.prc.slots[v.position] = (inUse: true, kind: slotFixed)
c.prc.slots[v.position] = (inUse: true,
kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
inc c.prc.maxSlots
proc genVarSection(c: PCtx; n: PNode) =
@ -959,36 +1002,56 @@ proc gen(c: PCtx; n: PNode; dest: var TDest) =
let s = n.sons[namePos].sym
discard genProc(c, s)
genLit(c, n.sons[namePos], dest)
of nkChckRangeF, nkChckRange64, nkChckRange:
let
tmp0 = c.genx(n.sons[0])
tmp1 = c.genx(n.sons[1])
tmp2 = c.genx(n.sons[2])
c.gABC(n, opcRangeChck, tmp0, tmp1, tmp2)
c.freeTemp(tmp1)
c.freeTemp(tmp2)
if dest >= 0:
gABC(c, n, whichAsgnOpc(n), dest, tmp0)
c.freeTemp(tmp0)
else:
dest = tmp0
of nkEmpty, nkCommentStmt, nkTypeSection, nkConstSection, nkPragma,
nkTemplateDef, nkIncludeStmt, nkImportStmt:
unused(n, dest)
of nkStringToCString, nkCStringToString:
gen(c, n.sons[0], dest)
else:
#of nkCurly, nkBracket, nkPar:
InternalError n.info, "too implement " & $n.kind
proc genStmt*(c: PCtx; n: PNode): int =
result = c.code.len
var d: TDest = -1
gen(c, n, d)
proc removeLastEof(c: PCtx) =
let last = c.code.len-1
if last >= 0 and c.code[last].opcode == opcEof:
# since we can re-use the EOF nothing happened:
result = last
else:
gABC(c, n, opcEof)
# overwrite last EOF:
assert c.code.len == c.debug.len
c.code.setLen(last)
c.debug.setLen(last)
proc genStmt*(c: PCtx; n: PNode): int =
c.removeLastEof
result = c.code.len
var d: TDest = -1
c.gen(n, d)
c.gABC(n, opcEof)
InternalAssert d < 0
proc genParams(c: PCtx; params: PNode) =
# res.sym.position is already 0
c.prc.slots[0] = (inUse: true, kind: slotFixed)
c.prc.slots[0] = (inUse: true, kind: slotFixedVar)
for i in 1.. <params.len:
let param = params.sons[i].sym
c.prc.slots[i] = (inUse: true, kind: slotFixed)
c.prc.slots[i] = (inUse: true, kind: slotFixedLet)
c.prc.maxSlots = max(params.len, 1)
proc genProc(c: PCtx; s: PSym): int =
let x = s.ast.sons[optimizedCodePos]
if x.kind == nkEmpty:
c.removeLastEof
result = c.code.len+1 # skip the jump instruction
s.ast.sons[optimizedCodePos] = newIntNode(nkIntLit, result)
# thanks to the jmp we can add top level statements easily and also nest
@ -1004,6 +1067,7 @@ proc genProc(c: PCtx; s: PSym): int =
# generate final 'return' statement:
c.gABC(body, opcRet)
c.patch(procStart)
c.gABC(body, opcEof)
s.position = c.prc.maxSlots
c.prc = oldPrc
else: