summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgexprs.nim6
-rw-r--r--compiler/ccgtypes.nim141
-rw-r--r--compiler/cgen.nim2
-rw-r--r--tests/destructor/tsimpletable.nim12
4 files changed, 99 insertions, 62 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index f3eb71bdc..1c1b9feac 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -2708,7 +2708,8 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope =
   else:
     globalError(p.config, info, "cannot create null element for: " & $t.kind)
 
-proc getNullValueAux(p: BProc; t: PType; obj, cons: PNode, result: var Rope; count: var int) =
+proc getNullValueAux(p: BProc; t: PType; obj, cons: PNode,
+                     result: var Rope; count: var int) =
   case obj.kind
   of nkRecList:
     for it in obj.sons:
@@ -2734,7 +2735,8 @@ proc getNullValueAux(p: BProc; t: PType; obj, cons: PNode, result: var Rope; cou
   else:
     localError(p.config, cons.info, "cannot create null element for: " & $obj)
 
-proc getNullValueAuxT(p: BProc; orig, t: PType; obj, cons: PNode, result: var Rope; count: var int) =
+proc getNullValueAuxT(p: BProc; orig, t: PType; obj, cons: PNode,
+                      result: var Rope; count: var int) =
   var base = t.sons[0]
   let oldRes = result
   if not p.module.compileToCpp: result.add "{"
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 5b46728fe..b28ecfd95 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -329,6 +329,9 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
       addAbiCheck(m, typ, result)
 
 proc pushType(m: BModule, typ: PType) =
+  for i in 0 .. high(m.typeStack):
+    # pointer equality is good enough here:
+    if m.typeStack[i] == typ: return
   add(m.typeStack, typ)
 
 proc getTypePre(m: BModule, typ: PType; sig: SigHash): Rope =
@@ -384,14 +387,53 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): Rope =
       result = getTypeForward(m, t, hashType(t))
       pushType(m, t)
   of tySequence:
+    let sig = hashType(t)
     if m.config.selectedGC == gcDestructors:
-      result = getTypeDescAux(m, t, check)
+      if skipTypes(etB.sons[0], typedescInst).kind == tyEmpty:
+        internalError(m.config, "cannot map the empty seq type to a C type")
+
+      result = cacheGetType(m.forwTypeCache, sig)
+      if result == nil:
+        result = getTypeName(m, t, sig)
+        if not isImportedType(t):
+          m.forwTypeCache[sig] = result
+          addForwardStructFormat(m, rope"struct", result)
+          let payload = result & "_Content"
+          addForwardStructFormat(m, rope"struct", payload)
+
+      if cacheGetType(m.typeCache, sig) == nil:
+        m.typeCache[sig] = result
+        #echo "adding ", sig, " ", typeToString(t), " ", m.module.name.s
+        appcg(m, m.s[cfsTypes],
+          "struct $1 {$n" &
+          "  NI len; $1_Content* p;$n" &
+          "};$n", [result])
     else:
-      result = getTypeForward(m, t, hashType(t)) & seqStar(m)
-      pushType(m, t)
+      result = getTypeForward(m, t, sig) & seqStar(m)
+    pushType(m, t)
   else:
     result = getTypeDescAux(m, t, check)
 
+proc getSeqPayloadType(m: BModule; t: PType): Rope =
+  var check = initIntSet()
+  result = getTypeDescWeak(m, t, check)
+  #result = getTypeForward(m, t, hashType(t)) & "_Content"
+
+proc seqV2ContentType(m: BModule; t: PType; check: var IntSet) =
+  let sig = hashType(t)
+  let result = cacheGetType(m.typeCache, sig)
+  if result == nil:
+    discard getTypeDescAux(m, t, check)
+  else:
+    # little hack for now to prevent multiple definitions of the same
+    # Seq_Content:
+    appcg(m, m.s[cfsTypes], """
+$3ifndef $2_Content_PP
+$3define $2_Content_PP
+struct $2_Content { NI cap;#AllocatorObj* allocator;$1 data[SEQ_DECL_SIZE];};
+$3endif
+      """, [getTypeDescAux(m, t.skipTypes(abstractInst).sons[0], check), result, rope"#"])
+
 proc paramStorageLoc(param: PSym): TStorageLoc =
   if param.typ.skipTypes({tyVar, tyLent, tyTypeDesc}).kind notin {
           tyArray, tyOpenArray, tyVarargs}:
@@ -513,7 +555,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
       if fieldType.kind == tyUncheckedArray:
         addf(result, "$1 $2[SEQ_DECL_SIZE];$n",
             [getTypeDescAux(m, fieldType.elemType, check), sname])
-      elif fieldType.kind == tySequence and m.config.selectedGC != gcDestructors:
+      elif fieldType.kind == tySequence:
         # 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:
@@ -627,15 +669,6 @@ proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
       result = if result.kind == tyGenericInst: result.sons[1]
                else: result.elemType
 
-proc getSeqPayloadType(m: BModule; t: PType): Rope =
-  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
   var t = origTyp.skipTypes(irrelevantForBackend-{tyOwned})
@@ -675,11 +708,15 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
         result = name & star
         m.typeCache[sig] = result
     of tySequence:
-      # no restriction! We have a forward declaration for structs
-      let name = getTypeForward(m, et, hashType et)
-      result = name & seqStar(m) & star
-      m.typeCache[sig] = result
-      pushType(m, et)
+      if m.config.selectedGC == gcDestructors:
+        result = getTypeDescWeak(m, et, check) & star
+        m.typeCache[sig] = result
+      else:
+        # no restriction! We have a forward declaration for structs
+        let name = getTypeForward(m, et, hashType et)
+        result = name & seqStar(m) & star
+        m.typeCache[sig] = result
+        pushType(m, et)
     else:
       # else we have a strong dependency  :-(
       result = getTypeDescAux(m, et, check) & star
