123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669 |
- type VarKind = enum
- Local
- Global
- Threadvar
- Const
- AlwaysConst ## const even on C++
- proc addVarHeader(builder: var Builder, kind: VarKind) =
- ## adds modifiers for given var kind:
- ## Local has no modifier
- ## Global has `static` modifier
- ## Const has `static NIM_CONST` modifier
- ## AlwaysConst has `static const` modifier (NIM_CONST is no-op on C++)
- ## Threadvar is unimplemented
- case kind
- of Local: discard
- of Global:
- builder.add("static ")
- of Const:
- builder.add("static NIM_CONST ")
- of AlwaysConst:
- builder.add("static const ")
- of Threadvar:
- doAssert false, "unimplemented"
- proc addVar(builder: var Builder, kind: VarKind = Local, name: string, typ: Snippet, initializer: Snippet = "") =
- ## adds a variable declaration to the builder
- builder.addVarHeader(kind)
- builder.add(typ)
- builder.add(" ")
- builder.add(name)
- if initializer.len != 0:
- builder.add(" = ")
- builder.add(initializer)
- builder.addLineEnd(";")
- template addVarWithType(builder: var Builder, kind: VarKind = Local, name: string, body: typed) =
- ## adds a variable declaration to the builder, with the `body` building the type
- builder.addVarHeader(kind)
- body
- builder.add(" ")
- builder.add(name)
- builder.addLineEnd(";")
- template addVarWithInitializer(builder: var Builder, kind: VarKind = Local, name: string,
- typ: Snippet, initializerBody: typed) =
- ## adds a variable declaration to the builder, with
- ## `initializerBody` building the initializer. initializer must be provided
- builder.addVarHeader(kind)
- builder.add(typ)
- builder.add(" ")
- builder.add(name)
- builder.add(" = ")
- 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
- builder.addVarHeader(kind)
- typeBody
- builder.add(" ")
- builder.add(name)
- builder.add(" = ")
- initializerBody
- builder.addLineEnd(";")
- proc addArrayVar(builder: var Builder, kind: VarKind = Local, name: string, elementType: Snippet, len: int, initializer: Snippet = "") =
- ## adds an array variable declaration to the builder
- builder.addVarHeader(kind)
- builder.add(elementType)
- builder.add(" ")
- builder.add(name)
- builder.add("[")
- builder.addIntValue(len)
- builder.add("]")
- if initializer.len != 0:
- builder.add(" = ")
- builder.add(initializer)
- builder.addLineEnd(";")
- template addArrayVarWithInitializer(builder: var Builder, kind: VarKind = Local, name: string, elementType: Snippet, len: int, body: typed) =
- ## adds an array variable declaration to the builder with the initializer built according to `body`
- builder.addVarHeader(kind)
- builder.add(elementType)
- builder.add(" ")
- builder.add(name)
- builder.add("[")
- builder.addIntValue(len)
- builder.add("] = ")
- body
- builder.addLineEnd(";")
- template addTypedef(builder: var Builder, name: string, typeBody: typed) =
- ## adds a typedef declaration to the builder with name `name` and type as
- ## built in `typeBody`
- builder.add("typedef ")
- typeBody
- builder.add(" ")
- builder.add(name)
- builder.addLineEnd(";")
- proc addProcTypedef(builder: var Builder, callConv: TCallingConvention, name: string, rettype, params: Snippet) =
- builder.add("typedef ")
- builder.add(CallingConvToStr[callConv])
- builder.add("_PTR(")
- builder.add(rettype)
- builder.add(", ")
- builder.add(name)
- builder.add(")")
- builder.add(params)
- builder.addLineEnd(";")
- template addArrayTypedef(builder: var Builder, name: string, len: BiggestInt, typeBody: typed) =
- ## adds an array typedef declaration to the builder with name `name`,
- ## length `len`, and element type as built in `typeBody`
- builder.add("typedef ")
- typeBody
- builder.add(" ")
- builder.add(name)
- builder.add("[")
- builder.addIntValue(len)
- builder.addLineEnd("];")
- type
- StructInitializerKind = enum
- siOrderedStruct ## struct constructor, but without named fields on C
- siNamedStruct ## struct constructor, with named fields i.e. C99 designated initializer
- siArray ## array constructor
- siWrapper ## wrapper for a single field, generates it verbatim
- StructInitializer = object
- ## context for building struct initializers, i.e. `{ field1, field2 }`
- kind: StructInitializerKind
- ## if true, fields will not be named, instead values are placed in order
- needsComma: bool
- proc initStructInitializer(builder: var Builder, kind: StructInitializerKind): StructInitializer =
- ## starts building a struct initializer, i.e. braced initializer list
- result = StructInitializer(kind: kind, needsComma: false)
- if kind != siWrapper:
- builder.add("{")
- template addField(builder: var Builder, constr: var StructInitializer, name: string, valueBody: typed) =
- ## adds a field to a struct initializer, with the value built in `valueBody`
- if constr.needsComma:
- assert constr.kind != siWrapper, "wrapper constructor cannot have multiple fields"
- builder.add(", ")
- else:
- constr.needsComma = true
- case constr.kind
- of siArray, siWrapper:
- # no name, can just add value
- valueBody
- of siOrderedStruct:
- # no name, can just add value on C
- assert name.len != 0, "name has to be given for struct initializer field"
- valueBody
- of siNamedStruct:
- assert name.len != 0, "name has to be given for struct initializer field"
- builder.add(".")
- builder.add(name)
- builder.add(" = ")
- valueBody
- proc finishStructInitializer(builder: var Builder, constr: StructInitializer) =
- ## finishes building a struct initializer
- if constr.kind != siWrapper:
- builder.add("}")
- template addStructInitializer(builder: var Builder, constr: out StructInitializer, kind: StructInitializerKind, body: typed) =
- ## builds a struct initializer, i.e. `{ field1, field2 }`
- ## a `var StructInitializer` must be declared and passed as a parameter so
- ## that it can be used with `addField`
- constr = builder.initStructInitializer(kind)
- body
- builder.finishStructInitializer(constr)
- proc addField(obj: var Builder; name, typ: Snippet; isFlexArray: bool = false; initializer: Snippet = "") =
- ## adds a field inside a struct/union type
- obj.add('\t')
- obj.add(typ)
- obj.add(" ")
- obj.add(name)
- if isFlexArray:
- obj.add("[SEQ_DECL_SIZE]")
- if initializer.len != 0:
- obj.add(initializer)
- obj.add(";\n")
- proc addArrayField(obj: var Builder; name, elementType: Snippet; len: int; initializer: Snippet = "") =
- ## adds an array field inside a struct/union type
- obj.add('\t')
- obj.add(elementType)
- obj.add(" ")
- obj.add(name)
- obj.add("[")
- obj.addIntValue(len)
- obj.add("]")
- if initializer.len != 0:
- obj.add(initializer)
- obj.add(";\n")
- proc addField(obj: var Builder; field: PSym; name, typ: Snippet; isFlexArray: bool = false; initializer: 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 initializer.len != 0:
- obj.add(initializer)
- 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")
- type
- BaseClassKind = enum
- ## denotes how and whether or not the base class/RTTI should be stored
- bcNone, bcCppInherit, bcSupField, bcNoneRtti, bcNoneTinyRtti
- StructBuilderInfo = object
- ## context for building `struct` types
- baseKind: BaseClassKind
- named: bool
- preFieldsLen: int
- proc structOrUnion(t: PType): Snippet =
- let t = t.skipTypes({tyAlias, tySink})
- if tfUnion in t.flags: "union"
- 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:
- 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")
- result.preFieldsLen = obj.buf.len
- if result.baseKind == bcSupField:
- obj.addField(name = "Sup", typ = baseType)
- proc finishSimpleStruct(obj: var Builder; m: BModule; info: StructBuilderInfo) =
- if info.baseKind == bcNone and info.preFieldsLen == obj.buf.len:
- # no fields were added, add dummy field
- obj.addField(name = "dummy", typ = CChar)
- if info.named:
- obj.add("};\n")
- 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`,
- ## `name` can be empty to build as a type expression and not a statement
- let info = startSimpleStruct(obj, m, name, baseType)
- body
- finishSimpleStruct(obj, m, info)
- 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:
- 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):
- result.baseKind = bcNone
- elif optTinyRtti in m.config.globalOptions:
- result.baseKind = bcNoneTinyRtti
- else:
- result.baseKind = bcNoneRtti
- elif m.compileToCpp:
- result.baseKind = bcCppInherit
- else:
- result.baseKind = bcSupField
- elif 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")
- result.preFieldsLen = obj.buf.len
- case result.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 t.itemId notin m.g.graph.memberProcsPerType and
- t.n != nil and t.n.len == 1 and t.n[0].kind == nkSym and
- t.n[0].sym.typ.skipTypes(abstractInst).kind == tyUncheckedArray:
- # only consists of flexible array field, add *initial* dummy field
- obj.addField(name = "dummy", typ = CChar)
- 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)
- proc finishStruct(obj: var Builder; m: BModule; t: PType; info: StructBuilderInfo) =
- if info.baseKind == bcNone and info.preFieldsLen == obj.buf.len and
- t.itemId notin m.g.graph.memberProcsPerType:
- # no fields were added, add dummy field
- obj.addField(name = "dummy", typ = CChar)
- if info.named:
- 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")
- 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`,
- ## `name` can be empty to build as a type expression and not a statement
- let info = startStruct(obj, m, typ, name, baseType)
- body
- finishStruct(obj, m, typ, info)
- template addFieldWithStructType(obj: var Builder; m: BModule; parentTyp: PType; fieldName: string, body: typed) =
- ## adds a field with a `struct { ... }` type, building the fields 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) =
- ## adds an anonymous union i.e. `union { ... };` with fields according to `body`
- obj.add "union{\n"
- body
- obj.add("};\n")
- template addUnionType(obj: var Builder; body: typed) =
- ## adds a union type i.e. `union { ... }` with fields according to `body`
- obj.add "union{\n"
- body
- obj.add("}")
- type DeclVisibility = enum
- None
- Extern
- ExternC
- ImportLib
- ExportLib
- ExportLibVar
- Private
- StaticProc
- proc addVisibilityPrefix(builder: var Builder, visibility: DeclVisibility) =
- # internal proc
- case visibility
- of None: discard
- of Extern:
- builder.add("extern ")
- of ExternC:
- builder.add("NIM_EXTERNC ")
- of ImportLib:
- builder.add("N_LIB_IMPORT ")
- of ExportLib:
- builder.add("N_LIB_EXPORT ")
- of ExportLibVar:
- builder.add("N_LIB_EXPORT_VAR ")
- of Private:
- builder.add("N_LIB_PRIVATE ")
- of StaticProc:
- builder.add("static ")
- template addDeclWithVisibility(builder: var Builder, visibility: DeclVisibility, declBody: typed) =
- ## adds a declaration as in `declBody` with the given visibility
- builder.addVisibilityPrefix(visibility)
- declBody
- type ProcParamBuilder = object
- needsComma: bool
- proc initProcParamBuilder(builder: var Builder): ProcParamBuilder =
- result = ProcParamBuilder(needsComma: false)
- builder.add("(")
- proc finishProcParamBuilder(builder: var Builder, params: ProcParamBuilder) =
- if params.needsComma:
- builder.add(")")
- else:
- builder.add("void)")
- template cgDeclFrmt*(s: PSym): string =
- s.constraint.strVal
- proc addParam(builder: var Builder, params: var ProcParamBuilder, name: string, typ: Snippet) =
- if params.needsComma:
- builder.add(", ")
- else:
- params.needsComma = true
- builder.add(typ)
- builder.add(" ")
- builder.add(name)
- proc addParam(builder: var Builder, params: var ProcParamBuilder, param: PSym, typ: Snippet) =
- if params.needsComma:
- builder.add(", ")
- else:
- params.needsComma = true
- var modifiedTyp = typ
- if sfNoalias in param.flags:
- modifiedTyp.add(" NIM_NOALIAS")
- if sfCodegenDecl notin param.flags:
- builder.add(modifiedTyp)
- builder.add(" ")
- builder.add(param.loc.snippet)
- else:
- builder.add runtimeFormat(param.cgDeclFrmt, [modifiedTyp, param.loc.snippet])
- proc addUnnamedParam(builder: var Builder, params: var ProcParamBuilder, typ: Snippet) =
- if params.needsComma:
- builder.add(", ")
- else:
- params.needsComma = true
- builder.add(typ)
- proc addProcTypedParam(builder: var Builder, paramBuilder: var ProcParamBuilder, callConv: TCallingConvention, name: string, rettype, params: Snippet) =
- if paramBuilder.needsComma:
- builder.add(", ")
- else:
- paramBuilder.needsComma = true
- builder.add(CallingConvToStr[callConv])
- builder.add("_PTR(")
- builder.add(rettype)
- builder.add(", ")
- builder.add(name)
- builder.add(")")
- builder.add(params)
- proc addVarargsParam(builder: var Builder, params: var ProcParamBuilder) =
- # does not exist in NIFC, needs to be proc pragma
- if params.needsComma:
- builder.add(", ")
- else:
- params.needsComma = true
- builder.add("...")
- template addProcParams(builder: var Builder, params: out ProcParamBuilder, body: typed) =
- params = initProcParamBuilder(builder)
- body
- finishProcParamBuilder(builder, params)
- type SimpleProcParam = tuple
- name, typ: string
- proc cProcParams(params: varargs[SimpleProcParam]): Snippet =
- if params.len == 0: return "(void)"
- result = "("
- for i in 0 ..< params.len:
- if i != 0: result.add(", ")
- result.add(params[i].typ)
- if params[i].name.len != 0:
- result.add(" ")
- result.add(params[i].name)
- result.add(")")
- template addProcHeaderWithParams(builder: var Builder, callConv: TCallingConvention,
- name: string, rettype: Snippet, paramBuilder: typed) =
- # on nifc should build something like (proc name params type pragmas
- # with no body given
- # or enforce this with secondary builder object
- builder.add(CallingConvToStr[callConv])
- builder.add("(")
- builder.add(rettype)
- builder.add(", ")
- builder.add(name)
- builder.add(")")
- paramBuilder
- proc addProcHeader(builder: var Builder, callConv: TCallingConvention,
- name: string, rettype, params: Snippet) =
- # on nifc should build something like (proc name params type pragmas
- # with no body given
- # or enforce this with secondary builder object
- addProcHeaderWithParams(builder, callConv, name, rettype):
- builder.add(params)
- proc addProcHeader(builder: var Builder, name: string, rettype, params: Snippet, isConstructor = false) =
- # no callconv
- builder.add(rettype)
- builder.add(" ")
- if isConstructor:
- builder.add("__attribute__((constructor)) ")
- builder.add(name)
- builder.add(params)
- proc addProcHeader(builder: var Builder, m: BModule, prc: PSym, name: string, params, rettype: Snippet, addAttributes: bool) =
- # on nifc should build something like (proc name params type pragmas
- # with no body given
- # or enforce this with secondary builder object
- let noreturn = isNoReturn(m, prc)
- if sfPure in prc.flags and hasDeclspec in extccomp.CC[m.config.cCompiler].props:
- builder.add("__declspec(naked) ")
- if noreturn and hasDeclspec in extccomp.CC[m.config.cCompiler].props:
- builder.add("__declspec(noreturn) ")
- builder.add(CallingConvToStr[prc.typ.callConv])
- builder.add("(")
- builder.add(rettype)
- builder.add(", ")
- builder.add(name)
- builder.add(")")
- builder.add(params)
- if addAttributes:
- if sfPure in prc.flags and hasAttribute in extccomp.CC[m.config.cCompiler].props:
- builder.add(" __attribute__((naked))")
- if noreturn and hasAttribute in extccomp.CC[m.config.cCompiler].props:
- builder.add(" __attribute__((noreturn))")
- proc finishProcHeaderAsProto(builder: var Builder) =
- builder.addLineEnd(";")
- template finishProcHeaderWithBody(builder: var Builder, body: typed) =
- builder.addLineEndIndent(" {")
- body
- builder.addLineEndDedent("}")
- builder.addNewline
- proc addProcVar(builder: var Builder, m: BModule, prc: PSym, name: string, params, rettype: Snippet,
- isStatic = false, ignoreAttributes = false) =
- # on nifc, builds full variable
- if isStatic:
- builder.add("static ")
- let noreturn = isNoReturn(m, prc)
- if not ignoreAttributes:
- if sfPure in prc.flags and hasDeclspec in extccomp.CC[m.config.cCompiler].props:
- builder.add("__declspec(naked) ")
- if noreturn and hasDeclspec in extccomp.CC[m.config.cCompiler].props:
- builder.add("__declspec(noreturn) ")
- builder.add(CallingConvToStr[prc.typ.callConv])
- builder.add("_PTR(")
- builder.add(rettype)
- builder.add(", ")
- builder.add(name)
- builder.add(")")
- builder.add(params)
- if not ignoreAttributes:
- if sfPure in prc.flags and hasAttribute in extccomp.CC[m.config.cCompiler].props:
- builder.add(" __attribute__((naked))")
- if noreturn and hasAttribute in extccomp.CC[m.config.cCompiler].props:
- builder.add(" __attribute__((noreturn))")
- # ensure we are just adding a variable:
- builder.addLineEnd(";")
- proc addProcVar(builder: var Builder, callConv: TCallingConvention,
- name: string, params, rettype: Snippet,
- isStatic = false, isVolatile = false) =
- # on nifc, builds full variable
- if isStatic:
- builder.add("static ")
- builder.add(CallingConvToStr[callConv])
- builder.add("_PTR(")
- builder.add(rettype)
- builder.add(", ")
- if isVolatile:
- builder.add("volatile ")
- builder.add(name)
- builder.add(")")
- builder.add(params)
- # ensure we are just adding a variable:
- builder.addLineEnd(";")
- proc addProcVar(builder: var Builder,
- name: string, params, rettype: Snippet,
- isStatic = false, isVolatile = false) =
- # no callconv
- if isStatic:
- builder.add("static ")
- builder.add(rettype)
- builder.add(" (*")
- if isVolatile:
- builder.add("volatile ")
- builder.add(name)
- builder.add(")")
- builder.add(params)
- # ensure we are just adding a variable:
- builder.addLineEnd(";")
- type VarInitializerKind = enum
- Assignment, CppConstructor
- proc addVar(builder: var Builder, m: BModule, s: PSym, name: string, typ: Snippet, kind = Local, visibility: DeclVisibility = None, initializer: Snippet = "", initializerKind: VarInitializerKind = Assignment) =
- if sfCodegenDecl in s.flags:
- builder.add(runtimeFormat(s.cgDeclFrmt, [typ, name]))
- if initializer.len != 0:
- if initializerKind == Assignment:
- builder.add(" = ")
- builder.add(initializer)
- builder.addLineEnd(";")
- return
- if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
- builder.add("NIM_ALIGN(" & $s.alignment & ") ")
- builder.addVisibilityPrefix(visibility)
- if kind == Threadvar:
- if optThreads in m.config.globalOptions:
- let sym = s.typ.sym
- if sym != nil and sfCppNonPod in sym.flags:
- builder.add("NIM_THREAD_LOCAL ")
- else: builder.add("NIM_THREADVAR ")
- else:
- builder.addVarHeader(kind)
- builder.add(typ)
- if sfRegister in s.flags: builder.add(" register")
- if sfVolatile in s.flags: builder.add(" volatile")
- if sfNoalias in s.flags: builder.add(" NIM_NOALIAS")
- builder.add(" ")
- builder.add(name)
- if initializer.len != 0:
- if initializerKind == Assignment:
- builder.add(" = ")
- builder.add(initializer)
- builder.addLineEnd(";")
- proc addInclude(builder: var Builder, value: Snippet) =
- builder.addLineEnd("#include " & value)
|