123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- type
- Snippet = string
- Builder = string
- template newBuilder(s: string): Builder =
- s
- proc addField(obj: var Builder; name, typ: Snippet) =
- obj.add('\t')
- obj.add(typ)
- obj.add(" ")
- obj.add(name)
- obj.add(";\n")
- proc addField(obj: var Builder; field: PSym; name, typ: Snippet; isFlexArray: bool; initializer: Snippet) =
- obj.add('\t')
- if field.alignment > 0:
- obj.add("NIM_ALIGN(")
- obj.addInt(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.addInt(field.bitsize)
- if initializer.len != 0:
- obj.add(initializer)
- obj.add(";\n")
- proc structOrUnion(t: PType): Snippet =
- let t = t.skipTypes({tyAlias, tySink})
- if tfUnion in t.flags: "union"
- else: "struct"
- proc ptrType(t: Snippet): Snippet =
- t & "*"
- template addStruct(obj: var Builder; m: BModule; typ: PType; name: string; baseType: string; body: typed) =
- if tfPacked in typ.flags:
- if hasAttribute in CC[m.config.cCompiler].props:
- obj.add(structOrUnion(typ))
- obj.add(" __attribute__((__packed__))")
- else:
- obj.add("#pragma pack(push, 1)\n")
- obj.add(structOrUnion(typ))
- else:
- obj.add(structOrUnion(typ))
- obj.add(" ")
- obj.add(name)
- type BaseClassKind = enum
- bcNone, bcCppInherit, bcSupField, bcNoneRtti, bcNoneTinyRtti
- var baseKind = bcNone
- if typ.kind == tyObject:
- if typ.baseClass == nil:
- if lacksMTypeField(typ):
- baseKind = bcNone
- elif optTinyRtti in m.config.globalOptions:
- baseKind = bcNoneTinyRtti
- else:
- baseKind = bcNoneRtti
- elif m.compileToCpp:
- baseKind = bcCppInherit
- else:
- baseKind = bcSupField
- if baseKind == bcCppInherit:
- obj.add(" : public ")
- obj.add(baseType)
- obj.add(" ")
- obj.add("{\n")
- let currLen = obj.len
- case baseKind
- of bcNone:
- # rest of the options add a field or don't need it due to inheritance,
- # we need to add the dummy field for uncheckedarray ahead of time
- # so that it remains trailing
- if typ.itemId notin m.g.graph.memberProcsPerType and
- typ.n != nil and typ.n.len == 1 and typ.n[0].kind == nkSym and
- typ.n[0].sym.typ.skipTypes(abstractInst).kind == tyUncheckedArray:
- # only consists of flexible array field, add *initial* dummy field
- obj.addField(name = "dummy", typ = "char")
- of bcCppInherit: discard
- of bcNoneRtti:
- obj.addField(name = "m_type", typ = ptrType(cgsymValue(m, "TNimType")))
- of bcNoneTinyRtti:
- obj.addField(name = "m_type", typ = ptrType(cgsymValue(m, "TNimTypeV2")))
- of bcSupField:
- obj.addField(name = "Sup", typ = baseType)
- body
- if baseKind == bcNone and currLen == obj.len and typ.itemId notin m.g.graph.memberProcsPerType:
- # no fields were added, add dummy field
- obj.addField(name = "dummy", typ = "char")
- obj.add("};\n")
- if tfPacked in typ.flags and hasAttribute notin CC[m.config.cCompiler].props:
- result.add("#pragma pack(pop)\n")
- template addFieldWithStructType(obj: var Builder; m: BModule; parentTyp: PType; fieldName: string, body: typed) =
- ## adds a field with a `struct { ... }` type, building it according to `body`
- obj.add('\t')
- if tfPacked in parentTyp.flags:
- if hasAttribute in CC[m.config.cCompiler].props:
- obj.add("struct __attribute__((__packed__)) {\n")
- else:
- obj.add("#pragma pack(push, 1)\nstruct {")
- else:
- obj.add("struct {\n")
- body
- obj.add("} ")
- obj.add(fieldName)
- obj.add(";\n")
- if tfPacked in parentTyp.flags and hasAttribute notin CC[m.config.cCompiler].props:
- result.add("#pragma pack(pop)\n")
- template addAnonUnion(obj: var Builder; body: typed) =
- obj.add "union{\n"
- body
- obj.add("};\n")
|