Skip to content

Commit

Permalink
cbuilder: add calls, sizeof/alignof/offsetof, use in ccgtypes (#24362)
Browse files Browse the repository at this point in the history
follows #24360, #24351
  • Loading branch information
metagn authored Oct 26, 2024
1 parent 031ad95 commit 24aa92c
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 42 deletions.
50 changes: 50 additions & 0 deletions compiler/cbuilderexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,53 @@ proc derefField(a, b: Snippet): Snippet =

proc bitOr(a, b: Snippet): Snippet =
"(" & a & " | " & b & ")"

type CallBuilder = object
needsComma: bool

proc initCallBuilder(builder: var Builder, callee: Snippet): CallBuilder =
result = CallBuilder(needsComma: false)
builder.add(callee)
builder.add("(")

template addArgument(builder: var Builder, call: var CallBuilder, valueBody: typed) =
if call.needsComma:
builder.add(", ")
else:
call.needsComma = true
valueBody

proc finishCallBuilder(builder: var Builder, call: CallBuilder) =
builder.add(")")

template addCall(builder: var Builder, call: out CallBuilder, callee: Snippet, body: typed) =
call = initCallBuilder(builder, callee)
body
finishCallBuilder(builder, call)

proc addNullaryCall(builder: var Builder, callee: Snippet) =
builder.add(callee)
builder.add("()")

proc addUnaryCall(builder: var Builder, callee: Snippet, arg: Snippet) =
builder.add(callee)
builder.add("(")
builder.add(arg)
builder.add(")")

proc addSizeof(builder: var Builder, val: Snippet) =
builder.add("sizeof(")
builder.add(val)
builder.add(")")

proc addAlignof(builder: var Builder, val: Snippet) =
builder.add("NIM_ALIGNOF(")
builder.add(val)
builder.add(")")

proc addOffsetof(builder: var Builder, val, member: Snippet) =
builder.add("offsetof(")
builder.add(val)
builder.add(", ")
builder.add(member)
builder.add(")")
5 changes: 5 additions & 0 deletions compiler/cbuilderstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ template addSubscriptAssignment(builder: var Builder, lhs: Snippet, index: Snipp
builder.add("[" & index & "] = ")
valueBody
builder.add(";\n")

template addStmt(builder: var Builder, stmtBody: typed) =
## makes an expression built by `stmtBody` into a statement
stmtBody
builder.add(";\n")
149 changes: 107 additions & 42 deletions compiler/ccgtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1287,33 +1287,53 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
size = rope"void*"
else:
size = getTypeDesc(m, origType, dkVar)
m.s[cfsTypeInit3].addf(
"$1.size = sizeof($2);$n$1.align = NIM_ALIGNOF($2);$n$1.kind = $3;$n$1.base = $4;$n",
[nameHcr, size, rope(nimtypeKind), base]
)
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "size"):
m.s[cfsTypeInit3].addSizeof(size)
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "align"):
m.s[cfsTypeInit3].addAlignof(size)
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "kind"):
m.s[cfsTypeInit3].addIntValue(nimtypeKind)
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "base"):
m.s[cfsTypeInit3].add(base)
# compute type flags for GC optimization
var flags = 0
if not containsGarbageCollectedRef(typ): flags = flags or 1
if not canFormAcycle(m.g.graph, typ): flags = flags or 2
#else echo("can contain a cycle: " & typeToString(typ))
if flags != 0:
m.s[cfsTypeInit3].addf("$1.flags = $2;$n", [nameHcr, rope(flags)])
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "flags"):
m.s[cfsTypeInit3].addIntValue(flags)
cgsym(m, "TNimType")
if isDefined(m.config, "nimTypeNames"):
var typename = typeToString(if origType.typeInst != nil: origType.typeInst
else: origType, preferName)
if typename == "ref object" and origType.skipTypes(skipPtrs).sym != nil:
typename = "anon ref object from " & m.config$origType.skipTypes(skipPtrs).sym.info
m.s[cfsTypeInit3].addf("$1.name = $2;$n",
[nameHcr, makeCString typename])
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "name"):
m.s[cfsTypeInit3].add(makeCString typename)
cgsym(m, "nimTypeRoot")
m.s[cfsTypeInit3].addf("$1.nextType = nimTypeRoot; nimTypeRoot=&$1;$n",
[nameHcr])
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "nextType"):
m.s[cfsTypeInit3].add("nimTypeRoot")
m.s[cfsTypeInit3].addAssignment("nimTypeRoot"):
m.s[cfsTypeInit3].add(cAddr(nameHcr))

