parent
d4cae118dc
commit
abe07eb75d
6 changed files with 156 additions and 11 deletions
|
|
@ -606,6 +606,17 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
regs[ra].node = src.sons[idx]
|
regs[ra].node = src.sons[idx]
|
||||||
else:
|
else:
|
||||||
stackTrace(c, tos, pc, formatErrorIndexBound(idx, src.len-1))
|
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:
|
of opcLdStrIdx:
|
||||||
decodeBC(rkInt)
|
decodeBC(rkInt)
|
||||||
let idx = regs[rc].intVal.int
|
let idx = regs[rc].intVal.int
|
||||||
|
|
@ -643,9 +654,25 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
else:
|
else:
|
||||||
let n = src.sons[rc]
|
let n = src.sons[rc]
|
||||||
regs[ra].node = n
|
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:
|
of opcWrObj:
|
||||||
# a.b = c
|
# a.b = c
|
||||||
decodeBC(rkNode)
|
decodeBC(rkNode)
|
||||||
|
assert regs[ra].node != nil
|
||||||
let shiftedRb = rb + ord(regs[ra].node.kind == nkObjConstr)
|
let shiftedRb = rb + ord(regs[ra].node.kind == nkObjConstr)
|
||||||
let dest = regs[ra].node
|
let dest = regs[ra].node
|
||||||
if dest.kind == nkNilLit:
|
if dest.kind == nkNilLit:
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,10 @@ type
|
||||||
opcNodeToReg,
|
opcNodeToReg,
|
||||||
|
|
||||||
opcLdArr, # a = b[c]
|
opcLdArr, # a = b[c]
|
||||||
|
opcLdArrAddr, # a = addr(b[c])
|
||||||
opcWrArr, # a[b] = c
|
opcWrArr, # a[b] = c
|
||||||
opcLdObj, # a = b.c
|
opcLdObj, # a = b.c
|
||||||
|
opcLdObjAddr, # a = addr(b.c)
|
||||||
opcWrObj, # a.b = c
|
opcWrObj, # a.b = c
|
||||||
opcAddrReg,
|
opcAddrReg,
|
||||||
opcAddrNode,
|
opcAddrNode,
|
||||||
|
|
|
||||||
|
|
@ -1417,12 +1417,11 @@ proc genAddr(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) =
|
||||||
gen(c, m, dest, flags)
|
gen(c, m, dest, flags)
|
||||||
return
|
return
|
||||||
|
|
||||||
let af = if n[0].kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr}: {gfNode}
|
let newflags = flags-{gfNode}+{gfNodeAddr}
|
||||||
else: {gfNodeAddr}
|
|
||||||
let newflags = flags-{gfNode, gfNodeAddr}+af
|
|
||||||
|
|
||||||
if isGlobal(n.sons[0]):
|
if isGlobal(n.sons[0]) or n[0].kind in {nkDotExpr, nkCheckedFieldExpr, nkBracketExpr}:
|
||||||
gen(c, n.sons[0], dest, flags+af)
|
# checking for this pattern: addr(obj.field) / addr(array[i])
|
||||||
|
gen(c, n.sons[0], dest, newflags)
|
||||||
else:
|
else:
|
||||||
let tmp = c.genx(n.sons[0], newflags)
|
let tmp = c.genx(n.sons[0], newflags)
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
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 a = c.genx(n.sons[0], flags)
|
||||||
let b = c.genIndex(n.sons[1], n.sons[0].typ)
|
let b = c.genIndex(n.sons[1], n.sons[0].typ)
|
||||||
if dest < 0: dest = c.getTemp(n.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)
|
var cc = c.getTemp(n.typ)
|
||||||
c.gABC(n, opc, cc, a, b)
|
c.gABC(n, opc, cc, a, b)
|
||||||
c.gABC(n, opcNodeToReg, dest, cc)
|
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 a = c.genx(n.sons[0], flags)
|
||||||
let b = genField(c, n.sons[1])
|
let b = genField(c, n.sons[1])
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
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)
|
var cc = c.getTemp(n.typ)
|
||||||
c.gABC(n, opcLdObj, cc, a, b)
|
c.gABC(n, opcLdObj, cc, a, b)
|
||||||
c.gABC(n, opcNodeToReg, dest, cc)
|
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
|
# Load the content now
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
let fieldPos = genField(c, field)
|
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)
|
var cc = c.getTemp(accessExpr.typ)
|
||||||
c.gABC(n, opcLdObj, cc, objR, fieldPos)
|
c.gABC(n, opcLdObj, cc, objR, fieldPos)
|
||||||
c.gABC(n, opcNodeToReg, dest, cc)
|
c.gABC(n, opcNodeToReg, dest, cc)
|
||||||
|
|
|
||||||
110
tests/vm/taddrof.nim
Normal file
110
tests/vm/taddrof.nim
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
discard """
|
||||||
|
nimout: '''
|
||||||
|
true
|
||||||
|
true
|
||||||
|
[nil, nil, nil, nil]
|
||||||
|
[MyObjectRef(123, 321), nil, nil, nil]
|
||||||
|
['A', '\x00', '\x00', '\x00']
|
||||||
|
MyObjectRef(123, 321)
|
||||||
|
(key: 8, val: 0)
|
||||||
|
'''
|
||||||
|
output: '''
|
||||||
|
true
|
||||||
|
true
|
||||||
|
[nil, nil, nil, nil]
|
||||||
|
[MyObjectRef(123, 321), nil, nil, nil]
|
||||||
|
['A', '\x00', '\x00', '\x00']
|
||||||
|
MyObjectRef(123, 321)
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
type
|
||||||
|
MyObjectRef = ref object
|
||||||
|
a,b: int
|
||||||
|
|
||||||
|
MyContainerObject = ref object
|
||||||
|
member: MyObjectRef
|
||||||
|
|
||||||
|
MySuperContainerObject = ref object
|
||||||
|
member: MyContainerObject
|
||||||
|
arr: array[4, MyObjectRef]
|
||||||
|
|
||||||
|
MyOtherObject = ref object
|
||||||
|
case kind: bool
|
||||||
|
of true:
|
||||||
|
member: MyObjectRef
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc `$`(arg: MyObjectRef): string =
|
||||||
|
result = "MyObjectRef("
|
||||||
|
result.addInt arg.a
|
||||||
|
result.add ", "
|
||||||
|
result.addInt arg.b
|
||||||
|
result.add ")"
|
||||||
|
|
||||||
|
proc foobar(dst: var MyObjectRef) =
|
||||||
|
dst = new(MyObjectRef)
|
||||||
|
dst.a = 123
|
||||||
|
dst.b = 321
|
||||||
|
|
||||||
|
proc changeChar(c: var char) =
|
||||||
|
c = 'A'
|
||||||
|
|
||||||
|
proc test() =
|
||||||
|
# when it comes from a var, it works
|
||||||
|
var y: MyObjectRef
|
||||||
|
foobar(y)
|
||||||
|
echo y != nil
|
||||||
|
# when it comes from a member, it fails on VM
|
||||||
|
var x = new(MyContainerObject)
|
||||||
|
foobar(x.member)
|
||||||
|
echo x.member != nil
|
||||||
|
|
||||||
|
# when it comes from an array, it fails on VM
|
||||||
|
var arr: array[4, MyObjectRef]
|
||||||
|
echo arr
|
||||||
|
foobar(arr[0])
|
||||||
|
echo arr
|
||||||
|
|
||||||
|
var arr2: array[4, char]
|
||||||
|
changeChar(arr2[0])
|
||||||
|
echo arr2
|
||||||
|
|
||||||
|
|
||||||
|
var z = MyOtherObject(kind: true)
|
||||||
|
foobar(z.member)
|
||||||
|
echo z.member
|
||||||
|
|
||||||
|
# this still doesn't work
|
||||||
|
# var sc = new(MySuperContainerObject)
|
||||||
|
# sc.member = new(MyContainerObject)
|
||||||
|
# foobar(sc.member.member)
|
||||||
|
# echo sc.member.member
|
||||||
|
# foobar(sc.arr[1])
|
||||||
|
# echo sc.arr
|
||||||
|
|
||||||
|
#var str = "---"
|
||||||
|
#changeChar(str[1])
|
||||||
|
#echo str
|
||||||
|
|
||||||
|
test()
|
||||||
|
static:
|
||||||
|
test()
|
||||||
|
|
||||||
|
type T = object
|
||||||
|
f: seq[tuple[key, val: int]]
|
||||||
|
|
||||||
|
proc foo(s: var seq[tuple[key, val: int]]; i: int) =
|
||||||
|
s[i].key = 4*i
|
||||||
|
# r4 = addr(s[i])
|
||||||
|
# r4[0] = 4*i
|
||||||
|
|
||||||
|
proc bar() =
|
||||||
|
var s: T
|
||||||
|
s.f = newSeq[tuple[key, val: int]](3)
|
||||||
|
foo(s.f, 2)
|
||||||
|
echo s.f[2]
|
||||||
|
|
||||||
|
static:
|
||||||
|
bar()
|
||||||
|
|
@ -42,7 +42,7 @@ proc getOrElse[T](o: Option[T], def: T): T =
|
||||||
proc quoteStr(s: string): Option[string] =
|
proc quoteStr(s: string): Option[string] =
|
||||||
s.some.notEmpty.map(v => "`" & v & "`")
|
s.some.notEmpty.map(v => "`" & v & "`")
|
||||||
|
|
||||||
macro str(s: string): typed =
|
macro str(s: string): void =
|
||||||
let x = s.strVal
|
let x = s.strVal
|
||||||
let y = quoteStr(x)
|
let y = quoteStr(x)
|
||||||
let sn = newStrLitNode(y.getOrElse("NONE"))
|
let sn = newStrLitNode(y.getOrElse("NONE"))
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ discard """
|
||||||
# bug #3731
|
# bug #3731
|
||||||
var list {.compileTime.} = newSeq[int]()
|
var list {.compileTime.} = newSeq[int]()
|
||||||
|
|
||||||
macro calc*(): typed =
|
macro calc*(): void =
|
||||||
list.add(1)
|
list.add(1)
|
||||||
for c in list.mitems:
|
for c in list.mitems:
|
||||||
c = 13
|
c = 13
|
||||||
|
|
@ -19,7 +19,7 @@ calc()
|
||||||
|
|
||||||
# bug #3859
|
# bug #3859
|
||||||
import macros
|
import macros
|
||||||
macro m: typed =
|
macro m: void =
|
||||||
var s = newseq[NimNode](3)
|
var s = newseq[NimNode](3)
|
||||||
# var s: array[3,NimNode] # not working either
|
# var s: array[3,NimNode] # not working either
|
||||||
for i in 0..<s.len: s[i] = newLit(3) # works
|
for i in 0..<s.len: s[i] = newLit(3) # works
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue