diff options
author | Araq <rumpf_a@web.de> | 2013-12-13 01:21:23 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-12-13 01:21:23 +0100 |
commit | 328f1932925889d5bb7f91c68fb1504b9b26ba8c (patch) | |
tree | f26fa7993b085104fef4d54701d27eae5f40cc18 | |
parent | 6db20a4be8556621b3a33f87854b4b857c4dcf9e (diff) | |
download | Nim-328f1932925889d5bb7f91c68fb1504b9b26ba8c.tar.gz |
new VM: globals kinda work
-rw-r--r-- | compiler/renderer.nim | 10 | ||||
-rw-r--r-- | compiler/semmagic.nim | 4 | ||||
-rw-r--r-- | compiler/vm.nim | 10 | ||||
-rw-r--r-- | compiler/vmdef.nim | 5 | ||||
-rw-r--r-- | compiler/vmgen.nim | 24 | ||||
-rw-r--r-- | tests/compile/tmacro2.nim | 2 | ||||
-rw-r--r-- | tests/reject/twrongiter.nim | 2 |
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" """ |