if m.hcrOn:
m.s[cfsStrData].addf("static TNimType* $1;$n", [name])
m.hcrCreateTypeInfosProc.addf("\thcrRegisterGlobal($2, \"$1\", sizeof(TNimType), NULL, (void**)&$1);$n",
[name, getModuleDllPath(m, m.module)])
m.s[cfsStrData].addVar(kind = Global, name = name, typ = ptrType("TNimType"))
m.hcrCreateTypeInfosProc.add('\t')
var registerHcr: CallBuilder
m.hcrCreateTypeInfosProc.addStmt():
m.hcrCreateTypeInfosProc.addCall(registerHcr, callee = "hcrRegisterGlobal"):
m.hcrCreateTypeInfosProc.addArgument(registerHcr):
m.hcrCreateTypeInfosProc.add(getModuleDllPath(m, m.module))
m.hcrCreateTypeInfosProc.addArgument(registerHcr):
m.hcrCreateTypeInfosProc.add(makeCString(name))
m.hcrCreateTypeInfosProc.addArgument(registerHcr):
m.hcrCreateTypeInfosProc.addSizeof("TNimType")
m.hcrCreateTypeInfosProc.addArgument(registerHcr):
m.hcrCreateTypeInfosProc.add("NULL")
m.hcrCreateTypeInfosProc.addArgument(registerHcr):
m.hcrCreateTypeInfosProc.addCast(typ = "void**"):
m.hcrCreateTypeInfosProc.add(cAddr(name))
else:
m.s[cfsStrData].addf("N_LIB_PRIVATE TNimType $1;$n", [name])

Expand Down Expand Up @@ -1347,13 +1367,27 @@ proc discriminatorTableDecl(m: BModule; objtype: PType, d: PSym): Rope =
var tmp = discriminatorTableName(m, objtype, d)
result = "TNimNode* $1[$2];$n" % [tmp, rope(lengthOrd(m.config, d.typ)+1)]

proc genTNimNodeArray(m: BModule; name: Rope, size: Rope) =
proc genTNimNodeArray(m: BModule; name: Rope, size: int) =
if m.hcrOn:
m.s[cfsData].addf("static TNimNode** $1;$n", [name])
m.hcrCreateTypeInfosProc.addf("\thcrRegisterGlobal($3, \"$1\", sizeof(TNimNode*) * $2, NULL, (void**)&$1);$n",
[name, size, getModuleDllPath(m, m.module)])
m.s[cfsData].addVar(kind = Global, name = name, typ = ptrType(ptrType("TNimNode")))
var registerHcr: CallBuilder
m.hcrCreateTypeInfosProc.addStmt():
m.hcrCreateTypeInfosProc.addCall(registerHcr, callee = "hcrRegisterGlobal"):
m.hcrCreateTypeInfosProc.addArgument(registerHcr):
m.hcrCreateTypeInfosProc.add(getModuleDllPath(m, m.module))
m.hcrCreateTypeInfosProc.addArgument(registerHcr):
m.hcrCreateTypeInfosProc.add(makeCString(name))
m.hcrCreateTypeInfosProc.addArgument(registerHcr):
# XXX use cbuilder here
m.hcrCreateTypeInfosProc.add("sizeof(TNimNode*) * " & $size)
m.hcrCreateTypeInfosProc.addArgument(registerHcr):
m.hcrCreateTypeInfosProc.add("NULL")
m.hcrCreateTypeInfosProc.addArgument(registerHcr):
m.hcrCreateTypeInfosProc.addCast(typ = "void**"):
m.hcrCreateTypeInfosProc.add(cAddr(name))
else:
m.s[cfsTypeInit1].addf("static TNimNode* $1[$2];$n", [name, size])
m.s[cfsTypeInit1].addArrayVar(kind = Global, name = name,
elementType = ptrType("TNimNode"), len = size)

