new VM: register allocator bugfix; implemented more magics
This commit is contained in:
parent
06b3852143
commit
288cd05f89
5 changed files with 195 additions and 64 deletions
128
compiler/vm.nim
128
compiler/vm.nim
|
|
@ -14,7 +14,7 @@ import
|
||||||
strutils, ast, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned,
|
strutils, ast, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned,
|
||||||
parser, vmdeps, idents
|
parser, vmdeps, idents
|
||||||
|
|
||||||
from semfold import leValueConv
|
from semfold import leValueConv, ordinalValToString
|
||||||
|
|
||||||
type
|
type
|
||||||
PStackFrame* = ref TStackFrame
|
PStackFrame* = ref TStackFrame
|
||||||
|
|
@ -60,6 +60,12 @@ when not defined(nimHasInterpreterLoop):
|
||||||
template inc(pc: ptr TInstr, diff = 1) =
|
template inc(pc: ptr TInstr, diff = 1) =
|
||||||
inc cast[TAddress](pc), TInstr.sizeof * diff
|
inc cast[TAddress](pc), TInstr.sizeof * diff
|
||||||
|
|
||||||
|
proc myreset(n: PNode) =
|
||||||
|
when defined(system.reset):
|
||||||
|
var oldInfo = n.info
|
||||||
|
reset(n[])
|
||||||
|
n.info = oldInfo
|
||||||
|
|
||||||
template ensureKind(k: expr) {.immediate, dirty.} =
|
template ensureKind(k: expr) {.immediate, dirty.} =
|
||||||
if regs[ra].kind != k:
|
if regs[ra].kind != k:
|
||||||
myreset(regs[ra])
|
myreset(regs[ra])
|
||||||
|
|
@ -170,6 +176,57 @@ proc cleanUpOnReturn(c: PCtx; f: PStackFrame): int =
|
||||||
return pc
|
return pc
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
|
proc opConv*(dest, src: PNode, typ: PType): bool =
|
||||||
|
if typ.kind == tyString:
|
||||||
|
if dest.kind != nkStrLit:
|
||||||
|
myreset(dest)
|
||||||
|
dest.kind = nkStrLit
|
||||||
|
case src.typ.skipTypes(abstractRange).kind
|
||||||
|
of tyEnum:
|
||||||
|
dest.strVal = ordinalValToString(src)
|
||||||
|
of tyInt..tyInt64, tyUInt..tyUInt64:
|
||||||
|
dest.strVal = $src.intVal
|
||||||
|
of tyBool:
|
||||||
|
dest.strVal = if src.intVal == 0: "false" else: "true"
|
||||||
|
of tyFloat..tyFloat128:
|
||||||
|
dest.strVal = $src.floatVal
|
||||||
|
of tyString, tyCString:
|
||||||
|
dest.strVal = src.strVal
|
||||||
|
of tyChar:
|
||||||
|
dest.strVal = $chr(src.intVal)
|
||||||
|
else:
|
||||||
|
internalError("cannot convert to string " & typ.typeToString)
|
||||||
|
else:
|
||||||
|
case skipTypes(typ, abstractRange).kind
|
||||||
|
of tyInt..tyInt64:
|
||||||
|
if dest.kind != nkIntLit:
|
||||||
|
myreset(dest); dest.kind = nkIntLit
|
||||||
|
case skipTypes(src.typ, abstractRange).kind
|
||||||
|
of tyFloat..tyFloat64:
|
||||||
|
dest.intVal = system.toInt(src.floatVal)
|
||||||
|
else:
|
||||||
|
dest.intVal = src.intVal
|
||||||
|
if dest.intVal < firstOrd(typ) or dest.intVal > lastOrd(typ):
|
||||||
|
return true
|
||||||
|
of tyUInt..tyUInt64:
|
||||||
|
if dest.kind != nkIntLit:
|
||||||
|
myreset(dest); dest.kind = nkIntLit
|
||||||
|
case skipTypes(src.typ, abstractRange).kind
|
||||||
|
of tyFloat..tyFloat64:
|
||||||
|
dest.intVal = system.toInt(src.floatVal)
|
||||||
|
else:
|
||||||
|
dest.intVal = src.intVal and ((1 shl typ.size)-1)
|
||||||
|
of tyFloat..tyFloat64:
|
||||||
|
if dest.kind != nkFloatLit:
|
||||||
|
myreset(dest); dest.kind = nkFloatLit
|
||||||
|
case skipTypes(src.typ, abstractRange).kind
|
||||||
|
of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyBool, tyChar:
|
||||||
|
dest.floatVal = toFloat(src.intVal.int)
|
||||||
|
else:
|
||||||
|
dest.floatVal = src.floatVal
|
||||||
|
else:
|
||||||
|
asgnComplex(dest, src)
|
||||||
|
|
||||||
proc compile(c: PCtx, s: PSym): int =
|
proc compile(c: PCtx, s: PSym): int =
|
||||||
result = vmgen.genProc(c, s)
|
result = vmgen.genProc(c, s)
|
||||||
#c.echoCode
|
#c.echoCode
|
||||||
|
|
@ -243,6 +300,7 @@ proc execute(c: PCtx, start: int) =
|
||||||
let rb = instr.regB
|
let rb = instr.regB
|
||||||
let rc = instr.regC
|
let rc = instr.regC
|
||||||
# XXX this creates a wrong alias
|
# XXX this creates a wrong alias
|
||||||
|
#Message(c.debug[pc], warnUser, $regs[rb].len & " " & $rc)
|
||||||
asgnComplex(regs[ra], regs[rb].sons[rc])
|
asgnComplex(regs[ra], regs[rb].sons[rc])
|
||||||
of opcWrObj:
|
of opcWrObj:
|
||||||
# a.b = c
|
# a.b = c
|
||||||
|
|
@ -380,8 +438,9 @@ proc execute(c: PCtx, start: int) =
|
||||||
regs[ra].intVal = ord(regs[rb].intVal <% regs[rc].intVal)
|
regs[ra].intVal = ord(regs[rb].intVal <% regs[rc].intVal)
|
||||||
of opcEqRef:
|
of opcEqRef:
|
||||||
decodeBC(nkIntLit)
|
decodeBC(nkIntLit)
|
||||||
regs[ra].intVal = ord(regs[rb] == regs[rc])
|
regs[ra].intVal = ord((regs[rb].kind == nkNilLit and
|
||||||
# XXX is this correct? nope ...
|
regs[rc].kind == nkNilLit) or
|
||||||
|
regs[rb].sons == regs[rc].sons)
|
||||||
of opcXor:
|
of opcXor:
|
||||||
decodeBC(nkIntLit)
|
decodeBC(nkIntLit)
|
||||||
regs[ra].intVal = ord(regs[rb].intVal != regs[rc].intVal)
|
regs[ra].intVal = ord(regs[rb].intVal != regs[rc].intVal)
|
||||||
|
|
@ -448,7 +507,11 @@ proc execute(c: PCtx, start: int) =
|
||||||
decodeB(nkBracket)
|
decodeB(nkBracket)
|
||||||
regs[ra].add(copyTree(regs[rb]))
|
regs[ra].add(copyTree(regs[rb]))
|
||||||
of opcEcho:
|
of opcEcho:
|
||||||
echo regs[ra].strVal
|
let rb = instr.regB
|
||||||
|
for i in ra..ra+rb-1:
|
||||||
|
if regs[i].kind != nkStrLit: debug regs[i]
|
||||||
|
write(stdout, regs[i].strVal)
|
||||||
|
writeln(stdout, "")
|
||||||
of opcContainsSet:
|
of opcContainsSet:
|
||||||
decodeBC(nkIntLit)
|
decodeBC(nkIntLit)
|
||||||
regs[ra].intVal = Ord(inSet(regs[rb], regs[rc]))
|
regs[ra].intVal = Ord(inSet(regs[rb], regs[rc]))
|
||||||
|
|
@ -691,7 +754,62 @@ proc execute(c: PCtx, start: int) =
|
||||||
let rb = instr.regB
|
let rb = instr.regB
|
||||||
inc pc
|
inc pc
|
||||||
let typ = c.types[c.code[pc].regBx - wordExcess]
|
let typ = c.types[c.code[pc].regBx - wordExcess]
|
||||||
opConv(regs[ra], regs[rb], typ)
|
if opConv(regs[ra], regs[rb], typ):
|
||||||
|
stackTrace(c, tos, pc, errGenerated,
|
||||||
|
msgKindToString(errIllegalConvFromXtoY) % [
|
||||||
|
"unknown type" , "unknown type"])
|
||||||
|
of opcNSetIntVal:
|
||||||
|
let rb = instr.regB
|
||||||
|
if regs[ra].kind in {nkCharLit..nkInt64Lit} and
|
||||||
|
regs[rb].kind in {nkCharLit..nkInt64Lit}:
|
||||||
|
regs[ra].intVal = regs[rb].intVal
|
||||||
|
else:
|
||||||
|
stackTrace(c, tos, pc, errFieldXNotFound, "intVal")
|
||||||
|
of opcNSetFloatVal:
|
||||||
|
let rb = instr.regB
|
||||||
|
if regs[ra].kind in {nkFloatLit..nkFloat64Lit} and
|
||||||
|
regs[rb].kind in {nkFloatLit..nkFloat64Lit}:
|
||||||
|
regs[ra].floatVal = regs[rb].floatVal
|
||||||
|
else:
|
||||||
|
stackTrace(c, tos, pc, errFieldXNotFound, "floatVal")
|
||||||
|
of opcNSetSymbol:
|
||||||
|
let rb = instr.regB
|
||||||
|
if regs[ra].kind == nkSym and regs[rb].kind == nkSym:
|
||||||
|
regs[ra].sym = regs[rb].sym
|
||||||
|
else:
|
||||||
|
stackTrace(c, tos, pc, errFieldXNotFound, "symbol")
|
||||||
|
of opcNSetIdent:
|
||||||
|
let rb = instr.regB
|
||||||
|
if regs[ra].kind == nkIdent and regs[rb].kind == nkIdent:
|
||||||
|
regs[ra].ident = regs[rb].ident
|
||||||
|
else:
|
||||||
|
stackTrace(c, tos, pc, errFieldXNotFound, "ident")
|
||||||
|
of opcNSetType:
|
||||||
|
let b = regs[instr.regB]
|
||||||
|
InternalAssert b.kind == nkSym and b.sym.kind == skType
|
||||||
|
regs[ra].typ = b.sym.typ
|
||||||
|
of opcNSetStrVal:
|
||||||
|
let rb = instr.regB
|
||||||
|
if regs[ra].kind in {nkStrLit..nkTripleStrLit} and
|
||||||
|
regs[rb].kind in {nkStrLit..nkTripleStrLit}:
|
||||||
|
regs[ra].strVal = regs[rb].strVal
|
||||||
|
else:
|
||||||
|
stackTrace(c, tos, pc, errFieldXNotFound, "strVal")
|
||||||
|
of opcNNewNimNode:
|
||||||
|
let rb = instr.regB
|
||||||
|
let rc = instr.regC
|
||||||
|
var k = regs[rb].intVal
|
||||||
|
if k < 0 or k > ord(high(TNodeKind)):
|
||||||
|
internalError(c.debug[pc],
|
||||||
|
"request to create a NimNode with invalid kind")
|
||||||
|
regs[ra] = newNodeI(TNodeKind(int(k)),
|
||||||
|
if regs[rc].kind == nkNilLit: c.debug[pc] else: regs[rc].info)
|
||||||
|
of opcNCopyNimNode:
|
||||||
|
let rb = instr.regB
|
||||||
|
regs[ra] = copyNode(regs[rb])
|
||||||
|
of opcNCopyNimTree:
|
||||||
|
let rb = instr.regB
|
||||||
|
regs[ra] = copyTree(regs[rb])
|
||||||
else:
|
else:
|
||||||
InternalError(c.debug[pc], "unknown opcode " & $instr.opcode)
|
InternalError(c.debug[pc], "unknown opcode " & $instr.opcode)
|
||||||
inc pc
|
inc pc
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,10 @@ type
|
||||||
opcNGetType,
|
opcNGetType,
|
||||||
opcNStrVal,
|
opcNStrVal,
|
||||||
|
|
||||||
|
opcNSetIntVal,
|
||||||
|
opcNSetFloatVal, opcNSetSymbol, opcNSetIdent, opcNSetType, opcNSetStrVal,
|
||||||
|
opcNNewNimNode, opcNCopyNimNode, opcNCopyNimTree,
|
||||||
|
|
||||||
opcSlurp,
|
opcSlurp,
|
||||||
opcGorge,
|
opcGorge,
|
||||||
opcParseExprToAst,
|
opcParseExprToAst,
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
import ast, types, msgs, osproc, streams, options, semfold
|
import ast, types, msgs, osproc, streams, options
|
||||||
|
|
||||||
proc readOutput(p: PProcess): string =
|
proc readOutput(p: PProcess): string =
|
||||||
result = ""
|
result = ""
|
||||||
|
|
@ -35,35 +35,6 @@ proc opSlurp*(file: string, info: TLineInfo, module: PSym): string =
|
||||||
result = ""
|
result = ""
|
||||||
LocalError(info, errCannotOpenFile, file)
|
LocalError(info, errCannotOpenFile, file)
|
||||||
|
|
||||||
proc myreset*(n: PNode) =
|
|
||||||
when defined(system.reset):
|
|
||||||
var oldInfo = n.info
|
|
||||||
reset(n[])
|
|
||||||
n.info = oldInfo
|
|
||||||
|
|
||||||
proc opConv*(dest, src: PNode, typ: PType) =
|
|
||||||
if typ.kind == tyString:
|
|
||||||
if dest.kind != nkStrLit:
|
|
||||||
myreset(dest)
|
|
||||||
dest.kind = nkStrLit
|
|
||||||
case src.typ.skipTypes(abstractRange).kind
|
|
||||||
of tyEnum:
|
|
||||||
dest.strVal = ordinalValToString(src)
|
|
||||||
of tyInt..tyInt64, tyUInt..tyUInt64:
|
|
||||||
dest.strVal = $src.intVal
|
|
||||||
of tyBool:
|
|
||||||
dest.strVal = if src.intVal == 0: "false" else: "true"
|
|
||||||
of tyFloat..tyFloat128:
|
|
||||||
dest.strVal = $src.floatVal
|
|
||||||
of tyString, tyCString:
|
|
||||||
dest.strVal = src.strVal
|
|
||||||
of tyChar:
|
|
||||||
dest.strVal = $chr(src.intVal)
|
|
||||||
else:
|
|
||||||
internalError("cannot convert to string " & typ.typeToString)
|
|
||||||
else:
|
|
||||||
discard
|
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
proc opExpandToAst*(c: PEvalContext, original: PNode): PNode =
|
proc opExpandToAst*(c: PEvalContext, original: PNode): PNode =
|
||||||
var
|
var
|
||||||
|
|
|
||||||
|
|
@ -137,9 +137,9 @@ proc getTempRange(c: PCtx; n: int; kind: TSlotKind): TRegister =
|
||||||
# if register pressure is high, we re-use more aggressively:
|
# if register pressure is high, we re-use more aggressively:
|
||||||
let c = c.prc
|
let c = c.prc
|
||||||
if c.maxSlots >= HighRegisterPressure or c.maxSlots+n >= high(TRegister):
|
if c.maxSlots >= HighRegisterPressure or c.maxSlots+n >= high(TRegister):
|
||||||
for i in 0 .. c.maxSlots-1:
|
for i in 0 .. c.maxSlots-n:
|
||||||
block search:
|
|
||||||
if not c.slots[i].inUse:
|
if not c.slots[i].inUse:
|
||||||
|
block search:
|
||||||
for j in i+1 .. i+n-1:
|
for j in i+1 .. i+n-1:
|
||||||
if c.slots[j].inUse: break search
|
if c.slots[j].inUse: break search
|
||||||
result = TRegister(i)
|
result = TRegister(i)
|
||||||
|
|
@ -186,6 +186,14 @@ proc genx(c: PCtx; n: PNode): TRegister =
|
||||||
gen(c, n, tmp)
|
gen(c, n, tmp)
|
||||||
result = TRegister(tmp)
|
result = TRegister(tmp)
|
||||||
|
|
||||||
|
proc isNotOpr(n: PNode): bool =
|
||||||
|
n.kind in nkCallKinds and n.sons[0].kind == nkSym and
|
||||||
|
n.sons[0].sym.magic == mNot
|
||||||
|
|
||||||
|
proc isTrue(n: PNode): bool =
|
||||||
|
n.kind == nkSym and n.sym.kind == skEnumField and n.sym.position != 0 or
|
||||||
|
n.kind == nkIntLit and n.intVal != 0
|
||||||
|
|
||||||
proc genWhile(c: PCtx; n: PNode) =
|
proc genWhile(c: PCtx; n: PNode) =
|
||||||
# L1:
|
# L1:
|
||||||
# cond, tmp
|
# cond, tmp
|
||||||
|
|
@ -195,6 +203,17 @@ proc genWhile(c: PCtx; n: PNode) =
|
||||||
# L2:
|
# L2:
|
||||||
let L1 = c.genLabel
|
let L1 = c.genLabel
|
||||||
withBlock(nil):
|
withBlock(nil):
|
||||||
|
if isTrue(n.sons[0]):
|
||||||
|
c.gen(n.sons[1])
|
||||||
|
c.jmpBack(n, opcJmp, L1)
|
||||||
|
elif isNotOpr(n.sons[0]):
|
||||||
|
var tmp = c.genx(n.sons[0].sons[1])
|
||||||
|
let L2 = c.xjmp(n, opcTJmp, tmp)
|
||||||
|
c.freeTemp(tmp)
|
||||||
|
c.gen(n.sons[1])
|
||||||
|
c.jmpBack(n, opcJmp, L1)
|
||||||
|
c.patch(L2)
|
||||||
|
else:
|
||||||
var tmp = c.genx(n.sons[0])
|
var tmp = c.genx(n.sons[0])
|
||||||
let L2 = c.xjmp(n, opcFJmp, tmp)
|
let L2 = c.xjmp(n, opcFJmp, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
|
|
@ -209,7 +228,7 @@ proc genBlock(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
proc genBreak(c: PCtx; n: PNode) =
|
proc genBreak(c: PCtx; n: PNode) =
|
||||||
let L1 = c.xjmp(n, opcJmp)
|
let L1 = c.xjmp(n, opcJmp)
|
||||||
if n.sons[0].kind == nkSym:
|
if n.sons[0].kind == nkSym:
|
||||||
echo cast[int](n.sons[0].sym)
|
#echo cast[int](n.sons[0].sym)
|
||||||
for i in countdown(c.prc.blocks.len-1, 0):
|
for i in countdown(c.prc.blocks.len-1, 0):
|
||||||
if c.prc.blocks[i].label == n.sons[0].sym:
|
if c.prc.blocks[i].label == n.sons[0].sym:
|
||||||
c.prc.blocks[i].fixups.add L1
|
c.prc.blocks[i].fixups.add L1
|
||||||
|
|
@ -235,8 +254,13 @@ proc genIf(c: PCtx, n: PNode; dest: var TDest) =
|
||||||
var it = n.sons[i]
|
var it = n.sons[i]
|
||||||
if it.len == 2:
|
if it.len == 2:
|
||||||
withTemp(tmp, it.sons[0].typ):
|
withTemp(tmp, it.sons[0].typ):
|
||||||
|
var elsePos: TPosition
|
||||||
|
if isNotOpr(it.sons[0]):
|
||||||
|
c.gen(it.sons[0].sons[1], tmp)
|
||||||
|
elsePos = c.xjmp(it.sons[0].sons[1], opcTJmp, tmp) # if true
|
||||||
|
else:
|
||||||
c.gen(it.sons[0], tmp)
|
c.gen(it.sons[0], tmp)
|
||||||
let elsePos = c.xjmp(it.sons[0], opcFJmp, tmp) # if false
|
elsePos = c.xjmp(it.sons[0], opcFJmp, tmp) # if false
|
||||||
c.gen(it.sons[1], dest) # then part
|
c.gen(it.sons[1], dest) # then part
|
||||||
if i < sonsLen(n)-1:
|
if i < sonsLen(n)-1:
|
||||||
endings.add(c.xjmp(it.sons[1], opcJmp, 0))
|
endings.add(c.xjmp(it.sons[1], opcJmp, 0))
|
||||||
|
|
@ -629,10 +653,12 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
of mEcho:
|
of mEcho:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
|
let x = c.getTempRange(n.len-1, slotTempUnknown)
|
||||||
for i in 1.. <n.len:
|
for i in 1.. <n.len:
|
||||||
var d = c.genx(n.sons[i])
|
var r: TRegister = x+i-1
|
||||||
c.gABC(n, opcEcho, d)
|
c.gen(n.sons[i], r)
|
||||||
c.freeTemp(d)
|
c.gABC(n, opcEcho, x, n.len-1)
|
||||||
|
c.freeTempRange(x, n.len-1)
|
||||||
of mAppendStrCh:
|
of mAppendStrCh:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
genBinaryStmt(c, n, opcAddStrCh)
|
genBinaryStmt(c, n, opcAddStrCh)
|
||||||
|
|
@ -675,15 +701,27 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
of mNIdent: genUnaryABC(c, n, dest, opcNIdent)
|
of mNIdent: genUnaryABC(c, n, dest, opcNIdent)
|
||||||
of mNGetType: genUnaryABC(c, n, dest, opcNGetType)
|
of mNGetType: genUnaryABC(c, n, dest, opcNGetType)
|
||||||
of mNStrVal: genUnaryABC(c, n, dest, opcNStrVal)
|
of mNStrVal: genUnaryABC(c, n, dest, opcNStrVal)
|
||||||
of mNSetIntVal: InternalError(n.info, "cannot generate code for: " & $m)
|
of mNSetIntVal:
|
||||||
of mNSetFloatVal: InternalError(n.info, "cannot generate code for: " & $m)
|
unused(n, dest)
|
||||||
of mNSetSymbol: InternalError(n.info, "cannot generate code for: " & $m)
|
genBinaryStmt(c, n, opcNSetIntVal)
|
||||||
of mNSetIdent: InternalError(n.info, "cannot generate code for: " & $m)
|
of mNSetFloatVal:
|
||||||
of mNSetType: InternalError(n.info, "cannot generate code for: " & $m)
|
unused(n, dest)
|
||||||
of mNSetStrVal: InternalError(n.info, "cannot generate code for: " & $m)
|
genBinaryStmt(c, n, opcNSetFloatVal)
|
||||||
of mNNewNimNode: InternalError(n.info, "cannot generate code for: " & $m)
|
of mNSetSymbol:
|
||||||
of mNCopyNimNode: InternalError(n.info, "cannot generate code for: " & $m)
|
unused(n, dest)
|
||||||
of mNCopyNimTree: InternalError(n.info, "cannot generate code for: " & $m)
|
genBinaryStmt(c, n, opcNSetSymbol)
|
||||||
|
of mNSetIdent:
|
||||||
|
unused(n, dest)
|
||||||
|
genBinaryStmt(c, n, opcNSetIdent)
|
||||||
|
of mNSetType:
|
||||||
|
unused(n, dest)
|
||||||
|
genBinaryStmt(c, n, opcNSetType)
|
||||||
|
of mNSetStrVal:
|
||||||
|
unused(n, dest)
|
||||||
|
genBinaryStmt(c, n, opcNSetStrVal)
|
||||||
|
of mNNewNimNode: genBinaryABC(c, n, dest, opcNNewNimNode)
|
||||||
|
of mNCopyNimNode: genUnaryABC(c, n, dest, opcNCopyNimNode)
|
||||||
|
of mNCopyNimTree: genUnaryABC(c, n, dest, opcNCopyNimTree)
|
||||||
of mNBindSym: genUnaryABC(c, n, dest, opcNBindSym)
|
of mNBindSym: genUnaryABC(c, n, dest, opcNBindSym)
|
||||||
of mStrToIdent: genUnaryABC(c, n, dest, opcStrToIdent)
|
of mStrToIdent: genUnaryABC(c, n, dest, opcStrToIdent)
|
||||||
of mIdentToStr: genUnaryABC(c, n, dest, opcIdentToStr)
|
of mIdentToStr: genUnaryABC(c, n, dest, opcIdentToStr)
|
||||||
|
|
@ -1203,5 +1241,6 @@ proc genProc(c: PCtx; s: PSym): int =
|
||||||
c.gABC(body, opcEof)
|
c.gABC(body, opcEof)
|
||||||
s.position = c.prc.maxSlots
|
s.position = c.prc.maxSlots
|
||||||
c.prc = oldPrc
|
c.prc = oldPrc
|
||||||
|
#c.echoCode
|
||||||
else:
|
else:
|
||||||
result = x.intVal.int
|
result = x.intVal.int
|
||||||
|
|
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -2,7 +2,6 @@ version 0.9.4
|
||||||
=============
|
=============
|
||||||
|
|
||||||
- new VM:
|
- new VM:
|
||||||
- implement opcConv
|
|
||||||
- implement missing magics
|
- implement missing magics
|
||||||
- implement overflow checking
|
- implement overflow checking
|
||||||
- implement the glue to replace evals.nim
|
- implement the glue to replace evals.nim
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue