new VM is getting stable

This commit is contained in:
Araq 2014-02-24 01:30:40 +01:00
commit 0c31686fec
10 changed files with 98 additions and 39 deletions

View file

@ -67,7 +67,7 @@ type
errAmbiguousCallXYZ, errWrongNumberOfArguments, errAmbiguousCallXYZ, errWrongNumberOfArguments,
errXCannotBePassedToProcVar, errXCannotBePassedToProcVar,
errXCannotBeInParamDecl, errPragmaOnlyInHeaderOfProc, errImplOfXNotAllowed, errXCannotBeInParamDecl, errPragmaOnlyInHeaderOfProc, errImplOfXNotAllowed,
errImplOfXexpected, errNoSymbolToBorrowFromFound, errDiscardValue, errImplOfXexpected, errNoSymbolToBorrowFromFound, errDiscardValueX,
errInvalidDiscard, errIllegalConvFromXtoY, errCannotBindXTwice, errInvalidDiscard, errIllegalConvFromXtoY, errCannotBindXTwice,
errInvalidOrderInArrayConstructor, errInvalidOrderInArrayConstructor,
errInvalidOrderInEnumX, errEnumXHasHoles, errExceptExpected, errInvalidTry, errInvalidOrderInEnumX, errEnumXHasHoles, errExceptExpected, errInvalidTry,
@ -264,7 +264,7 @@ const
errImplOfXNotAllowed: "implementation of \'$1\' is not allowed", errImplOfXNotAllowed: "implementation of \'$1\' is not allowed",
errImplOfXexpected: "implementation of \'$1\' expected", errImplOfXexpected: "implementation of \'$1\' expected",
errNoSymbolToBorrowFromFound: "no symbol to borrow from found", errNoSymbolToBorrowFromFound: "no symbol to borrow from found",
errDiscardValue: "value returned by statement has to be discarded", errDiscardValueX: "value of type '$1' has to be discarded",
errInvalidDiscard: "statement returns no value that can be discarded", errInvalidDiscard: "statement returns no value that can be discarded",
errIllegalConvFromXtoY: "conversion from $1 to $2 is invalid", errIllegalConvFromXtoY: "conversion from $1 to $2 is invalid",
errCannotBindXTwice: "cannot bind parameter \'$1\' twice", errCannotBindXTwice: "cannot bind parameter \'$1\' twice",

View file

@ -890,7 +890,7 @@ proc loadStub*(s: PSym) =
# deactivate the GC here because we do a deep recursion and generate no # deactivate the GC here because we do a deep recursion and generate no
# garbage when restoring parts of the object graph anyway. # garbage when restoring parts of the object graph anyway.
# Since we die with internal errors if this fails, so no try-finally is # Since we die with internal errors if this fails, no try-finally is
# necessary. # necessary.
GC_disable() GC_disable()
rawLoadStub(s) rawLoadStub(s)

View file

@ -220,7 +220,7 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
return nil return nil
result = fixupTypeAfterEval(c, result, e) result = fixupTypeAfterEval(c, result, e)
except: except ERecoverableError:
return nil return nil
proc semConstExpr(c: PContext, n: PNode): PNode = proc semConstExpr(c: PContext, n: PNode): PNode =

View file

@ -641,9 +641,11 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
result = evalStaticExpr(c.module, call, c.p.owner) result = evalStaticExpr(c.module, call, c.p.owner)
if result.isNil: if result.isNil:
localError(n.info, errCannotInterpretNodeX, renderTree(call)) localError(n.info, errCannotInterpretNodeX, renderTree(call))
else: result = fixupTypeAfterEval(c, result, n)
else: else:
result = evalConstExpr(c.module, call) result = evalConstExpr(c.module, call)
if result.isNil: result = n if result.isNil: result = n
else: result = fixupTypeAfterEval(c, result, n)
#if result != n: #if result != n:
# echo "SUCCESS evaluated at compile time: ", call.renderTree # echo "SUCCESS evaluated at compile time: ", call.renderTree
@ -653,6 +655,8 @@ proc semStaticExpr(c: PContext, n: PNode): PNode =
if result.isNil: if result.isNil:
localError(n.info, errCannotInterpretNodeX, renderTree(n)) localError(n.info, errCannotInterpretNodeX, renderTree(n))
result = emptyNode result = emptyNode
else:
result = fixupTypeAfterEval(c, result, a)
proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode, proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
flags: TExprFlags): PNode = flags: TExprFlags): PNode =

View file

@ -126,7 +126,7 @@ proc implicitlyDiscardable(n: PNode): bool =
proc fixNilType(n: PNode) = proc fixNilType(n: PNode) =
if isAtom(n): if isAtom(n):
if n.kind != nkNilLit and n.typ != nil: if n.kind != nkNilLit and n.typ != nil:
localError(n.info, errDiscardValue) localError(n.info, errDiscardValueX, n.typ.typeToString)
elif n.kind in {nkStmtList, nkStmtListExpr}: elif n.kind in {nkStmtList, nkStmtListExpr}:
n.kind = nkStmtList n.kind = nkStmtList
for it in n: fixNilType(it) for it in n: fixNilType(it)
@ -154,7 +154,7 @@ proc discardCheck(c: PContext, result: PNode) =
else: else:
var n = result var n = result
while n.kind in skipForDiscardable: n = n.lastSon while n.kind in skipForDiscardable: n = n.lastSon
localError(n.info, errDiscardValue) localError(n.info, errDiscardValueX, result.typ.typeToString)
proc semIf(c: PContext, n: PNode): PNode = proc semIf(c: PContext, n: PNode): PNode =
result = n result = n
@ -331,6 +331,7 @@ proc checkNilable(v: PSym) =
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
var b: PNode var b: PNode
result = copyNode(n) result = copyNode(n)
var hasCompileTime = false
for i in countup(0, sonsLen(n)-1): for i in countup(0, sonsLen(n)-1):
var a = n.sons[i] var a = n.sons[i]
if gCmd == cmdIdeTools: suggestStmt(c, a) if gCmd == cmdIdeTools: suggestStmt(c, a)
@ -405,6 +406,8 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
v.typ = tup.sons[j] v.typ = tup.sons[j]
b.sons[j] = newSymNode(v) b.sons[j] = newSymNode(v)
checkNilable(v) checkNilable(v)
if sfCompileTime in v.flags: hasCompileTime = true
if hasCompileTime: vm.setupCompileTimeVar(c.module, result)
proc semConst(c: PContext, n: PNode): PNode = proc semConst(c: PContext, n: PNode): PNode =
result = copyNode(n) result = copyNode(n)

View file

