mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-03 18:34:43 +00:00
cbuilder: add decl visibilities, use it for HCR & typeinfo (#24368)
follows up #24362
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 & "*"
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user