summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ccgexprs.nim44
-rw-r--r--compiler/ccgliterals.nim18
-rw-r--r--compiler/ccgtrav.nim16
-rw-r--r--compiler/ccgtypes.nim40
-rw-r--r--compiler/cgen.nim4
5 files changed, 79 insertions, 43 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index d25a4ad3d..69175fd18 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -256,8 +256,8 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   # (for objects, etc.):
   if p.config.selectedGC == gcDestructors:
     linefmt(p, cpsStmts,
-        "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
-        addrLoc(p.config, dest), addrLoc(p.config, src), rdLoc(dest))
+        "$1.len = $2.len; $1.p = $2.p;$n",
+        rdLoc(dest), rdLoc(src))
   elif needToCopy notin flags or
       tfShallow in skipTypes(dest.t, abstractVarRange).flags:
     if dest.storage == OnStack or not usesWriteBarrier(p.config):
@@ -1512,28 +1512,19 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     if op == mHigh: unaryExpr(p, e, d, "($1 ? (#nimCStrLen($1)-1) : -1)")
     else: unaryExpr(p, e, d, "($1 ? #nimCStrLen($1) : 0)")
   of tyString:
-    if not p.module.compileToCpp:
-      if op == mHigh: unaryExpr(p, e, d, "($1 ? ($1->Sup.len-1) : -1)")
-      else: unaryExpr(p, e, d, "($1 ? $1->Sup.len : 0)")
-    else:
-      if op == mHigh: unaryExpr(p, e, d, "($1 ? ($1->len-1) : -1)")
-      else: unaryExpr(p, e, d, "($1 ? $1->len : 0)")
+    var a: TLoc
+    initLocExpr(p, e.sons[1], a)
+    var x = lenExpr(p, a)
+    if op == mHigh: x = "($1-1)" % [x]
+    putIntoDest(p, d, e, x)
   of tySequence:
+    # we go through a temporary here because people write bullshit code.
     var a, tmp: TLoc
     initLocExpr(p, e[1], a)
     getIntTemp(p, tmp)
-    var frmt: FormatStr
-    if not p.module.compileToCpp:
-      if op == mHigh:
-        frmt = "$1 = ($2 ? ($2->Sup.len-1) : -1);$n"
-      else:
-        frmt = "$1 = ($2 ? $2->Sup.len : 0);$n"
-    else:
-      if op == mHigh:
-        frmt = "$1 = ($2 ? ($2->len-1) : -1);$n"
-      else:
-        frmt = "$1 = ($2 ? $2->len : 0);$n"
-    lineCg(p, cpsStmts, frmt, tmp.r, rdLoc(a))
+    var x = lenExpr(p, a)
+    if op == mHigh: x = "($1-1)" % [x]
+    lineCg(p, cpsStmts, "$1 = $2;$n", tmp.r, x)
     putIntoDest(p, d, e, tmp.r)
   of tyArray:
     # YYY: length(sideeffect) is optimized away incorrectly?
@@ -1889,7 +1880,11 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     else:
       binaryStmt(p, e, d, "$1 = #addChar($1, $2);$n")
   of mAppendStrStr: genStrAppend(p, e, d)
-  of mAppendSeqElem: genSeqElemAppend(p, e, d)
+  of mAppendSeqElem:
+    if p.config.selectedGc == gcDestructors:
+      genCall(p, e, d)
+    else:
+      genSeqElemAppend(p, e, d)
   of mEqStr: genStrEquals(p, e, d)
   of mLeStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) <= 0)")
   of mLtStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) < 0)")
@@ -2537,6 +2532,13 @@ proc genConstExpr(p: BProc, n: PNode): Rope =
       result = genConstSimpleList(p, n)
   of nkObjConstr:
     result = genConstObjConstr(p, n)
+  of nkStrLit..nkTripleStrLit:
+    if p.config.selectedGc == gcDestructors:
+      result = genStringLiteralV2Const(p.module, n)
+    else:
+      var d: TLoc
+      initLocExpr(p, n, d)
+      result = rdLoc(d)
   else:
     var d: TLoc
     initLocExpr(p, n, d)
