diff options
Diffstat (limited to 'compiler/vm.nim')
-rw-r--r-- | compiler/vm.nim | 70 |
1 files changed, 52 insertions, 18 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim index ded66d3d0..f275b7b9b 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -10,12 +10,14 @@ ## This file implements the new evaluation engine for Nim code. ## An instruction is 1-3 int32s in memory, it is a register based VM. -const debugEchoCode = false +const + debugEchoCode = false + traceCode = debugEchoCode import ast except getstr import - strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned, + strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, parser, vmdeps, idents, trees, renderer, options, transf, parseutils, vmmarshal @@ -121,7 +123,7 @@ template move(a, b: expr) {.immediate, dirty.} = system.shallowCopy(a, b) # XXX fix minor 'shallowCopy' overloading bug in compiler proc createStrKeepNode(x: var TFullReg; keepNode=true) = - if x.node.isNil: + if x.node.isNil or not keepNode: x.node = newNode(nkStrLit) elif x.node.kind == nkNilLit and keepNode: when defined(useNodeIds): @@ -255,9 +257,12 @@ proc cleanUpOnException(c: PCtx; tos: PStackFrame): nextExceptOrFinally = pc2 + c.code[pc2].regBx - wordExcess inc pc2 while c.code[pc2].opcode == opcExcept: - let exceptType = c.types[c.code[pc2].regBx-wordExcess].skipTypes( + let excIndex = c.code[pc2].regBx-wordExcess + let exceptType = if excIndex > 0: c.types[excIndex].skipTypes( abstractPtrs) - if inheritanceDiff(exceptType, raisedType) <= 0: + else: nil + #echo typeToString(exceptType), " ", typeToString(raisedType) + if exceptType.isNil or inheritanceDiff(exceptType, raisedType) <= 0: # mark exception as handled but keep it in B for # the getCurrentException() builtin: c.currentExceptionB = c.currentExceptionA @@ -356,7 +361,14 @@ proc opConv*(dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool = of tyFloat..tyFloat64: dest.intVal = int(src.floatVal) else: - dest.intVal = src.intVal and ((1 shl (desttyp.size*8))-1) + let srcDist = (sizeof(src.intVal) - srctyp.size) * 8 + let destDist = (sizeof(dest.intVal) - desttyp.size) * 8 + when system.cpuEndian == bigEndian: + dest.intVal = (src.intVal shr srcDist) shl srcDist + dest.intVal = (dest.intVal shr destDist) shl destDist + else: + dest.intVal = (src.intVal shl srcDist) shr srcDist + dest.intVal = (dest.intVal shl destDist) shr destDist of tyFloat..tyFloat64: if dest.kind != rkFloat: myreset(dest); dest.kind = rkFloat @@ -394,7 +406,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = let instr = c.code[pc] let ra = instr.regA #if c.traceActive: - #echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra, " rb ", instr.regB, " rc ", instr.regC + when traceCode: + echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra, " rb ", instr.regB, " rc ", instr.regC # message(c.debug[pc], warnUser, "Trace") case instr.opcode @@ -511,7 +524,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = regs[ra].regAddr = addr(regs[rb]) of opcAddrNode: decodeB(rkNodeAddr) - regs[ra].nodeAddr = addr(regs[rb].node) + if regs[rb].kind == rkNode: + regs[ra].nodeAddr = addr(regs[rb].node) + else: + stackTrace(c, tos, pc, errGenerated, "limited VM support for 'addr'") of opcLdDeref: # a = b[] let ra = instr.regA @@ -529,7 +545,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = if regs[rb].node.kind == nkRefTy: regs[ra].node = regs[rb].node.sons[0] else: - stackTrace(c, tos, pc, errGenerated, "limited VM support for 'ref'") + stackTrace(c, tos, pc, errGenerated, "limited VM support for pointers") else: stackTrace(c, tos, pc, errNilAccess) of opcWrDeref: @@ -605,7 +621,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = addSon(regs[ra].node, r.copyTree) of opcExcl: decodeB(rkNode) - var b = newNodeIT(nkCurly, regs[rb].node.info, regs[rb].node.typ) + var b = newNodeIT(nkCurly, regs[ra].node.info, regs[ra].node.typ) addSon(b, regs[rb].regToNode) var r = diffSets(regs[ra].node, b) discardSons(regs[ra].node) @@ -808,13 +824,13 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcEcho: let rb = instr.regB if rb == 1: - msgWriteln(regs[ra].node.strVal) + msgWriteln(regs[ra].node.strVal, {msgStdout}) else: var outp = "" for i in ra..ra+rb-1: #if regs[i].kind != rkNode: debug regs[i] outp.add(regs[i].node.strVal) - msgWriteln(outp) + msgWriteln(outp, {msgStdout}) of opcContainsSet: decodeBC(rkInt) regs[ra].intVal = ord(inSet(regs[rb].node, regs[rc].regToNode)) @@ -1169,24 +1185,41 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcNGetType: let rb = instr.regB let rc = instr.regC - if rc == 0: + case rc: + of 0: + # getType opcode: ensureKind(rkNode) if regs[rb].kind == rkNode and regs[rb].node.typ != nil: regs[ra].node = opMapTypeToAst(regs[rb].node.typ, c.debug[pc]) else: stackTrace(c, tos, pc, errGenerated, "node has no type") - else: + of 1: # typeKind opcode: ensureKind(rkInt) if regs[rb].kind == rkNode and regs[rb].node.typ != nil: regs[ra].intVal = ord(regs[rb].node.typ.kind) #else: # stackTrace(c, tos, pc, errGenerated, "node has no type") + of 2: + # getTypeInst opcode: + ensureKind(rkNode) + if regs[rb].kind == rkNode and regs[rb].node.typ != nil: + regs[ra].node = opMapTypeInstToAst(regs[rb].node.typ, c.debug[pc]) + else: + stackTrace(c, tos, pc, errGenerated, "node has no type") + else: + # getTypeImpl opcode: + ensureKind(rkNode) + if regs[rb].kind == rkNode and regs[rb].node.typ != nil: + regs[ra].node = opMapTypeImplToAst(regs[rb].node.typ, c.debug[pc]) + else: + stackTrace(c, tos, pc, errGenerated, "node has no type") of opcNStrVal: decodeB(rkNode) createStr regs[ra] let a = regs[rb].node if a.kind in {nkStrLit..nkTripleStrLit}: regs[ra].node.strVal = a.strVal + elif a.kind == nkCommentStmt: regs[ra].node.strVal = a.comment else: stackTrace(c, tos, pc, errFieldXNotFound, "strVal") of opcSlurp: decodeB(rkNode) @@ -1576,12 +1609,13 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode = for i in 1.. <sym.typ.len: tos.slots[i] = setupMacroParam(n.sons[i], sym.typ.sons[i]) - if sfImmediate notin sym.flags: - let gp = sym.ast[genericParamsPos] - for i in 0 .. <gp.len: + let gp = sym.ast[genericParamsPos] + for i in 0 .. <gp.len: + if sfImmediate notin sym.flags: let idx = sym.typ.len + i tos.slots[idx] = setupMacroParam(n.sons[idx], gp[i].sym.typ) - + elif gp[i].sym.typ.kind in {tyStatic, tyTypeDesc}: + globalError(n.info, "static[T] or typedesc nor supported for .immediate macros") # temporary storage: #for i in L .. <maxSlots: tos.slots[i] = newNode(nkEmpty) result = rawExecute(c, start, tos).regToNode |