cbuilder: add assignments, fields, subscripts, deref (#24351)

This PR is somewhat large, worst case it can be split into one with just
assignments and one with just fields/derefs etc.

Assignments with calls as values have not been touched so they can be
done when calls are implemented. Similarly codegen with complex logic
i.e. `genEnumInfo`, `genTypeInfoV2`, `unaryExpr` is not completely
ported yet so they can be done in standalone PRs.
This commit is contained in:
metagn
2024-10-25 15:16:39 +03:00
committed by GitHub
parent 2864830941
commit 820e2bee9c
5 changed files with 243 additions and 90 deletions

View File

@@ -19,6 +19,10 @@ proc procPtrType(conv: TCallingConvention, rettype: Snippet, name: string): Snip
proc cCast(typ, value: Snippet): Snippet =
"((" & typ & ") " & value & ")"
proc wrapPar(value: Snippet): Snippet =
# used for expression group, no-op on sexp
"(" & value & ")"
template addCast(builder: var Builder, typ: Snippet, valueBody: typed) =
## adds a cast to `typ` with value built by `valueBody`
builder.add "(("
@@ -30,5 +34,17 @@ template addCast(builder: var Builder, typ: Snippet, valueBody: typed) =
proc cAddr(value: Snippet): Snippet =
"&" & value
proc cDeref(value: Snippet): Snippet =
"(*" & value & ")"
proc subscript(a, b: Snippet): Snippet =
a & "[" & b & "]"
proc dotField(a, b: Snippet): Snippet =
a & "." & b
proc derefField(a, b: Snippet): Snippet =
a & "->" & b
proc bitOr(a, b: Snippet): Snippet =
"(" & a & " | " & b & ")"

View File

@@ -0,0 +1,23 @@
template addAssignment(builder: var Builder, lhs: Snippet, valueBody: typed) =
builder.add(lhs)
builder.add(" = ")
valueBody
builder.add(";\n")
template addFieldAssignment(builder: var Builder, lhs: Snippet, name: string, valueBody: typed) =
builder.add(lhs)
builder.add("." & name & " = ")
valueBody
builder.add(";\n")
template addDerefFieldAssignment(builder: var Builder, lhs: Snippet, name: string, valueBody: typed) =
builder.add(lhs)
builder.add("->" & name & " = ")
valueBody
builder.add(";\n")
template addSubscriptAssignment(builder: var Builder, lhs: Snippet, index: Snippet, valueBody: typed) =
builder.add(lhs)
builder.add("[" & index & "] = ")
valueBody
builder.add(";\n")

View File

@@ -814,7 +814,7 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) =
# careful 'addr(myptrToArray)' needs to get the ampersand:
if e[0].typ.skipTypes(abstractInstOwned).kind in {tyRef, tyPtr}:
var a: TLoc = initLocExpr(p, e[0])
putIntoDest(p, d, e, "&" & a.snippet, a.storage)
putIntoDest(p, d, e, cAddr(a.snippet), a.storage)
#Message(e.info, warnUser, "HERE NEW &")
elif mapType(p.config, e[0].typ, mapTypeChooser(e[0]) == skParam) == ctArray or isCppRef(p, e.typ):
expr(p, e[0], d)
@@ -1680,7 +1680,8 @@ proc genNewFinalize(p: BProc, e: PNode) =
var f = initLocExpr(p, e[2])
b = initLoc(locExpr, a.lode, OnHeap)
ti = genTypeInfo(p.config, p.module, refType, e.info)
p.module.s[cfsTypeInit3].addf("$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
p.module.s[cfsTypeInit3].addDerefFieldAssignment(ti, "finalizer"):
p.module.s[cfsTypeInit3].add(cCast("void*", rdLoc(f)))
b.snippet = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [
getTypeDesc(p.module, refType),
ti, getTypeDesc(p.module, skipTypes(refType.elementType, abstractRange))])
@@ -1704,7 +1705,10 @@ proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo; result: var Ro
cgsym(p.module, "TNimType")
inc p.module.labels
let cache = "Nim_OfCheck_CACHE" & p.module.labels.rope
p.module.s[cfsVars].addf("static TNimType* $#[2];$n", [cache])
p.module.s[cfsVars].addArrayVar(kind = Global,
name = cache,
elementType = ptrType("TNimType"),
len = 2)
appcg(p.module, result, "#isObjWithCache($#.m_type, $#, $#)", [a, ti, cache])
proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
@@ -1716,12 +1720,12 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
while t.kind in {tyVar, tyLent, tyPtr, tyRef}:
if t.kind notin {tyVar, tyLent}: nilCheck = r
if t.kind notin {tyVar, tyLent} or not p.module.compileToCpp:
r = ropecg(p.module, "(*$1)", [r])
r = cDeref(r)
t = skipTypes(t.elementType, typedescInst+{tyOwned})
discard getTypeDesc(p.module, t)
if not p.module.compileToCpp:
while t.kind == tyObject and t.baseClass != nil:
r.add(".Sup")
r = dotField(r, "Sup")
t = skipTypes(t.baseClass, skipPtrs)
if isObjLackingTypeField(t):
globalError(p.config, x.info,
@@ -1805,17 +1809,17 @@ proc rdMType(p: BProc; a: TLoc; nilCheck: var Rope; result: var Rope; enforceV1
while t.kind in {tyVar, tyLent, tyPtr, tyRef}:
if t.kind notin {tyVar, tyLent}: nilCheck = derefs
if t.kind notin {tyVar, tyLent} or not p.module.compileToCpp:
derefs = "(*$1)" % [derefs]
derefs = cDeref(derefs)
t = skipTypes(t.elementType, abstractInst)
result.add derefs
discard getTypeDesc(p.module, t)
if not p.module.compileToCpp:
while t.kind == tyObject and t.baseClass != nil:
result.add(".Sup")
result = dotField(result, "Sup")
t = skipTypes(t.baseClass, skipPtrs)
result.add ".m_type"
result = dotField(result, "m_type")
if optTinyRtti in p.config.globalOptions and enforceV1:
result.add "->typeInfoV1"
result = derefField(result, "typeInfoV1")
proc genGetTypeInfo(p: BProc, e: PNode, d: var TLoc) =
cgsym(p.module, "TNimType")
@@ -1900,7 +1904,8 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
var a = initLocExpr(p, e[1])
var x = lenExpr(p, a)
if op == mHigh: x = "($1-1)" % [x]
lineCg(p, cpsStmts, "$1 = $2;$n", [tmp.snippet, x])
p.s(cpsStmts).addAssignment(tmp.snippet):
p.s(cpsStmts).add(x)
putIntoDest(p, d, e, tmp.snippet)
of tyArray:
# YYY: length(sideeffect) is optimized away incorrectly?
@@ -2144,19 +2149,32 @@ proc genSomeCast(p: BProc, e: PNode, d: var TLoc) =
let etyp = skipTypes(e.typ, abstractRange+{tyOwned})
let srcTyp = skipTypes(e[1].typ, abstractRange)
if etyp.kind in ValueTypes and lfIndirect notin a.flags:
putIntoDest(p, d, e, "(*($1*) ($2))" %
[getTypeDesc(p.module, e.typ), addrLoc(p.config, a)], a.storage)
let destTyp = getTypeDesc(p.module, e.typ)
let val = addrLoc(p.config, a)
# (* (destType*) val)
putIntoDest(p, d, e,
cDeref(
cCast(
ptrType(destTyp),
wrapPar(val))),
a.storage)
elif etyp.kind == tyProc and etyp.callConv == ccClosure and srcTyp.callConv != ccClosure:
putIntoDest(p, d, e, "(($1) ($2))" %
[getClosureType(p.module, etyp, clHalfWithEnv), rdCharLoc(a)], a.storage)
let destTyp = getClosureType(p.module, etyp, clHalfWithEnv)
let val = rdCharLoc(a)
# (destTyp) val
putIntoDest(p, d, e, cCast(destTyp, wrapPar(val)), a.storage)
else:
# C++ does not like direct casts from pointer to shorter integral types
if srcTyp.kind in {tyPtr, tyPointer} and etyp.kind in IntegralTypes:
putIntoDest(p, d, e, "(($1) (ptrdiff_t) ($2))" %
[getTypeDesc(p.module, e.typ), rdCharLoc(a)], a.storage)
let destTyp = getTypeDesc(p.module, e.typ)
let val = rdCharLoc(a)
# (destTyp) (ptrdiff_t) val
putIntoDest(p, d, e, cCast(destTyp, cCast("ptrdiff_t", wrapPar(val))), a.storage)
elif optSeqDestructors in p.config.globalOptions and etyp.kind in {tySequence, tyString}:
putIntoDest(p, d, e, "(*($1*) (&$2))" %
[getTypeDesc(p.module, e.typ), rdCharLoc(a)], a.storage)
let destTyp = getTypeDesc(p.module, e.typ)
let val = rdCharLoc(a)
# (* (destType*) (&val))
putIntoDest(p, d, e, cDeref(cCast(ptrType(destTyp), wrapPar(cAddr(val)))), a.storage)
elif etyp.kind == tyBool and srcTyp.kind in IntegralTypes:
putIntoDest(p, d, e, "(($1) != 0)" % [rdCharLoc(a)], a.storage)
else:
@@ -2165,8 +2183,9 @@ proc genSomeCast(p: BProc, e: PNode, d: var TLoc) =
let internalType = etyp.skipTypes({tyPtr})
if internalType.kind == tyObject:
discard getTypeDesc(p.module, internalType)
putIntoDest(p, d, e, "(($1) ($2))" %
[getTypeDesc(p.module, e.typ), rdCharLoc(a)], a.storage)
let destTyp = getTypeDesc(p.module, e.typ)
let val = rdCharLoc(a)
putIntoDest(p, d, e, cCast(destTyp, wrapPar(val)), a.storage)
proc genCast(p: BProc, e: PNode, d: var TLoc) =
const ValueTypes = {tyFloat..tyFloat128, tyTuple, tyObject, tyArray}
@@ -2178,7 +2197,7 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
inc(p.labels)
var lbl = p.labels.rope
var tmp: TLoc = default(TLoc)
tmp.snippet = "LOC$1.source" % [lbl]
tmp.snippet = dotField("LOC" & lbl, "source")
let destsize = getSize(p.config, destt)
let srcsize = getSize(p.config, srct)
@@ -2193,7 +2212,7 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
tmp.storage = OnStack
tmp.flags = {}
expr(p, e[1], tmp)
putIntoDest(p, d, e, "LOC$#.dest" % [lbl], tmp.storage)
putIntoDest(p, d, e, dotField("LOC" & lbl, "dest"), tmp.storage)
else:
# I prefer the shorter cast version for pointer types -> generate less
# C code; plus it's the right thing to do for closures:
@@ -2245,10 +2264,12 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc) =
if sameBackendTypeIgnoreRange(dest, n[0].typ):
# don't cast so an address can be taken for `var` conversions
putIntoDest(p, d, n, "($1)" % [rdCharLoc(a)], a.storage)
let val = rdCharLoc(a)
putIntoDest(p, d, n, wrapPar(val), a.storage)
else:
putIntoDest(p, d, n, "(($1) ($2))" %
[getTypeDesc(p.module, dest), rdCharLoc(a)], a.storage)
let destType = getTypeDesc(p.module, dest)
let val = rdCharLoc(a)
putIntoDest(p, d, n, cCast(destType, wrapPar(val)), a.storage)
proc genConv(p: BProc, e: PNode, d: var TLoc) =
let destType = e.typ.skipTypes({tyVar, tyLent, tyGenericInst, tyAlias, tySink})
@@ -2333,7 +2354,13 @@ proc genMove(p: BProc; n: PNode; d: var TLoc) =
var src: TLoc = initLocExpr(p, n[2])
linefmt(p, cpsStmts, "if ($1.p != $2.p) {", [rdLoc(a), rdLoc(src)])
genStmts(p, n[3])
linefmt(p, cpsStmts, "}$n$1.len = $2.len; $1.p = $2.p;$n", [rdLoc(a), rdLoc(src)])
linefmt(p, cpsStmts, "}$n", [])
let destVal = rdLoc(a)
let srcVal = rdLoc(src)
p.s(cpsStmts).addFieldAssignment(destVal, "len"):
p.s(cpsStmts).add(dotField(srcVal, "len"))
p.s(cpsStmts).addFieldAssignment(destVal, "p"):
p.s(cpsStmts).add(dotField(srcVal, "p"))
else:
if d.k == locNone: d = getTemp(p, n.typ)
if p.config.selectedGC in {gcArc, gcAtomicArc, gcOrc}:
@@ -2421,7 +2448,11 @@ proc genSlice(p: BProc; e: PNode; d: var TLoc) =
e[1].typ.skipTypes(abstractInst).kind == tyString and
p.config.selectedGC in {gcArc, gcAtomicArc, gcOrc})
if d.k == locNone: d = getTemp(p, e.typ)
linefmt(p, cpsStmts, "$1.Field0 = $2; $1.Field1 = $3;$n", [rdLoc(d), x, y])
let dest = rdLoc(d)
p.s(cpsStmts).addFieldAssignment(dest, "Field0"):
p.s(cpsStmts).add(x)
p.s(cpsStmts).addFieldAssignment(dest, "Field1"):
p.s(cpsStmts).add(y)
when false:
localError(p.config, e.info, "invalid context for 'toOpenArray'; " &
"'toOpenArray' is only valid within a call expression")
@@ -2464,8 +2495,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
let res = binaryArithOverflowRaw(p, ranged, a, b,
if underlying.kind == tyInt64: fun64[op] else: fun[op])
putIntoDest(p, a, e[1], "($#)($#)" % [
getTypeDesc(p.module, ranged), res])
let destTyp = getTypeDesc(p.module, ranged)
putIntoDest(p, a, e[1], cCast(destTyp, wrapPar(res)))
of mConStrStr: genStrConcat(p, e, d)
of mAppendStrCh:
@@ -2664,7 +2695,8 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
else:
# small set
var ts = "NU" & $(getSize(p.config, e.typ) * 8)
lineF(p, cpsStmts, "$1 = 0;$n", [rdLoc(d)])
p.s(cpsStmts).addAssignment(rdLoc(d)):
p.s(cpsStmts).add("0")
for it in e.sons:
if it.kind == nkRange:
idx = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt)) # our counter
@@ -2705,7 +2737,7 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
var it = n[i]
if it.kind == nkExprColonExpr: it = it[1]
rec = initLoc(locExpr, it, dest[].storage)
rec.snippet = "$1.Field$2" % [rdLoc(dest[]), rope(i)]
rec.snippet = dotField(rdLoc(dest[]), "Field" & rope(i))
rec.flags.incl(lfEnforceDeref)
expr(p, it, rec)
@@ -2741,12 +2773,18 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
# tasyncawait.nim breaks with this optimization:
when false:
if d.k != locNone:
linefmt(p, cpsStmts, "$1.ClP_0 = $2; $1.ClE_0 = $3;$n",
[d.rdLoc, a.rdLoc, b.rdLoc])
let dest = d.rdLoc
p.s(cpsStmts).addFieldAssignment(dest, "ClP_0"):
p.s(cpsStmts).add(a.rdLoc)
p.s(cpsStmts).addFieldAssignment(dest, "ClE_0"):
p.s(cpsStmts).add(b.rdLoc)
else:
tmp = getTemp(p, n.typ)
linefmt(p, cpsStmts, "$1.ClP_0 = $2; $1.ClE_0 = $3;$n",
[tmp.rdLoc, a.rdLoc, b.rdLoc])
let dest = tmp.rdLoc
p.s(cpsStmts).addFieldAssignment(dest, "ClP_0"):
p.s(cpsStmts).add(a.rdLoc)
p.s(cpsStmts).addFieldAssignment(dest, "ClE_0"):
p.s(cpsStmts).add(b.rdLoc)
putLocIntoDest(p, d, tmp)
proc genArrayConstr(p: BProc, n: PNode, d: var TLoc) =
@@ -2757,7 +2795,7 @@ proc genArrayConstr(p: BProc, n: PNode, d: var TLoc) =
arr = initLoc(locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), d.storage)
var lit = newRopeAppender()
intLiteral(i, lit)
arr.snippet = "$1[$2]" % [rdLoc(d), lit]
arr.snippet = subscript(rdLoc(d), lit)
expr(p, n[i], arr)
proc genComplexConst(p: BProc, sym: PSym, d: var TLoc) =
@@ -2825,15 +2863,27 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
linefmt p, cpsStmts, "}$n", []
if n[0].typ.kind != tyObject:
let destTyp = getTypeDesc(p.module, n.typ)
let val = rdLoc(a)
if n.isLValue:
# (*((destType) (&(val))))"
putIntoDest(p, d, n,
"(*(($1*) (&($2))))" % [getTypeDesc(p.module, n.typ), rdLoc(a)], a.storage)
cDeref(
cCast(ptrType(destTyp),
wrapPar(cAddr(wrapPar(val))))),
a.storage)
else:
putIntoDest(p, d, n,
"(($1) ($2))" % [getTypeDesc(p.module, n.typ), rdLoc(a)], a.storage)
# ((destType) (val))"
putIntoDest(p, d, n, cCast(destTyp, wrapPar(val)), a.storage)
else:
putIntoDest(p, d, n, "(*($1*) ($2))" %
[getTypeDesc(p.module, dest), addrLoc(p.config, a)], a.storage)
let destTyp = getTypeDesc(p.module, dest)
let val = addrLoc(p.config, a)
# (* (destType*) val)
putIntoDest(p, d, n,
cDeref(
cCast(ptrType(destTyp),
wrapPar(val))),
a.storage)
proc downConv(p: BProc, n: PNode, d: var TLoc) =
var arg = n[0]
@@ -2850,16 +2900,29 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) =
# init(TFigure(my)) # where it is passed to a 'var TFigure'. We test
# this by ensuring the destination is also a pointer:
var a: TLoc = initLocExpr(p, arg)
let destType = getTypeDesc(p.module, n.typ)
let val = rdLoc(a)
# (* ((destType*) (&(val))))
putIntoDest(p, d, n,
"(*(($1*) (&($2))))" % [getTypeDesc(p.module, n.typ), rdLoc(a)], a.storage)
cDeref(
cCast(ptrType(destType),
wrapPar(cAddr(wrapPar(val))))),
a.storage)
elif p.module.compileToCpp:
# C++ implicitly downcasts for us
expr(p, arg, d)
else:
var a: TLoc = initLocExpr(p, arg)
var r = rdLoc(a) & (if isRef: "->Sup" else: ".Sup")
for i in 2..abs(inheritanceDiff(dest, src)): r.add(".Sup")
putIntoDest(p, d, n, if isRef: "&" & r else: r, a.storage)
var r = rdLoc(a)
if isRef:
r = derefField(r, "Sup")
else:
r = dotField(r, "Sup")
for i in 2..abs(inheritanceDiff(dest, src)):
r = dotField(r, "Sup")
if isRef:
r = cAddr(r)
putIntoDest(p, d, n, r, a.storage)
proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
let t = n.typ
@@ -2870,10 +2933,11 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
if id == p.module.labels:
# expression not found in the cache:
inc(p.module.labels)
p.module.s[cfsData].addf("static NIM_CONST $1 $2 = ",
[getTypeDesc(p.module, t, dkConst), tmp])
genBracedInit(p, n, isConst = true, t, p.module.s[cfsData])
p.module.s[cfsData].addf(";$n", [])
p.module.s[cfsData].addVarWithTypeAndInitializer(
kind = Const, name = tmp):
p.module.s[cfsData].add(getTypeDesc(p.module, t, dkConst))
do:
genBracedInit(p, n, isConst = true, t, p.module.s[cfsData])
if d.k == locNone:
fillLoc(d, locData, n, tmp, OnStatic)
@@ -3001,7 +3065,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
if sfThread in sym.flags:
accessThreadLocalVar(p, sym)
if emulatedThreadVars(p.config):
putIntoDest(p, d, sym.loc.lode, "NimTV_->" & sym.loc.snippet)
putIntoDest(p, d, sym.loc.lode, derefField("NimTV_", sym.loc.snippet))
else:
putLocIntoDest(p, d, sym.loc)
else:

View File

@@ -1265,11 +1265,11 @@ proc genProcHeader(m: BModule; prc: PSym; result: var Rope; asPtr: bool = false)
proc genTypeInfoV1(m: BModule; t: PType; info: TLineInfo): Rope
proc getNimNode(m: BModule): Rope =
result = "$1[$2]" % [m.typeNodesName, rope(m.typeNodes)]
result = subscript(m.typeNodesName, rope(m.typeNodes))
inc(m.typeNodes)
proc tiNameForHcr(m: BModule; name: Rope): Rope =
return if m.hcrOn: "(*".rope & name & ")" else: name
return if m.hcrOn: cDeref(name) else: name
proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
name, base: Rope; info: TLineInfo) =
@@ -1366,12 +1366,20 @@ proc genObjectFields(m: BModule; typ, origType: PType, n: PNode, expr: Rope;
genTNimNodeArray(m, tmp, rope(n.len))
for i in 0..<n.len:
var tmp2 = getNimNode(m)
m.s[cfsTypeInit3].addf("$1[$2] = &$3;$n", [tmp, rope(i), tmp2])
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, rope(i)):
m.s[cfsTypeInit3].add(cAddr(tmp2))
genObjectFields(m, typ, origType, n[i], tmp2, info)
m.s[cfsTypeInit3].addf("$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
[expr, rope(n.len), tmp])
m.s[cfsTypeInit3].addFieldAssignment(expr, "len"):
m.s[cfsTypeInit3].add(rope(n.len))
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind"):
m.s[cfsTypeInit3].add("2")
m.s[cfsTypeInit3].addFieldAssignment(expr, "sons"):
m.s[cfsTypeInit3].add(cAddr(subscript(tmp, "0")))
else:
m.s[cfsTypeInit3].addf("$1.len = $2; $1.kind = 2;$n", [expr, rope(n.len)])
m.s[cfsTypeInit3].addFieldAssignment(expr, "len"):
m.s[cfsTypeInit3].add(rope(n.len))
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind"):
m.s[cfsTypeInit3].add("2")
of nkRecCase:
assert(n[0].kind == nkSym)
var field = n[0].sym
@@ -1402,14 +1410,15 @@ proc genObjectFields(m: BModule; typ, origType: PType, n: PNode, expr: Rope;
var x = toInt(getOrdValue(b[j][0]))
var y = toInt(getOrdValue(b[j][1]))
while x <= y:
m.s[cfsTypeInit3].addf("$1[$2] = &$3;$n", [tmp, rope(x), tmp2])
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, rope(x)):
m.s[cfsTypeInit3].add(cAddr(tmp2))
inc(x)
else:
m.s[cfsTypeInit3].addf("$1[$2] = &$3;$n",
[tmp, rope(getOrdValue(b[j])), tmp2])
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, rope(getOrdValue(b[j]))):
m.s[cfsTypeInit3].add(cAddr(tmp2))
of nkElse:
m.s[cfsTypeInit3].addf("$1[$2] = &$3;$n",
[tmp, rope(L), tmp2])
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, rope(L)):
m.s[cfsTypeInit3].add(cAddr(tmp2))
else: internalError(m.config, n.info, "genObjectFields(nkRecCase)")
of nkSym:
var field = n.sym
@@ -1434,7 +1443,8 @@ proc genObjectInfo(m: BModule; typ, origType: PType, name: Rope; info: TLineInfo
var tmp = getNimNode(m)
if (not isImportedType(typ)) or tfCompleteStruct in typ.flags:
genObjectFields(m, typ, origType, typ.n, tmp, info)
m.s[cfsTypeInit3].addf("$1.node = &$2;$n", [tiNameForHcr(m, name), tmp])
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "node"):
m.s[cfsTypeInit3].add(cAddr(tmp))
var t = typ.baseClass
while t != nil:
t = t.skipTypes(skipPtrs)
@@ -1449,18 +1459,26 @@ proc genTupleInfo(m: BModule; typ, origType: PType, name: Rope; info: TLineInfo)
genTNimNodeArray(m, tmp, rope(typ.kidsLen))
for i, a in typ.ikids:
var tmp2 = getNimNode(m)
m.s[cfsTypeInit3].addf("$1[$2] = &$3;$n", [tmp, rope(i), tmp2])
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, rope(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].addf("$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
[expr, rope(typ.kidsLen), tmp])
m.s[cfsTypeInit3].addFieldAssignment(expr, "len"):
m.s[cfsTypeInit3].add(rope(typ.kidsLen))
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind"):
m.s[cfsTypeInit3].add("2")
m.s[cfsTypeInit3].addFieldAssignment(expr, "sons"):
m.s[cfsTypeInit3].add(cAddr(subscript(tmp, "0")))
else:
m.s[cfsTypeInit3].addf("$1.len = $2; $1.kind = 2;$n",
[expr, rope(typ.kidsLen)])
m.s[cfsTypeInit3].addf("$1.node = &$2;$n", [tiNameForHcr(m, name), expr])
m.s[cfsTypeInit3].addFieldAssignment(expr, "len"):
m.s[cfsTypeInit3].add(rope(typ.kidsLen))
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind"):
m.s[cfsTypeInit3].add("2")
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "node"):
m.s[cfsTypeInit3].add(cAddr(expr))
proc genEnumInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) =
# Type information for enumerations is quite heavy, so we do some
@@ -1484,7 +1502,8 @@ proc genEnumInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) =
enumNames.add(makeCString(field.ast.strVal))
if i < typ.n.len - 1: enumNames.add(", \L")
if field.position != i or tfEnumHasHoles in typ.flags:
specialCases.addf("$1.offset = $2;$n", [elemNode, rope(field.position)])
specialCases.addFieldAssignment(elemNode, "offset"):
specialCases.add(rope(field.position))
hasHoles = true
var enumArray = getTempName(m)
var counter = getTempName(m)
@@ -1496,9 +1515,15 @@ proc genEnumInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) =
"$3[$1+$4].name = $5[$1];$n" & "$6[$1] = &$3[$1+$4];$n" & "}$n", [counter,
rope(typ.n.len), m.typeNodesName, rope(firstNimNode), enumArray, nodePtrs])
m.s[cfsTypeInit3].add(specialCases)
m.s[cfsTypeInit3].addf(
"$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n$4.node = &$1;$n",
[getNimNode(m), rope(typ.n.len), nodePtrs, tiNameForHcr(m, name)])
let n = getNimNode(m)
m.s[cfsTypeInit3].addFieldAssignment(n, "len"):
m.s[cfsTypeInit3].add(rope(typ.n.len))
m.s[cfsTypeInit3].addFieldAssignment(n, "kind"):
m.s[cfsTypeInit3].add("2")
m.s[cfsTypeInit3].addFieldAssignment(n, "sons"):
m.s[cfsTypeInit3].add(cAddr(subscript(nodePtrs, "0")))
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "node"):
m.s[cfsTypeInit3].add(cAddr(n))
if hasHoles:
# 1 << 2 is {ntfEnumHole}
m.s[cfsTypeInit3].addf("$1.flags = 1<<2;$n", [tiNameForHcr(m, name)])
@@ -1507,8 +1532,12 @@ proc genSetInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) =
assert(typ.elementType != nil)
genTypeInfoAux(m, typ, typ, name, info)
var tmp = getNimNode(m)
m.s[cfsTypeInit3].addf("$1.len = $2; $1.kind = 0;$n$3.node = &$1;$n",
[tmp, rope(firstOrd(m.config, typ)), tiNameForHcr(m, name)])
m.s[cfsTypeInit3].addFieldAssignment(tmp, "len"):
m.s[cfsTypeInit3].add(rope(firstOrd(m.config, typ)))
m.s[cfsTypeInit3].addFieldAssignment(tmp, "kind"):
m.s[cfsTypeInit3].add("0")
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "node"):
m.s[cfsTypeInit3].add(cAddr(tmp))
proc genArrayInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) =
genTypeInfoAuxBase(m, typ, typ, name, genTypeInfoV1(m, typ.elementType, info), info)
@@ -1677,11 +1706,12 @@ proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLin
if not canFormAcycle(m.g.graph, t): flags = flags or 1
var typeEntry = newRopeAppender()
addf(typeEntry, "$1.destructor = (void*)", [name])
genHook(m, t, info, attachedDestructor, typeEntry)
addf(typeEntry, "; $1.traceImpl = (void*)", [name])
genHook(m, t, info, attachedTrace, typeEntry)
typeEntry.addFieldAssignment(name, "destructor"):
typeEntry.addCast("void*"):
genHook(m, t, info, attachedDestructor, typeEntry)
typeEntry.addFieldAssignment(name, "traceImpl"):
typeEntry.addCast("void*"):
genHook(m, t, info, attachedTrace, typeEntry)
let objDepth = if t.kind == tyObject: getObjDepth(t) else: -1
@@ -1695,23 +1725,34 @@ proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLin
typeName = genTypeInfo2Name(m, t)
else:
typeName = rope("NIM_NIL")
addf(typeEntry, "; $1.name = $2", [name, typeName])
addf(typeEntry, "; $1.size = sizeof($2); $1.align = (NI16) NIM_ALIGNOF($2); $1.depth = $3; $1.flags = $4;",
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)])
if objDepth >= 0:
let objDisplay = genDisplay(m, t, objDepth)
let objDisplayStore = getTempName(m)
m.s[cfsVars].addf("static $1 $2[$3] = $4;$n", [getTypeDesc(m, getSysType(m.g.graph, unknownLineInfo, tyUInt32), dkVar), objDisplayStore, rope(objDepth+1), objDisplay])
addf(typeEntry, "$1.display = $2;$n", [name, rope(objDisplayStore)])
m.s[cfsVars].addArrayVar(kind = Global,
name = objDisplayStore,
elementType = getTypeDesc(m, getSysType(m.g.graph, unknownLineInfo, tyUInt32), dkVar),
len = objDepth + 1,
initializer = objDisplay)
typeEntry.addFieldAssignment(name, "display"):
typeEntry.add(rope(objDisplayStore))
let dispatchMethods = toSeq(getMethodsPerType(m.g.graph, t))
if dispatchMethods.len > 0:
let vTablePointerName = getTempName(m)
m.s[cfsVars].addf("static void* $1[$2] = $3;$n", [vTablePointerName, rope(dispatchMethods.len), genVTable(dispatchMethods)])
m.s[cfsVars].addArrayVar(kind = Global,
name = vTablePointerName,
elementType = "void*",
len = dispatchMethods.len,
initializer = genVTable(dispatchMethods))
for i in dispatchMethods:
genProcPrototype(m, i)
addf(typeEntry, "$1.vTable = $2;$n", [name, vTablePointerName])
typeEntry.addFieldAssignment(name, "vTable"):
typeEntry.add(vTablePointerName)
m.s[cfsTypeInit3].add typeEntry
@@ -1742,7 +1783,11 @@ proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineIn
if objDepth >= 0:
let objDisplay = genDisplay(m, t, objDepth)
let objDisplayStore = getTempName(m)
m.s[cfsVars].addf("static NIM_CONST $1 $2[$3] = $4;$n", [getTypeDesc(m, getSysType(m.g.graph, unknownLineInfo, tyUInt32), dkVar), objDisplayStore, rope(objDepth+1), objDisplay])
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
@@ -1907,12 +1952,14 @@ proc genTypeInfoV1(m: BModule; t: PType; info: TLineInfo): Rope =
genTypeInfoAux(m, t, t, result, info)
if m.config.selectedGC in {gcMarkAndSweep, gcRefc, gcGo}:
let markerProc = genTraverseProc(m, origType, sig)
m.s[cfsTypeInit3].addf("$1.marker = $2;$n", [tiNameForHcr(m, result), markerProc])
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, result), "marker"):
m.s[cfsTypeInit3].add(markerProc)
of tyRef:
genTypeInfoAux(m, t, t, result, info)
if m.config.selectedGC in {gcMarkAndSweep, gcRefc, gcGo}:
let markerProc = genTraverseProc(m, origType, sig)
m.s[cfsTypeInit3].addf("$1.marker = $2;$n", [tiNameForHcr(m, result), markerProc])
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, result), "marker"):
m.s[cfsTypeInit3].add(markerProc)
of tyPtr, tyRange, tyUncheckedArray: genTypeInfoAux(m, t, t, result, info)
of tyArray: genArrayInfo(m, t, result, info)
of tySet: genSetInfo(m, t, result, info)
@@ -1938,8 +1985,10 @@ proc genTypeInfoV1(m: BModule; t: PType; info: TLineInfo): Rope =
if optTinyRtti in m.config.globalOptions and t.kind == tyObject and sfImportc notin t.sym.flags:
let v2info = genTypeInfoV2(m, origType, info)
addf(m.s[cfsTypeInit3], "$1->typeInfoV1 = (void*)&$2; $2.typeInfoV2 = (void*)$1;$n", [
v2info, result])
m.s[cfsTypeInit3].addDerefFieldAssignment(v2info, "typeInfoV1"):
m.s[cfsTypeInit3].add(cCast("void*", cAddr(result)))
m.s[cfsTypeInit3].addFieldAssignment(result, "typeInfoV2"):
m.s[cfsTypeInit3].add(cCast("void*", v2info))
result = prefixTI.rope & result & ")".rope

View File

@@ -376,6 +376,7 @@ proc genProcPrototype(m: BModule, sym: PSym)
include cbuilderbase
include cbuilderexprs
include cbuilderdecls
include cbuilderstmts
include ccgliterals
include ccgtypes