From 2e9422df570e4be88c88dfb4263864cd438603fe Mon Sep 17 00:00:00 2001 From: metagn Date: Mon, 28 Oct 2024 07:27:11 +0300 Subject: [PATCH] cbuilder: add decl visibilities, use it for HCR & typeinfo (#24368) follows up #24362 --- compiler/cbuilderdecls.nim | 22 ++++++++ compiler/cbuilderexprs.nim | 3 ++ compiler/ccgexprs.nim | 64 +++++++++++++++++------- compiler/ccgtypes.nim | 100 ++++++++++++++++++++++--------------- 4 files changed, 132 insertions(+), 57 deletions(-) diff --git a/compiler/cbuilderdecls.nim b/compiler/cbuilderdecls.nim index 959beae51d..54f23f74af 100644 --- a/compiler/cbuilderdecls.nim +++ b/compiler/cbuilderdecls.nim @@ -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 diff --git a/compiler/cbuilderexprs.nim b/compiler/cbuilderexprs.nim index 4f2426965e..9250f79a3a 100644 --- a/compiler/cbuilderexprs.nim +++ b/compiler/cbuilderexprs.nim @@ -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 & "*" diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 7ffb799a61..4cae6748a1 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -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. diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 5aea0d0f1e..f1b03f00e3 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -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)