summary refs log tree commit diff stats
path: root/compiler/vm.nim
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-12-12 01:34:01 +0100
committerAraq <rumpf_a@web.de>2013-12-12 01:34:01 +0100
commit6db20a4be8556621b3a33f87854b4b857c4dcf9e (patch)
treeb160173ad85e9c75f2a11d4746b971cac5c9e8ac /compiler/vm.nim
parent29357ab556a25ea75d0cf837eace079b46d51fc8 (diff)
downloadNim-6db20a4be8556621b3a33f87854b4b857c4dcf9e.tar.gz
new VM: improvements
Diffstat (limited to 'compiler/vm.nim')
-rw-r--r--compiler/vm.nim78
1 files changed, 60 insertions, 18 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 94ff8a4c7..984cc4bb8 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -52,9 +52,9 @@ proc stackTraceAux(c: PCtx; x: PStackFrame; pc: int) =
 
 proc stackTrace(c: PCtx, tos: PStackFrame, pc: int,
                 msg: TMsgKind, arg = "") =
-  MsgWriteln("stack trace: (most recent call last)")
+  msgWriteln("stack trace: (most recent call last)")
   stackTraceAux(c, tos, pc)
-  LocalError(c.debug[pc], msg, arg)
+  localError(c.debug[pc], msg, arg)
 
 proc bailOut(c: PCtx; tos: PStackFrame) =
   stackTrace(c, tos, c.exceptionInstr, errUnhandledExceptionX,
@@ -63,9 +63,6 @@ proc bailOut(c: PCtx; tos: PStackFrame) =
 when not defined(nimComputedGoto):
   {.pragma: computedGoto.}
 
-template inc(pc: ptr TInstr, diff = 1) =
-  inc cast[TAddress](pc), TInstr.sizeof * diff
-
 proc myreset(n: PNode) =
   when defined(system.reset): 
     var oldInfo = n.info
@@ -299,6 +296,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
     let instr = c.code[pc]
     let ra = instr.regA
     #echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra
+    #message(c.debug[pc], warnUser, "gah")
     case instr.opcode
     of opcEof: return regs[ra]
     of opcRet:
@@ -338,25 +336,38 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       # a = b[c]
       let rb = instr.regB
       let rc = instr.regC
-      let idx = regs[rc].intVal
+      let idx = regs[rc].intVal.int
       # XXX what if the array is not 0-based? -> codegen should insert a sub
       assert regs[rb].kind != nkMetaNode
-      asgnComplex(regs[ra], regs[rb].sons[idx.int])
+      let src = regs[rb]
+      if src.kind notin {nkEmpty..nkNilLit} and idx <% src.len:
+        asgnComplex(regs[ra], src.sons[idx])
+      else:
+        stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcLdStrIdx:
       decodeBC(nkIntLit)
-      let idx = regs[rc].intVal
-      regs[ra].intVal = regs[rb].strVal[idx.int].ord
+      let idx = regs[rc].intVal.int
+      if idx <=% regs[rb].strVal.len:
+        regs[ra].intVal = regs[rb].strVal[idx].ord
+      else:
+        stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcWrArr:
       # a[b] = c
       let rb = instr.regB
       let rc = instr.regC
-      let idx = regs[rb].intVal
-      asgnComplex(regs[ra].sons[idx.int], regs[rc])
+      let idx = regs[rb].intVal.int
+      if idx <% regs[ra].len:
+        asgnComplex(regs[ra].sons[idx], regs[rc])
+      else:
+        stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcWrArrRef:
       let rb = instr.regB
       let rc = instr.regC
-      let idx = regs[rb].intVal
-      asgnRef(regs[ra].sons[idx.int], regs[rc])
+      let idx = regs[rb].intVal.int
+      if idx <% regs[ra].len:
+        asgnRef(regs[ra].sons[idx], regs[rc])
+      else:
+        stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcLdObj:
       # a = b.c
       let rb = instr.regB
@@ -381,7 +392,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
     of opcWrStrIdx:
       decodeBC(nkStrLit)
       let idx = regs[rb].intVal.int
-      regs[ra].strVal[idx] = chr(regs[rc].intVal)
+      if idx <% regs[ra].strVal.len:
+        regs[ra].strVal[idx] = chr(regs[rc].intVal)
+      else:
+        stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcAddr:
       decodeB(nkRefTy)
       if regs[ra].len == 0: regs[ra].add regs[rb]
@@ -631,7 +645,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
         #echo "new pc ", newPc, " calling: ", prc.name.s
         var newFrame = PStackFrame(prc: prc, comesFrom: pc, next: tos)
         newSeq(newFrame.slots, prc.offset)
-        if not isEmptyType(prc.typ.sons[0]):
+        if not isEmptyType(prc.typ.sons[0]) or prc.kind == skMacro:
           newFrame.slots[0] = getNullValue(prc.typ.sons[0], prc.info)
         # pass every parameter by var (the language definition allows this):
         for i in 1 .. rc-1:
@@ -769,7 +783,15 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       regs[ra].strVal.setLen(regs[rb].getOrdValue.int)
     of opcOf:
       decodeBC(nkIntLit)
-      regs[ra].intVal = ord(inheritanceDiff(regs[rb].typ, regs[rc].typ) >= 0)
+      let typ = c.types[regs[rc].intVal.int]
+      regs[ra].intVal = ord(inheritanceDiff(regs[rb].typ, typ) >= 0)
+    of opcIs:
+      decodeBC(nkIntLit)
+      let t1 = regs[rb].typ.skipTypes({tyTypeDesc})
+      let t2 = c.types[regs[rc].intVal.int]
+      let match = if t2.kind == tyTypeClass: matchTypeClass(t2, t1)
+                  else: sameType(t1, t2)
+      regs[ra].intVal = ord(match)
     of opcSetLenSeq:
       decodeB(nkBracket)
       let newLen = regs[rb].getOrdValue.int
@@ -787,10 +809,20 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       decodeBC(nkMetaNode)
       if regs[rb].kind != nkMetaNode:
         internalError(c.debug[pc], "no MetaNode")
-      setMeta(regs[ra], regs[rb].uast.sons[regs[rc].intVal.int])
+      let idx = regs[rc].intVal.int
+      let src = regs[rb].uast
+      if src.kind notin {nkEmpty..nkNilLit} and idx <% src.len:
+        setMeta(regs[ra], src.sons[idx])
+      else:
+        stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcNSetChild:
       decodeBC(nkMetaNode)
-      regs[ra].uast.sons[regs[rb].intVal.int] = regs[rc].uast
+      let idx = regs[rb].intVal.int
+      var dest = regs[ra].uast
+      if dest.kind notin {nkEmpty..nkNilLit} and idx <% dest.len:
+        dest.sons[idx] = regs[rc].uast
+      else:
+        stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcNAdd:
       decodeBC(nkMetaNode)
       var u = regs[rb].uast
@@ -986,6 +1018,15 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       decodeB(nkStrLit)
       let typ = regs[rb].sym.typ.skipTypes({tyTypeDesc})
       regs[ra].strVal = typ.typeToString(preferExported)
+    of opcGlobalOnce:
+      let rb = instr.regBx
+      if c.globals.sons[rb - wordExcess - 1].kind != nkEmpty:
+        # skip initialization instructions:
+        while true:
+          inc pc
+          if c.code[pc].opcode in {opcWrGlobal, opcWrGlobalRef} and
+             c.code[pc].regBx == rb:
+            break
     inc pc
 
 proc fixType(result, n: PNode) {.inline.} =
@@ -1073,6 +1114,7 @@ proc setupMacroParam(x: PNode): PNode =
   y.flags.incl nfIsRef
   result = newNode(nkMetaNode)
   result.add y
+  result.typ = x.typ
 
 var evalMacroCounter: int