Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
 (#19902) [backport]

* revert #12217 since the root problem seems to have been fixed; fix #15974;fix #12551; fix #19464

* fix #16020; fix #16780

* fix tests and #16613

* fix #14553

* fix #19909; skip skipRegisterAddr

* fix #18641
  • Loading branch information
ringabout authored Jun 22, 2022
1 parent a65db5e commit 3cb2d7a
Show file tree
Hide file tree
Showing 4 changed files with 263 additions and 14 deletions.
28 changes: 18 additions & 10 deletions compiler/vm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,7 @@ when not defined(nimHasSinkInference):

template takeAddress(reg, source) =
reg.nodeAddr = addr source
when defined(gcDestructors):
GC_ref source
GC_ref source

proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
var pc = start
Expand Down Expand Up @@ -1011,6 +1010,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
decodeBC(rkInt)
template getTyp(n): untyped =
n.typ.skipTypes(abstractInst)
template skipRegisterAddr(n: TFullReg): TFullReg =
var tmp = n
while tmp.kind == rkRegisterAddr:
tmp = tmp.regAddr[]
tmp

proc ptrEquality(n1: ptr PNode, n2: PNode): bool =
## true if n2.intVal represents a ptr equal to n1
let p1 = cast[int](n1)
Expand All @@ -1024,16 +1029,19 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
return t2.kind in PtrLikeKinds and n2.intVal == p1
else: return false

if regs[rb].kind == rkNodeAddr:
if regs[rc].kind == rkNodeAddr:
ret = regs[rb].nodeAddr == regs[rc].nodeAddr
let rbReg = skipRegisterAddr(regs[rb])
let rcReg = skipRegisterAddr(regs[rc])

if rbReg.kind == rkNodeAddr:
if rcReg.kind == rkNodeAddr:
ret = rbReg.nodeAddr == rcReg.nodeAddr
else:
ret = ptrEquality(regs[rb].nodeAddr, regs[rc].node)
elif regs[rc].kind == rkNodeAddr:
ret = ptrEquality(regs[rc].nodeAddr, regs[rb].node)
ret = ptrEquality(rbReg.nodeAddr, rcReg.node)
elif rcReg.kind == rkNodeAddr:
ret = ptrEquality(rcReg.nodeAddr, rbReg.node)
else:
let nb = regs[rb].node
let nc = regs[rc].node
let nb = rbReg.node
let nc = rcReg.node
if nb.kind != nc.kind: discard
elif (nb == nc) or (nb.kind == nkNilLit): ret = true # intentional
elif nb.kind in {nkSym, nkTupleConstr, nkClosure} and nb.typ != nil and nb.typ.kind == tyProc and sameConstant(nb, nc):
Expand Down
3 changes: 0 additions & 3 deletions compiler/vmgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1382,9 +1382,6 @@ proc unneededIndirection(n: PNode): bool =
n.typ.skipTypes(abstractInstOwned-{tyTypeDesc}).kind == tyRef

proc canElimAddr(n: PNode): PNode =
if n[0].typ.skipTypes(abstractInst).kind in {tyObject, tyTuple, tyArray}:
# objects are reference types in the VM
return n[0]
case n[0].kind
of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
var m = n[0][0]
Expand Down
50 changes: 49 additions & 1 deletion tests/vm/tissues.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import macros

block t9043: # issue #9043
block t9043: # bug #9043
proc foo[N: static[int]](dims: array[N, int]): string =
const N1 = N
const N2 = dims.len
Expand All @@ -26,3 +26,51 @@ block t4952:
let tree = newTree(nnkExprColonExpr)
let t = (n: tree)
doAssert: t.n.kind == tree.kind


# bug #19909
type
SinglyLinkedList[T] = ref object
SinglyLinkedListObj[T] = ref object


proc addMoved[T](a, b: var SinglyLinkedList[T]) =
if a.addr != b.addr: discard

proc addMoved[T](a, b: var SinglyLinkedListObj[T]) =
if a.addr != b.addr: discard

proc main =
var a: SinglyLinkedList[int]; new a
var b: SinglyLinkedList[int]; new b
a.addMoved b

var a0: SinglyLinkedListObj[int]
var b0: SinglyLinkedListObj[int]
a0.addMoved b0

static: main()


# bug #18641

type A = object
ha1: int
static:
var a = A()
var a2 = a.addr
a2.ha1 = 11
doAssert a2.ha1 == 11
a.ha1 = 12
doAssert a.ha1 == 12
doAssert a2.ha1 == 12 # ok
static:
proc fn() =
var a = A()
var a2 = a.addr
a2.ha1 = 11
doAssert a2.ha1 == 11
a.ha1 = 12
doAssert a.ha1 == 12
doAssert a2.ha1 == 12 # fails
fn()
196 changes: 196 additions & 0 deletions tests/vm/tmisc_vm.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
discard """
targets: "c js"
output: '''
[127, 127, 0, 255][127, 127, 0, 255]
(data: 1)
(2, 1)
(2, 1)
(2, 1)
(f0: 5)
'''
nimout: '''caught Exception
Expand All @@ -17,6 +22,19 @@ foo4
(a: 0, b: 0)
(a: 0, b: 0)
(a: 0, b: 0)
z1 m: (lo: 12)
z2 a: (lo: 3)
x1 a: (lo: 3)
x2 a: (lo: 6)
x3 a: (lo: 0)
z3 a: (lo: 3)
x1 a: (lo: 3)
x2 a: (lo: 6)
x3 a: (lo: 0)
(2, 1)
(2, 1)
(2, 1)
(f0: 5)
'''
"""
import std/sets
Expand Down Expand Up @@ -249,3 +267,181 @@ static:
echo x2[]
let x3 = new(ref MyObject) # cannot generate VM code for ref MyObject
echo x3[]

# bug #19464
type
Wrapper = object
inner: int

proc assign(r: var Wrapper, a: Wrapper) =
r = a

proc myEcho(a: Wrapper) =
var tmp = a
assign(tmp, Wrapper(inner: 0)) # this shouldn't modify `a`
doAssert a.inner == 1

static:
var result: Wrapper
assign(result, Wrapper(inner: 1))
myEcho(result)

when true:
# bug #15974
type Foo = object
f0: int

proc fn(a: var Foo) =
var s: Foo
a = Foo(f0: 2)
s = a
doAssert s.f0 == 2
a = Foo(f0: 3)
doAssert s.f0 == 2

proc test2()=
var a = Foo(f0: 1)
fn(a)

static: test2()
test2()

# bug #12551
type
StUint = object
lo: uint64

func `+=`(x: var Stuint, y: Stuint) =
x.lo += y.lo

func `-`(x, y: Stuint): Stuint =
result.lo = x.lo - y.lo

func `+`(x, y: Stuint): Stuint =
result.lo = x.lo + y.lo

func `-=`(x: var Stuint, y: Stuint) =
x = x - y

func `<`(x, y: Stuint): bool=
x.lo < y.lo

func `==`(x, y: Stuint): bool =
x.lo == y.lo

func `<=`(x, y: Stuint): bool =
x.lo <= y.lo

proc div3n2n(r: var Stuint, b: Stuint) =
var d: Stuint
r = d
r += b

func div2n1n(r: var Stuint, b: Stuint) =
div3n2n(r, b)

func divmodBZ(x, y: Stuint, r: var Stuint)=
div2n1n(r, y)
r.lo = 3

func `mod`(x, y: Stuint): Stuint =
divmodBZ(x, y, result)

func doublemod_internal(a, m: Stuint): Stuint =
result = a
if a >= m - a:
result -= m
result += a

func mulmod_internal(a, b, m: Stuint): Stuint =
var (a, b) = (a, b)
swap(a, b)
debugEcho "x1 a: ", a
a = doublemod_internal(a, m)
debugEcho "x2 a: ", a
a = doublemod_internal(a, m)
debugEcho "x3 a: ", a

func powmod_internal(a, m: Stuint): Stuint =
var a = a
debugEcho "z1 m: ", m
debugEcho "z2 a: ", a
result = mulmod_internal(result, a, m)
debugEcho "z3 a: ", a
a = mulmod_internal(a, a, m)

func powmod*(a, m: Stuint) =
discard powmod_internal(a mod m, m)

static:
var x = Stuint(lo: high(uint64))
var y = Stuint(lo: 12)

powmod(x, y)

# bug #16780
when true:
template swap*[T](a, b: var T) =
var a2 = addr(a)
var b2 = addr(b)
var aOld = a2[]
a2[] = b2[]
b2[] = aOld

proc rather =
block:
var a = 1
var b = 2
swap(a, b)
echo (a,b)

block:
type Foo = ref object
x: int
var a = Foo(x:1)
var b = Foo(x:2)
swap(a, b)
echo (a.x, b.x)

block:
type Foo = object
x: int
var a = Foo(x:1)
var b = Foo(x:2)
swap(a, b)
echo (a.x,b.x)

static: rather()
rather()

# bug #16020
when true:
block:
type Foo = object
f0: int
proc main=
var f = Foo(f0: 3)
var f2 = f.addr
f2[].f0 += 1
f2.f0 += 1
echo f
static: main()
main()

import tables, strutils

# bug #14553
const PpcPatterns = @[("aaaa", "bbbb"), ("aaaaa", "bbbbb"), ("aaaaaa", "bbbbbb"), ("aaaaaaa", "bbbbbbb"), ("aaaaaaaa", "bbbbb")]

static:
var
needSecondIdentifier = initTable[uint32, seq[(string, string)]]()

for (name, pattern) in PpcPatterns:
let
firstPart = 0'u32
lastPart = "test"

needSecondIdentifier.mgetOrPut(firstPart, @[]).add((name, pattern))

doAssert needSecondIdentifier[0] == @[("aaaa", "bbbb"), ("aaaaa", "bbbbb"), ("aaaaaa", "bbbbbb"), ("aaaaaaa", "bbbbbbb"), ("aaaaaaaa", "bbbbb")]

0 comments on commit 3cb2d7a

Please sign in to comment.