@ -109,11 +109,17 @@ template decodeBx(k: expr) {.immediate, dirty.} =
template move(a, b: expr) {.immediate, dirty.} = system.shallowCopy(a, b) template move(a, b: expr) {.immediate, dirty.} = system.shallowCopy(a, b)
# XXX fix minor 'shallowCopy' overloading bug in compiler # XXX fix minor 'shallowCopy' overloading bug in compiler
template createStr(x) = template createStrKeepNode(x) =
if x.node.isNil: x.node = newNode(nkStrLit) if x.node.isNil:
x.node = newNode(nkStrLit)
elif x.node.kind == nkNilLit: elif x.node.kind == nkNilLit:
system.reset(x.node[]) system.reset(x.node[])
x.node.kind = nkStrLit x.node.kind = nkStrLit
else:
assert x.node.kind in {nkStrLit..nkTripleStrLit}
template createStr(x) =
x.node = newNode(nkStrLit)
proc moveConst(x: var TRegister, y: TRegister) = proc moveConst(x: var TRegister, y: TRegister) =
if x.kind != y.kind: if x.kind != y.kind:
@ -254,7 +260,7 @@ proc opConv*(dest: var TRegister, src: TRegister, desttyp, srctyp: PType): bool
if dest.kind != rkNode: if dest.kind != rkNode:
myreset(dest) myreset(dest)
dest.kind = rkNode dest.kind = rkNode
dest.node = newNode(nkStrLit) dest.node = newNode(nkStrLit)
let styp = srctyp.skipTypes(abstractRange) let styp = srctyp.skipTypes(abstractRange)
case styp.kind case styp.kind
of tyEnum: of tyEnum:
@ -329,8 +335,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
#{.computedGoto.} #{.computedGoto.}
let instr = c.code[pc] let instr = c.code[pc]
let ra = instr.regA let ra = instr.regA
#echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra #if c.traceActive:
#message(c.debug[pc], warnUser, "gah") # echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra
# message(c.debug[pc], warnUser, "Trace")
case instr.opcode case instr.opcode
of opcEof: return regs[ra] of opcEof: return regs[ra]
of opcRet: of opcRet:
@ -354,7 +361,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
regs[ra].intVal = regs[rb].intVal regs[ra].intVal = regs[rb].intVal
of opcAsgnStr: of opcAsgnStr:
decodeB(rkNode) decodeB(rkNode)
createStr regs[ra] createStrKeepNode regs[ra]
regs[ra].node.strVal = regs[rb].node.strVal regs[ra].node.strVal = regs[rb].node.strVal
of opcAsgnFloat: of opcAsgnFloat:
decodeB(rkFloat) decodeB(rkFloat)
@ -454,7 +461,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
of opcWrDeref: of opcWrDeref:
# a[] = b # a[] = b
decodeBC(rkNode) decodeBC(rkNode)
putIntoNode(regs[ra].node, regs[rc]) putIntoNode(regs[ra].node, regs[rb])
of opcAddInt: of opcAddInt:
decodeBC(rkInt) decodeBC(rkInt)
regs[ra].intVal = regs[rb].intVal + regs[rc].intVal regs[ra].intVal = regs[rb].intVal + regs[rc].intVal
@ -484,8 +491,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
of opcInclRange: of opcInclRange:
decodeBC(rkNode) decodeBC(rkNode)
var r = newNode(nkRange) var r = newNode(nkRange)
r.add regs[rb].node r.add regs[rb].regToNode
r.add regs[rc].node r.add regs[rc].regToNode
addSon(regs[ra].node, r.copyTree) addSon(regs[ra].node, r.copyTree)
of opcExcl: of opcExcl:
decodeB(rkNode) decodeB(rkNode)
@ -643,15 +650,18 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
regs[ra].node.strVal.add getstr(regs[i]) regs[ra].node.strVal.add getstr(regs[i])
of opcAddStrCh: of opcAddStrCh:
decodeB(rkNode) decodeB(rkNode)
createStr regs[ra] createStrKeepNode regs[ra]
regs[ra].node.strVal.add(regs[rb].intVal.chr) regs[ra].node.strVal.add(regs[rb].intVal.chr)
of opcAddStrStr: of opcAddStrStr:
decodeB(rkNode) decodeB(rkNode)
createStr regs[ra] createStrKeepNode regs[ra]
regs[ra].node.strVal.add(regs[rb].node.strVal) regs[ra].node.strVal.add(regs[rb].node.strVal)
of opcAddSeqElem: of opcAddSeqElem:
decodeB(rkNode) decodeB(rkNode)
regs[ra].node.add(copyTree(regs[rb].node)) if regs[ra].node.kind == nkBracket:
regs[ra].node.add(copyTree(regs[rb].regToNode))
else:
stackTrace(c, tos, pc, errNilAccess)
of opcEcho: of opcEcho:
let rb = instr.regB let rb = instr.regB
for i in ra..ra+rb-1: for i in ra..ra+rb-1:
@ -660,7 +670,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
writeln(stdout, "") writeln(stdout, "")
of opcContainsSet: of opcContainsSet:
decodeBC(rkInt) decodeBC(rkInt)
regs[ra].intVal = ord(inSet(regs[rb].node, regs[rc].node)) regs[ra].intVal = ord(inSet(regs[rb].node, regs[rc].regToNode))
of opcSubStr: of opcSubStr:
decodeBC(rkNode) decodeBC(rkNode)
inc pc inc pc
@ -815,8 +825,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
ensureKind(rkNode) ensureKind(rkNode)
let typ = c.types[instr.regBx - wordExcess] let typ = c.types[instr.regBx - wordExcess]
regs[ra].node = getNullValue(typ, c.debug[pc]) regs[ra].node = getNullValue(typ, c.debug[pc])
if regs[ra].node.kind in {nkStrLit..nkTripleStrLit}: # opcLdNull really is the gist of the VM's problems: should it load
regs[ra].kind = rkNode # a fresh null to regs[ra].node or to regs[ra].node[]? This really
# depends on whether regs[ra] represents the variable itself or wether
# it holds the indirection! Due to the way registers are re-used we cannot
# say for sure here! --> The codegen has to deal with it
# via 'genAsgnPatch'.
of opcLdNullReg: of opcLdNullReg:
let typ = c.types[instr.regBx - wordExcess] let typ = c.types[instr.regBx - wordExcess]
if typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc}).kind in { if typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc}).kind in {
@ -858,7 +872,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
return TRegister(kind: rkNone) return TRegister(kind: rkNone)
of opcSetLenStr: of opcSetLenStr:
decodeB(rkNode) decodeB(rkNode)
createStr regs[ra] createStrKeepNode regs[ra]
regs[ra].node.strVal.setLen(regs[rb].intVal.int) regs[ra].node.strVal.setLen(regs[rb].intVal.int)
of opcOf: of opcOf:
decodeBC(rkInt) decodeBC(rkInt)
@ -1209,6 +1223,9 @@ proc evalStaticExpr*(module: PSym, e: PNode, prc: PSym): PNode =
proc evalStaticStmt*(module: PSym, e: PNode, prc: PSym) = proc evalStaticStmt*(module: PSym, e: PNode, prc: PSym) =
discard evalConstExprAux(module, prc, e, emStaticStmt) discard evalConstExprAux(module, prc, e, emStaticStmt)
proc setupCompileTimeVar*(module: PSym, n: PNode) =
discard evalConstExprAux(module, nil, n, emStaticStmt)
proc setupMacroParam(x: PNode): PNode = proc setupMacroParam(x: PNode): PNode =
result = x result = x
if result.kind in {nkHiddenSubConv, nkHiddenStdConv}: result = result.sons[1] if result.kind in {nkHiddenSubConv, nkHiddenStdConv}: result = result.sons[1]
@ -1250,3 +1267,4 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
if cyclicTree(result): globalError(n.info, errCyclicTree) if cyclicTree(result): globalError(n.info, errCyclicTree)
dec(evalMacroCounter) dec(evalMacroCounter)
c.callsite = nil c.callsite = nil
#debug result

View file

@ -163,8 +163,6 @@ type
blocks*: seq[TBlock] # blocks; temp data structure blocks*: seq[TBlock] # blocks; temp data structure
slots*: array[TRegister, tuple[inUse: bool, kind: TSlotKind]] slots*: array[TRegister, tuple[inUse: bool, kind: TSlotKind]]
maxSlots*: int maxSlots*: int
globals*: array[TRegister, int] # hack: to support passing globals byref
# we map a slot persistently to a global
PCtx* = ref TCtx PCtx* = ref TCtx
TCtx* = object of passes.TPassContext # code gen context TCtx* = object of passes.TPassContext # code gen context
@ -181,6 +179,7 @@ type
callsite*: PNode callsite*: PNode
mode*: TEvalMode mode*: TEvalMode
features*: TSandboxFlags features*: TSandboxFlags
traceActive*: bool
TPosition* = distinct int TPosition* = distinct int

View file

@ -451,9 +451,11 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) =
c.gABC(n, opcIndCallAsgn, dest, x, n.len) c.gABC(n, opcIndCallAsgn, dest, x, n.len)
c.freeTempRange(x, n.len) c.freeTempRange(x, n.len)
template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
proc needsAsgnPatch(n: PNode): bool = proc needsAsgnPatch(n: PNode): bool =
n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr, n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr,
nkDerefExpr, nkHiddenDeref} nkDerefExpr, nkHiddenDeref} or (n.kind == nkSym and n.sym.isGlobal)
proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) = proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
case le.kind case le.kind
@ -461,15 +463,25 @@ proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
let dest = c.genx(le.sons[0], {gfAddrOf}) let dest = c.genx(le.sons[0], {gfAddrOf})
let idx = c.genx(le.sons[1]) let idx = c.genx(le.sons[1])
c.gABC(le, opcWrArr, dest, idx, value) c.gABC(le, opcWrArr, dest, idx, value)
c.freeTemp(dest)
c.freeTemp(idx)
of nkDotExpr, nkCheckedFieldExpr: of nkDotExpr, nkCheckedFieldExpr:
# XXX field checks here # XXX field checks here
let left = if le.kind == nkDotExpr: le else: le.sons[0] let left = if le.kind == nkDotExpr: le else: le.sons[0]
let dest = c.genx(left.sons[0], {gfAddrOf}) let dest = c.genx(left.sons[0], {gfAddrOf})
let idx = c.genx(left.sons[1]) let idx = c.genx(left.sons[1])
c.gABC(left, opcWrObj, dest, idx, value) c.gABC(left, opcWrObj, dest, idx, value)
c.freeTemp(dest)
c.freeTemp(idx)
of nkDerefExpr, nkHiddenDeref: of nkDerefExpr, nkHiddenDeref:
let dest = c.genx(le.sons[0], {gfAddrOf}) let dest = c.genx(le.sons[0], {gfAddrOf})
c.gABC(le, opcWrDeref, dest, value) c.gABC(le, opcWrDeref, dest, value)
c.freeTemp(dest)
of nkSym:
if le.sym.isGlobal:
let dest = c.genx(le, {gfAddrOf})
c.gABC(le, opcWrDeref, dest, value)
c.freeTemp(dest)
else: else:
discard discard
@ -608,6 +620,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
c.genAddSubInt(n, dest, opcAddInt) c.genAddSubInt(n, dest, opcAddInt)
of mInc, mDec: of mInc, mDec:
unused(n, dest) unused(n, dest)
# XXX generates inefficient code for globals
var d = c.genx(n.sons[1]).TDest var d = c.genx(n.sons[1]).TDest
c.genAddSubInt(n, d, if m == mInc: opcAddInt else: opcSubInt) c.genAddSubInt(n, d, if m == mInc: opcAddInt else: opcSubInt)
c.genAsgnPatch(n.sons[1], d) c.genAsgnPatch(n.sons[1], d)
@ -621,6 +634,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
c.genNewSeq(n) c.genNewSeq(n)
of mNewString: of mNewString:
genUnaryABC(c, n, dest, opcNewStr) genUnaryABC(c, n, dest, opcNewStr)
# XXX buggy
of mNewStringOfCap: of mNewStringOfCap:
# we ignore the 'cap' argument and translate it as 'newString(0)'. # we ignore the 'cap' argument and translate it as 'newString(0)'.
# eval n.sons[1] for possible side effects: # eval n.sons[1] for possible side effects:
@ -629,6 +643,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
if dest < 0: dest = c.getTemp(n.typ) if dest < 0: dest = c.getTemp(n.typ)
c.gABC(n, opcNewStr, dest, tmp) c.gABC(n, opcNewStr, dest, tmp)
c.freeTemp(tmp) c.freeTemp(tmp)
# XXX buggy
of mLengthOpenArray, mLengthArray, mLengthSeq: of mLengthOpenArray, mLengthArray, mLengthSeq:
genUnaryABI(c, n, dest, opcLenSeq) genUnaryABI(c, n, dest, opcLenSeq)
of mLengthStr: of mLengthStr:
@ -955,8 +970,6 @@ proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
gABC(c, ri, whichAsgnOpc(ri), dest, tmp) gABC(c, ri, whichAsgnOpc(ri), dest, tmp)
c.freeTemp(tmp) c.freeTemp(tmp)
template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
proc setSlot(c: PCtx; v: PSym) = proc setSlot(c: PCtx; v: PSym) =
# XXX generate type initialization here? # XXX generate type initialization here?
if v.position == 0: if v.position == 0:
@ -1035,14 +1048,22 @@ proc cannotEval(n: PNode) {.noinline.} =
globalError(n.info, errGenerated, "cannot evaluate at compile time: " & globalError(n.info, errGenerated, "cannot evaluate at compile time: " &
n.renderTree) n.renderTree)
proc getNullValue*(typ: PType, info: TLineInfo): PNode
proc genGlobalInit(c: PCtx; n: PNode; s: PSym) = proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
c.globals.add(emptyNode.copyNode) c.globals.add(getNullValue(s.typ, n.info))
s.position = c.globals.len s.position = c.globals.len
# This is rather hard to support, due to the laziness of the VM code # This is rather hard to support, due to the laziness of the VM code
# generator. See tests/compile/tmacro2 for why this is necesary: # generator. See tests/compile/tmacro2 for why this is necesary:
# var decls{.compileTime.}: seq[PNimrodNode] = @[] # var decls{.compileTime.}: seq[PNimrodNode] = @[]
let dest = c.getTemp(s.typ)
c.gABx(n, opcLdGlobal, dest, s.position)
let tmp = c.genx(s.ast)
c.gABC(n, opcWrDeref, dest, tmp)
c.freeTemp(dest)
c.freeTemp(tmp)
proc genRdVar(c: PCtx; n: PNode; dest: var TDest) = proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
let s = n.sym let s = n.sym
if s.isGlobal: if s.isGlobal:
if sfCompileTime in s.flags or c.mode == emRepl: if sfCompileTime in s.flags or c.mode == emRepl:
@ -1052,7 +1073,14 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
if s.position == 0: if s.position == 0:
if sfImportc in s.flags: c.importcSym(n.info, s) if sfImportc in s.flags: c.importcSym(n.info, s)
else: genGlobalInit(c, n, s) else: genGlobalInit(c, n, s)
c.gABx(n, opcLdGlobal, dest, s.position) if dest < 0: dest = c.getTemp(n.typ)
if gfAddrOf notin flags and fitsRegister(s.typ):
var cc = c.getTemp(n.typ)
c.gABx(n, opcLdGlobal, cc, s.position)
c.gABC(n, opcNodeToReg, dest, cc)
c.freeTemp(cc)
else:
c.gABx(n, opcLdGlobal, dest, s.position)
else: else:
if s.kind == skForVar and c.mode == emRepl: c.setSlot s if s.kind == skForVar and c.mode == emRepl: c.setSlot s
if s.position > 0 or (s.position == 0 and if s.position > 0 or (s.position == 0 and
@ -1095,7 +1123,6 @@ proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
else: else:
genAccess(c, n, dest, opcLdArr, flags) genAccess(c, n, dest, opcLdArr, flags)
proc getNullValue*(typ: PType, info: TLineInfo): PNode
proc getNullValueAux(obj: PNode, result: PNode) = proc getNullValueAux(obj: PNode, result: PNode) =
case obj.kind case obj.kind
of nkRecList: of nkRecList:
@ -1161,7 +1188,7 @@ proc genVarSection(c: PCtx; n: PNode) =
setSlot(c, a[i].sym) setSlot(c, a[i].sym)
# v = t[i] # v = t[i]
var v: TDest = -1 var v: TDest = -1
genRdVar(c, a[i], v) genRdVar(c, a[i], v, {gfAddrOf})
c.gABC(n, opcWrObj, v, tmp, i) c.gABC(n, opcWrObj, v, tmp, i)
# XXX globals? # XXX globals?
c.freeTemp(tmp) c.freeTemp(tmp)
@ -1184,6 +1211,7 @@ proc genVarSection(c: PCtx; n: PNode) =
let val = c.genx(a.sons[2]) let val = c.genx(a.sons[2])
c.gABC(a, opcWrDeref, tmp, val) c.gABC(a, opcWrDeref, tmp, val)
c.freeTemp(val) c.freeTemp(val)
c.freeTemp(tmp)
else: else:
setSlot(c, s) setSlot(c, s)
if a.sons[2].kind == nkEmpty: if a.sons[2].kind == nkEmpty:
@ -1202,8 +1230,17 @@ proc genVarSection(c: PCtx; n: PNode) =
proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) = proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
if dest < 0: dest = c.getTemp(n.typ) if dest < 0: dest = c.getTemp(n.typ)
c.gABx(n, opcLdNull, dest, c.genType(n.typ)) c.gABx(n, opcLdNull, dest, c.genType(n.typ))
let intType = getSysType(tyInt)
let seqType = n.typ.skipTypes(abstractVar-{tyTypeDesc})
if seqType.kind == tySequence:
var tmp = c.getTemp(intType)
c.gABx(n, opcLdImmInt, tmp, n.len)
c.gABx(n, opcNewSeq, dest, c.genType(seqType))
c.gABx(n, opcNewSeq, tmp, 0)
c.freeTemp(tmp)
if n.len > 0: if n.len > 0:
let intType = getSysType(tyInt)
var tmp = getTemp(c, intType) var tmp = getTemp(c, intType)
c.gABx(n, opcLdNullReg, tmp, c.genType(intType)) c.gABx(n, opcLdNullReg, tmp, c.genType(intType))
for x in n: for x in n:
@ -1271,7 +1308,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
let s = n.sym let s = n.sym
case s.kind case s.kind
of skVar, skForVar, skTemp, skLet, skParam, skResult: of skVar, skForVar, skTemp, skLet, skParam, skResult:
genRdVar(c, n, dest) genRdVar(c, n, dest, flags)
of skProc, skConverter, skMacro, skTemplate, skMethod, skIterator: of skProc, skConverter, skMacro, skTemplate, skMethod, skIterator:
# 'skTemplate' is only allowed for 'getAst' support: # 'skTemplate' is only allowed for 'getAst' support:
if sfImportc in s.flags: c.importcSym(n.info, s) if sfImportc in s.flags: c.importcSym(n.info, s)
@ -1503,7 +1540,7 @@ proc genProc(c: PCtx; s: PSym): int =
c.gABC(body, opcEof, eofInstr.regA) c.gABC(body, opcEof, eofInstr.regA)
c.optimizeJumps(result) c.optimizeJumps(result)
s.offset = c.prc.maxSlots s.offset = c.prc.maxSlots
#if s.name.s == "traverse": #if s.name.s == "importImpl_forward" or s.name.s == "importImpl":
# c.echoCode(result) # c.echoCode(result)
# echo renderTree(body) # echo renderTree(body)
c.prc = oldPrc c.prc = oldPrc

View file

@ -51,7 +51,7 @@ macro okayy:stmt =
for node in decls: result.add node for node in decls: result.add node
for node in impls: result.add node for node in impls: result.add node
importimpl(Item, int): importImpl(Item, int):
echo 42 echo 42
importImpl(Foo, int16): importImpl(Foo, int16):
echo 77 echo 77

View file

@ -1,7 +1,6 @@
version 0.9.4 version 0.9.4
============= =============
- fix macros\tstringinterp.nim
- fix GC issues - fix GC issues
- test and fix showoff - test and fix showoff
@ -24,7 +23,6 @@ version 0.9.x
- implement 'union' and 'bits' pragmas - implement 'union' and 'bits' pragmas
- fix closures - fix closures
- test and fix exception handling
- ensure (ref T)(a, b) works as a type conversion and type constructor - ensure (ref T)(a, b) works as a type conversion and type constructor
- optimize 'genericReset'; 'newException' leads to code bloat - optimize 'genericReset'; 'newException' leads to code bloat
- stack-less GC - stack-less GC