cbuilder: add decl visibilities, use it for HCR & typeinfo (#24368)

follows up #24362
This commit is contained in:
metagn
2024-10-28 07:27:11 +03:00
committed by GitHub
parent 24aa92c14f
commit 2e9422df57
4 changed files with 132 additions and 57 deletions

View File

@@ -347,3 +347,25 @@ template addAnonUnion(obj: var Builder; body: typed) =
obj.add "union{\n"
body
obj.add("};\n")
type DeclVisibility = enum
Extern
ImportLib
ExportLib
ExportLibVar
Private
template addDeclWithVisibility(builder: var Builder, visibility: DeclVisibility, declBody: typed) =
## adds a declaration as in `declBody` with the given visibility
case visibility
of Extern:
builder.add("extern ")
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 ")
declBody

View File

@@ -1,6 +1,9 @@
# XXX make complex ones like bitOr use builder instead
# XXX add stuff like NI, NIM_NIL as constants
proc constType(t: Snippet): Snippet =
"NIM_CONST " & t
proc ptrType(t: Snippet): Snippet =
t & "*"

View File

@@ -2962,13 +2962,22 @@ proc genConstHeader(m, q: BModule; p: BProc, sym: PSym) =
if not genConstSetup(p, sym): return
assert(sym.loc.snippet != "", $sym.name.s & $sym.itemId)
if m.hcrOn:
m.s[cfsVars].addf("static $1* $2;$n", [getTypeDesc(m, sym.loc.t, dkVar), sym.loc.snippet]);
m.initProc.procSec(cpsLocals).addf(
"\t$1 = ($2*)hcrGetGlobal($3, \"$1\");$n", [sym.loc.snippet,
getTypeDesc(m, sym.loc.t, dkVar), getModuleDllPath(q, sym)])
m.s[cfsVars].addVar(kind = Global, name = sym.loc.snippet,
typ = ptrType(getTypeDesc(m, sym.loc.t, dkVar)))
m.initProc.procSec(cpsLocals).add('\t')
m.initProc.procSec(cpsLocals).addAssignment(sym.loc.snippet):
m.initProc.procSec(cpsLocals).addCast(ptrType(getTypeDesc(m, sym.loc.t, dkVar))):
var getGlobalCall: CallBuilder
m.initProc.procSec(cpsLocals).addCall(getGlobalCall, "hcrGetGlobal"):
m.initProc.procSec(cpsLocals).addArgument(getGlobalCall):
m.initProc.procSec(cpsLocals).add(getModuleDllPath(q, sym))
m.initProc.procSec(cpsLocals).addArgument(getGlobalCall):
m.initProc.procSec(cpsLocals).add('"' & sym.loc.snippet & '"')
else:
let headerDecl = "extern NIM_CONST $1 $2;$n" %
[getTypeDesc(m, sym.loc.t, dkVar), sym.loc.snippet]
var headerDecl = newBuilder("")
headerDecl.addDeclWithVisibility(Extern):
headerDecl.addVar(kind = Local, name = sym.loc.snippet,
typ = constType(getTypeDesc(m, sym.loc.t, dkVar)))
m.s[cfsData].add(headerDecl)
if sfExportc in sym.flags and p.module.g.generatedHeader != nil:
p.module.g.generatedHeader.s[cfsData].add(headerDecl)
@@ -2977,23 +2986,44 @@ proc genConstDefinition(q: BModule; p: BProc; sym: PSym) =
# add a suffix for hcr - will later init the global pointer with this data
let actualConstName = if q.hcrOn: sym.loc.snippet & "_const" else: sym.loc.snippet
var data = newRopeAppender()
data.addf("N_LIB_PRIVATE NIM_CONST $1 $2 = ",
[getTypeDesc(q, sym.typ), actualConstName])
genBracedInit(q.initProc, sym.astdef, isConst = true, sym.typ, data)
data.addf(";$n", [])
data.addDeclWithVisibility(Private):
data.addVarWithTypeAndInitializer(Local, actualConstName):
data.add(constType(getTypeDesc(q, sym.typ)))
do:
genBracedInit(q.initProc, sym.astdef, isConst = true, sym.typ, data)
q.s[cfsData].add data
if q.hcrOn:
# generate the global pointer with the real name
q.s[cfsVars].addf("static $1* $2;$n", [getTypeDesc(q, sym.loc.t, dkVar), sym.loc.snippet])
q.s[cfsVars].addVar(kind = Global, name = sym.loc.snippet,
typ = ptrType(getTypeDesc(q, sym.loc.t, dkVar)))
# register it (but ignore the boolean result of hcrRegisterGlobal)
q.initProc.procSec(cpsLocals).addf(
"\thcrRegisterGlobal($1, \"$2\", sizeof($3), NULL, (void**)&$2);$n",
[getModuleDllPath(q, sym), sym.loc.snippet, rdLoc(sym.loc)])
q.initProc.procSec(cpsLocals).add('\t')
q.initProc.procSec(cpsLocals).addStmt():
var registerCall: CallBuilder
q.initProc.procSec(cpsLocals).addCall(registerCall, "hcrRegisterGlobal"):
q.initProc.procSec(cpsLocals).addArgument(registerCall):
q.initProc.procSec(cpsLocals).add(getModuleDllPath(q, sym))
q.initProc.procSec(cpsLocals).addArgument(registerCall):
q.initProc.procSec(cpsLocals).add('"' & sym.loc.snippet & '"')
q.initProc.procSec(cpsLocals).addArgument(registerCall):
q.initProc.procSec(cpsLocals).addSizeof(rdLoc(sym.loc))
q.initProc.procSec(cpsLocals).addArgument(registerCall):
q.initProc.procSec(cpsLocals).add("NULL")
q.initProc.procSec(cpsLocals).addArgument(registerCall):
q.initProc.procSec(cpsLocals).addCast("void**"):
q.initProc.procSec(cpsLocals).add(cAddr(sym.loc.snippet))
# always copy over the contents of the actual constant with the _const
# suffix ==> this means that the constant is reloadable & updatable!
q.initProc.procSec(cpsLocals).add(ropecg(q,
"\t#nimCopyMem((void*)$1, (NIM_CONST void*)&$2, sizeof($3));$n",
[sym.loc.snippet, actualConstName, rdLoc(sym.loc)]))
q.initProc.procSec(cpsLocals).add('\t')
q.initProc.procSec(cpsLocals).addStmt():
var copyCall: CallBuilder
q.initProc.procSec(cpsLocals).addCall(copyCall, cgsymValue(q, "nimCopyMem")):
q.initProc.procSec(cpsLocals).addArgument(copyCall):
q.initProc.procSec(cpsLocals).add(cCast("void*", sym.loc.snippet))
q.initProc.procSec(cpsLocals).addArgument(copyCall):
q.initProc.procSec(cpsLocals).add(cCast(constType("void*"), cAddr(actualConstName)))
q.initProc.procSec(cpsLocals).addArgument(copyCall):
q.initProc.procSec(cpsLocals).addSizeof(rdLoc(sym.loc))
proc genConstStmt(p: BProc, n: PNode) =
# This code is only used in the new DCE implementation.

View File

@@ -1335,7 +1335,8 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
m.hcrCreateTypeInfosProc.addCast(typ = "void**"):
m.hcrCreateTypeInfosProc.add(cAddr(name))
else:
m.s[cfsStrData].addf("N_LIB_PRIVATE TNimType $1;$n", [name])
m.s[cfsStrData].addDeclWithVisibility(Private):
m.s[cfsStrData].addVar(kind = Local, name = name, typ = "TNimType")
proc genTypeInfoAux(m: BModule; typ, origType: PType, name: Rope;
info: TLineInfo) =
@@ -1764,7 +1765,8 @@ proc genVTable(seqs: seq[PSym]): string =
proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLineInfo) =
cgsym(m, "TNimTypeV2")
m.s[cfsStrData].addf("N_LIB_PRIVATE TNimTypeV2 $1;$n", [name])
m.s[cfsStrData].addDeclWithVisibility(Private):
m.s[cfsStrData].addVar(kind = Local, name = name, typ = "TNimTypeV2")
var flags = 0
if not canFormAcycle(m.g.graph, t): flags = flags or 1
@@ -1833,54 +1835,72 @@ proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLin
proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineInfo) =
cgsym(m, "TNimTypeV2")
m.s[cfsStrData].addf("N_LIB_PRIVATE TNimTypeV2 $1;$n", [name])
m.s[cfsStrData].addDeclWithVisibility(Private):
m.s[cfsStrData].addVar(kind = Local, name = name, typ = "TNimTypeV2")
var flags = 0
if not canFormAcycle(m.g.graph, t): flags = flags or 1
var typeEntry = newRopeAppender()
addf(typeEntry, "N_LIB_PRIVATE TNimTypeV2 $1 = {", [name])
add(typeEntry, ".destructor = (void*)")
genHook(m, t, info, attachedDestructor, typeEntry)
typeEntry.addDeclWithVisibility(Private):
typeEntry.addVarWithTypeAndInitializer(kind = Local, name = name):
typeEntry.add("TNimTypeV2")
do:
var typeInit: StructInitializer
typeEntry.addStructInitializer(typeInit, kind = siNamedStruct):
typeEntry.addField(typeInit, name = "destructor"):
typeEntry.addCast("void*"):
genHook(m, t, info, attachedDestructor, typeEntry)
let objDepth = if t.kind == tyObject: getObjDepth(t) else: -1
let objDepth = if t.kind == tyObject: getObjDepth(t) else: -1
if t.kind in {tyObject, tyDistinct} and incompleteType(t):
localError(m.config, info, "request for RTTI generation for incomplete object: " &
typeToString(t))
if t.kind in {tyObject, tyDistinct} and incompleteType(t):
localError(m.config, info, "request for RTTI generation for incomplete object: " &
typeToString(t))
addf(typeEntry, ", .size = sizeof($1), .align = (NI16) NIM_ALIGNOF($1), .depth = $2",
[getTypeDesc(m, t), rope(objDepth)])
let sizeType = getTypeDesc(m, t)
typeEntry.addField(typeInit, name = "size"):
typeEntry.addSizeof(sizeType)
typeEntry.addField(typeInit, name = "align"):
typeEntry.addCast("NI16"):
typeEntry.addAlignof(sizeType)
typeEntry.addField(typeInit, name = "depth"):
typeEntry.addIntValue(objDepth)
if objDepth >= 0:
let objDisplay = genDisplay(m, t, objDepth)
let objDisplayStore = getTempName(m)
m.s[cfsVars].addArrayVar(kind = Const,
name = objDisplayStore,
elementType = getTypeDesc(m, getSysType(m.g.graph, unknownLineInfo, tyUInt32), dkVar),
len = objDepth + 1,
initializer = objDisplay)
addf(typeEntry, ", .display = $1", [rope(objDisplayStore)])
if isDefined(m.config, "nimTypeNames"):
var typeName: Rope
if t.kind in {tyObject, tyDistinct}:
typeName = genTypeInfo2Name(m, t)
else:
typeName = rope("NIM_NIL")
addf(typeEntry, ", .name = $1", [typeName])
add(typeEntry, ", .traceImpl = (void*)")
genHook(m, t, info, attachedTrace, typeEntry)
if objDepth >= 0:
let objDisplay = genDisplay(m, t, objDepth)
let objDisplayStore = getTempName(m)
m.s[cfsVars].addArrayVar(kind = Const,
name = objDisplayStore,
elementType = getTypeDesc(m, getSysType(m.g.graph, unknownLineInfo, tyUInt32), dkVar),
len = objDepth + 1,
initializer = objDisplay)
typeEntry.addField(typeInit, name = "display"):
typeEntry.add(objDisplayStore)
if isDefined(m.config, "nimTypeNames"):
var typeName: Rope
if t.kind in {tyObject, tyDistinct}:
typeName = genTypeInfo2Name(m, t)
else:
typeName = rope("NIM_NIL")
typeEntry.addField(typeInit, name = "name"):
typeEntry.add(typeName)
typeEntry.addField(typeInit, name = "traceImpl"):
typeEntry.addCast("void*"):
genHook(m, t, info, attachedTrace, typeEntry)
let dispatchMethods = toSeq(getMethodsPerType(m.g.graph, t))
if dispatchMethods.len > 0:
addf(typeEntry, ", .flags = $1", [rope(flags)])
for i in dispatchMethods:
genProcPrototype(m, i)
addf(typeEntry, ", .vTable = $1};$n", [genVTable(dispatchMethods)])
m.s[cfsVars].add typeEntry
else:
addf(typeEntry, ", .flags = $1};$n", [rope(flags)])
m.s[cfsVars].add typeEntry
let dispatchMethods = toSeq(getMethodsPerType(m.g.graph, t))
if dispatchMethods.len > 0:
typeEntry.addField(typeInit, name = "flags"):
typeEntry.addIntValue(flags)
for i in dispatchMethods:
genProcPrototype(m, i)
typeEntry.addField(typeInit, name = "vTable"):
typeEntry.add(genVTable(dispatchMethods))
else:
typeEntry.addField(typeInit, name = "flags"):
typeEntry.addIntValue(flags)
m.s[cfsVars].add typeEntry
if t.kind == tyObject and t.baseClass != nil and optEnableDeepCopy in m.config.globalOptions:
discard genTypeInfoV1(m, t, info)