Skip to content

Commit

Permalink
cbuilder: upper half of cgen, variable decls (#24423)
Browse files Browse the repository at this point in the history
The lower half of cgen contains the main proc and HCR init code which
cause a large diff, so they are excluded from this PR. In general things
like generated defines, line directives, the stacktrace macros (`nimfr_`
etc) are also not done, since there are not exact equivalents for these
in NIFC (NIFC does generate line directives but based on the NIF line
info mechanism).
  • Loading branch information
metagn authored Nov 10, 2024
1 parent 1fddb61 commit 9d61f2c
Show file tree
Hide file tree
Showing 6 changed files with 341 additions and 230 deletions.
46 changes: 44 additions & 2 deletions compiler/cbuilderdecls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,8 @@ type DeclVisibility = enum
Private
StaticProc

template addDeclWithVisibility(builder: var Builder, visibility: DeclVisibility, declBody: typed) =
## adds a declaration as in `declBody` with the given visibility
proc addVisibilityPrefix(builder: var Builder, visibility: DeclVisibility) =
# internal proc
case visibility
of None: discard
of Extern:
Expand All @@ -415,6 +415,10 @@ template addDeclWithVisibility(builder: var Builder, visibility: DeclVisibility,
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
Expand Down Expand Up @@ -568,3 +572,41 @@ proc addProcVar(builder: var Builder, callConv: TCallingConvention,
builder.add(params)
# ensure we are just adding a variable:
builder.add(";\n")

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.add(";\n")
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.add(";\n")

proc addInclude(builder: var Builder, value: Snippet) =
builder.add("#include " & value & "\n")
26 changes: 10 additions & 16 deletions compiler/ccgstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -348,13 +348,6 @@ proc genCppParamsForCtor(p: BProc; call: PNode; didGenTemp: var bool): Snippet =
genOtherArg(p, call, i, typ, res, argBuilder)
result = extract(res)

proc genCppVarForCtor(p: BProc; call: PNode; decl: var Rope, didGenTemp: var bool) =
let params = genCppParamsForCtor(p, call, didGenTemp)
if params.len == 0:
decl = runtimeFormat("$#;\n", [decl])
else:
decl = runtimeFormat("$#($#);\n", [decl, params])

proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
if sfGoto in v.flags:
# translate 'var state {.goto.} = X' into 'goto LX':
Expand Down Expand Up @@ -416,18 +409,19 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
# parameterless constructor followed by an assignment operator. So we
# generate better code here: 'Foo f = x;'
genLineDir(p, vn)
var decl = localVarDecl(p, vn)
var tmp: TLoc
var initializer: Snippet = ""
var initializerKind: VarInitializerKind = Assignment
if isCppCtorCall:
var didGenTemp = false
genCppVarForCtor(p, value, decl, didGenTemp)
line(p, cpsStmts, decl)
initializer = genCppParamsForCtor(p, value, didGenTemp)
if initializer.len != 0:
initializer = "(" & initializer & ")"
initializerKind = CppConstructor
else:
tmp = initLocExprSingleUse(p, value)
if value.kind == nkEmpty:
lineF(p, cpsStmts, "$#;\n", [decl])
else:
lineF(p, cpsStmts, "$# = $#;\n", [decl, tmp.rdLoc])
var tmp = initLocExprSingleUse(p, value)
if value.kind != nkEmpty:
initializer = tmp.rdLoc
localVarDecl(p.s(cpsStmts), p, vn, initializer, initializerKind)
return
assignLocalVar(p, vn)
initLocalVar(p, v, imm)
Expand Down
50 changes: 28 additions & 22 deletions compiler/ccgthreadvars.nim
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ proc accessThreadLocalVar(p: BProc, s: PSym) =
if emulatedThreadVars(p.config) and threadVarAccessed notin p.flags:
p.flags.incl threadVarAccessed
incl p.module.flags, usesThreadVars
p.procSec(cpsLocals).addf("\tNimThreadVars* NimTV_;$n", [])
p.procSec(cpsInit).add(
ropecg(p.module, "\tNimTV_ = (NimThreadVars*) #GetThreadLocalVars();$n", []))
p.procSec(cpsLocals).addVar(kind = Local,
name = "NimTV_",
typ = ptrType("NimThreadVars"))
p.procSec(cpsInit).addAssignment("NimTV_",
cCast(ptrType("NimThreadVars"),
cCall(cgsymValue(p.module, "GetThreadLocalVars"))))

proc declareThreadVar(m: BModule, s: PSym, isExtern: bool) =
if emulatedThreadVars(m.config):
Expand All @@ -30,32 +33,35 @@ proc declareThreadVar(m: BModule, s: PSym, isExtern: bool) =
# allocator for it :-(
if not containsOrIncl(m.g.nimtvDeclared, s.id):
m.g.nimtvDeps.add(s.loc.t)
m.g.nimtv.addf("$1 $2;$n", [getTypeDesc(m, s.loc.t), s.loc.snippet])
m.g.nimtv.addField(name = s.loc.snippet, typ = getTypeDesc(m, s.loc.t))
else:
if isExtern: m.s[cfsVars].add("extern ")
elif lfExportLib in s.loc.flags: m.s[cfsVars].add("N_LIB_EXPORT_VAR ")
else: m.s[cfsVars].add("N_LIB_PRIVATE ")
if optThreads in m.config.globalOptions:
let sym = s.typ.sym
if sym != nil and sfCppNonPod in sym.flags:
m.s[cfsVars].add("NIM_THREAD_LOCAL ")
else: m.s[cfsVars].add("NIM_THREADVAR ")
m.s[cfsVars].add(getTypeDesc(m, s.loc.t))
m.s[cfsVars].addf(" $1;$n", [s.loc.snippet])
let vis =
if isExtern: Extern
elif lfExportLib in s.loc.flags: ExportLibVar
else: Private
m.s[cfsVars].addVar(m, s,
name = s.loc.snippet,
typ = getTypeDesc(m, s.loc.t),
kind = Threadvar,
visibility = vis)

proc generateThreadLocalStorage(m: BModule) =
if m.g.nimtv != "" and (usesThreadVars in m.flags or sfMainModule in m.module.flags):
if m.g.nimtv.buf.len != 0 and (usesThreadVars in m.flags or sfMainModule in m.module.flags):
for t in items(m.g.nimtvDeps): discard getTypeDesc(m, t)
finishTypeDescriptions(m)
m.s[cfsSeqTypes].addTypedef(name = "NimThreadVars"):
m.s[cfsSeqTypes].addSimpleStruct(m, name = "", baseType = ""):
m.s[cfsSeqTypes].add(m.g.nimtv)
m.s[cfsSeqTypes].add(extract(m.g.nimtv))

proc generateThreadVarsSize(m: BModule) =
if m.g.nimtv != "":
if m.g.nimtv.buf.len != 0:
let externc = if m.config.backend == backendCpp or
sfCompileToCpp in m.module.flags: "extern \"C\" "
else: ""
m.s[cfsProcs].addf(
"$#NI NimThreadVarsSize(){return (NI)sizeof(NimThreadVars);}$n",
[externc.rope])
sfCompileToCpp in m.module.flags: ExternC
else: None
m.s[cfsProcs].addDeclWithVisibility(externc):
m.s[cfsProcs].addProcHeaderWithParams(ccNoConvention, "NimThreadVarsSize", "NI"):
var params: ProcParamBuilder
m.s[cfsProcs].addProcParams(params):
discard
m.s[cfsProcs].finishProcHeaderWithBody():
m.s[cfsProcs].addReturn(cCast("NI", cSizeof("NimThreadVars")))
54 changes: 27 additions & 27 deletions compiler/ccgtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1690,28 +1690,30 @@ proc genDisplayElem(d: MD5Digest): uint32 =
result += uint32(d[i])
result = result shl 8

proc genDisplay(m: BModule; t: PType, depth: int): Rope =
result = Rope"{"
proc genDisplay(result: var Builder, m: BModule; t: PType, depth: int) =
var x = t
var seqs = newSeq[string](depth+1)
var seqs = newSeq[Snippet](depth+1)
var i = 0
while x != nil:
x = skipTypes(x, skipPtrs)
seqs[i] = $genDisplayElem(MD5Digest(hashType(x, m.config)))
seqs[i] = cIntValue(genDisplayElem(MD5Digest(hashType(x, m.config))))
x = x[0]
inc i

for i in countdown(depth, 1):
result.add seqs[i] & ", "
result.add seqs[0]
result.add "}"

proc genVTable(seqs: seq[PSym]): string =
result = "{"
for i in 0..<seqs.len:
if i > 0: result.add ", "
result.add "(void *) " & seqs[i].loc.snippet
result.add "}"
var arr: StructInitializer
result.addStructInitializer(arr, siArray):
for i in countdown(depth, 1):
result.addField(arr, ""):
result.add(seqs[i])
result.addField(arr, ""):
result.add(seqs[0])

proc genVTable(result: var Builder, seqs: seq[PSym]) =
var table: StructInitializer
result.addStructInitializer(table, siArray):
for i in 0..<seqs.len:
result.addField(table, ""):
result.add(cCast("void*", seqs[i].loc.snippet))

proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLineInfo) =
cgsym(m, "TNimTypeV2")
Expand Down Expand Up @@ -1752,23 +1754,22 @@ proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLin
typeEntry.addFieldAssignment(name, "flags", flags)

if objDepth >= 0:
let objDisplay = genDisplay(m, t, objDepth)
let objDisplayStore = getTempName(m)
m.s[cfsVars].addArrayVar(kind = Global,
m.s[cfsVars].addArrayVarWithInitializer(kind = Global,
name = objDisplayStore,
elementType = getTypeDesc(m, getSysType(m.g.graph, unknownLineInfo, tyUInt32), dkVar),
len = objDepth + 1,
initializer = objDisplay)
len = objDepth + 1):
genDisplay(m.s[cfsVars], m, t, objDepth)
typeEntry.addFieldAssignment(name, "display", objDisplayStore)

let dispatchMethods = toSeq(getMethodsPerType(m.g.graph, t))
if dispatchMethods.len > 0:
let vTablePointerName = getTempName(m)
m.s[cfsVars].addArrayVar(kind = Global,
m.s[cfsVars].addArrayVarWithInitializer(kind = Global,
name = vTablePointerName,
elementType = "void*",
len = dispatchMethods.len,
initializer = genVTable(dispatchMethods))
len = dispatchMethods.len):
genVTable(m.s[cfsVars], dispatchMethods)
for i in dispatchMethods:
genProcPrototype(m, i)
typeEntry.addFieldAssignment(name, "vTable", vTablePointerName)
Expand Down Expand Up @@ -1811,13 +1812,12 @@ proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineIn
typeEntry.addIntValue(objDepth)

if objDepth >= 0:
let objDisplay = genDisplay(m, t, objDepth)
let objDisplayStore = getTempName(m)
m.s[cfsVars].addArrayVar(kind = Const,
m.s[cfsVars].addArrayVarWithInitializer(kind = Const,
name = objDisplayStore,
elementType = getTypeDesc(m, getSysType(m.g.graph, unknownLineInfo, tyUInt32), dkVar),
len = objDepth + 1,
initializer = objDisplay)
len = objDepth + 1):
genDisplay(m.s[cfsVars], m, t, objDepth)
typeEntry.addField(typeInit, name = "display"):
typeEntry.add(objDisplayStore)
if isDefined(m.config, "nimTypeNames"):
Expand All @@ -1839,7 +1839,7 @@ proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineIn
for i in dispatchMethods:
genProcPrototype(m, i)
typeEntry.addField(typeInit, name = "vTable"):
typeEntry.add(genVTable(dispatchMethods))
genVTable(typeEntry, dispatchMethods)
else:
typeEntry.addField(typeInit, name = "flags"):
typeEntry.addIntValue(flags)
Expand Down
Loading

0 comments on commit 9d61f2c

Please sign in to comment.