Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cgen: improve code generation for seq types #1272

Merged
merged 3 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 30 additions & 38 deletions compiler/backend/ccgtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -294,29 +294,6 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): Rope =
of tyObject, tyTuple:
result = getTypeForward(m, t, hashType(t))
pushType(m, t)
of tySequence:
let sig = hashType(t)
m.config.internalAssert(skipTypes(etB[0], typedescInst).kind != tyEmpty,
"cannot map the empty seq type to a C type")

result = cacheGetType(m.forwTypeCache, sig)
if result == "":
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) == "":
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])

pushType(m, t)
else:
result = getTypeDescAux(m, t, check)

Expand All @@ -329,16 +306,12 @@ proc seqV2ContentType(m: BModule; t: PType; check: var IntSet) =
let sig = hashType(t)
let result = cacheGetType(m.typeCache, sig)
if result == "":
# the struct definition hasn't been emitted yet
discard getTypeDescAux(m, t, check)
else:
# little hack for now to prevent multiple definitions of the same
# Seq_Content:
appcg(m, m.s[cfsTypes], """$N
$3ifndef $2_Content_PP
$3define $2_Content_PP
struct $2_Content { NI cap; $1 data[SEQ_DECL_SIZE];};
$3endif$N
""", [getTypeDescAux(m, t.skipTypes(abstractInst)[0], check), result, rope"#"])
# emit the payload type:
appcg(m, m.s[cfsTypes], "struct $2_Content { NI cap; $1 data[SEQ_DECL_SIZE];};$N",
[getTypeDescAux(m, t.skipTypes(abstractInst)[0], check), result])

proc prepareParameters(m: BModule, t: PType): seq[TLoc] =
## Sets up and returns the locs of the parameter symbols for procedure
Expand Down Expand Up @@ -497,9 +470,6 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
if fieldType.kind == tyUncheckedArray:
result.addf("$1 $2[SEQ_DECL_SIZE];$n",
[getTypeDescAux(m, fieldType.elemType, check), sname])
elif fieldType.kind == tySequence:
# we need to use a weak dependency here for trecursive_table.
result.addf("$1$3 $2;$n", [getTypeDescWeak(m, field.typ, check), sname, noAlias])
elif field.bitsize != 0:
result.addf("$1$4 $2:$3;$n", [getTypeDescAux(m, field.typ, check), sname, rope($field.bitsize), noAlias])
else:
Expand Down Expand Up @@ -618,12 +588,10 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
et = elemType(etB)
etB = et.skipTypes(abstractInst)
case etB.kind
of tyObject, tyTuple:
of tyObject, tyTuple, tySequence:
# no restriction! We have a forward declaration for structs
let name = getTypeForward(m, et, hashType et)
result = name & star
of tySequence:
result = getTypeDescWeak(m, et, check) & star
of tyOpenArray:
result = getTypeDescAux(m, etB, check)
else:
Expand Down Expand Up @@ -667,7 +635,31 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
"void* ClE_0;$n} $1;$n",
[result, rettype, desc])
of tySequence:
result = getTypeDescWeak(m, t, check)
# a sequence type is two structs underneath: one for the seq itself, and
# one for its payload
m.config.internalAssert(skipTypes(t[0], typedescInst).kind != tyEmpty,
"cannot map the empty seq type to a C type")

result = cacheGetType(m.forwTypeCache, sig)
if result == "":
result = getTypeName(m, origTyp, sig)
if not isImportedType(t):
m.forwTypeCache[sig] = result
addForwardStructFormat(m, structOrUnion(t), result)

# it's possible that the element type cannot be emitted yet because it
# depends on the sequence type (a cyclic type). For this reason, the
# payload type is only forward-declared here, and the actual definition
# is emitted later
addForwardStructFormat(m, structOrUnion(t), result & "_Content")
# note: force push the type (by not using ``pushType``)
m.typeStack.add origTyp

m.typeCache[sig] = result
appcg(m, m.s[cfsTypes],
"struct $1 {$N" &
" NI len; $1_Content* p;$N" &
"};$N", [result])
of tyUncheckedArray:
result = getTypeName(m, origTyp, sig)
m.typeCache[sig] = result
Expand Down
2 changes: 1 addition & 1 deletion tests/ccgbugs/trecursive_table.nim
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ type
of eY:
nil

proc p*(x: Table[string, T]) =
proc p*(x: Table[string, T]) {.exportc.} =
discard
Loading