From c4dd9dc77e36eed0a71bf7b5d983d9de8e2e19e4 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 5 Feb 2017 08:51:35 +0100 Subject: fixes #5269 --- compiler/vmgen.nim | 16 ++++++++++------ tests/vm/tcopy_global_var.nim | 30 ++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 tests/vm/tcopy_global_var.nim 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" -- cgit 1.4.1-2-gfad0