mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-15 07:43:26 +00:00
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:
@@ -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 & ")"
|
||||
|
||||
23
compiler/cbuilderstmts.nim
Normal file
23
compiler/cbuilderstmts.nim
Normal 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")
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -376,6 +376,7 @@ proc genProcPrototype(m: BModule, sym: PSym)
|
||||
include cbuilderbase
|
||||
include cbuilderexprs
|
||||
include cbuilderdecls
|
||||
include cbuilderstmts
|
||||
include ccgliterals
|
||||
include ccgtypes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user