diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2019-11-28 09:56:02 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-11-28 09:56:02 +0100 |
commit | abe07eb75d31189e8afea90c3c8608574f1a0751 (patch) | |
tree | e32eb4ed08c0accc79975d2567b018c622b0eecd /compiler | |
parent | d4cae118dcf6248122ecfaf109fde826dbd5da45 (diff) | |
download | Nim-abe07eb75d31189e8afea90c3c8608574f1a0751.tar.gz |
VM: improvements for var T/addr (#12667); fixes #12489
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/vm.nim | 27 | ||||
-rw-r--r-- | compiler/vmdef.nim | 2 | ||||
-rw-r--r-- | compiler/vmgen.nim | 22 |
3 files changed, 43 insertions, 8 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim index 52faeaf38..ce473c12a 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -606,6 +606,17 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = regs[ra].node = src.sons[idx] else: stackTrace(c, tos, pc, formatErrorIndexBound(idx, src.len-1)) + of opcLdArrAddr: + # a = addr(b[c]) + decodeBC(rkNodeAddr) + if regs[rc].intVal > high(int): + stackTrace(c, tos, pc, formatErrorIndexBound(regs[rc].intVal, high(int))) + let idx = regs[rc].intVal.int + let src = if regs[rb].kind == rkNode: regs[rb].node else: regs[rb].nodeAddr[] + if src.kind notin {nkEmpty..nkTripleStrLit} and idx <% src.len: + regs[ra].nodeAddr = addr src.sons[idx] + else: + stackTrace(c, tos, pc, formatErrorIndexBound(idx, src.len-1)) of opcLdStrIdx: decodeBC(rkInt) let idx = regs[rc].intVal.int @@ -643,9 +654,25 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = else: let n = src.sons[rc] regs[ra].node = n + of opcLdObjAddr: + # a = addr(b.c) + decodeBC(rkNodeAddr) + let src = if regs[rb].kind == rkNode: regs[rb].node else: regs[rb].nodeAddr[] + case src.kind + of nkEmpty..nkNilLit: + stackTrace(c, tos, pc, errNilAccess) + of nkObjConstr: + let n = src.sons[rc + 1] + if n.kind == nkExprColonExpr: + regs[ra].nodeAddr = addr n.sons[1] + else: + regs[ra].nodeAddr = addr src.sons[rc + 1] + else: + regs[ra].nodeAddr = addr src.sons[rc] of opcWrObj: # a.b = c decodeBC(rkNode) + assert regs[ra].node != nil let shiftedRb = rb + ord(regs[ra].node.kind == nkObjConstr) let dest = regs[ra].node if dest.kind == nkNilLit: diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index 54c18b03a..06e309678 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -42,8 +42,10 @@ type opcNodeToReg, opcLdArr, # a = b[c] + opcLdArrAddr, # a = addr(b[c]) opcWrArr, # a[b] = c opcLdObj, # a = b.c + opcLdObjAddr, # a = addr(b.c) opcWrObj, # a.b = c opcAddrReg, opcAddrNode, diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index cd66e3301..668c496c6 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1417,12 +1417,11 @@ proc genAddr(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) = gen(c, m, dest, flags) return - let af = if n[0].kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr}: {gfNode} - else: {gfNodeAddr} - let newflags = flags-{gfNode, gfNodeAddr}+af + let newflags = flags-{gfNode}+{gfNodeAddr} - if isGlobal(n.sons[0]): - gen(c, n.sons[0], dest, flags+af) + if isGlobal(n.sons[0]) or n[0].kind in {nkDotExpr, nkCheckedFieldExpr, nkBracketExpr}: + # checking for this pattern: addr(obj.field) / addr(array[i]) + gen(c, n.sons[0], dest, newflags) else: let tmp = c.genx(n.sons[0], newflags) if dest < 0: dest = c.getTemp(n.typ) @@ -1663,7 +1662,9 @@ proc genArrAccessOpcode(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; let a = c.genx(n.sons[0], flags) let b = c.genIndex(n.sons[1], n.sons[0].typ) if dest < 0: dest = c.getTemp(n.typ) - if needsRegLoad(): + if opc == opcLdArr and {gfNodeAddr} * flags != {}: + c.gABC(n, opcLdArrAddr, dest, a, b) + elif needsRegLoad(): var cc = c.getTemp(n.typ) c.gABC(n, opc, cc, a, b) c.gABC(n, opcNodeToReg, dest, cc) @@ -1679,7 +1680,9 @@ proc genObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = let a = c.genx(n.sons[0], flags) let b = genField(c, n.sons[1]) if dest < 0: dest = c.getTemp(n.typ) - if needsRegLoad(): + if {gfNodeAddr} * flags != {}: + c.gABC(n, opcLdObjAddr, dest, a, b) + elif needsRegLoad(): var cc = c.getTemp(n.typ) c.gABC(n, opcLdObj, cc, a, b) c.gABC(n, opcNodeToReg, dest, cc) @@ -1733,7 +1736,10 @@ proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = # Load the content now if dest < 0: dest = c.getTemp(n.typ) let fieldPos = genField(c, field) - if needsRegLoad(): + + if {gfNodeAddr} * flags != {}: + c.gABC(n, opcLdObjAddr, dest, objR, fieldPos) + elif needsRegLoad(): var cc = c.getTemp(accessExpr.typ) c.gABC(n, opcLdObj, cc, objR, fieldPos) c.gABC(n, opcNodeToReg, dest, cc) |