diff --git a/compiler/ccgliterals.nim b/compiler/ccgliterals.nim
index a06e4e5d0..34677ec06 100644
--- a/compiler/ccgliterals.nim
+++ b/compiler/ccgliterals.nim
@@ -54,9 +54,9 @@ proc genStringLiteralV1(m: BModule; n: PNode): Rope =
 proc genStringLiteralDataOnlyV2(m: BModule, s: string): Rope =
   result = getTempName(m)
   addf(m.s[cfsData], "static const struct {$n" &
-       "  NI cap; void* allocator; NIM_CHAR[$2] data;$n" &
+       "  NI cap; void* allocator; NIM_CHAR data[$2];$n" &
        "} $1 = { $2, NIM_NIL, $3 };$n",
-       [result, rope(len(s)+1), makeCString(s)])
+       [result, rope(len(s)), makeCString(s)])
 
 proc genStringLiteralV2(m: BModule; n: PNode): Rope =
   let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
@@ -67,10 +67,22 @@ proc genStringLiteralV2(m: BModule; n: PNode): Rope =
     let pureLit = genStringLiteralDataOnlyV2(m, n.strVal)
     result = getTempName(m)
     addf(m.s[cfsData], "static const NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
-        [result, rope(len(n.strVal)+1), pureLit])
+          [result, rope(len(n.strVal)), pureLit])
   else:
     result = m.tmpBase & rope(id)
 
+proc genStringLiteralV2Const(m: BModule; n: PNode): Rope =
+  let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
+  var pureLit: Rope
+  if id == m.labels:
+    discard cgsym(m, "NimStrPayload")
+    discard cgsym(m, "NimStringV2")
+    # string literal not found in the cache:
+    pureLit = genStringLiteralDataOnlyV2(m, n.strVal)
+  else:
+    pureLit = m.tmpBase & rope(id)
+  result = "{$1, (NimStrPayload*)&$2}" % [rope(len(n.strVal)), pureLit]
+
 # ------ Version selector ---------------------------------------------------
 
 proc genStringLiteralDataOnly(m: BModule; s: string; info: TLineInfo): Rope =
diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim
index 5a6dc8a6e..c69bb2c80 100644
--- a/compiler/ccgtrav.nim
+++ b/compiler/ccgtrav.nim
@@ -7,8 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-## Generates traversal procs for the C backend. Traversal procs are only an
-## optimization; the GC works without them too.
+## Generates traversal procs for the C backend.
 
 # included from cgen.nim
 
@@ -61,6 +60,7 @@ proc parentObj(accessor: Rope; m: BModule): Rope {.inline.} =
   else:
     result = accessor
 
+proc genTraverseProcSeq(c: TTraversalClosure, accessor: Rope, typ: PType)
 proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
   if typ == nil: return
 
@@ -93,8 +93,18 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
     let typ = getUniqueType(typ)
     for i in countup(0, sonsLen(typ) - 1):
       genTraverseProc(c, ropecg(c.p.module, "$1.Field$2", accessor, i.rope), typ.sons[i])
-  of tyRef, tyString, tySequence:
+  of tyRef:
     lineCg(p, cpsStmts, c.visitorFrmt, accessor)
+  of tySequence:
+    if tfHasAsgn notin typ.flags:
+      lineCg(p, cpsStmts, c.visitorFrmt, accessor)
+    elif containsGarbageCollectedRef(typ.lastSon):
+      # destructor based seqs are themselves not traced but their data is, if
+      # they contain a GC'ed type:
+      genTraverseProcSeq(c, accessor, typ)
+  of tyString:
+    if tfHasAsgn notin typ.flags:
+      lineCg(p, cpsStmts, c.visitorFrmt, accessor)
   of tyProc:
     if typ.callConv == ccClosure:
       lineCg(p, cpsStmts, c.visitorFrmt, ropecg(c.p.module, "$1.ClE_0", accessor))
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index b83c96660..59fbfc3e1 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -359,8 +359,11 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): Rope =
       result = getTypeForward(m, t, hashType(t))
       pushType(m, t)
   of tySequence:
-    result = getTypeForward(m, t, hashType(t)) & seqStar(m)
-    pushType(m, t)
+    if m.config.selectedGC == gcDestructors:
+      result = getTypeDescAux(m, t, check)
+    else:
+      result = getTypeForward(m, t, hashType(t)) & seqStar(m)
+      pushType(m, t)
   else:
     result = getTypeDescAux(m, t, check)
 
@@ -491,7 +494,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
       if fieldType.kind == tyArray and tfUncheckedArray in fieldType.flags:
         addf(result, "$1 $2[SEQ_DECL_SIZE];$n",
             [getTypeDescAux(m, fieldType.elemType, check), sname])
-      elif fieldType.kind == tySequence:
+      elif fieldType.kind == tySequence and m.config.selectedGC != gcDestructors:
         # we need to use a weak dependency here for trecursive_table.
         addf(result, "$1 $2;$n", [getTypeDescWeak(m, field.loc.t, check), sname])
       elif field.bitsize != 0:
@@ -606,12 +609,13 @@ proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
                else: result.elemType
 
 proc getSeqPayloadType(m: BModule; t: PType): Rope =
-  var check = initIntSet()
-  result = getTypeForward(m, t, hashType(t))
-  # XXX remove this duplication:
-  appcg(m, m.s[cfsSeqTypes],
-    "struct $2_Content { NI cap; void* allocator; $1 data[SEQ_DECL_SIZE];$n } ",
-    [getTypeDescAux(m, t.sons[0], check), result])
+  result = getTypeForward(m, t, hashType(t)) & "_Content"
+  when false:
+    var check = initIntSet()
+    # XXX remove this duplication:
+    appcg(m, m.s[cfsSeqTypes],
+      "struct $2_Content { NI cap; void* allocator; $1 data[SEQ_DECL_SIZE]; };$n",
+      [getTypeDescAux(m, t.sons[0], check), result])
 
 proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
   # returns only the type's name
@@ -725,11 +729,11 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
           cSeq = "struct $2 {$n" &
                  "  #TGenericSeq Sup;$n"
         if m.config.selectedGC == gcDestructors:
-          appcg(m, m.s[cfsSeqTypes],
-              "struct $2_Content { NI cap; void* allocator; $1 data[SEQ_DECL_SIZE];$n } " &
-              "struct $2 {$n" &
-              "  NI len; $2_Content* p;$n" &
-              "};$n", [getTypeDescAux(m, t.sons[0], check), result])
+          appcg(m, m.s[cfsTypes],
+            "typedef struct{ NI cap;void* allocator;$1 data[SEQ_DECL_SIZE];}$2_Content;$n" &
+            "struct $2 {$n" &
+            "  NI len; $2_Content* p;$n" &
+            "};$n", [getTypeDescAux(m, t.sons[0], check), result])
         else:
           appcg(m, m.s[cfsSeqTypes],
               (if m.compileToCpp: cppSeq else: cSeq) &
@@ -1198,7 +1202,13 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
     else:
       let x = fakeClosureType(m, t.owner)
       genTupleInfo(m, x, x, result, info)
-  of tySequence, tyRef, tyOptAsRef:
+  of tySequence:
+    if tfHasAsgn notin t.flags:
+      genTypeInfoAux(m, t, t, result, info)
+      if m.config.selectedGC >= gcMarkAndSweep:
+        let markerProc = genTraverseProc(m, origType, sig)
+        addf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [result, markerProc])
+  of tyRef, tyOptAsRef:
     genTypeInfoAux(m, t, t, result, info)
     if m.config.selectedGC >= gcMarkAndSweep:
       let markerProc = genTraverseProc(m, origType, sig)
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 8d8fdfcd9..80c03f9e4 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -334,7 +334,9 @@ proc resetLoc(p: BProc, loc: var TLoc) =
 
 proc constructLoc(p: BProc, loc: TLoc, isTemp = false) =
   let typ = loc.t
-  if not isComplexValueType(typ):
+  if p.config.selectedGc == gcDestructors and skipTypes(typ, abstractInst).kind in {tyString, tySequence}:
+    linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", rdLoc(loc))
+  elif not isComplexValueType(typ):
     linefmt(p, cpsStmts, "$1 = ($2)0;$n", rdLoc(loc),
       getTypeDesc(p.module, typ))
   else: