diff options
-rw-r--r-- | compiler/vm.nim | 20 | ||||
-rw-r--r-- | compiler/vmdef.nim | 2 | ||||
-rw-r--r-- | compiler/vmgen.nim | 35 |
3 files changed, 32 insertions, 25 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim index a7980ae1d..b57db3aaa 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -216,6 +216,18 @@ proc asgnComplex(x: var TFullReg, y: TFullReg) = of rkRegisterAddr: x.regAddr = y.regAddr of rkNodeAddr: x.nodeAddr = y.nodeAddr +proc fastAsgnComplex(x: var TFullReg, y: TFullReg) = + if x.kind != y.kind: + myreset(x) + x.kind = y.kind + case x.kind + of rkNone: discard + of rkInt: x.intVal = y.intVal + of rkFloat: x.floatVal = y.floatVal + of rkNode: x.node = y.node + of rkRegisterAddr: x.regAddr = y.regAddr + of rkNodeAddr: x.nodeAddr = y.nodeAddr + proc writeField(n: var PNode, x: TFullReg) = case x.kind of rkNone: discard @@ -535,10 +547,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcAsgnInt: decodeB(rkInt) regs[ra].intVal = regs[rb].intVal - of opcAsgnStr: - decodeBC(rkNode) - createStrKeepNode regs[ra], rc != 0 - regs[ra].node.strVal = regs[rb].node.strVal of opcAsgnFloat: decodeB(rkFloat) regs[ra].floatVal = regs[rb].floatVal @@ -560,6 +568,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = regs[ra].floatVal = cast[float64](int64(regs[rb].intVal)) of opcAsgnComplex: asgnComplex(regs[ra], regs[instr.regB]) + of opcFastAsgnComplex: + fastAsgnComplex(regs[ra], regs[instr.regB]) of opcAsgnRef: asgnRef(regs[ra], regs[instr.regB]) of opcNodeToReg: @@ -976,11 +986,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = regs[ra].node.strVal.add getstr(regs[i]) of opcAddStrCh: decodeB(rkNode) - #createStrKeepNode regs[ra] regs[ra].node.strVal.add(regs[rb].intVal.chr) of opcAddStrStr: decodeB(rkNode) - #createStrKeepNode regs[ra] regs[ra].node.strVal.add(regs[rb].node.strVal) of opcAddSeqElem: decodeB(rkNode) diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index 17c133b08..f530ceeb2 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -31,7 +31,6 @@ type opcYldVal, # yield with a value opcAsgnInt, - opcAsgnStr, opcAsgnFloat, opcAsgnRef, opcAsgnIntFromFloat32, # int and float must be of the same byte size @@ -39,6 +38,7 @@ type opcAsgnFloat32FromInt, # int and float must be of the same byte size opcAsgnFloat64FromInt, # int and float must be of the same byte size opcAsgnComplex, + opcFastAsgnComplex, opcNodeToReg, opcLdArr, # a = b[c] diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 648ab926c..58e3a35eb 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -43,6 +43,7 @@ type TGenFlag = enum gfNode # Affects how variables are loaded - always loads as rkNode gfNodeAddr # Affects how variables are loaded - always loads as rkNodeAddr + gfIsParam # do not deepcopy parameters, they are immutable TGenFlags = set[TGenFlag] proc debugInfo(c: PCtx; info: TLineInfo): string = @@ -568,7 +569,7 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) = # let paramType = fntyp.n.sons[i] # if paramType.typ.isCompileTimeOnly: continue var r: TRegister = x+i - c.gen(n.sons[i], r) + c.gen(n.sons[i], r, {gfIsParam}) if i >= fntyp.len: internalAssert c.config, tfVarargs in fntyp.flags c.gABx(n, opcSetType, r, c.genType(n.sons[i].typ)) @@ -917,20 +918,16 @@ proc ldNullOpcode(t: PType): TOpcode = assert t != nil if fitsRegister(t): opcLdNullReg else: opcLdNull -proc whichAsgnOpc(n: PNode): TOpcode = +proc whichAsgnOpc(n: PNode; requiresCopy = true): TOpcode = case n.typ.skipTypes(abstractRange+{tyOwned}-{tyTypeDesc}).kind of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64: opcAsgnInt - of tyString, tyCString: - opcAsgnStr of tyFloat..tyFloat128: opcAsgnFloat of tyRef, tyNil, tyVar, tyLent, tyPtr: opcAsgnRef else: - opcAsgnComplex - -proc whichAsgnOpc(n: PNode; opc: TOpcode): TOpcode = opc + (if requiresCopy: opcAsgnComplex else: opcFastAsgnComplex) proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) = case m @@ -1317,7 +1314,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) = let a = c.genx(arg) assert dest >= 0 if dest < 0: dest = c.getTemp(arg.typ) - gABC(c, arg, whichAsgnOpc(arg), dest, a, 1) + gABC(c, arg, whichAsgnOpc(arg, requiresCopy=false), dest, a) # XXX use ldNullOpcode() here? c.gABx(n, opcLdNull, a, c.genType(arg.typ)) c.gABx(n, opcNodeToReg, a, a) @@ -1419,7 +1416,7 @@ proc genDeref(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) = proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) = let tmp = c.genx(ri) assert dest >= 0 - gABC(c, ri, whichAsgnOpc(ri), dest, tmp, 1-ord(requiresCopy)) + gABC(c, ri, whichAsgnOpc(ri, requiresCopy), dest, tmp) c.freeTemp(tmp) proc setSlot(c: PCtx; v: PSym) = @@ -1465,7 +1462,7 @@ template needsAdditionalCopy(n): untyped = proc genAdditionalCopy(c: PCtx; n: PNode; opc: TOpcode; dest, idx, value: TRegister) = var cc = c.getTemp(n.typ) - c.gABC(n, whichAsgnOpc(n), cc, value, 0) + c.gABC(n, whichAsgnOpc(n), cc, value) c.gABC(n, opc, dest, idx, cc) c.freeTemp(cc) @@ -1529,7 +1526,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) = if needsAdditionalCopy(le) and s.kind in {skResult, skVar, skParam}: var cc = c.getTemp(le.typ) gen(c, ri, cc) - c.gABC(le, whichAsgnOpc(le), dest, cc, 1) + c.gABC(le, whichAsgnOpc(le), dest, cc) c.freeTemp(cc) else: gen(c, ri, dest) @@ -1608,7 +1605,9 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = internalAssert(c.config, c.prc.slots[dest].kind < slotSomeTemp) else: # we need to generate an assignment: - genAsgn(c, dest, n, c.prc.slots[dest].kind >= slotSomeTemp) + let requiresCopy = c.prc.slots[dest].kind >= slotSomeTemp and + gfIsParam notin flags + genAsgn(c, dest, n, requiresCopy) else: # see tests/t99bott for an example that triggers it: cannotEval(c, n) @@ -1818,7 +1817,7 @@ proc genVarSection(c: PCtx; n: PNode) = if not fitsRegister(le.typ) and s.kind in {skResult, skVar, skParam}: var cc = c.getTemp(le.typ) gen(c, a.sons[2], cc) - c.gABC(le, whichAsgnOpc(le), s.position.TRegister, cc, 1) + c.gABC(le, whichAsgnOpc(le), s.position.TRegister, cc) c.freeTemp(cc) else: gen(c, a.sons[2], s.position.TRegister) @@ -1849,7 +1848,7 @@ proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) = c.gABx(n, opcLdNullReg, tmp, c.genType(intType)) for x in n: let a = c.genx(x) - c.preventFalseAlias(n, whichAsgnOpc(x, opcWrArr), dest, tmp, a) + c.preventFalseAlias(n, opcWrArr, dest, tmp, a) c.gABI(n, opcAddImmInt, tmp, tmp, 1) c.freeTemp(a) c.freeTemp(tmp) @@ -1881,7 +1880,7 @@ proc genObjConstr(c: PCtx, n: PNode, dest: var TDest) = if it.kind == nkExprColonExpr and it.sons[0].kind == nkSym: let idx = genField(c, it.sons[0]) let tmp = c.genx(it.sons[1]) - c.preventFalseAlias(it.sons[1], whichAsgnOpc(it.sons[1], opcWrObj), + c.preventFalseAlias(it.sons[1], opcWrObj, dest, idx, tmp) c.freeTemp(tmp) else: @@ -1896,12 +1895,12 @@ proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) = if it.kind == nkExprColonExpr: let idx = genField(c, it.sons[0]) let tmp = c.genx(it.sons[1]) - c.preventFalseAlias(it.sons[1], whichAsgnOpc(it.sons[1], opcWrObj), + c.preventFalseAlias(it.sons[1], opcWrObj, dest, idx, tmp) c.freeTemp(tmp) else: let tmp = c.genx(it) - c.preventFalseAlias(it, whichAsgnOpc(it, opcWrObj), dest, i.TRegister, tmp) + c.preventFalseAlias(it, opcWrObj, dest, i.TRegister, tmp) c.freeTemp(tmp) proc genProc*(c: PCtx; s: PSym): int @@ -2065,7 +2064,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = c.freeTemp(tmp1) c.freeTemp(tmp2) if dest >= 0: - gABC(c, n, whichAsgnOpc(n), dest, tmp0, 1) + gABC(c, n, whichAsgnOpc(n), dest, tmp0) c.freeTemp(tmp0) else: dest = tmp0 |