cbuilder: add switch stmt, use for ccgreset and ccgtrav (#24408)

Not all uses of switch statements are implemented, `genCaseGeneric` and
`genIfForCaseUntil` still exist. The main purpose is to finish
`ccgreset` and `ccgtrav`.
This commit is contained in:
metagn
2024-11-05 12:30:47 +03:00
committed by GitHub
parent 0bc3f5c74c
commit f4b9fcc8ac
6 changed files with 251 additions and 105 deletions

View File

@@ -471,9 +471,31 @@ template addProcParams(builder: var Builder, params: out ProcParamBuilder, body:
body
finishProcParamBuilder(builder, params)
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, 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) ")
@@ -525,3 +547,18 @@ proc addProcVar(builder: var Builder, m: BModule, prc: PSym, name: string, param
builder.add(" __attribute__((noreturn))")
# ensure we are just adding a variable:
builder.add(";\n")
proc addProcVar(builder: var Builder, callConv: TCallingConvention,
name: string, params, rettype: Snippet, isStatic = false) =
# on nifc, builds full variable
if isStatic:
builder.add("static ")
builder.add(CallingConvToStr[callConv])
builder.add("_PTR(")
builder.add(rettype)
builder.add(", ")
builder.add(name)
builder.add(")")
builder.add(params)
# ensure we are just adding a variable:
builder.add(";\n")

View File

@@ -29,6 +29,9 @@ proc procPtrTypeUnnamed(rettype, params: Snippet): Snippet =
proc procPtrTypeUnnamedNimCall(rettype, params: Snippet): Snippet =
rettype & "(N_RAW_NIMCALL*)" & params
proc procPtrTypeUnnamed(callConv: TCallingConvention, rettype, params: Snippet): Snippet =
CallingConvToStr[callConv] & "_PTR(" & rettype & ", )" & params
proc cCast(typ, value: Snippet): Snippet =
"((" & typ & ") " & value & ")"

View File

@@ -119,6 +119,61 @@ template addForRangeInclusive(builder: var Builder, i, start, bound: Snippet, bo
body
builder.add("}\n")
template addSwitchStmt(builder: var Builder, val: Snippet, body: typed) =
builder.add("switch (")
builder.add(val)
builder.add(") {\n")
body
builder.add("}\n")
template addSingleSwitchCase(builder: var Builder, val: Snippet, body: typed) =
builder.add("case ")
builder.add(val)
builder.add(":\n")
body
type
SwitchCaseState = enum
None, Of, Else, Finished
SwitchCaseBuilder = object
state: SwitchCaseState
proc addCase(builder: var Builder, info: var SwitchCaseBuilder, val: Snippet) =
if info.state != Of:
assert info.state == None
info.state = Of
builder.add("case ")
builder.add(val)
builder.add(":\n")
proc addCaseRange(builder: var Builder, info: var SwitchCaseBuilder, first, last: Snippet) =
if info.state != Of:
assert info.state == None
info.state = Of
builder.add("case ")
builder.add(first)
builder.add(" ... ")
builder.add(last)
builder.add(":\n")
proc addCaseElse(builder: var Builder, info: var SwitchCaseBuilder) =
assert info.state == None
info.state = Else
builder.add("default:\n")
template addSwitchCase(builder: var Builder, info: out SwitchCaseBuilder, caseBody, body: typed) =
info = SwitchCaseBuilder(state: None)
caseBody
info.state = Finished
body
template addSwitchElse(builder: var Builder, body: typed) =
builder.add("default:\n")
body
proc addBreak(builder: var Builder) =
builder.add("break;\n")
template addScope(builder: var Builder, body: typed) =
builder.add("{")
body

View File

@@ -27,25 +27,28 @@ proc specializeResetN(p: BProc, accessor: Rope, n: PNode;
if disc.loc.snippet == "": fillObjectFields(p.module, typ)
if disc.loc.t == nil:
internalError(p.config, n.info, "specializeResetN()")
lineF(p, cpsStmts, "switch ($1.$2) {$n", [accessor, disc.loc.snippet])
for i in 1..<n.len:
let branch = n[i]
assert branch.kind in {nkOfBranch, nkElse}
if branch.kind == nkOfBranch:
genCaseRange(p, branch)
else:
lineF(p, cpsStmts, "default:$n", [])
specializeResetN(p, accessor, lastSon(branch), typ)
lineF(p, cpsStmts, "break;$n", [])
lineF(p, cpsStmts, "} $n", [])
specializeResetT(p, "$1.$2" % [accessor, disc.loc.snippet], disc.loc.t)
let discField = dotField(accessor, disc.loc.snippet)
p.s(cpsStmts).addSwitchStmt(discField):
for i in 1..<n.len:
let branch = n[i]
assert branch.kind in {nkOfBranch, nkElse}
var caseBuilder: SwitchCaseBuilder
p.s(cpsStmts).addSwitchCase(caseBuilder):
if branch.kind == nkOfBranch:
genCaseRange(p, branch, caseBuilder)
else:
p.s(cpsStmts).addCaseElse(caseBuilder)
do:
specializeResetN(p, accessor, lastSon(branch), typ)
p.s(cpsStmts).addBreak()
specializeResetT(p, discField, disc.loc.t)
of nkSym:
let field = n.sym
if field.typ.kind == tyVoid: return
if field.loc.snippet == "": fillObjectFields(p.module, typ)
if field.loc.t == nil:
internalError(p.config, n.info, "specializeResetN()")
specializeResetT(p, "$1.$2" % [accessor, field.loc.snippet], field.loc.t)
specializeResetT(p, dotField(accessor, field.loc.snippet), field.loc.t)
else: internalError(p.config, n.info, "specializeResetN()")
proc specializeResetT(p: BProc, accessor: Rope, typ: PType) =
@@ -58,10 +61,8 @@ proc specializeResetT(p: BProc, accessor: Rope, typ: PType) =
of tyArray:
let arraySize = lengthOrd(p.config, typ.indexType)
var i: TLoc = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt))
linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
[i.snippet, arraySize])
specializeResetT(p, ropecg(p.module, "$1[$2]", [accessor, i.snippet]), typ.elementType)
lineF(p, cpsStmts, "}$n", [])
p.s(cpsStmts).addForRangeExclusive(i.snippet, cIntValue(0), cIntValue(arraySize)):
specializeResetT(p, subscript(accessor, i.snippet), typ.elementType)
of tyObject:
var x = typ.baseClass
if x != nil: x = x.skipTypes(skipPtrs)
@@ -70,28 +71,34 @@ proc specializeResetT(p: BProc, accessor: Rope, typ: PType) =
of tyTuple:
let typ = getUniqueType(typ)
for i, a in typ.ikids:
specializeResetT(p, ropecg(p.module, "$1.Field$2", [accessor, i]), a)
specializeResetT(p, dotField(accessor, "Field" & $i), a)
of tyString, tyRef, tySequence:
lineCg(p, cpsStmts, "#unsureAsgnRef((void**)&$1, NIM_NIL);$n", [accessor])
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "unsureAsgnRef"),
cCast("void**", cAddr(accessor)),
"NIM_NIL")
of tyProc:
if typ.callConv == ccClosure:
lineCg(p, cpsStmts, "#unsureAsgnRef((void**)&$1.ClE_0, NIM_NIL);$n", [accessor])
lineCg(p, cpsStmts, "$1.ClP_0 = NIM_NIL;$n", [accessor])
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "unsureAsgnRef"),
cCast("void**", cAddr(dotField(accessor, "ClE_0"))),
"NIM_NIL")
p.s(cpsStmts).addFieldAssignment(accessor, "ClP_0", "NIM_NIL")
else:
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor])
p.s(cpsStmts).addAssignment(accessor, "NIM_NIL")
of tyChar, tyBool, tyEnum, tyRange, tyInt..tyUInt64:
lineCg(p, cpsStmts, "$1 = 0;$n", [accessor])
p.s(cpsStmts).addAssignment(accessor, cIntValue(0))
of tyCstring, tyPointer, tyPtr, tyVar, tyLent:
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor])
p.s(cpsStmts).addAssignment(accessor, "NIM_NIL")
of tySet:
case mapSetType(p.config, typ)
of ctArray:
lineCg(p, cpsStmts, "#nimZeroMem($1, sizeof($2));$n",
[accessor, getTypeDesc(p.module, typ)])
let t = getTypeDesc(p.module, typ)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimZeroMem"),
accessor,
cSizeof(t))
of ctInt8, ctInt16, ctInt32, ctInt64:
lineCg(p, cpsStmts, "$1 = 0;$n", [accessor])
p.s(cpsStmts).addAssignment(accessor, cIntValue(0))
else:
raiseAssert "unexpected set type kind"
of tyNone, tyEmpty, tyNil, tyUntyped, tyTyped, tyGenericInvocation,

View File

@@ -960,7 +960,7 @@ proc ifSwitchSplitPoint(p: BProc, n: PNode): int =
if branch.kind == nkOfBranch and branchHasTooBigRange(branch):
result = i
proc genCaseRange(p: BProc, branch: PNode) =
proc genCaseRange(p: BProc, branch: PNode, info: var SwitchCaseBuilder) =
for j in 0..<branch.len-1:
if branch[j].kind == nkRange:
if hasSwitchRange in CC[p.config.cCompiler].props:
@@ -968,18 +968,18 @@ proc genCaseRange(p: BProc, branch: PNode) =
var litB = newBuilder("")
genLiteral(p, branch[j][0], litA)
genLiteral(p, branch[j][1], litB)
lineF(p, cpsStmts, "case $1 ... $2:$n", [extract(litA), extract(litB)])
p.s(cpsStmts).addCaseRange(info, extract(litA), extract(litB))
else:
var v = copyNode(branch[j][0])
while v.intVal <= branch[j][1].intVal:
var litA = newBuilder("")
genLiteral(p, v, litA)
lineF(p, cpsStmts, "case $1:$n", [extract(litA)])
p.s(cpsStmts).addCase(info, extract(litA))
inc(v.intVal)
else:
var litA = newBuilder("")
genLiteral(p, branch[j], litA)
lineF(p, cpsStmts, "case $1:$n", [extract(litA)])
p.s(cpsStmts).addCase(info, extract(litA))
proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
# analyse 'case' statement:
@@ -994,26 +994,31 @@ proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
# generate switch part (might be empty):
if splitPoint+1 < n.len:
lineF(p, cpsStmts, "switch ($1) {$n", [rdCharLoc(a)])
var hasDefault = false
for i in splitPoint+1..<n.len:
# bug #4230: avoid false sharing between branches:
if d.k == locTemp and isEmptyType(n.typ): d.k = locNone
var branch = n[i]
if branch.kind == nkOfBranch:
genCaseRange(p, branch)
else:
# else part of case statement:
lineF(p, cpsStmts, "default:$n", [])
hasDefault = true
exprBlock(p, branch.lastSon, d)
lineF(p, cpsStmts, "break;$n", [])
if not hasDefault:
if hasBuiltinUnreachable in CC[p.config.cCompiler].props:
lineF(p, cpsStmts, "default: __builtin_unreachable();$n", [])
elif hasAssume in CC[p.config.cCompiler].props:
lineF(p, cpsStmts, "default: __assume(0);$n", [])
lineF(p, cpsStmts, "}$n", [])
let rca = rdCharLoc(a)
p.s(cpsStmts).addSwitchStmt(rca):
var hasDefault = false
for i in splitPoint+1..<n.len:
# bug #4230: avoid false sharing between branches:
if d.k == locTemp and isEmptyType(n.typ): d.k = locNone
var branch = n[i]
var caseBuilder: SwitchCaseBuilder
p.s(cpsStmts).addSwitchCase(caseBuilder):
if branch.kind == nkOfBranch:
genCaseRange(p, branch, caseBuilder)
else:
# else part of case statement:
hasDefault = true
p.s(cpsStmts).addCaseElse(caseBuilder)
do:
exprBlock(p, branch.lastSon, d)
p.s(cpsStmts).addBreak()
if not hasDefault:
if hasBuiltinUnreachable in CC[p.config.cCompiler].props:
p.s(cpsStmts).addSwitchElse():
p.s(cpsStmts).addCallStmt("__builtin_unreachable")
elif hasAssume in CC[p.config.cCompiler].props:
p.s(cpsStmts).addSwitchElse():
p.s(cpsStmts).addCallStmt("__assume", cIntValue(0))
if lend != "": fixLabel(p, lend)
proc genCase(p: BProc, t: PNode, d: var TLoc) =