@@ -731,29 +768,25 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
             "void* ClE_0;$n} $1;$n",
              [result, rettype, desc])
   of tySequence:
-    # we cannot use getTypeForward here because then t would be associated
-    # with the name of the struct, not with the pointer to the struct:
-    result = cacheGetType(m.forwTypeCache, sig)
-    if result == nil:
-      result = getTypeName(m, origTyp, sig)
+    if m.config.selectedGC == gcDestructors:
+      result = getTypeDescWeak(m, t, check)
+    else:
+      # we cannot use getTypeForward here because then t would be associated
+      # with the name of the struct, not with the pointer to the struct:
+      result = cacheGetType(m.forwTypeCache, sig)
+      if result == nil:
+        result = getTypeName(m, origTyp, sig)
+        if not isImportedType(t):
+          addForwardStructFormat(m, structOrUnion(t), result)
+        m.forwTypeCache[sig] = result
+      assert(cacheGetType(m.typeCache, sig) == nil)
+      m.typeCache[sig] = result & seqStar(m)
       if not isImportedType(t):
-        addForwardStructFormat(m, structOrUnion(t), result)
-      m.forwTypeCache[sig] = result
-    assert(cacheGetType(m.typeCache, sig) == nil)
-    m.typeCache[sig] = result & seqStar(m)
-    if not isImportedType(t):
-      if skipTypes(t.sons[0], typedescInst).kind != tyEmpty:
-        const
-          cppSeq = "struct $2 : #TGenericSeq {$n"
-          cSeq = "struct $2 {$n" &
-                 "  #TGenericSeq Sup;$n"
-        if m.config.selectedGC == gcDestructors:
-          appcg(m, m.s[cfsTypes],
-            "typedef struct{ NI cap;#AllocatorObj* 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:
+        if skipTypes(t.sons[0], typedescInst).kind != tyEmpty:
+          const
+            cppSeq = "struct $2 : #TGenericSeq {$n"
+            cSeq = "struct $2 {$n" &
+                  "  #TGenericSeq Sup;$n"
           if m.compileToCpp:
             appcg(m, m.s[cfsSeqTypes],
                 cppSeq & "  $1 data[SEQ_DECL_SIZE];$n" &
@@ -762,11 +795,9 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
             appcg(m, m.s[cfsSeqTypes],
                 cSeq & "  $1 data[SEQ_DECL_SIZE];$n" &
                 "};$n", [getTypeDescAux(m, t.sons[0], check), result])
-      elif m.config.selectedGC == gcDestructors:
-        internalError(m.config, "cannot map the empty seq type to a C type")
-      else:
-        result = rope("TGenericSeq")
-    add(result, seqStar(m))
+        else:
+          result = rope("TGenericSeq")
+      add(result, seqStar(m))
   of tyUncheckedArray:
     result = getTypeName(m, origTyp, sig)
     m.typeCache[sig] = result
@@ -830,21 +861,8 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
       m.typeCache[sig] = typedefName
       result = typedefName
     else:
-      when false:
-        if t.sym != nil and t.sym.name.s == "KeyValuePair":
-          if t == origTyp:
-            echo "wtf: came here"
-            writeStackTrace()
-            quit 1
       result = cacheGetType(m.forwTypeCache, sig)
       if result == nil:
-        when false:
-          if t.sym != nil and t.sym.name.s == "KeyValuePair":
-            # or {sfImportc, sfExportc} * t.sym.flags == {}:
-            if t.loc.r != nil:
-              echo t.kind, " ", hashType t
-              echo origTyp.kind, " ", sig
-            assert t.loc.r == nil
         result = getTypeName(m, origTyp, sig)
         m.forwTypeCache[sig] = result
         if not isImportedType(t):
@@ -903,8 +921,13 @@ proc getClosureType(m: BModule, t: PType, kind: TClosureTypeKind): Rope =
 
 proc finishTypeDescriptions(m: BModule) =
   var i = 0
+  var check = initIntSet()
   while i < len(m.typeStack):
-    discard getTypeDesc(m, m.typeStack[i])
+    let t = m.typeStack[i]
+    if m.config.selectedGC == gcDestructors and t.skipTypes(abstractInst).kind == tySequence:
+      seqV2ContentType(m, t, check)
+    else:
+      discard getTypeDescAux(m, t, check)
     inc(i)
 
 template cgDeclFrmt*(s: PSym): string =
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 95f1ee9ae..96698f92d 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -780,7 +780,7 @@ proc cgsym(m: BModule, name: string): Rope =
     # we're picky here for the system module too:
     rawMessage(m.config, errGenerated, "system module needs: " & name)
   result = sym.loc.r
-  if m.hcrOn and sym != nil and sym.kind in skProc..skIterator:
+  if m.hcrOn and sym != nil and sym.kind in {skProc..skIterator}:
     result.addActualPrefixForHCR(m.module, sym)
 
 proc generateHeaders(m: BModule) =
diff --git a/tests/destructor/tsimpletable.nim b/tests/destructor/tsimpletable.nim
index 36546b9f6..07efc86d9 100644
--- a/tests/destructor/tsimpletable.nim
+++ b/tests/destructor/tsimpletable.nim
@@ -20,5 +20,17 @@ proc main =
 
 main()
 
+# bug #11563
+type
+  MyTypeType = enum
+    Zero, One
+  MyType = object
+    case kind: MyTypeType
+    of Zero:
+      s*: seq[MyType]
+    of One:
+      x*: int
+var t: MyType
+
 let (a, d) = allocCounters()
 discard cprintf("%ld %ld  new: %ld\n", a, d, allocs)