summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2017-02-05 08:51:35 +0100
committerAndreas Rumpf <rumpf_a@web.de>2017-02-05 08:51:43 +0100
commitc4dd9dc77e36eed0a71bf7b5d983d9de8e2e19e4 (patch)
treece0ab3753c0f7e4e569d2462dd1d82bd15fb2814
parent3978845266d154c9dba42a8d17266f057a52d90f (diff)
downloadNim-c4dd9dc77e36eed0a71bf7b5d983d9de8e2e19e4.tar.gz
fixes #5269
-rw-r--r--compiler/vmgen.nim16
-rw-r--r--tests/vm/tcopy_global_var.nim30
2 files changed, 40 insertions, 6 deletions
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index e0f737f08..9460f1809 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -1259,6 +1259,13 @@ proc isTemp(c: PCtx; dest: TDest): bool =
 template needsAdditionalCopy(n): untyped =
   not c.isTemp(dest) and not fitsRegister(n.typ)
 
+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, opc, dest, idx, cc)
+  c.freeTemp(cc)
+
 proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
                        dest, idx, value: TRegister) =
   # opcLdObj et al really means "load address". We sometimes have to create a
@@ -1266,10 +1273,7 @@ proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
   # mylocal = a.b  # needs a copy of the data!
   assert n.typ != nil
   if needsAdditionalCopy(n):
-    var cc = c.getTemp(n.typ)
-    c.gABC(n, whichAsgnOpc(n), cc, value, 0)
-    c.gABC(n, opc, dest, idx, cc)
-    c.freeTemp(cc)
+    genAdditionalCopy(c, n, opc, dest, idx, value)
   else:
     c.gABC(n, opc, dest, idx, value)
 
@@ -1352,7 +1356,7 @@ proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
   c.gABx(n, opcLdGlobal, dest, s.position)
   if s.ast != nil:
     let tmp = c.genx(s.ast)
-    c.preventFalseAlias(n, opcWrDeref, dest, 0, tmp)
+    c.genAdditionalCopy(n, opcWrDeref, dest, 0, tmp)
     c.freeTemp(dest)
     c.freeTemp(tmp)
 
@@ -1525,7 +1529,7 @@ proc genVarSection(c: PCtx; n: PNode) =
         if a.sons[2].kind != nkEmpty:
           let tmp = c.genx(a.sons[0], {gfAddrOf})
           let val = c.genx(a.sons[2])
-          c.preventFalseAlias(a.sons[2], opcWrDeref, tmp, 0, val)
+          c.genAdditionalCopy(a.sons[2], opcWrDeref, tmp, 0, val)
           c.freeTemp(val)
           c.freeTemp(tmp)
       else:
diff --git a/tests/vm/tcopy_global_var.nim b/tests/vm/tcopy_global_var.nim
new file mode 100644
index 000000000..eadd27b9a
--- /dev/null
+++ b/tests/vm/tcopy_global_var.nim
@@ -0,0 +1,30 @@
+discard """
+  nimout: "static done"
+"""
+
+# bug #5269
+
+proc assertEq[T](arg0, arg1: T): void =
+  assert arg0 == arg1, $arg0 & " == " & $arg1
+
+type
+  MyType = object
+    str: string
+    a: int
+
+block:
+  var localValue = MyType(str: "Original strning, (OK)", a: 0)
+  var valueCopy = localValue
+  valueCopy.a = 123
+  valueCopy.str = "Modified strning, (not OK when in localValue)"
+  assertEq(localValue.str, "Original strning, (OK)")
+  assertEq(localValue.a,   0)
+
+static:
+  var localValue = MyType(str: "Original strning, (OK)", a: 0)
+  var valueCopy = localValue
+  valueCopy.a = 123
+  valueCopy.str = "Modified strning, (not OK when in localValue)"
+  assertEq(localValue.str, "Original strning, (OK)")
+  assertEq(localValue.a,   0)
+  echo "static done"