proc genObjectFields(m: BModule; typ, origType: PType, n: PNode, expr: Rope;
info: TLineInfo) =
Expand All @@ -1363,7 +1397,7 @@ proc genObjectFields(m: BModule; typ, origType: PType, n: PNode, expr: Rope;
genObjectFields(m, typ, origType, n[0], expr, info)
elif n.len > 0:
var tmp = getTempName(m) & "_" & $n.len
genTNimNodeArray(m, tmp, rope(n.len))
genTNimNodeArray(m, tmp, n.len)
for i in 0..<n.len:
var tmp2 = getNimNode(m)
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, cIntValue(i)):
Expand All @@ -1389,14 +1423,21 @@ proc genObjectFields(m: BModule; typ, origType: PType, n: PNode, expr: Rope;
if field.loc.snippet == "": fillObjectFields(m, typ)
if field.loc.t == nil:
internalError(m.config, n.info, "genObjectFields")
m.s[cfsTypeInit3].addf("$1.kind = 3;$n" &
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
"$1.name = $5;$n" & "$1.sons = &$6[0];$n" &
"$1.len = $7;$n", [expr, getTypeDesc(m, origType, dkVar), field.loc.snippet,
genTypeInfoV1(m, field.typ, info),
makeCString(field.name.s),
tmp, rope(L)])
m.s[cfsData].addf("TNimNode* $1[$2];$n", [tmp, rope(L+1)])
let fieldTypInfo = genTypeInfoV1(m, field.typ, info)
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind"):
m.s[cfsTypeInit3].addIntValue(3)
m.s[cfsTypeInit3].addFieldAssignment(expr, "offset"):
m.s[cfsTypeInit3].addOffsetof(getTypeDesc(m, origType, dkVar), field.loc.snippet)
m.s[cfsTypeInit3].addFieldAssignment(expr, "typ"):
m.s[cfsTypeInit3].add(fieldTypInfo)
m.s[cfsTypeInit3].addFieldAssignment(expr, "name"):
m.s[cfsTypeInit3].add(makeCString(field.name.s))
m.s[cfsTypeInit3].addFieldAssignment(expr, "sons"):
m.s[cfsTypeInit3].add(cAddr(subscript(tmp, "0")))
m.s[cfsTypeInit3].addFieldAssignment(expr, "len"):
m.s[cfsTypeInit3].addIntValue(L)
m.s[cfsData].addArrayVar(kind = Local, name = tmp,
elementType = ptrType("TNimNode"), len = toInt(L)+1)
for i in 1..<n.len:
var b = n[i] # branch
var tmp2 = getNimNode(m)
Expand Down Expand Up @@ -1428,10 +1469,15 @@ proc genObjectFields(m: BModule; typ, origType: PType, n: PNode, expr: Rope;
if field.loc.snippet == "": fillObjectFields(m, typ)
if field.loc.t == nil:
internalError(m.config, n.info, "genObjectFields")
m.s[cfsTypeInit3].addf("$1.kind = 1;$n" &
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
"$1.name = $5;$n", [expr, getTypeDesc(m, origType, dkVar),
field.loc.snippet, genTypeInfoV1(m, field.typ, info), makeCString(field.name.s)])
let fieldTypInfo = genTypeInfoV1(m, field.typ, info)
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind"):
m.s[cfsTypeInit3].addIntValue(1)
m.s[cfsTypeInit3].addFieldAssignment(expr, "offset"):
m.s[cfsTypeInit3].addOffsetof(getTypeDesc(m, origType, dkVar), field.loc.snippet)
m.s[cfsTypeInit3].addFieldAssignment(expr, "typ"):
m.s[cfsTypeInit3].add(fieldTypInfo)
m.s[cfsTypeInit3].addFieldAssignment(expr, "name"):
m.s[cfsTypeInit3].add(makeCString(field.name.s))
else: internalError(m.config, n.info, "genObjectFields")

proc genObjectInfo(m: BModule; typ, origType: PType, name: Rope; info: TLineInfo) =
Expand All @@ -1456,16 +1502,20 @@ proc genTupleInfo(m: BModule; typ, origType: PType, name: Rope; info: TLineInfo)
var expr = getNimNode(m)
if not typ.isEmptyTupleType:
var tmp = getTempName(m) & "_" & $typ.kidsLen
genTNimNodeArray(m, tmp, rope(typ.kidsLen))
genTNimNodeArray(m, tmp, typ.kidsLen)
for i, a in typ.ikids:
var tmp2 = getNimNode(m)
let fieldTypInfo = genTypeInfoV1(m, a, info)
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, cIntValue(i)):
m.s[cfsTypeInit3].add(cAddr(tmp2))
m.s[cfsTypeInit3].addf("$1.kind = 1;$n" &
"$1.offset = offsetof($2, Field$3);$n" &
"$1.typ = $4;$n" &
"$1.name = \"Field$3\";$n",
[tmp2, getTypeDesc(m, origType, dkVar), rope(i), genTypeInfoV1(m, a, info)])
m.s[cfsTypeInit3].addFieldAssignment(tmp2, "kind"):
m.s[cfsTypeInit3].addIntValue(1)
m.s[cfsTypeInit3].addFieldAssignment(tmp2, "offset"):
m.s[cfsTypeInit3].addOffsetof(getTypeDesc(m, origType, dkVar), "Field" & $i)
m.s[cfsTypeInit3].addFieldAssignment(tmp2, "typ"):
m.s[cfsTypeInit3].add(fieldTypInfo)
m.s[cfsTypeInit3].addFieldAssignment(tmp2, "name"):
m.s[cfsTypeInit3].add("\"Field" & $i & "\"")
m.s[cfsTypeInit3].addFieldAssignment(expr, "len"):
m.s[cfsTypeInit3].addIntValue(typ.kidsLen)
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind"):
Expand All @@ -1487,7 +1537,7 @@ proc genEnumInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) =
# positions will be reset after the loop.
genTypeInfoAux(m, typ, typ, name, info)
var nodePtrs = getTempName(m) & "_" & $typ.n.len
genTNimNodeArray(m, nodePtrs, rope(typ.n.len))
genTNimNodeArray(m, nodePtrs, typ.n.len)
var enumNames = newBuilder("")
var enumNamesInit: StructInitializer
var specialCases = newBuilder("")
Expand Down Expand Up @@ -1568,9 +1618,16 @@ proc genDeepCopyProc(m: BModule; s: PSym; result: Rope) =
proc declareNimType(m: BModule; name: string; str: Rope, module: int) =
let nr = rope(name)
if m.hcrOn:
m.s[cfsStrData].addf("static $2* $1;$n", [str, nr])
m.s[cfsTypeInit1].addf("\t$1 = ($3*)hcrGetGlobal($2, \"$1\");$n",
[str, getModuleDllPath(m, module), nr])
m.s[cfsStrData].addVar(kind = Global, name = str, typ = ptrType(nr))
m.s[cfsTypeInit1].add('\t')
m.s[cfsTypeInit1].addAssignment(str):
m.s[cfsTypeInit1].addCast(typ = ptrType(nr)):
var hcrGlobal: CallBuilder
m.s[cfsTypeInit1].addCall(hcrGlobal, "hcrGetGlobal"):
m.s[cfsTypeInit1].addArgument(hcrGlobal):
m.s[cfsTypeInit1].add(getModuleDllPath(m, module))
m.s[cfsTypeInit1].addArgument(hcrGlobal):
m.s[cfsTypeInit1].add("\"" & str & "\"")
else:
m.s[cfsStrData].addf("extern $2 $1;$n", [str, nr])

Expand Down Expand Up @@ -1734,8 +1791,16 @@ proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLin
typeName = rope("NIM_NIL")
typeEntry.addFieldAssignment(name, "name"):
typeEntry.add(typeName)
addf(typeEntry, "$1.size = sizeof($2); $1.align = (NI16) NIM_ALIGNOF($2); $1.depth = $3; $1.flags = $4;",
[name, getTypeDesc(m, t), rope(objDepth), rope(flags)])
let sizeTyp = getTypeDesc(m, t)
typeEntry.addFieldAssignment(name, "size"):
typeEntry.addSizeof(sizeTyp)
typeEntry.addFieldAssignment(name, "align"):
typeEntry.addCast(typ = "NI16"):
typeEntry.addAlignof(sizeTyp)
typeEntry.addFieldAssignment(name, "depth"):
typeEntry.addIntValue(objDepth)
typeEntry.addFieldAssignment(name, "flags"):
typeEntry.addIntValue(flags)

if objDepth >= 0:
let objDisplay = genDisplay(m, t, objDepth)
Expand Down

0 comments on commit 24aa92c

Please sign in to comment.