View File

@@ -16,13 +16,16 @@ type
p: BProc
visitorFrmt: string
const
visitorFrmt = "#nimGCvisit((void*)$1, $2);$n"
proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType)
proc genCaseRange(p: BProc, branch: PNode)
proc genCaseRange(p: BProc, branch: PNode, info: var SwitchCaseBuilder)
proc getTemp(p: BProc, t: PType, needsInit=false): TLoc
proc visit(p: BProc, data, visitor: Snippet) =
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimGCvisit"),
cCast("void*", data),
visitor)
proc genTraverseProc(c: TTraversalClosure, accessor: Rope, n: PNode;
typ: PType) =
if n == nil: return
@@ -37,29 +40,32 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, n: PNode;
if disc.loc.snippet == "": fillObjectFields(c.p.module, typ)
if disc.loc.t == nil:
internalError(c.p.config, n.info, "genTraverseProc()")
lineF(p, cpsStmts, "switch ($1.$2) {$n", [accessor, disc.loc.snippet])
for i in 1..<n.len:
let branch = n[i]
assert branch.kind in {nkOfBranch, nkElse}
if branch.kind == nkOfBranch:
genCaseRange(c.p, branch)
else:
lineF(p, cpsStmts, "default:$n", [])
genTraverseProc(c, accessor, lastSon(branch), typ)
lineF(p, cpsStmts, "break;$n", [])
lineF(p, cpsStmts, "} $n", [])
let discField = dotField(accessor, disc.loc.snippet)
p.s(cpsStmts).addSwitchStmt(discField):
for i in 1..<n.len:
let branch = n[i]
assert branch.kind in {nkOfBranch, nkElse}
var caseBuilder: SwitchCaseBuilder
p.s(cpsStmts).addSwitchCase(caseBuilder):
if branch.kind == nkOfBranch:
genCaseRange(c.p, branch, caseBuilder)
else:
p.s(cpsStmts).addCaseElse(caseBuilder)
do:
genTraverseProc(c, accessor, lastSon(branch), typ)
p.s(cpsStmts).addBreak()
of nkSym:
let field = n.sym
if field.typ.kind == tyVoid: return
if field.loc.snippet == "": fillObjectFields(c.p.module, typ)
if field.loc.t == nil:
internalError(c.p.config, n.info, "genTraverseProc()")
genTraverseProc(c, "$1.$2" % [accessor, field.loc.snippet], field.loc.t)
genTraverseProc(c, dotField(accessor, field.loc.snippet), field.loc.t)
else: internalError(c.p.config, n.info, "genTraverseProc()")
proc parentObj(accessor: Rope; m: BModule): Rope {.inline.} =
if not m.compileToCpp:
result = "$1.Sup" % [accessor]
result = dotField(accessor, "Sup")
else:
result = accessor
@@ -76,15 +82,14 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
let arraySize = lengthOrd(c.p.config, typ.indexType)
var i: TLoc = getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo, tyInt))
var oldCode = p.s(cpsStmts)
linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
[i.snippet, arraySize])
let oldLen = p.s(cpsStmts).buf.len
genTraverseProc(c, ropecg(c.p.module, "$1[$2]", [accessor, i.snippet]), typ.elementType)
if p.s(cpsStmts).buf.len == oldLen:
var oldLen, newLen: int
p.s(cpsStmts).addForRangeExclusive(i.snippet, cIntValue(0), cIntValue(arraySize)):
oldLen = p.s(cpsStmts).buf.len
genTraverseProc(c, subscript(accessor, i.snippet), typ.elementType)
newLen = p.s(cpsStmts).buf.len
if oldLen == newLen:
# do not emit dummy long loops for faster debug builds:
p.s(cpsStmts) = oldCode
else:
lineF(p, cpsStmts, "}$n", [])
of tyObject:
var x = typ.baseClass
if x != nil: x = x.skipTypes(skipPtrs)
@@ -93,23 +98,25 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
of tyTuple:
let typ = getUniqueType(typ)
for i, a in typ.ikids:
genTraverseProc(c, ropecg(c.p.module, "$1.Field$2", [accessor, i]), a)
genTraverseProc(c, dotField(accessor, "Field" & $i), a)
of tyRef:
lineCg(p, cpsStmts, visitorFrmt, [accessor, c.visitorFrmt])
visit(p, accessor, c.visitorFrmt)
of tySequence:
if optSeqDestructors notin c.p.module.config.globalOptions:
lineCg(p, cpsStmts, visitorFrmt, [accessor, c.visitorFrmt])
visit(p, accessor, c.visitorFrmt)
elif containsGarbageCollectedRef(typ.elementType):
# destructor based seqs are themselves not traced but their data is, if
# they contain a GC'ed type:
lineCg(p, cpsStmts, "#nimGCvisitSeq((void*)$1, $2);$n", [accessor, c.visitorFrmt])
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimGCvisitSeq"),
cCast("void*", accessor),
c.visitorFrmt)
#genTraverseProcSeq(c, accessor, typ)
of tyString:
if tfHasAsgn notin typ.flags:
lineCg(p, cpsStmts, visitorFrmt, [accessor, c.visitorFrmt])
visit(p, accessor, c.visitorFrmt)
of tyProc:
if typ.callConv == ccClosure:
lineCg(p, cpsStmts, visitorFrmt, [ropecg(c.p.module, "$1.ClE_0", [accessor]), c.visitorFrmt])
visit(p, dotField(accessor, "ClE_0"), c.visitorFrmt)
else:
discard
@@ -118,17 +125,17 @@ proc genTraverseProcSeq(c: TTraversalClosure, accessor: Rope, typ: PType) =
assert typ.kind == tySequence
var i = getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo, tyInt))
var oldCode = p.s(cpsStmts)
var oldLen, newLen: int
var a = TLoc(snippet: accessor)
let le = lenExpr(c.p, a)
lineF(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
[i.snippet, lenExpr(c.p, a)])
let oldLen = p.s(cpsStmts).buf.len
genTraverseProc(c, "$1$3[$2]" % [accessor, i.snippet, dataField(c.p)], typ.elementType)
if p.s(cpsStmts).buf.len == oldLen:
p.s(cpsStmts).addForRangeExclusive(i.snippet, cIntValue(0), le):
oldLen = p.s(cpsStmts).buf.len
genTraverseProc(c, subscript(dataField(c.p, accessor), i.snippet), typ.elementType)
newLen = p.s(cpsStmts).buf.len
if newLen == oldLen:
# do not emit dummy long loops for faster debug builds:
p.s(cpsStmts) = oldCode
else:
lineF(p, cpsStmts, "}$n", [])
proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash): Rope =
var p = newProc(nil, m)
@@ -137,11 +144,10 @@ proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash): Rope =
hcrOn = m.hcrOn
typ = origTyp.skipTypes(abstractInstOwned)
markerName = if hcrOn: result & "_actual" else: result
header = "static N_NIMCALL(void, $1)(void* p, NI op)" % [markerName]
t = getTypeDesc(m, typ)
lineF(p, cpsLocals, "$1 a;$n", [t])
lineF(p, cpsInit, "a = ($1)p;$n", [t])
p.s(cpsLocals).addVar(kind = Local, name = "a", typ = t)
p.s(cpsInit).addAssignment("a", cCast(t, "p"))
var c = TTraversalClosure(p: p,
visitorFrmt: "op" # "#nimGCvisit((void*)$1, op);$n"
@@ -155,18 +161,40 @@ proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash): Rope =
# C's arrays are broken beyond repair:
genTraverseProc(c, "a".rope, typ.elementType)
else:
genTraverseProc(c, "(*a)".rope, typ.elementType)
genTraverseProc(c, cDeref("a"), typ.elementType)
let generatedProc = "$1 {$n$2$3$4}\n" %
[header, extract(p.s(cpsLocals)), extract(p.s(cpsInit)), extract(p.s(cpsStmts))]
var headerBuilder = newBuilder("")
headerBuilder.addProcHeaderWithParams(ccNimCall, markerName, "void"):
var paramBuilder: ProcParamBuilder
headerBuilder.addProcParams(paramBuilder):
headerBuilder.addParam(paramBuilder, name = "p", typ = "void*")
headerBuilder.addParam(paramBuilder, name = "op", typ = "NI")
let header = extract(headerBuilder)
m.s[cfsProcHeaders].addf("$1;\n", [header])
m.s[cfsProcs].add(generatedProc)
m.s[cfsProcHeaders].addDeclWithVisibility(StaticProc):
m.s[cfsProcHeaders].add(header)
m.s[cfsProcHeaders].finishProcHeaderAsProto()
m.s[cfsProcs].addDeclWithVisibility(StaticProc):
m.s[cfsProcs].add(header)
m.s[cfsProcs].finishProcHeaderWithBody():
m.s[cfsProcs].add(extract(p.s(cpsLocals)))
m.s[cfsProcs].add(extract(p.s(cpsInit)))
m.s[cfsProcs].add(extract(p.s(cpsStmts)))
if hcrOn:
m.s[cfsProcHeaders].addf("N_NIMCALL_PTR(void, $1)(void*, NI);\n", [result])
m.s[cfsDynLibInit].addf("\t$1 = (N_NIMCALL_PTR(void, )(void*, NI)) hcrRegisterProc($3, \"$1\", (void*)$2);\n",
[result, markerName, getModuleDllPath(m)])
var desc = newBuilder("")
var unnamedParamBuilder: ProcParamBuilder
desc.addProcParams(unnamedParamBuilder):
desc.addUnnamedParam(unnamedParamBuilder, "void*")
desc.addUnnamedParam(unnamedParamBuilder, "NI")
let unnamedParams = extract(desc)
m.s[cfsProcHeaders].addProcVar(ccNimCall, result, unnamedParams, "void")
m.s[cfsDynLibInit].addAssignmentWithValue(result):
m.s[cfsDynLibInit].addCast(procPtrTypeUnnamed(ccNimCall, "void", unnamedParams)):
m.s[cfsDynLibInit].addCall("hcrRegisterProc",
getModuleDllPath(m),
'"' & result & '"',
cCast("void*", markerName))
proc genTraverseProcForGlobal(m: BModule, s: PSym; info: TLineInfo): Rope =
discard genTypeInfoV1(m, s.loc.t, info)
@@ -177,17 +205,28 @@ proc genTraverseProcForGlobal(m: BModule, s: PSym; info: TLineInfo): Rope =
if sfThread in s.flags and emulatedThreadVars(m.config):
accessThreadLocalVar(p, s)
sLoc = "NimTV_->" & sLoc
sLoc = derefField("NimTV_", sLoc)
var c = TTraversalClosure(p: p,
visitorFrmt: "0" # "#nimGCvisit((void*)$1, 0);$n"
visitorFrmt: cIntValue(0) # "#nimGCvisit((void*)$1, 0);$n"
)
let header = "static N_NIMCALL(void, $1)(void)" % [result]
genTraverseProc(c, sLoc, s.loc.t)
let generatedProc = "$1 {$n$2$3$4}$n" %
[header, extract(p.s(cpsLocals)), extract(p.s(cpsInit)), extract(p.s(cpsStmts))]
var headerBuilder = newBuilder("")
headerBuilder.addProcHeaderWithParams(ccNimCall, result, "void"):
var paramBuilder: ProcParamBuilder
headerBuilder.addProcParams(paramBuilder):
# (void)
discard
let header = extract(headerBuilder)
m.s[cfsProcHeaders].addf("$1;$n", [header])
m.s[cfsProcs].add(generatedProc)
m.s[cfsProcHeaders].addDeclWithVisibility(StaticProc):
m.s[cfsProcHeaders].add(header)
m.s[cfsProcHeaders].finishProcHeaderAsProto()
m.s[cfsProcs].addDeclWithVisibility(StaticProc):
m.s[cfsProcs].add(header)
m.s[cfsProcs].finishProcHeaderWithBody():
m.s[cfsProcs].add(extract(p.s(cpsLocals)))
m.s[cfsProcs].add(extract(p.s(cpsInit)))
m.s[cfsProcs].add(extract(p.s(cpsStmts)))