summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-08-06 09:54:23 +0200
committerAraq <rumpf_a@web.de>2014-08-06 09:54:23 +0200
commita64d733029b1f8c76575f5d117399d587346b9cc (patch)
treeb0da407036a22032376169fc1977e42f934b8b4d
parent1e8a9aead060d27099bdd8634cbab6b89ecd9995 (diff)
downloadNim-a64d733029b1f8c76575f5d117399d587346b9cc.tar.gz
some bugfixes for 'deepCopy'
-rw-r--r--compiler/ccgexprs.nim11
-rw-r--r--lib/system/deepcopy.nim33
2 files changed, 29 insertions, 15 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index b4beb5a7e..d480373d4 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -360,13 +360,13 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   else: internalError("genAssignment: " & $ty.kind)
 
 proc genDeepCopy(p: BProc; dest, src: TLoc) =
-  var ty = skipTypes(dest.t, abstractRange)
+  var ty = skipTypes(dest.t, abstractVarRange)
   case ty.kind
-  of tyPtr, tyRef, tyString, tyProc, tyTuple, tyObject, tyArray, tyArrayConstr:
+  of tyPtr, tyRef, tyProc, tyTuple, tyObject, tyArray, tyArrayConstr:
     # XXX optimize this
     linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n",
             addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t))
-  of tySequence:
+  of tySequence, tyString:
     linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);$n",
             addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t))
   of tyOpenArray, tyVarargs:
@@ -1687,9 +1687,10 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     expr(p, n, d)
   of mDeepCopy:
     var a, b: TLoc
-    initLocExpr(p, e.sons[1], a)
+    let x = if e[1].kind in {nkAddr, nkHiddenAddr}: e[1][0] else: e[1]
+    initLocExpr(p, x, a)
     initLocExpr(p, e.sons[2], b)
-    genDeepCopy(p, a, b) 
+    genDeepCopy(p, a, b)
   else: internalError(e.info, "genMagicExpr: " & $op)
 
 proc genConstExpr(p: BProc, n: PNode): PRope
diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim
index d3f9c5d7c..5c10ef9ed 100644
--- a/lib/system/deepcopy.nim
+++ b/lib/system/deepcopy.nim
@@ -32,6 +32,12 @@ proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.gcsafe.} =
       genericDeepCopyAux(dest, src, m)
   of nkNone: sysAssert(false, "genericDeepCopyAux")
 
+proc copyDeepString(src: NimString): NimString {.inline.} =
+  if src != nil:
+    result = rawNewString(src.space)
+    result.len = src.len
+    c_memcpy(result.data, src.data, (src.len + 1) * sizeof(char))
+
 proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
   var
     d = cast[TAddress](dest)
@@ -44,10 +50,10 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
     if s2 == nil:
       unsureAsgnRef(x, s2)
     else:
-      unsureAsgnRef(x, copyString(cast[NimString](s2)))
+      unsureAsgnRef(x, copyDeepString(cast[NimString](s2)))
   of tySequence:
     var s2 = cast[PPointer](src)[]
-    var seq = cast[PGenericSeq](s2)      
+    var seq = cast[PGenericSeq](s2)
     var x = cast[PPointer](dest)
     if s2 == nil:
       unsureAsgnRef(x, s2)
@@ -76,25 +82,31 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
       genericDeepCopyAux(cast[pointer](d +% i*% mt.base.size),
                          cast[pointer](s +% i*% mt.base.size), mt.base)
   of tyRef:
-    var z: pointer
     if mt.base.deepCopy != nil:
-      z = mt.base.deepCopy(cast[PPointer](s)[])
+      let z = mt.base.deepCopy(cast[PPointer](src)[])
+      unsureAsgnRef(cast[PPointer](dest), z)
     else:
       # we modify the header of the cell temporarily; instead of the type
       # field we store a forwarding pointer. XXX This is bad when the cloning
       # fails due to OOM etc.
-      let x = usrToCell(cast[PPointer](s)[])
+      let s2 = cast[PPointer](src)[]
+      if s2 == nil:
+        unsureAsgnRef(cast[PPointer](dest), s2)
+        return
+      let x = usrToCell(s2)
       let forw = cast[int](x.typ)
       if (forw and 1) == 1:
         # we stored a forwarding pointer, so let's use that:
-        z = cast[pointer](forw and not 1)
+        let z = cast[pointer](forw and not 1)
+        unsureAsgnRef(cast[PPointer](dest), z)
       else:
         let realType = x.typ
-        z = newObj(realType, realType.base.size)
+        let z = newObj(realType, realType.base.size)
+        
+        unsureAsgnRef(cast[PPointer](dest), z)
         x.typ = cast[PNimType](cast[int](z) or 1)
-        genericDeepCopyAux(dest, addr(z), realType)
+        genericDeepCopyAux(z, s2, realType.base)
         x.typ = realType
-    unsureAsgnRef(cast[PPointer](dest), z)
   of tyPtr:
     # no cycle check here, but also not really required
     if mt.base.deepCopy != nil:
@@ -102,12 +114,13 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
     else:
       cast[PPointer](dest)[] = cast[PPointer](s)[]
   else:
-    copyMem(dest, src, mt.size) # copy raw bits
+    copyMem(dest, src, mt.size)
 
 proc genericDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =
   genericDeepCopyAux(dest, src, mt)
 
 proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =
+  # also invoked for 'string'
   var src = src
   genericDeepCopy(dest, addr(src), mt)