summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-12-13 01:21:23 +0100
committerAraq <rumpf_a@web.de>2013-12-13 01:21:23 +0100
commit328f1932925889d5bb7f91c68fb1504b9b26ba8c (patch)
treef26fa7993b085104fef4d54701d27eae5f40cc18
parent6db20a4be8556621b3a33f87854b4b857c4dcf9e (diff)
downloadNim-328f1932925889d5bb7f91c68fb1504b9b26ba8c.tar.gz
new VM: globals kinda work
-rw-r--r--compiler/renderer.nim10
-rw-r--r--compiler/semmagic.nim4
-rw-r--r--compiler/vm.nim10
-rw-r--r--compiler/vmdef.nim5
-rw-r--r--compiler/vmgen.nim24
-rw-r--r--tests/compile/tmacro2.nim2
-rw-r--r--tests/reject/twrongiter.nim2
7 files changed, 45 insertions, 12 deletions
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index f6fb0f8c0..c8fe70e02 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -557,7 +557,7 @@ proc longMode(n: PNode, start: int = 0, theEnd: int = - 1): bool =
 
 proc gstmts(g: var TSrcGen, n: PNode, c: TContext) = 
   if n.kind == nkEmpty: return 
-  if (n.kind == nkStmtList) or (n.kind == nkStmtListExpr): 
+  if n.kind in {nkStmtList, nkStmtListExpr, nkStmtListType}:
     indentNL(g)
     for i in countup(0, sonsLen(n) - 1): 
       optNL(g)
@@ -1069,7 +1069,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     put(g, tkSpaces, Space)
     putWithSpace(g, tkEquals, "=")
     gsub(g, n.sons[1])
-  of nkStmtList, nkStmtListExpr: gstmts(g, n, emptyContext)
+  of nkStmtList, nkStmtListExpr, nkStmtListType: gstmts(g, n, emptyContext)
   of nkIfStmt: 
     putWithSpace(g, tkIf, "if")
     gif(g, n)
@@ -1246,8 +1246,12 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
       put(g, tkBracketLe, "[")
       gcomma(g, n)
       put(g, tkBracketRi, "]")
+  of nkMetaNode:
+    put(g, tkParLe, "(META|")
+    gsub(g, n.sons[0])
+    put(g, tkParRi, ")")
   else: 
-    #nkNone, nkMetaNode, nkExplicitTypeListCall: 
+    #nkNone, nkExplicitTypeListCall: 
     InternalError(n.info, "rnimsyn.gsub(" & $n.kind & ')')
 
 proc renderTree(n: PNode, renderFlags: TRenderFlags = {}): string = 
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index a5f763519..aab4c82f5 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -51,7 +51,9 @@ proc semTypeTraits(c: PContext, n: PNode): PNode =
   checkMinSonsLen(n, 2)
   let t = n.sons[1].typ
   internalAssert t != nil
-  if not containsGenericType(t):
+  if t.kind == tyTypeDesc and t.len == 0:
+    result = n
+  elif not containsGenericType(t):
     result = evalTypeTrait(n[0], t, GetCurrOwner())
   else:
     # a typedesc variable, pass unmodified to evals
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 984cc4bb8..ef83860f7 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -1027,6 +1027,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
           if c.code[pc].opcode in {opcWrGlobal, opcWrGlobalRef} and
              c.code[pc].regBx == rb:
             break
+    of opcGlobalAlias:
+      let rb = instr.regBx - wordExcess - 1
+      regs[ra] = c.globals.sons[rb]
     inc pc
 
 proc fixType(result, n: PNode) {.inline.} =
@@ -1135,11 +1138,14 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
   # setup arguments:
   var L = n.safeLen
   if L == 0: L = 1
-  InternalAssert tos.slots.len >= L
+  # This is wrong for tests/reject/tind1.nim where the passed 'else' part
+  # doesn't end up in the parameter:
+  #InternalAssert tos.slots.len >= L
   # return value:
   tos.slots[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0])
   # setup parameters:
-  for i in 1 .. < L: tos.slots[i] = setupMacroParam(n.sons[i])
+  for i in 1 .. < min(tos.slots.len, L):
+    tos.slots[i] = setupMacroParam(n.sons[i])
   # temporary storage:
   for i in L .. <maxSlots: tos.slots[i] = newNode(nkEmpty)
   result = rawExecute(c, start, tos)
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index e31dc9de6..b2b900f66 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -122,6 +122,7 @@ type
     opcLdImmInt,  # dest = immediate value
     opcWrGlobal,
     opcWrGlobalRef,
