Skip to content

Commit

Permalink
test removing anon structs for vars, fields later
Browse files Browse the repository at this point in the history
  • Loading branch information
metagn committed Nov 21, 2024
1 parent f9a8891 commit c539815
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 105 deletions.
236 changes: 154 additions & 82 deletions compiler/cbuilderdecls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -100,29 +100,6 @@ template addVarWithInitializer(builder: var Builder, kind: VarKind = Local, name
initializerBody
builder.addLineEnd(";")

template addVarWithTypeAndInitializer(builder: var Builder, kind: VarKind = Local, name: string,
typeBody, initializerBody: typed) =
## adds a variable declaration to the builder, with `typeBody` building the type, and
## `initializerBody` building the initializer. initializer must be provided
when buildNifc:
builder.add("(")
builder.addVarHeader(kind)
builder.add(":")
builder.add(name)
builder.add(" . ") # pragmas
typeBody
builder.add(" ")
initializerBody
builder.addLineEnd(")")
else:
builder.addVarHeader(kind)
typeBody
builder.add(" ")
builder.add(name)
builder.add(" = ")
initializerBody
builder.addLineEnd(";")

when buildNifc:
proc getArrayType(m: BModule, elementType: Snippet, len: int): Snippet =
let key = (elementType, len)
Expand Down Expand Up @@ -368,34 +345,77 @@ proc addArrayField(obj: var Builder; m: BModule, name, elementType: Snippet; len

proc addField(obj: var Builder; field: PSym; name, typ: Snippet; isFlexArray: bool = false; cppInitializer: Snippet = "") =
## adds an field inside a struct/union type, based on an `skField` symbol
obj.add('\t')
if field.alignment > 0:
obj.add("NIM_ALIGN(")
obj.addIntValue(field.alignment)
obj.add(") ")
obj.add(typ)
if sfNoalias in field.flags:
obj.add(" NIM_NOALIAS")
obj.add(" ")
obj.add(name)
if isFlexArray:
obj.add("[SEQ_DECL_SIZE]")
if field.bitsize != 0:
obj.add(":")
obj.addIntValue(field.bitsize)
if cppInitializer.len != 0:
obj.add(cppInitializer)
obj.add(";\n")
when buildNifc:
obj.add("\n\t(fld :")
obj.add(name)
var pragmasInner = ""
if field.alignment > 0:
pragmasInner.add("(align ")
pragmasInner.addIntValue(field.alignment)
pragmasInner.add(")")
if field.bitsize != 0:
if pragmasInner.len != 0: pragmasInner.add(" ")
pragmasInner.add("(bits ")
pragmasInner.addIntValue(field.bitsize)
pragmasInner.add(")")
if sfNoalias in field.flags:
when false: # XXX not implemented in NIFC
if pragmasInner.len != 0: pragmasInner.add(" ")
pragmasInner.add("(restrict)")
if pragmasInner.len != 0:
obj.add(" (")
obj.add(pragmasInner)
obj.add(") ")
else:
obj.add(" . ")
if isFlexArray:
obj.add("(flexarray ")
obj.add(typ)
obj.add("))")
else:
obj.add(typ)
obj.add(")")
assert cppInitializer.len == 0, "cpp initializer unsupported in nifc"
else:
obj.add('\t')
if field.alignment > 0:
obj.add("NIM_ALIGN(")
obj.addIntValue(field.alignment)
obj.add(") ")
obj.add(typ)
if sfNoalias in field.flags:
obj.add(" NIM_NOALIAS")
obj.add(" ")
obj.add(name)
if isFlexArray:
obj.add("[SEQ_DECL_SIZE]")
if field.bitsize != 0:
obj.add(":")
obj.addIntValue(field.bitsize)
if cppInitializer.len != 0:
obj.add(cppInitializer)
obj.add(";\n")

proc addProcField(obj: var Builder, callConv: TCallingConvention, name: string, rettype, params: Snippet) =
obj.add(CallingConvToStr[callConv])
obj.add("_PTR(")
obj.add(rettype)
obj.add(", ")
obj.add(name)
obj.add(")")
obj.add(params)
obj.add(";\n")
when buildNifc:
obj.add("(fld :")
obj.add(name)
obj.add(" . (proctype . ")
obj.add(params)
obj.add(" ")
obj.add(rettype)
obj.add(" (pragmas ")
obj.add(CallingConvToStr[callConv])
obj.addLineEnd(")))")
else:
obj.add(CallingConvToStr[callConv])
obj.add("_PTR(")
obj.add(rettype)
obj.add(", ")
obj.add(name)
obj.add(")")
obj.add(params)
obj.add(";\n")

type
BaseClassKind = enum
Expand All @@ -410,24 +430,43 @@ type
proc structOrUnion(t: PType): Snippet =
let t = t.skipTypes({tyAlias, tySink})
if tfUnion in t.flags: "union"
else: "struct"
else:
when buildNifc:
"object"
else:
"struct"

proc startSimpleStruct(obj: var Builder; m: BModule; name: string; baseType: Snippet): StructBuilderInfo =
result = StructBuilderInfo(baseKind: bcNone, named: name.len != 0)
obj.add("struct")
if result.named:
when buildNifc:
if result.named:
obj.add("(type :")
obj.add(name)
obj.add(" (object ")
if baseType.len != 0:
if m.compileToCpp:
result.baseKind = bcCppInherit
else:
result.baseKind = bcSupField
obj.add(baseType)
obj.add(" ")
else:
obj.add(". ")
else:
obj.add("struct")
if result.named:
obj.add(" ")
obj.add(name)
if baseType.len != 0:
if m.compileToCpp:
result.baseKind = bcCppInherit
else:
result.baseKind = bcSupField
if result.baseKind == bcCppInherit:
obj.add(" : public ")
obj.add(baseType)
obj.add(" ")
obj.add(name)
if baseType.len != 0:
if m.compileToCpp:
result.baseKind = bcCppInherit
else:
result.baseKind = bcSupField
if result.baseKind == bcCppInherit:
obj.add(" : public ")
obj.add(baseType)
obj.add(" ")
obj.add("{\n")
obj.add("{\n")
result.preFieldsLen = obj.buf.len
if result.baseKind == bcSupField:
obj.addField(name = "Sup", typ = baseType)
Expand All @@ -437,9 +476,15 @@ proc finishSimpleStruct(obj: var Builder; m: BModule; info: StructBuilderInfo) =
# no fields were added, add dummy field
obj.addField(name = "dummy", typ = CChar)
if info.named:
obj.add("};\n")
when buildNifc:
obj.add("))\n")
else:
obj.add("};\n")
else:
obj.add("}")
when buildNifc:
obj.add(")")
else:
obj.add("}")

template addSimpleStruct(obj: var Builder; m: BModule; name: string; baseType: Snippet; body: typed) =
## builds a struct type not based on a Nim type with fields according to `body`,
Expand All @@ -450,18 +495,31 @@ template addSimpleStruct(obj: var Builder; m: BModule; name: string; baseType: S

proc startStruct(obj: var Builder; m: BModule; t: PType; name: string; baseType: Snippet): StructBuilderInfo =
result = StructBuilderInfo(baseKind: bcNone, named: name.len != 0)
if tfPacked in t.flags:
if hasAttribute in CC[m.config.cCompiler].props:
when buildNifc:
# XXX no attributes for object types in NIFC
if result.named:
obj.add("(type :")
obj.add(name)
obj.add(" (")
obj.add(structOrUnion(t))
obj.add(" __attribute__((__packed__))")
obj.add(" ")
else:
obj.add("#pragma pack(push, 1)\n")
obj.add("(")
obj.add(structOrUnion(t))
obj.add(" ")
else:
obj.add(structOrUnion(t))
if result.named:
obj.add(" ")
obj.add(name)
if tfPacked in t.flags:
if hasAttribute in CC[m.config.cCompiler].props:
obj.add(structOrUnion(t))
obj.add(" __attribute__((__packed__))")
else:
obj.add("#pragma pack(push, 1)\n")
obj.add(structOrUnion(t))
else:
obj.add(structOrUnion(t))
if result.named:
obj.add(" ")
obj.add(name)
if t.kind == tyObject:
if t.baseClass == nil:
if lacksMTypeField(t):
Expand All @@ -479,11 +537,18 @@ proc startStruct(obj: var Builder; m: BModule; t: PType; name: string; baseType:
result.baseKind = bcCppInherit
else:
result.baseKind = bcSupField
if result.baseKind == bcCppInherit:
obj.add(" : public ")
obj.add(baseType)
obj.add(" ")
obj.add("{\n")
when buildNifc:
if baseType.len != 0:
obj.add(baseType)
obj.add(" ")
else:
obj.add(". ")
else:
if result.baseKind == bcCppInherit:
obj.add(" : public ")
obj.add(baseType)
obj.add(" ")
obj.add("{\n")
result.preFieldsLen = obj.buf.len
case result.baseKind
of bcNone:
Expand All @@ -509,11 +574,18 @@ proc finishStruct(obj: var Builder; m: BModule; t: PType; info: StructBuilderInf
# no fields were added, add dummy field
obj.addField(name = "dummy", typ = CChar)
if info.named:
obj.add("};\n")
when buildNifc:
obj.add("))\n")
else:
obj.add("};\n")
else:
obj.add("}")
if tfPacked in t.flags and hasAttribute notin CC[m.config.cCompiler].props:
obj.add("#pragma pack(pop)\n")
when buildNifc:
obj.add(")")
else:
obj.add("}")
when not buildNifc:
if tfPacked in t.flags and hasAttribute notin CC[m.config.cCompiler].props:
obj.add("#pragma pack(pop)\n")

template addStruct(obj: var Builder; m: BModule; typ: PType; name: string; baseType: Snippet; body: typed) =
## builds a struct type directly based on `typ` with fields according to `body`,
Expand Down
31 changes: 19 additions & 12 deletions compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3886,15 +3886,19 @@ proc genConstSeq(p: BProc, n: PNode, t: PType; isConst: bool; result: var Builde
let base = t.skipTypes(abstractInst)[0]
let tmpName = getTempName(p.module)

let typ = tmpName & "_SeqLit"
var typBuilder = newBuilder("")
typBuilder.addTypedef(name = typ):
typBuilder.addSimpleStruct(p.module, name = "", baseType = ""):
typBuilder.addField(name = "sup", typ = cgsymValue(p.module, "TGenericSeq"))
typBuilder.addArrayField(p.module, name = "data", elementType = getTypeDesc(p.module, base), len = n.len)
p.module.s[cfsTypes].add(extract(typBuilder))
# genBracedInit can modify cfsStrData, we need an intermediate builder:
var def = newBuilder("")
def.addVarWithTypeAndInitializer(
def.addVarWithInitializer(
if isConst: Const else: Global,
name = tmpName):
def.addSimpleStruct(p.module, name = "", baseType = ""):
def.addField(name = "sup", typ = cgsymValue(p.module, "TGenericSeq"))
def.addArrayField(p.module, name = "data", elementType = getTypeDesc(p.module, base), len = n.len)
do:
name = tmpName,
typ = typ):
var structInit: StructInitializer
def.addStructInitializer(structInit, kind = siOrderedStruct):
def.addField(structInit, name = "sup"):
Expand All @@ -3919,15 +3923,18 @@ proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool; result: var Buil
let base = t.skipTypes(abstractInst)[0]
let payload = getTempName(p.module)

let typ = payload & "_SeqLit"
var typBuilder = newBuilder("")
typBuilder.addTypedef(name = typ):
typBuilder.addSimpleStruct(p.module, name = "", baseType = ""):
typBuilder.addField(name = "cap", typ = NimInt)
typBuilder.addArrayField(p.module, name = "data", elementType = getTypeDesc(p.module, base), len = n.len)
# genBracedInit can modify cfsStrData, we need an intermediate builder:
var def = newBuilder("")
def.addVarWithTypeAndInitializer(
def.addVarWithInitializer(
if isConst: AlwaysConst else: Global,
name = payload):
def.addSimpleStruct(p.module, name = "", baseType = ""):
def.addField(name = "cap", typ = NimInt)
def.addArrayField(p.module, name = "data", elementType = getTypeDesc(p.module, base), len = n.len)
do:
name = payload,
typ = typ):
var structInit: StructInitializer
def.addStructInitializer(structInit, kind = siOrderedStruct):
def.addField(structInit, name = "cap"):
Expand Down
29 changes: 18 additions & 11 deletions compiler/ccgliterals.nim
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,15 @@ proc genStringLiteralDataOnlyV1(m: BModule, s: string; result: var Rope) =
cgsym(m, "TGenericSeq")
let tmp = getTempName(m)
result.add tmp
let typ = tmp & "_StrLit"
var typBuilder = newBuilder("")
typBuilder.addTypedef(name = typ):
typBuilder.addSimpleStruct(m, name = "", baseType = ""):
typBuilder.addField(name = "Sup", typ = "TGenericSeq")
typBuilder.addArrayField(m, name = "data", elementType = NimChar, len = s.len + 1)
m.s[cfsTypes].add(extract(typBuilder))
var res = newBuilder("")
res.addVarWithTypeAndInitializer(AlwaysConst, name = tmp):
res.addSimpleStruct(m, name = "", baseType = ""):
res.addField(name = "Sup", typ = "TGenericSeq")
res.addArrayField(m, name = "data", elementType = NimChar, len = s.len + 1)
do:
res.addVarWithInitializer(AlwaysConst, name = tmp, typ = typ):
var strInit: StructInitializer
res.addStructInitializer(strInit, kind = siOrderedStruct):
res.addField(strInit, name = "Sup"):
Expand Down Expand Up @@ -71,14 +74,18 @@ proc genStringLiteralV1(m: BModule; n: PNode; result: var Builder) =
# ------ Version 2: destructor based strings and seqs -----------------------

proc genStringLiteralDataOnlyV2(m: BModule, s: string; result: Rope; isConst: bool) =
let typ = getTempName(m) & "_StrLit"
var typBuilder = newBuilder("")
typBuilder.addTypedef(name = typ):
typBuilder.addSimpleStruct(m, name = "", baseType = ""):
typBuilder.addField(name = "cap", typ = NimInt)
typBuilder.addArrayField(m, name = "data", elementType = NimChar, len = s.len + 1)
m.s[cfsTypes].add(extract(typBuilder))
var res = newBuilder("")
res.addVarWithTypeAndInitializer(
res.addVarWithInitializer(
if isConst: AlwaysConst else: Global,
name = result):
res.addSimpleStruct(m, name = "", baseType = ""):
res.addField(name = "cap", typ = NimInt)
res.addArrayField(m, name = "data", elementType = NimChar, len = s.len + 1)
do:
name = result,
typ = typ):
var structInit: StructInitializer
res.addStructInitializer(structInit, kind = siOrderedStruct):
res.addField(structInit, name = "cap"):
Expand Down

0 comments on commit c539815

Please sign in to comment.