diff options
-rw-r--r-- | compiler/ccgexprs.nim | 6 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 141 | ||||
-rw-r--r-- | compiler/cgen.nim | 2 | ||||
-rw-r--r-- | tests/destructor/tsimpletable.nim | 12 |
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) |