+    opcGlobalAlias, # load an alias to a global into a register
     opcGlobalOnce,  # used to introduce an assignment to a global once
     opcSetType,   # dest.typ = types[Bx]
     opcTypeTrait
@@ -162,6 +163,8 @@ type
     blocks*: seq[TBlock]    # blocks; temp data structure
     slots*: array[TRegister, tuple[inUse: bool, kind: TSlotKind]]
     maxSlots*: int
+    globals*: array[TRegister, int] # hack: to support passing globals byref
+                                    # we map a slot persistently to a global
     
   PCtx* = ref TCtx
   TCtx* = object of passes.TPassContext # code gen context
@@ -185,7 +188,7 @@ type
   
 proc newCtx*(module: PSym): PCtx =
   PCtx(code: @[], debug: @[],
-    globals: newNode(nkStmtList), constants: newNode(nkStmtList), types: @[],
+    globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[],
     prc: PProc(blocks: @[]), module: module)
 
 proc refresh*(c: PCtx, module: PSym) =
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 6f07a2dfe..654738ce4 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -134,6 +134,21 @@ proc getTemp(c: PCtx; typ: PType): TRegister =
   c.slots[c.maxSlots] = (inUse: true, kind: k)
   inc c.maxSlots
 
+proc getGlobalSlot(c: PCtx; n: PNode; s: PSym): TRegister =
+  let p = c.prc
+  for i in 0 .. p.maxSlots-1:
+    if p.globals[i] == s.id: return TRegister(i)
+
+  result = TRegister(p.maxSlots)
+  p.slots[p.maxSlots] = (inUse: true, kind: slotFixedVar)
+  p.globals[p.maxSlots] = s.id
+  inc p.maxSlots
+  # XXX this is still not correct! We need to load the global in a proc init
+  # section, otherwise control flow could lead to a usage before it's been
+  # loaded.
+  c.gABx(n, opcGlobalAlias, result, s.position)
+  # XXX add some internal asserts here
+
 proc freeTemp(c: PCtx; r: TRegister) =
   let c = c.prc
   if c.slots[r].kind >= slotSomeTemp: c.slots[r].inUse = false
@@ -929,7 +944,7 @@ proc cannotEval(n: PNode) {.noinline.} =
     n.renderTree)
 
 proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
-  c.globals.add(emptyNode)
+  c.globals.add(emptyNode.copyNode)
   s.position = c.globals.len
   # This is rather hard to support, due to the laziness of the VM code
   # generator. See tests/compile/tmacro2 for why this is necesary:
@@ -946,11 +961,14 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
       discard
     else:
       cannotEval(n)
-    if dest < 0: dest = c.getTemp(s.typ)
     if s.position == 0:
       if sfImportc in s.flags: c.importcSym(n.info, s)
       else: genGlobalInit(c, n, s)
-    c.gABx(n, opcLdGlobal, dest, s.position)
+    if dest < 0:
+      dest = c.getGlobalSlot(n, s)
+      #c.gABx(n, opcAliasGlobal, dest, s.position)
+    else:
+      c.gABx(n, opcLdGlobal, dest, s.position)
   else:
     if s.position > 0 or (s.position == 0 and s.kind in {skParam, skResult}):
       if dest < 0:
diff --git a/tests/compile/tmacro2.nim b/tests/compile/tmacro2.nim
index e7bc648db..39324e497 100644
--- a/tests/compile/tmacro2.nim
+++ b/tests/compile/tmacro2.nim
@@ -26,7 +26,7 @@ macro importImpl_forward(name, returns): stmt {.immediate.} =
   p2.add newIdentNode("errors")
   p2.add newNimNode(nnkVarTy)
   p2.add newNimNode(nnkEmpty)
-  p2[1].add newNimNOde(nnkBracketExpr)
+  p2[1].add newNimNode(nnkBracketExpr)
   p2[1][0].add newIdentNode("seq")
   p2[1][0].add newIdentNode("string")
   res[3].add p2
diff --git a/tests/reject/twrongiter.nim b/tests/reject/twrongiter.nim
index 2d2502a6a..33394219b 100644
--- a/tests/reject/twrongiter.nim
+++ b/tests/reject/twrongiter.nim
@@ -1,5 +1,5 @@
 discard """
-line: 14
+line: 12
 errormsg: "type mismatch"
 """