diff options
Diffstat (limited to 'compiler/vmgen.nim')
-rw-r--r-- | compiler/vmgen.nim | 89 |
1 files changed, 44 insertions, 45 deletions
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 3a6004e8b..c6fd75259 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -211,22 +211,22 @@ proc getFreeRegister(cc: PCtx; k: TSlotKind; start: int): TRegister = # we prefer the same slot kind here for efficiency. Unfortunately for # discardable return types we may not know the desired type. This can happen # for e.g. mNAdd[Multiple]: - for i in start..c.maxSlots-1: - if c.slots[i].kind == k and not c.slots[i].inUse: - c.slots[i].inUse = true + for i in start..c.regInfo.len-1: + if c.regInfo[i].kind == k and not c.regInfo[i].inUse: + c.regInfo[i].inUse = true return TRegister(i) # if register pressure is high, we re-use more aggressively: - if c.maxSlots >= high(TRegister): - for i in start..c.maxSlots-1: - if not c.slots[i].inUse: - c.slots[i] = (inUse: true, kind: k) + if c.regInfo.len >= high(TRegister): + for i in start..c.regInfo.len-1: + if not c.regInfo[i].inUse: + c.regInfo[i] = (inUse: true, kind: k) return TRegister(i) - if c.maxSlots >= high(TRegister): + if c.regInfo.len >= high(TRegister): globalError(cc.config, cc.bestEffort, "VM problem: too many registers required") - result = TRegister(max(c.maxSlots, start)) - c.slots[result] = (inUse: true, kind: k) - c.maxSlots = result + 1 + result = TRegister(max(c.regInfo.len, start)) + c.regInfo.setLen int(result)+1 + c.regInfo[result] = (inUse: true, kind: k) proc getTemp(cc: PCtx; tt: PType): TRegister = let typ = tt.skipTypesOrNil({tyStatic}) @@ -244,29 +244,29 @@ proc getTemp(cc: PCtx; tt: PType): TRegister = proc freeTemp(c: PCtx; r: TRegister) = let c = c.prc - if c.slots[r].kind in {slotSomeTemp..slotTempComplex}: + if c.regInfo[r].kind in {slotSomeTemp..slotTempComplex}: # this seems to cause https://github.com/nim-lang/Nim/issues/10647 - c.slots[r].inUse = false + c.regInfo[r].inUse = false proc getTempRange(cc: PCtx; n: int; kind: TSlotKind): TRegister = # if register pressure is high, we re-use more aggressively: let c = cc.prc # we could also customize via the following (with proper caching in ConfigRef): # let highRegisterPressure = cc.config.getConfigVar("vm.highRegisterPressure", "40").parseInt - if c.maxSlots >= HighRegisterPressure or c.maxSlots+n >= high(TRegister): - for i in 0..c.maxSlots-n: - if not c.slots[i].inUse: + if c.regInfo.len >= HighRegisterPressure or c.regInfo.len+n >= high(TRegister): + for i in 0..c.regInfo.len-n: + if not c.regInfo[i].inUse: block search: for j in i+1..i+n-1: - if c.slots[j].inUse: break search + if c.regInfo[j].inUse: break search result = TRegister(i) - for k in result..result+n-1: c.slots[k] = (inUse: true, kind: kind) + for k in result..result+n-1: c.regInfo[k] = (inUse: true, kind: kind) return - if c.maxSlots+n >= high(TRegister): + if c.regInfo.len+n >= high(TRegister): globalError(cc.config, cc.bestEffort, "VM problem: too many registers required") - result = TRegister(c.maxSlots) - inc c.maxSlots, n - for k in result..result+n-1: c.slots[k] = (inUse: true, kind: kind) + result = TRegister(c.regInfo.len) + setLen c.regInfo, c.regInfo.len+n + for k in result..result+n-1: c.regInfo[k] = (inUse: true, kind: kind) proc freeTempRange(c: PCtx; start: TRegister, n: int) = for i in start..start+n-1: c.freeTemp(TRegister(i)) @@ -350,21 +350,21 @@ proc genWhile(c: PCtx; n: PNode) = c.patch(lab2) proc genBlock(c: PCtx; n: PNode; dest: var TDest) = - let oldRegisterCount = c.prc.maxSlots + let oldRegisterCount = c.prc.regInfo.len withBlock(n[0].sym): c.gen(n[1], dest) - for i in oldRegisterCount..<c.prc.maxSlots: - #if c.prc.slots[i].kind in {slotFixedVar, slotFixedLet}: + for i in oldRegisterCount..<c.prc.regInfo.len: + #if c.prc.regInfo[i].kind in {slotFixedVar, slotFixedLet}: if i != dest: when not defined(release): - if c.prc.slots[i].inUse and c.prc.slots[i].kind in {slotTempUnknown, + if c.prc.regInfo[i].inUse and c.prc.regInfo[i].kind in {slotTempUnknown, slotTempInt, slotTempFloat, slotTempStr, slotTempComplex}: - doAssert false, "leaking temporary " & $i & " " & $c.prc.slots[i].kind - c.prc.slots[i] = (inUse: false, kind: slotEmpty) + doAssert false, "leaking temporary " & $i & " " & $c.prc.regInfo[i].kind + c.prc.regInfo[i] = (inUse: false, kind: slotEmpty) c.clearDest(n, dest) @@ -416,7 +416,7 @@ proc genIf(c: PCtx, n: PNode; dest: var TDest) = c.clearDest(n, dest) proc isTemp(c: PCtx; dest: TDest): bool = - result = dest >= 0 and c.prc.slots[dest].kind >= slotTempUnknown + result = dest >= 0 and c.prc.regInfo[dest].kind >= slotTempUnknown proc genAndOr(c: PCtx; n: PNode; opc: TOpcode; dest: var TDest) = # asgn dest, a @@ -583,7 +583,7 @@ proc genLit(c: PCtx; n: PNode; dest: var TDest) = # assignments now: #var opc = opcLdConst if dest < 0: dest = c.getTemp(n.typ) - #elif c.prc.slots[dest].kind == slotFixedVar: opc = opcAsgnConst + #elif c.prc.regInfo[dest].kind == slotFixedVar: opc = opcAsgnConst let lit = genLiteral(c, n) c.gABx(n, opcLdConst, dest, lit) @@ -814,7 +814,7 @@ proc genVarargsABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) = var r: TRegister = x+i-1 c.gen(n[i], r) c.gABC(n, opc, dest, x, n.len-1) - c.freeTempRange(x, n.len) + c.freeTempRange(x, n.len-1) proc isInt8Lit(n: PNode): bool = if n.kind in {nkCharLit..nkUInt64Lit}: @@ -1431,11 +1431,11 @@ proc genAddr(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) = else: let tmp = c.genx(n[0], newflags) if dest < 0: dest = c.getTemp(n.typ) - if c.prc.slots[tmp].kind >= slotTempUnknown: + if c.prc.regInfo[tmp].kind >= slotTempUnknown: gABC(c, n, opcAddrNode, dest, tmp) # hack ahead; in order to fix bug #1781 we mark the temporary as # permanent, so that it's not used for anything else: - c.prc.slots[tmp].kind = slotTempPerm + c.prc.regInfo[tmp].kind = slotTempPerm # XXX this is still a hack #message(c.congig, n.info, warnUser, "suspicious opcode used") else: @@ -1662,10 +1662,10 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = s.kind in {skParam, skResult}): if dest < 0: dest = s.position + ord(s.kind == skParam) - internalAssert(c.config, c.prc.slots[dest].kind < slotSomeTemp) + internalAssert(c.config, c.prc.regInfo[dest].kind < slotSomeTemp) else: # we need to generate an assignment: - let requiresCopy = c.prc.slots[dest].kind >= slotSomeTemp and + let requiresCopy = c.prc.regInfo[dest].kind >= slotSomeTemp and gfIsParam notin flags genAsgn(c, dest, n, requiresCopy) else: @@ -2188,10 +2188,10 @@ proc genExpr*(c: PCtx; n: PNode, requiresValue = true): int = proc genParams(c: PCtx; params: PNode) = # res.sym.position is already 0 - c.prc.slots[0] = (inUse: true, kind: slotFixedVar) + setLen(c.prc.regInfo, max(params.len, 1)) + c.prc.regInfo[0] = (inUse: true, kind: slotFixedVar) for i in 1..<params.len: - c.prc.slots[i] = (inUse: true, kind: slotFixedLet) - c.prc.maxSlots = max(params.len, 1) + c.prc.regInfo[i] = (inUse: true, kind: slotFixedLet) proc finalJumpTarget(c: PCtx; pc, diff: int) = internalAssert(c.config, regBxMin < diff and diff < regBxMax) @@ -2201,12 +2201,12 @@ proc finalJumpTarget(c: PCtx; pc, diff: int) = TInstrType(diff+wordExcess) shl regBxShift).TInstr proc genGenericParams(c: PCtx; gp: PNode) = - var base = c.prc.maxSlots + var base = c.prc.regInfo.len + setLen c.prc.regInfo, base + gp.len for i in 0..<gp.len: var param = gp[i].sym param.position = base + i # XXX: fix this earlier; make it consistent with templates - c.prc.slots[base + i] = (inUse: true, kind: slotFixedLet) - c.prc.maxSlots = base + gp.len + c.prc.regInfo[base + i] = (inUse: true, kind: slotFixedLet) proc optimizeJumps(c: PCtx; start: int) = const maxIterations = 10 @@ -2280,19 +2280,18 @@ proc genProc(c: PCtx; s: PSym): int = if tfCapturesEnv in s.typ.flags: #let env = s.ast[paramsPos].lastSon.sym #assert env.position == 2 - c.prc.slots[c.prc.maxSlots] = (inUse: true, kind: slotFixedLet) - inc c.prc.maxSlots + c.prc.regInfo.add (inUse: true, kind: slotFixedLet) gen(c, body) # generate final 'return' statement: c.gABC(body, opcRet) c.patch(procStart) c.gABC(body, opcEof, eofInstr.regA) c.optimizeJumps(result) - s.offset = c.prc.maxSlots + s.offset = c.prc.regInfo.len #if s.name.s == "main" or s.name.s == "[]": # echo renderTree(body) # c.echoCode(result) c.prc = oldPrc else: - c.prc.maxSlots = s.offset + c.prc.regInfo.setLen s.offset result = pos |