allow old styled RTTI for arc/orc (#15331)
This commit is contained in:
parent
0aaf4e2dfa
commit
fd31e8ff6f
23 changed files with 512 additions and 303 deletions
|
|
@ -680,7 +680,7 @@ type
|
||||||
mNBindSym, mNCallSite,
|
mNBindSym, mNCallSite,
|
||||||
mEqIdent, mEqNimrodNode, mSameNodeType, mGetImpl, mNGenSym,
|
mEqIdent, mEqNimrodNode, mSameNodeType, mGetImpl, mNGenSym,
|
||||||
mNHint, mNWarning, mNError,
|
mNHint, mNWarning, mNError,
|
||||||
mInstantiationInfo, mGetTypeInfo,
|
mInstantiationInfo, mGetTypeInfo, mGetTypeInfoV2,
|
||||||
mNimvm, mIntDefine, mStrDefine, mBoolDefine, mRunnableExamples,
|
mNimvm, mIntDefine, mStrDefine, mBoolDefine, mRunnableExamples,
|
||||||
mException, mBuiltinType, mSymOwner, mUncheckedArray, mGetImplTransf,
|
mException, mBuiltinType, mSymOwner, mUncheckedArray, mGetImplTransf,
|
||||||
mSymIsInstantiationOf, mNodeId
|
mSymIsInstantiationOf, mNodeId
|
||||||
|
|
|
||||||
|
|
@ -266,10 +266,10 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
[addrLoc(p.config, dest), addrLoc(p.config, src), rdLoc(dest)])
|
[addrLoc(p.config, dest), addrLoc(p.config, src), rdLoc(dest)])
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts, "#genericShallowAssign((void*)$1, (void*)$2, $3);$n",
|
linefmt(p, cpsStmts, "#genericShallowAssign((void*)$1, (void*)$2, $3);$n",
|
||||||
[addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfo(p.module, dest.t, dest.lode.info)])
|
[addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfoV1(p.module, dest.t, dest.lode.info)])
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
|
linefmt(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
|
||||||
[addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfo(p.module, dest.t, dest.lode.info)])
|
[addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfoV1(p.module, dest.t, dest.lode.info)])
|
||||||
|
|
||||||
proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc) =
|
proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc) =
|
||||||
assert d.k != locNone
|
assert d.k != locNone
|
||||||
|
|
@ -318,7 +318,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
|
linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
|
||||||
[addrLoc(p.config, dest), rdLoc(src),
|
[addrLoc(p.config, dest), rdLoc(src),
|
||||||
genTypeInfo(p.module, dest.t, dest.lode.info)])
|
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
|
||||||
of tyString:
|
of tyString:
|
||||||
if optSeqDestructors in p.config.globalOptions:
|
if optSeqDestructors in p.config.globalOptions:
|
||||||
genGenericAsgn(p, dest, src, flags)
|
genGenericAsgn(p, dest, src, flags)
|
||||||
|
|
@ -383,7 +383,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
linefmt(p, cpsStmts, # XXX: is this correct for arrays?
|
linefmt(p, cpsStmts, # XXX: is this correct for arrays?
|
||||||
"#genericAssignOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n",
|
"#genericAssignOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n",
|
||||||
[addrLoc(p.config, dest), addrLoc(p.config, src),
|
[addrLoc(p.config, dest), addrLoc(p.config, src),
|
||||||
genTypeInfo(p.module, dest.t, dest.lode.info)])
|
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts,
|
linefmt(p, cpsStmts,
|
||||||
# bug #4799, keep the nimCopyMem for a while
|
# bug #4799, keep the nimCopyMem for a while
|
||||||
|
|
@ -425,16 +425,21 @@ proc genDeepCopy(p: BProc; dest, src: TLoc) =
|
||||||
# XXX optimize this
|
# XXX optimize this
|
||||||
linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n",
|
linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n",
|
||||||
[addrLoc(p.config, dest), addrLocOrTemp(src),
|
[addrLoc(p.config, dest), addrLocOrTemp(src),
|
||||||
genTypeInfo(p.module, dest.t, dest.lode.info)])
|
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
|
||||||
of tySequence, tyString:
|
of tySequence, tyString:
|
||||||
|
if optTinyRtti in p.config.globalOptions:
|
||||||
|
linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n",
|
||||||
|
[addrLoc(p.config, dest), addrLocOrTemp(src),
|
||||||
|
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
|
||||||
|
else:
|
||||||
linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);$n",
|
linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);$n",
|
||||||
[addrLoc(p.config, dest), rdLoc(src),
|
[addrLoc(p.config, dest), rdLoc(src),
|
||||||
genTypeInfo(p.module, dest.t, dest.lode.info)])
|
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
|
||||||
of tyOpenArray, tyVarargs:
|
of tyOpenArray, tyVarargs:
|
||||||
linefmt(p, cpsStmts,
|
linefmt(p, cpsStmts,
|
||||||
"#genericDeepCopyOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n",
|
"#genericDeepCopyOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n",
|
||||||
[addrLoc(p.config, dest), addrLocOrTemp(src),
|
[addrLoc(p.config, dest), addrLocOrTemp(src),
|
||||||
genTypeInfo(p.module, dest.t, dest.lode.info)])
|
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
|
||||||
of tySet:
|
of tySet:
|
||||||
if mapSetType(p.config, ty) == ctArray:
|
if mapSetType(p.config, ty) == ctArray:
|
||||||
linefmt(p, cpsStmts, "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, $3);$n",
|
linefmt(p, cpsStmts, "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, $3);$n",
|
||||||
|
|
@ -1229,12 +1234,12 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||||
const seqAppendPattern = "($2) #incrSeqV3((TGenericSeq*)($1), $3)"
|
const seqAppendPattern = "($2) #incrSeqV3((TGenericSeq*)($1), $3)"
|
||||||
call.r = ropecg(p.module, seqAppendPattern, [rdLoc(a),
|
call.r = ropecg(p.module, seqAppendPattern, [rdLoc(a),
|
||||||
getTypeDesc(p.module, e[1].typ),
|
getTypeDesc(p.module, e[1].typ),
|
||||||
genTypeInfo(p.module, seqType, e.info)])
|
genTypeInfoV1(p.module, seqType, e.info)])
|
||||||
else:
|
else:
|
||||||
const seqAppendPattern = "($2) #incrSeqV3($1, $3)"
|
const seqAppendPattern = "($2) #incrSeqV3($1, $3)"
|
||||||
call.r = ropecg(p.module, seqAppendPattern, [rdLoc(a),
|
call.r = ropecg(p.module, seqAppendPattern, [rdLoc(a),
|
||||||
getTypeDesc(p.module, e[1].typ),
|
getTypeDesc(p.module, e[1].typ),
|
||||||
genTypeInfo(p.module, seqType, e.info)])
|
genTypeInfoV1(p.module, seqType, e.info)])
|
||||||
# emit the write barrier if required, but we can always move here, so
|
# emit the write barrier if required, but we can always move here, so
|
||||||
# use 'genRefAssign' for the seq.
|
# use 'genRefAssign' for the seq.
|
||||||
genRefAssign(p, a, call)
|
genRefAssign(p, a, call)
|
||||||
|
|
@ -1254,7 +1259,7 @@ proc genReset(p: BProc, n: PNode) =
|
||||||
when false:
|
when false:
|
||||||
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
||||||
[addrLoc(p.config, a),
|
[addrLoc(p.config, a),
|
||||||
genTypeInfo(p.module, skipTypes(a.t, {tyVar}), n.info)])
|
genTypeInfoV1(p.module, skipTypes(a.t, {tyVar}), n.info)])
|
||||||
|
|
||||||
proc genDefault(p: BProc; n: PNode; d: var TLoc) =
|
proc genDefault(p: BProc; n: PNode; d: var TLoc) =
|
||||||
if d.k == locNone: getTemp(p, n.typ, d, needsInit=true)
|
if d.k == locNone: getTemp(p, n.typ, d, needsInit=true)
|
||||||
|
|
@ -1280,7 +1285,7 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) =
|
||||||
[getTypeDesc(p.module, typ), sizeExpr])
|
[getTypeDesc(p.module, typ), sizeExpr])
|
||||||
genAssignment(p, a, b, {})
|
genAssignment(p, a, b, {})
|
||||||
else:
|
else:
|
||||||
let ti = genTypeInfo(p.module, typ, a.lode.info)
|
let ti = genTypeInfoV1(p.module, typ, a.lode.info)
|
||||||
if bt.destructor != nil and not isTrivialProc(bt.destructor):
|
if bt.destructor != nil and not isTrivialProc(bt.destructor):
|
||||||
# the prototype of a destructor is ``=destroy(x: var T)`` and that of a
|
# the prototype of a destructor is ``=destroy(x: var T)`` and that of a
|
||||||
# finalizer is: ``proc (x: ref T) {.nimcall.}``. We need to check the calling
|
# finalizer is: ``proc (x: ref T) {.nimcall.}``. We need to check the calling
|
||||||
|
|
@ -1339,18 +1344,18 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope; lenIsZero: bool) =
|
||||||
if p.config.selectedGC == gcGo:
|
if p.config.selectedGC == gcGo:
|
||||||
# we need the write barrier
|
# we need the write barrier
|
||||||
call.r = ropecg(p.module, "($1) #newSeq($2, $3)", [getTypeDesc(p.module, seqtype),
|
call.r = ropecg(p.module, "($1) #newSeq($2, $3)", [getTypeDesc(p.module, seqtype),
|
||||||
genTypeInfo(p.module, seqtype, dest.lode.info), length])
|
genTypeInfoV1(p.module, seqtype, dest.lode.info), length])
|
||||||
linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n", [addrLoc(p.config, dest), call.rdLoc])
|
linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n", [addrLoc(p.config, dest), call.rdLoc])
|
||||||
else:
|
else:
|
||||||
call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", [getTypeDesc(p.module, seqtype),
|
call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", [getTypeDesc(p.module, seqtype),
|
||||||
genTypeInfo(p.module, seqtype, dest.lode.info), length])
|
genTypeInfoV1(p.module, seqtype, dest.lode.info), length])
|
||||||
linefmt(p, cpsStmts, "$1 = $2;$n", [dest.rdLoc, call.rdLoc])
|
linefmt(p, cpsStmts, "$1 = $2;$n", [dest.rdLoc, call.rdLoc])
|
||||||
else:
|
else:
|
||||||
if lenIsZero:
|
if lenIsZero:
|
||||||
call.r = rope"NIM_NIL"
|
call.r = rope"NIM_NIL"
|
||||||
else:
|
else:
|
||||||
call.r = ropecg(p.module, "($1) #newSeq($2, $3)", [getTypeDesc(p.module, seqtype),
|
call.r = ropecg(p.module, "($1) #newSeq($2, $3)", [getTypeDesc(p.module, seqtype),
|
||||||
genTypeInfo(p.module, seqtype, dest.lode.info), length])
|
genTypeInfoV1(p.module, seqtype, dest.lode.info), length])
|
||||||
genAssignment(p, dest, call, {})
|
genAssignment(p, dest, call, {})
|
||||||
|
|
||||||
proc genNewSeq(p: BProc, e: PNode) =
|
proc genNewSeq(p: BProc, e: PNode) =
|
||||||
|
|
@ -1383,7 +1388,7 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
|
||||||
putIntoDest(p, d, e, ropecg(p.module,
|
putIntoDest(p, d, e, ropecg(p.module,
|
||||||
"($1)#nimNewSeqOfCap($2, $3)", [
|
"($1)#nimNewSeqOfCap($2, $3)", [
|
||||||
getTypeDesc(p.module, seqtype),
|
getTypeDesc(p.module, seqtype),
|
||||||
genTypeInfo(p.module, seqtype, e.info), a.rdLoc]))
|
genTypeInfoV1(p.module, seqtype, e.info), a.rdLoc]))
|
||||||
gcUsage(p.config, e)
|
gcUsage(p.config, e)
|
||||||
|
|
||||||
proc rawConstExpr(p: BProc, n: PNode; d: var TLoc) =
|
proc rawConstExpr(p: BProc, n: PNode; d: var TLoc) =
|
||||||
|
|
@ -1553,7 +1558,10 @@ proc genNewFinalize(p: BProc, e: PNode) =
|
||||||
initLocExpr(p, e[1], a)
|
initLocExpr(p, e[1], a)
|
||||||
initLocExpr(p, e[2], f)
|
initLocExpr(p, e[2], f)
|
||||||
initLoc(b, locExpr, a.lode, OnHeap)
|
initLoc(b, locExpr, a.lode, OnHeap)
|
||||||
ti = genTypeInfo(p.module, refType, e.info)
|
if optTinyRtti in p.config.globalOptions:
|
||||||
|
ti = genTypeInfoV2(p.module, refType, e.info)
|
||||||
|
else:
|
||||||
|
ti = genTypeInfoV1(p.module, refType, e.info)
|
||||||
p.module.s[cfsTypeInit3].addf("$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
|
p.module.s[cfsTypeInit3].addf("$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
|
||||||
b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [
|
b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [
|
||||||
getTypeDesc(p.module, refType),
|
getTypeDesc(p.module, refType),
|
||||||
|
|
@ -1568,9 +1576,9 @@ proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo): Rope =
|
||||||
result = ropecg(p.module, "#isObj($1.m_type, $2)",
|
result = ropecg(p.module, "#isObj($1.m_type, $2)",
|
||||||
[a, genTypeInfo2Name(p.module, dest)])
|
[a, genTypeInfo2Name(p.module, dest)])
|
||||||
else:
|
else:
|
||||||
# unfortunately 'genTypeInfo' sets tfObjHasKids as a side effect, so we
|
# unfortunately 'genTypeInfoV1' sets tfObjHasKids as a side effect, so we
|
||||||
# have to call it here first:
|
# have to call it here first:
|
||||||
let ti = genTypeInfo(p.module, dest, info)
|
let ti = genTypeInfoV1(p.module, dest, info)
|
||||||
if tfFinal in dest.flags or (objHasKidsValid in p.module.flags and
|
if tfFinal in dest.flags or (objHasKidsValid in p.module.flags and
|
||||||
tfObjHasKids notin dest.flags):
|
tfObjHasKids notin dest.flags):
|
||||||
result = "$1.m_type == $2" % [a, ti]
|
result = "$1.m_type == $2" % [a, ti]
|
||||||
|
|
@ -1583,7 +1591,7 @@ proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo): Rope =
|
||||||
when false:
|
when false:
|
||||||
# former version:
|
# former version:
|
||||||
result = ropecg(p.module, "#isObj($1.m_type, $2)",
|
result = ropecg(p.module, "#isObj($1.m_type, $2)",
|
||||||
[a, genTypeInfo(p.module, dest, info)])
|
[a, genTypeInfoV1(p.module, dest, info)])
|
||||||
|
|
||||||
proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
|
proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
|
|
@ -1633,12 +1641,12 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
of tyEnum, tyOrdinal:
|
of tyEnum, tyOrdinal:
|
||||||
putIntoDest(p, d, e,
|
putIntoDest(p, d, e,
|
||||||
ropecg(p.module, "#reprEnum((NI)$1, $2)", [
|
ropecg(p.module, "#reprEnum((NI)$1, $2)", [
|
||||||
rdLoc(a), genTypeInfo(p.module, t, e.info)]), a.storage)
|
rdLoc(a), genTypeInfoV1(p.module, t, e.info)]), a.storage)
|
||||||
of tyString:
|
of tyString:
|
||||||
putIntoDest(p, d, e, ropecg(p.module, "#reprStr($1)", [rdLoc(a)]), a.storage)
|
putIntoDest(p, d, e, ropecg(p.module, "#reprStr($1)", [rdLoc(a)]), a.storage)
|
||||||
of tySet:
|
of tySet:
|
||||||
putIntoDest(p, d, e, ropecg(p.module, "#reprSet($1, $2)", [
|
putIntoDest(p, d, e, ropecg(p.module, "#reprSet($1, $2)", [
|
||||||
addrLoc(p.config, a), genTypeInfo(p.module, t, e.info)]), a.storage)
|
addrLoc(p.config, a), genTypeInfoV1(p.module, t, e.info)]), a.storage)
|
||||||
of tyOpenArray, tyVarargs:
|
of tyOpenArray, tyVarargs:
|
||||||
var b: TLoc
|
var b: TLoc
|
||||||
case skipTypes(a.t, abstractVarRange).kind
|
case skipTypes(a.t, abstractVarRange).kind
|
||||||
|
|
@ -1653,20 +1661,20 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
else: internalError(p.config, e[0].info, "genRepr()")
|
else: internalError(p.config, e[0].info, "genRepr()")
|
||||||
putIntoDest(p, d, e,
|
putIntoDest(p, d, e,
|
||||||
ropecg(p.module, "#reprOpenArray($1, $2)", [rdLoc(b),
|
ropecg(p.module, "#reprOpenArray($1, $2)", [rdLoc(b),
|
||||||
genTypeInfo(p.module, elemType(t), e.info)]), a.storage)
|
genTypeInfoV1(p.module, elemType(t), e.info)]), a.storage)
|
||||||
of tyCString, tyArray, tyRef, tyPtr, tyPointer, tyNil, tySequence:
|
of tyCString, tyArray, tyRef, tyPtr, tyPointer, tyNil, tySequence:
|
||||||
putIntoDest(p, d, e,
|
putIntoDest(p, d, e,
|
||||||
ropecg(p.module, "#reprAny($1, $2)", [
|
ropecg(p.module, "#reprAny($1, $2)", [
|
||||||
rdLoc(a), genTypeInfo(p.module, t, e.info)]), a.storage)
|
rdLoc(a), genTypeInfoV1(p.module, t, e.info)]), a.storage)
|
||||||
of tyEmpty, tyVoid:
|
of tyEmpty, tyVoid:
|
||||||
localError(p.config, e.info, "'repr' doesn't support 'void' type")
|
localError(p.config, e.info, "'repr' doesn't support 'void' type")
|
||||||
else:
|
else:
|
||||||
putIntoDest(p, d, e, ropecg(p.module, "#reprAny($1, $2)",
|
putIntoDest(p, d, e, ropecg(p.module, "#reprAny($1, $2)",
|
||||||
[addrLoc(p.config, a), genTypeInfo(p.module, t, e.info)]),
|
[addrLoc(p.config, a), genTypeInfoV1(p.module, t, e.info)]),
|
||||||
a.storage)
|
a.storage)
|
||||||
gcUsage(p.config, e)
|
gcUsage(p.config, e)
|
||||||
|
|
||||||
proc rdMType(p: BProc; a: TLoc; nilCheck: var Rope): Rope =
|
proc rdMType(p: BProc; a: TLoc; nilCheck: var Rope; enforceV1 = false): Rope =
|
||||||
result = rdLoc(a)
|
result = rdLoc(a)
|
||||||
var t = skipTypes(a.t, abstractInst)
|
var t = skipTypes(a.t, abstractInst)
|
||||||
while t.kind in {tyVar, tyLent, tyPtr, tyRef}:
|
while t.kind in {tyVar, tyLent, tyPtr, tyRef}:
|
||||||
|
|
@ -1680,13 +1688,20 @@ proc rdMType(p: BProc; a: TLoc; nilCheck: var Rope): Rope =
|
||||||
result.add(".Sup")
|
result.add(".Sup")
|
||||||
t = skipTypes(t[0], skipPtrs)
|
t = skipTypes(t[0], skipPtrs)
|
||||||
result.add ".m_type"
|
result.add ".m_type"
|
||||||
|
if optTinyRtti in p.config.globalOptions and enforceV1:
|
||||||
|
result.add "->typeInfoV1"
|
||||||
|
|
||||||
proc genGetTypeInfo(p: BProc, e: PNode, d: var TLoc) =
|
proc genGetTypeInfo(p: BProc, e: PNode, d: var TLoc) =
|
||||||
discard cgsym(p.module, "TNimType")
|
discard cgsym(p.module, "TNimType")
|
||||||
|
let t = e[1].typ
|
||||||
|
# ordinary static type information
|
||||||
|
putIntoDest(p, d, e, genTypeInfoV1(p.module, t, e.info))
|
||||||
|
|
||||||
|
proc genGetTypeInfoV2(p: BProc, e: PNode, d: var TLoc) =
|
||||||
let t = e[1].typ
|
let t = e[1].typ
|
||||||
if isFinal(t) or e[0].sym.name.s != "getDynamicTypeInfo":
|
if isFinal(t) or e[0].sym.name.s != "getDynamicTypeInfo":
|
||||||
# ordinary static type information
|
# ordinary static type information
|
||||||
putIntoDest(p, d, e, genTypeInfo(p.module, t, e.info))
|
putIntoDest(p, d, e, genTypeInfoV2(p.module, t, e.info))
|
||||||
else:
|
else:
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
initLocExpr(p, e[1], a)
|
initLocExpr(p, e[1], a)
|
||||||
|
|
@ -1779,13 +1794,13 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
|
||||||
const setLenPattern = "($3) #setLengthSeqV2(&($1)->Sup, $4, $2)"
|
const setLenPattern = "($3) #setLengthSeqV2(&($1)->Sup, $4, $2)"
|
||||||
call.r = ropecg(p.module, setLenPattern, [
|
call.r = ropecg(p.module, setLenPattern, [
|
||||||
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
|
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
|
||||||
genTypeInfo(p.module, t.skipTypes(abstractInst), e.info)])
|
genTypeInfoV1(p.module, t.skipTypes(abstractInst), e.info)])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
const setLenPattern = "($3) #setLengthSeqV2($1, $4, $2)"
|
const setLenPattern = "($3) #setLengthSeqV2($1, $4, $2)"
|
||||||
call.r = ropecg(p.module, setLenPattern, [
|
call.r = ropecg(p.module, setLenPattern, [
|
||||||
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
|
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
|
||||||
genTypeInfo(p.module, t.skipTypes(abstractInst), e.info)])
|
genTypeInfoV1(p.module, t.skipTypes(abstractInst), e.info)])
|
||||||
|
|
||||||
genAssignment(p, a, call, {})
|
genAssignment(p, a, call, {})
|
||||||
gcUsage(p.config, e)
|
gcUsage(p.config, e)
|
||||||
|
|
@ -2226,6 +2241,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
of mAddI..mPred: binaryArithOverflow(p, e, d, op)
|
of mAddI..mPred: binaryArithOverflow(p, e, d, op)
|
||||||
of mRepr: genRepr(p, e, d)
|
of mRepr: genRepr(p, e, d)
|
||||||
of mGetTypeInfo: genGetTypeInfo(p, e, d)
|
of mGetTypeInfo: genGetTypeInfo(p, e, d)
|
||||||
|
of mGetTypeInfoV2: genGetTypeInfoV2(p, e, d)
|
||||||
of mSwap: genSwap(p, e, d)
|
of mSwap: genSwap(p, e, d)
|
||||||
of mInc, mDec:
|
of mInc, mDec:
|
||||||
const opr: array[mInc..mDec, string] = ["+=", "-="]
|
const opr: array[mInc..mDec, string] = ["+=", "-="]
|
||||||
|
|
@ -2534,7 +2550,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
|
||||||
let checkFor = if optTinyRtti in p.config.globalOptions:
|
let checkFor = if optTinyRtti in p.config.globalOptions:
|
||||||
genTypeInfo2Name(p.module, dest)
|
genTypeInfo2Name(p.module, dest)
|
||||||
else:
|
else:
|
||||||
genTypeInfo(p.module, dest, n.info)
|
genTypeInfoV1(p.module, dest, n.info)
|
||||||
if nilCheck != nil:
|
if nilCheck != nil:
|
||||||
linefmt(p, cpsStmts, "if ($1 && !#isObj($2, $3)){ #raiseObjectConversionError(); $4}$n",
|
linefmt(p, cpsStmts, "if ($1 && !#isObj($2, $3)){ #raiseObjectConversionError(); $4}$n",
|
||||||
[nilCheck, r, checkFor, raiseInstr(p)])
|
[nilCheck, r, checkFor, raiseInstr(p)])
|
||||||
|
|
@ -2951,7 +2967,10 @@ proc getNullValueAuxT(p: BProc; orig, t: PType; obj, constOrNil: PNode,
|
||||||
getNullValueAuxT(p, orig, base, base.n, constOrNil, result, count, isConst, info)
|
getNullValueAuxT(p, orig, base, base.n, constOrNil, result, count, isConst, info)
|
||||||
result.add "}"
|
result.add "}"
|
||||||
elif not isObjLackingTypeField(t):
|
elif not isObjLackingTypeField(t):
|
||||||
result.add genTypeInfo(p.module, orig, obj.info)
|
if optTinyRtti in p.config.globalOptions:
|
||||||
|
result.add genTypeInfoV2(p.module, orig, obj.info)
|
||||||
|
else:
|
||||||
|
result.add genTypeInfoV1(p.module, orig, obj.info)
|
||||||
inc count
|
inc count
|
||||||
getNullValueAux(p, t, obj, constOrNil, result, count, isConst, info)
|
getNullValueAux(p, t, obj, constOrNil, result, count, isConst, info)
|
||||||
# do not emit '{}' as that is not valid C:
|
# do not emit '{}' as that is not valid C:
|
||||||
|
|
|
||||||
|
|
@ -1040,7 +1040,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
let checkFor = if optTinyRtti in p.config.globalOptions:
|
let checkFor = if optTinyRtti in p.config.globalOptions:
|
||||||
genTypeInfo2Name(p.module, typeNode.typ)
|
genTypeInfo2Name(p.module, typeNode.typ)
|
||||||
else:
|
else:
|
||||||
genTypeInfo(p.module, typeNode.typ, typeNode.info)
|
genTypeInfoV1(p.module, typeNode.typ, typeNode.info)
|
||||||
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
|
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
|
||||||
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
|
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
|
||||||
|
|
||||||
|
|
@ -1255,7 +1255,7 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
|
||||||
let checkFor = if optTinyRtti in p.config.globalOptions:
|
let checkFor = if optTinyRtti in p.config.globalOptions:
|
||||||
genTypeInfo2Name(p.module, t[i][j].typ)
|
genTypeInfo2Name(p.module, t[i][j].typ)
|
||||||
else:
|
else:
|
||||||
genTypeInfo(p.module, t[i][j].typ, t[i][j].info)
|
genTypeInfoV1(p.module, t[i][j].typ, t[i][j].info)
|
||||||
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
|
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
|
||||||
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
|
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
|
||||||
|
|
||||||
|
|
@ -1383,7 +1383,7 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
let checkFor = if optTinyRtti in p.config.globalOptions:
|
let checkFor = if optTinyRtti in p.config.globalOptions:
|
||||||
genTypeInfo2Name(p.module, t[i][j].typ)
|
genTypeInfo2Name(p.module, t[i][j].typ)
|
||||||
else:
|
else:
|
||||||
genTypeInfo(p.module, t[i][j].typ, t[i][j].info)
|
genTypeInfoV1(p.module, t[i][j].typ, t[i][j].info)
|
||||||
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
|
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
|
||||||
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
|
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
|
||||||
|
|
||||||
|
|
@ -1508,7 +1508,7 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
|
||||||
field: PSym) =
|
field: PSym) =
|
||||||
var t = skipTypes(objtype, abstractVar)
|
var t = skipTypes(objtype, abstractVar)
|
||||||
assert t.kind == tyObject
|
assert t.kind == tyObject
|
||||||
discard genTypeInfo(p.module, t, a.lode.info)
|
discard genTypeInfoV1(p.module, t, a.lode.info)
|
||||||
if not containsOrIncl(p.module.declaredThings, field.id):
|
if not containsOrIncl(p.module.declaredThings, field.id):
|
||||||
appcg(p.module, cfsVars, "extern $1",
|
appcg(p.module, cfsVars, "extern $1",
|
||||||
[discriminatorTableDecl(p.module, t, field)])
|
[discriminatorTableDecl(p.module, t, field)])
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash): Rope =
|
||||||
[result, markerName, getModuleDllPath(m)])
|
[result, markerName, getModuleDllPath(m)])
|
||||||
|
|
||||||
proc genTraverseProcForGlobal(m: BModule, s: PSym; info: TLineInfo): Rope =
|
proc genTraverseProcForGlobal(m: BModule, s: PSym; info: TLineInfo): Rope =
|
||||||
discard genTypeInfo(m, s.loc.t, info)
|
discard genTypeInfoV1(m, s.loc.t, info)
|
||||||
|
|
||||||
var c: TTraversalClosure
|
var c: TTraversalClosure
|
||||||
var p = newProc(nil, m)
|
var p = newProc(nil, m)
|
||||||
|
|
|
||||||
|
|
@ -608,6 +608,9 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
|
||||||
if typ[0] == nil:
|
if typ[0] == nil:
|
||||||
if (typ.sym != nil and sfPure in typ.sym.flags) or tfFinal in typ.flags:
|
if (typ.sym != nil and sfPure in typ.sym.flags) or tfFinal in typ.flags:
|
||||||
appcg(m, result, " {$n", [])
|
appcg(m, result, " {$n", [])
|
||||||
|
else:
|
||||||
|
if optTinyRtti in m.config.globalOptions:
|
||||||
|
appcg(m, result, " {$n#TNimTypeV2* m_type;$n", [])
|
||||||
else:
|
else:
|
||||||
appcg(m, result, " {$n#TNimType* m_type;$n", [])
|
appcg(m, result, " {$n#TNimType* m_type;$n", [])
|
||||||
hasField = true
|
hasField = true
|
||||||
|
|
@ -1004,7 +1007,7 @@ proc genProcHeader(m: BModule, prc: PSym, asPtr: bool = false): Rope =
|
||||||
|
|
||||||
# ------------------ type info generation -------------------------------------
|
# ------------------ type info generation -------------------------------------
|
||||||
|
|
||||||
proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope
|
proc genTypeInfoV1(m: BModule, t: PType; info: TLineInfo): Rope
|
||||||
proc getNimNode(m: BModule): Rope =
|
proc getNimNode(m: BModule): Rope =
|
||||||
result = "$1[$2]" % [m.typeNodesName, rope(m.typeNodes)]
|
result = "$1[$2]" % [m.typeNodesName, rope(m.typeNodes)]
|
||||||
inc(m.typeNodes)
|
inc(m.typeNodes)
|
||||||
|
|
@ -1067,7 +1070,7 @@ proc genTypeInfoAux(m: BModule, typ, origType: PType, name: Rope;
|
||||||
if typ.kind == tyPtr and x.kind == tyObject and incompleteType(x):
|
if typ.kind == tyPtr and x.kind == tyObject and incompleteType(x):
|
||||||
base = rope("0")
|
base = rope("0")
|
||||||
else:
|
else:
|
||||||
base = genTypeInfo(m, x, info)
|
base = genTypeInfoV1(m, x, info)
|
||||||
else:
|
else:
|
||||||
base = rope("0")
|
base = rope("0")
|
||||||
genTypeInfoAuxBase(m, typ, origType, name, base, info)
|
genTypeInfoAuxBase(m, typ, origType, name, base, info)
|
||||||
|
|
@ -1126,7 +1129,7 @@ proc genObjectFields(m: BModule, typ, origType: PType, n: PNode, expr: Rope;
|
||||||
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
|
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
|
||||||
"$1.name = $5;$n" & "$1.sons = &$6[0];$n" &
|
"$1.name = $5;$n" & "$1.sons = &$6[0];$n" &
|
||||||
"$1.len = $7;$n", [expr, getTypeDesc(m, origType), field.loc.r,
|
"$1.len = $7;$n", [expr, getTypeDesc(m, origType), field.loc.r,
|
||||||
genTypeInfo(m, field.typ, info),
|
genTypeInfoV1(m, field.typ, info),
|
||||||
makeCString(field.name.s),
|
makeCString(field.name.s),
|
||||||
tmp, rope(L)])
|
tmp, rope(L)])
|
||||||
m.s[cfsData].addf("TNimNode* $1[$2];$n", [tmp, rope(L+1)])
|
m.s[cfsData].addf("TNimNode* $1[$2];$n", [tmp, rope(L+1)])
|
||||||
|
|
@ -1163,7 +1166,7 @@ proc genObjectFields(m: BModule, typ, origType: PType, n: PNode, expr: Rope;
|
||||||
m.s[cfsTypeInit3].addf("$1.kind = 1;$n" &
|
m.s[cfsTypeInit3].addf("$1.kind = 1;$n" &
|
||||||
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
|
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
|
||||||
"$1.name = $5;$n", [expr, getTypeDesc(m, origType),
|
"$1.name = $5;$n", [expr, getTypeDesc(m, origType),
|
||||||
field.loc.r, genTypeInfo(m, field.typ, info), makeCString(field.name.s)])
|
field.loc.r, genTypeInfoV1(m, field.typ, info), makeCString(field.name.s)])
|
||||||
else: internalError(m.config, n.info, "genObjectFields")
|
else: internalError(m.config, n.info, "genObjectFields")
|
||||||
|
|
||||||
proc genObjectInfo(m: BModule, typ, origType: PType, name: Rope; info: TLineInfo) =
|
proc genObjectInfo(m: BModule, typ, origType: PType, name: Rope; info: TLineInfo) =
|
||||||
|
|
@ -1198,7 +1201,7 @@ proc genTupleInfo(m: BModule, typ, origType: PType, name: Rope; info: TLineInfo)
|
||||||
"$1.offset = offsetof($2, Field$3);$n" &
|
"$1.offset = offsetof($2, Field$3);$n" &
|
||||||
"$1.typ = $4;$n" &
|
"$1.typ = $4;$n" &
|
||||||
"$1.name = \"Field$3\";$n",
|
"$1.name = \"Field$3\";$n",
|
||||||
[tmp2, getTypeDesc(m, origType), rope(i), genTypeInfo(m, a, info)])
|
[tmp2, getTypeDesc(m, origType), rope(i), genTypeInfoV1(m, a, info)])
|
||||||
m.s[cfsTypeInit3].addf("$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
|
m.s[cfsTypeInit3].addf("$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
|
||||||
[expr, rope(typ.len), tmp])
|
[expr, rope(typ.len), tmp])
|
||||||
else:
|
else:
|
||||||
|
|
@ -1255,7 +1258,7 @@ proc genSetInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =
|
||||||
[tmp, rope(firstOrd(m.config, typ)), tiNameForHcr(m, name)])
|
[tmp, rope(firstOrd(m.config, typ)), tiNameForHcr(m, name)])
|
||||||
|
|
||||||
proc genArrayInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =
|
proc genArrayInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =
|
||||||
genTypeInfoAuxBase(m, typ, typ, name, genTypeInfo(m, typ[1], info), info)
|
genTypeInfoAuxBase(m, typ, typ, name, genTypeInfoV1(m, typ[1], info), info)
|
||||||
|
|
||||||
proc fakeClosureType(m: BModule; owner: PSym): PType =
|
proc fakeClosureType(m: BModule; owner: PSym): PType =
|
||||||
# we generate the same RTTI as for a tuple[pointer, ref tuple[]]
|
# we generate the same RTTI as for a tuple[pointer, ref tuple[]]
|
||||||
|
|
@ -1273,13 +1276,14 @@ proc genDeepCopyProc(m: BModule; s: PSym; result: Rope) =
|
||||||
m.s[cfsTypeInit3].addf("$1.deepcopy =(void* (N_RAW_NIMCALL*)(void*))$2;$n",
|
m.s[cfsTypeInit3].addf("$1.deepcopy =(void* (N_RAW_NIMCALL*)(void*))$2;$n",
|
||||||
[result, s.loc.r])
|
[result, s.loc.r])
|
||||||
|
|
||||||
proc declareNimType(m: BModule, str: Rope, ownerModule: PSym) =
|
proc declareNimType(m: BModule, name: string; str: Rope, ownerModule: PSym) =
|
||||||
|
let nr = rope(name)
|
||||||
if m.hcrOn:
|
if m.hcrOn:
|
||||||
m.s[cfsData].addf("static TNimType* $1;$n", [str])
|
m.s[cfsData].addf("static $2* $1;$n", [str, nr])
|
||||||
m.s[cfsTypeInit1].addf("\t$1 = (TNimType*)hcrGetGlobal($2, \"$1\");$n",
|
m.s[cfsTypeInit1].addf("\t$1 = ($3*)hcrGetGlobal($2, \"$1\");$n",
|
||||||
[str, getModuleDllPath(m, ownerModule)])
|
[str, getModuleDllPath(m, ownerModule), nr])
|
||||||
else:
|
else:
|
||||||
m.s[cfsData].addf("extern TNimType $1;$n", [str])
|
m.s[cfsData].addf("extern $2 $1;$n", [str, nr])
|
||||||
|
|
||||||
proc genTypeInfo2Name(m: BModule; t: PType): Rope =
|
proc genTypeInfo2Name(m: BModule; t: PType): Rope =
|
||||||
var res = "|"
|
var res = "|"
|
||||||
|
|
@ -1327,7 +1331,7 @@ proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp): Rope =
|
||||||
internalError(m.config, info, "no attached trace proc found")
|
internalError(m.config, info, "no attached trace proc found")
|
||||||
result = rope("NIM_NIL")
|
result = rope("NIM_NIL")
|
||||||
|
|
||||||
proc genTypeInfoV2(m: BModule, t, origType: PType, name: Rope; info: TLineInfo) =
|
proc genTypeInfoV2Impl(m: BModule, t, origType: PType, name: Rope; info: TLineInfo) =
|
||||||
var typeName: Rope
|
var typeName: Rope
|
||||||
if t.kind == tyObject:
|
if t.kind == tyObject:
|
||||||
if incompleteType(t):
|
if incompleteType(t):
|
||||||
|
|
@ -1337,8 +1341,8 @@ proc genTypeInfoV2(m: BModule, t, origType: PType, name: Rope; info: TLineInfo)
|
||||||
else:
|
else:
|
||||||
typeName = rope("NIM_NIL")
|
typeName = rope("NIM_NIL")
|
||||||
|
|
||||||
discard cgsym(m, "TNimType")
|
discard cgsym(m, "TNimTypeV2")
|
||||||
m.s[cfsData].addf("N_LIB_PRIVATE TNimType $1;$n", [name])
|
m.s[cfsData].addf("N_LIB_PRIVATE TNimTypeV2 $1;$n", [name])
|
||||||
let destroyImpl = genHook(m, t, info, attachedDestructor)
|
let destroyImpl = genHook(m, t, info, attachedDestructor)
|
||||||
let traceImpl = genHook(m, t, info, attachedTrace)
|
let traceImpl = genHook(m, t, info, attachedTrace)
|
||||||
let disposeImpl = genHook(m, t, info, attachedDispose)
|
let disposeImpl = genHook(m, t, info, attachedDispose)
|
||||||
|
|
@ -1347,7 +1351,43 @@ proc genTypeInfoV2(m: BModule, t, origType: PType, name: Rope; info: TLineInfo)
|
||||||
name, destroyImpl, getTypeDesc(m, t), typeName,
|
name, destroyImpl, getTypeDesc(m, t), typeName,
|
||||||
traceImpl, disposeImpl])
|
traceImpl, disposeImpl])
|
||||||
|
|
||||||
proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
|
proc genTypeInfoV2(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||||
|
let origType = t
|
||||||
|
var t = skipTypes(origType, irrelevantForBackend + tyUserTypeClasses)
|
||||||
|
|
||||||
|
let prefixTI = if m.hcrOn: "(" else: "(&"
|
||||||
|
|
||||||
|
let sig = hashType(origType)
|
||||||
|
result = m.typeInfoMarkerV2.getOrDefault(sig)
|
||||||
|
if result != nil:
|
||||||
|
return prefixTI.rope & result & ")".rope
|
||||||
|
|
||||||
|
let marker = m.g.typeInfoMarkerV2.getOrDefault(sig)
|
||||||
|
if marker.str != nil:
|
||||||
|
discard cgsym(m, "TNimTypeV2")
|
||||||
|
declareNimType(m, "TNimTypeV2", marker.str, marker.owner)
|
||||||
|
# also store in local type section:
|
||||||
|
m.typeInfoMarkerV2[sig] = marker.str
|
||||||
|
return prefixTI.rope & marker.str & ")".rope
|
||||||
|
|
||||||
|
result = "NTIv2$1_" % [rope($sig)]
|
||||||
|
m.typeInfoMarkerV2[sig] = result
|
||||||
|
|
||||||
|
let owner = t.skipTypes(typedescPtrs).owner.getModule
|
||||||
|
if owner != m.module:
|
||||||
|
# make sure the type info is created in the owner module
|
||||||
|
assert m.g.modules[owner.position] != nil
|
||||||
|
discard genTypeInfoV2(m.g.modules[owner.position], origType, info)
|
||||||
|
# reference the type info as extern here
|
||||||
|
discard cgsym(m, "TNimTypeV2")
|
||||||
|
declareNimType(m, "TNimTypeV2", result, owner)
|
||||||
|
return prefixTI.rope & result & ")".rope
|
||||||
|
|
||||||
|
m.g.typeInfoMarkerV2[sig] = (str: result, owner: owner)
|
||||||
|
genTypeInfoV2Impl(m, t, origType, result, info)
|
||||||
|
result = prefixTI.rope & result & ")".rope
|
||||||
|
|
||||||
|
proc genTypeInfoV1(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||||
let origType = t
|
let origType = t
|
||||||
var t = skipTypes(origType, irrelevantForBackend + tyUserTypeClasses)
|
var t = skipTypes(origType, irrelevantForBackend + tyUserTypeClasses)
|
||||||
|
|
||||||
|
|
@ -1362,7 +1402,7 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||||
if marker.str != nil:
|
if marker.str != nil:
|
||||||
discard cgsym(m, "TNimType")
|
discard cgsym(m, "TNimType")
|
||||||
discard cgsym(m, "TNimNode")
|
discard cgsym(m, "TNimNode")
|
||||||
declareNimType(m, marker.str, marker.owner)
|
declareNimType(m, "TNimType", marker.str, marker.owner)
|
||||||
# also store in local type section:
|
# also store in local type section:
|
||||||
m.typeInfoMarker[sig] = marker.str
|
m.typeInfoMarker[sig] = marker.str
|
||||||
return prefixTI.rope & marker.str & ")".rope
|
return prefixTI.rope & marker.str & ")".rope
|
||||||
|
|
@ -1374,28 +1414,25 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||||
if owner != m.module:
|
if owner != m.module:
|
||||||
# make sure the type info is created in the owner module
|
# make sure the type info is created in the owner module
|
||||||
assert m.g.modules[owner.position] != nil
|
assert m.g.modules[owner.position] != nil
|
||||||
discard genTypeInfo(m.g.modules[owner.position], origType, info)
|
discard genTypeInfoV1(m.g.modules[owner.position], origType, info)
|
||||||
# reference the type info as extern here
|
# reference the type info as extern here
|
||||||
discard cgsym(m, "TNimType")
|
discard cgsym(m, "TNimType")
|
||||||
discard cgsym(m, "TNimNode")
|
discard cgsym(m, "TNimNode")
|
||||||
declareNimType(m, result, owner)
|
declareNimType(m, "TNimType", result, owner)
|
||||||
return prefixTI.rope & result & ")".rope
|
return prefixTI.rope & result & ")".rope
|
||||||
|
|
||||||
m.g.typeInfoMarker[sig] = (str: result, owner: owner)
|
m.g.typeInfoMarker[sig] = (str: result, owner: owner)
|
||||||
|
|
||||||
if optTinyRtti in m.config.globalOptions:
|
|
||||||
genTypeInfoV2(m, t, origType, result, info)
|
|
||||||
else:
|
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyEmpty, tyVoid: result = rope"0"
|
of tyEmpty, tyVoid: result = rope"0"
|
||||||
of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar, tyLent:
|
of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar, tyLent:
|
||||||
genTypeInfoAuxBase(m, t, t, result, rope"0", info)
|
genTypeInfoAuxBase(m, t, t, result, rope"0", info)
|
||||||
of tyStatic:
|
of tyStatic:
|
||||||
if t.n != nil: result = genTypeInfo(m, lastSon t, info)
|
if t.n != nil: result = genTypeInfoV1(m, lastSon t, info)
|
||||||
else: internalError(m.config, "genTypeInfo(" & $t.kind & ')')
|
else: internalError(m.config, "genTypeInfoV1(" & $t.kind & ')')
|
||||||
of tyUserTypeClasses:
|
of tyUserTypeClasses:
|
||||||
internalAssert m.config, t.isResolvedUserTypeClass
|
internalAssert m.config, t.isResolvedUserTypeClass
|
||||||
return genTypeInfo(m, t.lastSon, info)
|
return genTypeInfoV1(m, t.lastSon, info)
|
||||||
of tyProc:
|
of tyProc:
|
||||||
if t.callConv != ccClosure:
|
if t.callConv != ccClosure:
|
||||||
genTypeInfoAuxBase(m, t, t, result, rope"0", info)
|
genTypeInfoAuxBase(m, t, t, result, rope"0", info)
|
||||||
|
|
@ -1404,7 +1441,6 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||||
genTupleInfo(m, x, x, result, info)
|
genTupleInfo(m, x, x, result, info)
|
||||||
of tySequence:
|
of tySequence:
|
||||||
genTypeInfoAux(m, t, t, result, info)
|
genTypeInfoAux(m, t, t, result, info)
|
||||||
if optSeqDestructors notin m.config.globalOptions:
|
|
||||||
if m.config.selectedGC >= gcMarkAndSweep:
|
if m.config.selectedGC >= gcMarkAndSweep:
|
||||||
let markerProc = genTraverseProc(m, origType, sig)
|
let markerProc = genTraverseProc(m, origType, sig)
|
||||||
m.s[cfsTypeInit3].addf("$1.marker = $2;$n", [tiNameForHcr(m, result), markerProc])
|
m.s[cfsTypeInit3].addf("$1.marker = $2;$n", [tiNameForHcr(m, result), markerProc])
|
||||||
|
|
@ -1425,12 +1461,18 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||||
# BUGFIX: use consistently RTTI without proper field names; otherwise
|
# BUGFIX: use consistently RTTI without proper field names; otherwise
|
||||||
# results are not deterministic!
|
# results are not deterministic!
|
||||||
genTupleInfo(m, t, origType, result, info)
|
genTupleInfo(m, t, origType, result, info)
|
||||||
else: internalError(m.config, "genTypeInfo(" & $t.kind & ')')
|
else: internalError(m.config, "genTypeInfoV1(" & $t.kind & ')')
|
||||||
|
|
||||||
if t.attachedOps[attachedDeepCopy] != nil:
|
if t.attachedOps[attachedDeepCopy] != nil:
|
||||||
genDeepCopyProc(m, t.attachedOps[attachedDeepCopy], result)
|
genDeepCopyProc(m, t.attachedOps[attachedDeepCopy], result)
|
||||||
elif origType.attachedOps[attachedDeepCopy] != nil:
|
elif origType.attachedOps[attachedDeepCopy] != nil:
|
||||||
genDeepCopyProc(m, origType.attachedOps[attachedDeepCopy], result)
|
genDeepCopyProc(m, origType.attachedOps[attachedDeepCopy], result)
|
||||||
|
|
||||||
|
if optTinyRtti in m.config.globalOptions and t.kind == tyObject:
|
||||||
|
let v2info = genTypeInfoV2(m, origType, info)
|
||||||
|
addf(m.s[cfsTypeInit3], "$1->typeInfoV1 = (void*)&$2; $2.typeInfoV2 = (void*)$1;$n", [
|
||||||
|
v2info, result])
|
||||||
|
|
||||||
result = prefixTI.rope & result & ")".rope
|
result = prefixTI.rope & result & ")".rope
|
||||||
|
|
||||||
proc genTypeSection(m: BModule, n: PNode) =
|
proc genTypeSection(m: BModule, n: PNode) =
|
||||||
|
|
|
||||||
|
|
@ -360,7 +360,10 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: var TLoc,
|
||||||
while s.kind == tyObject and s[0] != nil:
|
while s.kind == tyObject and s[0] != nil:
|
||||||
r.add(".Sup")
|
r.add(".Sup")
|
||||||
s = skipTypes(s[0], skipPtrs)
|
s = skipTypes(s[0], skipPtrs)
|
||||||
linefmt(p, section, "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t, a.lode.info)])
|
if optTinyRtti in p.config.globalOptions:
|
||||||
|
linefmt(p, section, "$1.m_type = $2;$n", [r, genTypeInfoV2(p.module, t, a.lode.info)])
|
||||||
|
else:
|
||||||
|
linefmt(p, section, "$1.m_type = $2;$n", [r, genTypeInfoV1(p.module, t, a.lode.info)])
|
||||||
of frEmbedded:
|
of frEmbedded:
|
||||||
if optTinyRtti in p.config.globalOptions:
|
if optTinyRtti in p.config.globalOptions:
|
||||||
var tmp: TLoc
|
var tmp: TLoc
|
||||||
|
|
@ -376,7 +379,7 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: var TLoc,
|
||||||
else:
|
else:
|
||||||
# worst case for performance:
|
# worst case for performance:
|
||||||
var r = if mode == constructObj: addrLoc(p.config, a) else: rdLoc(a)
|
var r = if mode == constructObj: addrLoc(p.config, a) else: rdLoc(a)
|
||||||
linefmt(p, section, "#objectInit($1, $2);$n", [r, genTypeInfo(p.module, t, a.lode.info)])
|
linefmt(p, section, "#objectInit($1, $2);$n", [r, genTypeInfoV1(p.module, t, a.lode.info)])
|
||||||
|
|
||||||
if isException(t):
|
if isException(t):
|
||||||
var r = rdLoc(a)
|
var r = rdLoc(a)
|
||||||
|
|
@ -417,7 +420,7 @@ proc resetLoc(p: BProc, loc: var TLoc) =
|
||||||
specializeReset(p, loc)
|
specializeReset(p, loc)
|
||||||
when false:
|
when false:
|
||||||
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
||||||
[addrLoc(p.config, loc), genTypeInfo(p.module, loc.t, loc.lode.info)])
|
[addrLoc(p.config, loc), genTypeInfoV1(p.module, loc.t, loc.lode.info)])
|
||||||
# XXX: generated reset procs should not touch the m_type
|
# XXX: generated reset procs should not touch the m_type
|
||||||
# field, so disabling this should be safe:
|
# field, so disabling this should be safe:
|
||||||
genObjectInit(p, cpsStmts, loc.t, loc, constructObj)
|
genObjectInit(p, cpsStmts, loc.t, loc, constructObj)
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,7 @@ type
|
||||||
forwardedProcs*: seq[PSym] # proc:s that did not yet have a body
|
forwardedProcs*: seq[PSym] # proc:s that did not yet have a body
|
||||||
generatedHeader*: BModule
|
generatedHeader*: BModule
|
||||||
typeInfoMarker*: TypeCacheWithOwner
|
typeInfoMarker*: TypeCacheWithOwner
|
||||||
|
typeInfoMarkerV2*: TypeCacheWithOwner
|
||||||
config*: ConfigRef
|
config*: ConfigRef
|
||||||
graph*: ModuleGraph
|
graph*: ModuleGraph
|
||||||
strVersion*, seqVersion*: int # version of the string/seq implementation to use
|
strVersion*, seqVersion*: int # version of the string/seq implementation to use
|
||||||
|
|
@ -155,6 +156,7 @@ type
|
||||||
declaredProtos*: IntSet # prototypes we have declared in this .c file
|
declaredProtos*: IntSet # prototypes we have declared in this .c file
|
||||||
headerFiles*: seq[string] # needed headers to include
|
headerFiles*: seq[string] # needed headers to include
|
||||||
typeInfoMarker*: TypeCache # needed for generating type information
|
typeInfoMarker*: TypeCache # needed for generating type information
|
||||||
|
typeInfoMarkerV2*: TypeCache
|
||||||
initProc*: BProc # code for init procedure
|
initProc*: BProc # code for init procedure
|
||||||
preInitProc*: BProc # code executed before the init proc
|
preInitProc*: BProc # code executed before the init proc
|
||||||
hcrCreateTypeInfosProc*: Rope # type info globals are in here when HCR=on
|
hcrCreateTypeInfosProc*: Rope # type info globals are in here when HCR=on
|
||||||
|
|
|
||||||
|
|
@ -523,7 +523,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
var cond: PNode
|
var cond: PNode
|
||||||
if isCyclic:
|
if isCyclic:
|
||||||
if isFinal(elemType):
|
if isFinal(elemType):
|
||||||
let typInfo = genBuiltin(c.g, mGetTypeInfo, "getTypeInfo", newNodeIT(nkType, x.info, elemType))
|
let typInfo = genBuiltin(c.g, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType))
|
||||||
typInfo.typ = getSysType(c.g, c.info, tyPointer)
|
typInfo.typ = getSysType(c.g, c.info, tyPointer)
|
||||||
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicStatic", c.info, x, typInfo)
|
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicStatic", c.info, x, typInfo)
|
||||||
else:
|
else:
|
||||||
|
|
@ -546,7 +546,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
of attachedDeepCopy: assert(false, "cannot happen")
|
of attachedDeepCopy: assert(false, "cannot happen")
|
||||||
of attachedTrace:
|
of attachedTrace:
|
||||||
if isFinal(elemType):
|
if isFinal(elemType):
|
||||||
let typInfo = genBuiltin(c.g, mGetTypeInfo, "getTypeInfo", newNodeIT(nkType, x.info, elemType))
|
let typInfo = genBuiltin(c.g, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType))
|
||||||
typInfo.typ = getSysType(c.g, c.info, tyPointer)
|
typInfo.typ = getSysType(c.g, c.info, tyPointer)
|
||||||
body.add callCodegenProc(c.g, "nimTraceRef", c.info, genAddrOf(x), typInfo, y)
|
body.add callCodegenProc(c.g, "nimTraceRef", c.info, genAddrOf(x), typInfo, y)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -136,9 +136,8 @@ type
|
||||||
cmdCompileToBackend, # compile to backend in TBackend
|
cmdCompileToBackend, # compile to backend in TBackend
|
||||||
TStringSeq* = seq[string]
|
TStringSeq* = seq[string]
|
||||||
TGCMode* = enum # the selected GC
|
TGCMode* = enum # the selected GC
|
||||||
gcUnselected, gcNone, gcBoehm, gcRegions, gcMarkAndSweep, gcArc, gcOrc,
|
gcUnselected, gcNone, gcBoehm, gcRegions, gcArc, gcOrc,
|
||||||
gcHooks,
|
gcMarkAndSweep, gcHooks, gcRefc, gcV2, gcGo
|
||||||
gcRefc, gcV2, gcGo
|
|
||||||
# gcRefc and the GCs that follow it use a write barrier,
|
# gcRefc and the GCs that follow it use a write barrier,
|
||||||
# as far as usesWriteBarrier() is concerned
|
# as far as usesWriteBarrier() is concerned
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@
|
||||||
## work with the types' AST representation at compile time. See, for example,
|
## work with the types' AST representation at compile time. See, for example,
|
||||||
## the `getTypeImpl proc<macros.html#getTypeImpl,NimNode>`_. As an alternative
|
## the `getTypeImpl proc<macros.html#getTypeImpl,NimNode>`_. As an alternative
|
||||||
## approach to storing arbitrary types at runtime, consider using generics.
|
## approach to storing arbitrary types at runtime, consider using generics.
|
||||||
##
|
|
||||||
##
|
|
||||||
|
|
||||||
{.push hints: off.}
|
{.push hints: off.}
|
||||||
|
|
||||||
|
|
@ -77,12 +75,22 @@ type
|
||||||
ppointer = ptr pointer
|
ppointer = ptr pointer
|
||||||
pbyteArray = ptr array[0xffff, int8]
|
pbyteArray = ptr array[0xffff, int8]
|
||||||
|
|
||||||
|
when not defined(gcDestructors):
|
||||||
|
type
|
||||||
TGenericSeq {.importc.} = object
|
TGenericSeq {.importc.} = object
|
||||||
len, space: int
|
len, space: int
|
||||||
when defined(gogc):
|
when defined(gogc):
|
||||||
elemSize: int
|
elemSize: int
|
||||||
PGenSeq = ptr TGenericSeq
|
PGenSeq = ptr TGenericSeq
|
||||||
|
|
||||||
|
when defined(gogc):
|
||||||
|
const GenericSeqSize = (3 * sizeof(int))
|
||||||
|
else:
|
||||||
|
const GenericSeqSize = (2 * sizeof(int))
|
||||||
|
|
||||||
|
else:
|
||||||
|
include system/seqs_v2_reimpl
|
||||||
|
|
||||||
when not defined(js):
|
when not defined(js):
|
||||||
template rawType(x: Any): PNimType =
|
template rawType(x: Any): PNimType =
|
||||||
cast[PNimType](x.rawTypePtr)
|
cast[PNimType](x.rawTypePtr)
|
||||||
|
|
@ -90,18 +98,20 @@ when not defined(js):
|
||||||
template `rawType=`(x: var Any, p: PNimType) =
|
template `rawType=`(x: var Any, p: PNimType) =
|
||||||
x.rawTypePtr = cast[pointer](p)
|
x.rawTypePtr = cast[pointer](p)
|
||||||
|
|
||||||
when defined(gogc):
|
|
||||||
const GenericSeqSize = (3 * sizeof(int))
|
|
||||||
else:
|
|
||||||
const GenericSeqSize = (2 * sizeof(int))
|
|
||||||
|
|
||||||
proc genericAssign(dest, src: pointer, mt: PNimType) {.importCompilerProc.}
|
proc genericAssign(dest, src: pointer, mt: PNimType) {.importCompilerProc.}
|
||||||
proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.
|
|
||||||
|
when not defined(gcDestructors):
|
||||||
|
proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.
|
||||||
|
importCompilerProc.}
|
||||||
|
proc incrSeq(seq: PGenSeq, elemSize, elemAlign: int): PGenSeq {.importCompilerProc.}
|
||||||
|
proc newObj(typ: PNimType, size: int): pointer {.importCompilerProc.}
|
||||||
|
proc newSeq(typ: PNimType, len: int): pointer {.importCompilerProc.}
|
||||||
|
proc objectInit(dest: pointer, typ: PNimType) {.importCompilerProc.}
|
||||||
|
else:
|
||||||
|
proc nimNewObj(size: int): pointer {.importCompilerProc.}
|
||||||
|
proc newSeqPayload(cap, elemSize, elemAlign: int): pointer {.importCompilerProc.}
|
||||||
|
proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {.
|
||||||
importCompilerProc.}
|
importCompilerProc.}
|
||||||
proc incrSeq(seq: PGenSeq, elemSize, elemAlign: int): PGenSeq {.importCompilerProc.}
|
|
||||||
proc newObj(typ: PNimType, size: int): pointer {.importCompilerProc.}
|
|
||||||
proc newSeq(typ: PNimType, len: int): pointer {.importCompilerProc.}
|
|
||||||
proc objectInit(dest: pointer, typ: PNimType) {.importCompilerProc.}
|
|
||||||
|
|
||||||
template `+!!`(a, b): untyped = cast[pointer](cast[ByteAddress](a) + b)
|
template `+!!`(a, b): untyped = cast[pointer](cast[ByteAddress](a) + b)
|
||||||
|
|
||||||
|
|
@ -167,18 +177,33 @@ proc baseTypeSize*(x: Any): int {.inline.} =
|
||||||
proc invokeNew*(x: Any) =
|
proc invokeNew*(x: Any) =
|
||||||
## performs ``new(x)``. `x` needs to represent a ``ref``.
|
## performs ``new(x)``. `x` needs to represent a ``ref``.
|
||||||
assert x.rawType.kind == tyRef
|
assert x.rawType.kind == tyRef
|
||||||
|
when defined(gcDestructors):
|
||||||
|
cast[ppointer](x.value)[] = nimNewObj(x.rawType.base.size)
|
||||||
|
else:
|
||||||
var z = newObj(x.rawType, x.rawType.base.size)
|
var z = newObj(x.rawType, x.rawType.base.size)
|
||||||
genericAssign(x.value, addr(z), x.rawType)
|
genericAssign(x.value, addr(z), x.rawType)
|
||||||
|
|
||||||
proc invokeNewSeq*(x: Any, len: int) =
|
proc invokeNewSeq*(x: Any, len: int) =
|
||||||
## performs ``newSeq(x, len)``. `x` needs to represent a ``seq``.
|
## performs ``newSeq(x, len)``. `x` needs to represent a ``seq``.
|
||||||
assert x.rawType.kind == tySequence
|
assert x.rawType.kind == tySequence
|
||||||
|
when defined(gcDestructors):
|
||||||
|
var s = cast[ptr NimSeqV2Reimpl](x.value)
|
||||||
|
s.len = len
|
||||||
|
let elem = x.rawType.base
|
||||||
|
s.p = cast[ptr NimSeqPayloadReimpl](newSeqPayload(len, elem.size, elem.align))
|
||||||
|
else:
|
||||||
var z = newSeq(x.rawType, len)
|
var z = newSeq(x.rawType, len)
|
||||||
genericShallowAssign(x.value, addr(z), x.rawType)
|
genericShallowAssign(x.value, addr(z), x.rawType)
|
||||||
|
|
||||||
proc extendSeq*(x: Any) =
|
proc extendSeq*(x: Any) =
|
||||||
## performs ``setLen(x, x.len+1)``. `x` needs to represent a ``seq``.
|
## performs ``setLen(x, x.len+1)``. `x` needs to represent a ``seq``.
|
||||||
assert x.rawType.kind == tySequence
|
assert x.rawType.kind == tySequence
|
||||||
|
when defined(gcDestructors):
|
||||||
|
var s = cast[ptr NimSeqV2Reimpl](x.value)
|
||||||
|
let elem = x.rawType.base
|
||||||
|
s.p = cast[ptr NimSeqPayloadReimpl](prepareSeqAdd(s.len, s.p, 1, elem.size, elem.align))
|
||||||
|
inc s.len
|
||||||
|
else:
|
||||||
var y = cast[ptr PGenSeq](x.value)[]
|
var y = cast[ptr PGenSeq](x.value)[]
|
||||||
var z = incrSeq(y, x.rawType.base.size, x.rawType.base.align)
|
var z = incrSeq(y, x.rawType.base.size, x.rawType.base.align)
|
||||||
# 'incrSeq' already freed the memory for us and copied over the RC!
|
# 'incrSeq' already freed the memory for us and copied over the RC!
|
||||||
|
|
@ -189,6 +214,9 @@ proc extendSeq*(x: Any) =
|
||||||
proc setObjectRuntimeType*(x: Any) =
|
proc setObjectRuntimeType*(x: Any) =
|
||||||
## this needs to be called to set `x`'s runtime object type field.
|
## this needs to be called to set `x`'s runtime object type field.
|
||||||
assert x.rawType.kind == tyObject
|
assert x.rawType.kind == tyObject
|
||||||
|
when defined(gcDestructors):
|
||||||
|
cast[ppointer](x.value)[] = x.rawType.typeInfoV2
|
||||||
|
else:
|
||||||
objectInit(x.value, x.rawType)
|
objectInit(x.value, x.rawType)
|
||||||
|
|
||||||
proc skipRange(x: PNimType): PNimType {.inline.} =
|
proc skipRange(x: PNimType): PNimType {.inline.} =
|
||||||
|
|
@ -202,14 +230,23 @@ proc `[]`*(x: Any, i: int): Any =
|
||||||
## accessor for an any `x` that represents an array or a sequence.
|
## accessor for an any `x` that represents an array or a sequence.
|
||||||
case x.rawType.kind
|
case x.rawType.kind
|
||||||
of tyArray:
|
of tyArray:
|
||||||
var bs = x.rawType.base.size
|
let bs = x.rawType.base.size
|
||||||
if i >=% x.rawType.size div bs:
|
if i >=% x.rawType.size div bs:
|
||||||
raise newException(IndexDefect, formatErrorIndexBound(i, x.rawType.size div bs))
|
raise newException(IndexDefect, formatErrorIndexBound(i, x.rawType.size div bs))
|
||||||
return newAny(x.value +!! i*bs, x.rawType.base)
|
return newAny(x.value +!! i*bs, x.rawType.base)
|
||||||
of tySequence:
|
of tySequence:
|
||||||
|
when defined(gcDestructors):
|
||||||
|
var s = cast[ptr NimSeqV2Reimpl](x.value)
|
||||||
|
if i >=% s.len:
|
||||||
|
raise newException(IndexDefect, formatErrorIndexBound(i, s.len-1))
|
||||||
|
let bs = x.rawType.base.size
|
||||||
|
let ba = x.rawType.base.align
|
||||||
|
let headerSize = align(sizeof(int), ba)
|
||||||
|
return newAny(s.p +!! (headerSize+i*bs), x.rawType.base)
|
||||||
|
else:
|
||||||
var s = cast[ppointer](x.value)[]
|
var s = cast[ppointer](x.value)[]
|
||||||
if s == nil: raise newException(ValueError, "sequence is nil")
|
if s == nil: raise newException(ValueError, "sequence is nil")
|
||||||
var bs = x.rawType.base.size
|
let bs = x.rawType.base.size
|
||||||
if i >=% cast[PGenSeq](s).len:
|
if i >=% cast[PGenSeq](s).len:
|
||||||
raise newException(IndexDefect, formatErrorIndexBound(i, cast[PGenSeq](s).len-1))
|
raise newException(IndexDefect, formatErrorIndexBound(i, cast[PGenSeq](s).len-1))
|
||||||
return newAny(s +!! (align(GenericSeqSize, x.rawType.base.align)+i*bs), x.rawType.base)
|
return newAny(s +!! (align(GenericSeqSize, x.rawType.base.align)+i*bs), x.rawType.base)
|
||||||
|
|
@ -225,6 +262,16 @@ proc `[]=`*(x: Any, i: int, y: Any) =
|
||||||
assert y.rawType == x.rawType.base
|
assert y.rawType == x.rawType.base
|
||||||
genericAssign(x.value +!! i*bs, y.value, y.rawType)
|
genericAssign(x.value +!! i*bs, y.value, y.rawType)
|
||||||
of tySequence:
|
of tySequence:
|
||||||
|
when defined(gcDestructors):
|
||||||
|
var s = cast[ptr NimSeqV2Reimpl](x.value)
|
||||||
|
if i >=% s.len:
|
||||||
|
raise newException(IndexDefect, formatErrorIndexBound(i, s.len-1))
|
||||||
|
let bs = x.rawType.base.size
|
||||||
|
let ba = x.rawType.base.align
|
||||||
|
let headerSize = align(sizeof(int), ba)
|
||||||
|
assert y.rawType == x.rawType.base
|
||||||
|
genericAssign(s.p +!! (headerSize+i*bs), y.value, y.rawType)
|
||||||
|
else:
|
||||||
var s = cast[ppointer](x.value)[]
|
var s = cast[ppointer](x.value)[]
|
||||||
if s == nil: raise newException(ValueError, "sequence is nil")
|
if s == nil: raise newException(ValueError, "sequence is nil")
|
||||||
var bs = x.rawType.base.size
|
var bs = x.rawType.base.size
|
||||||
|
|
@ -240,6 +287,9 @@ proc len*(x: Any): int =
|
||||||
of tyArray:
|
of tyArray:
|
||||||
result = x.rawType.size div x.rawType.base.size
|
result = x.rawType.size div x.rawType.base.size
|
||||||
of tySequence:
|
of tySequence:
|
||||||
|
when defined(gcDestructors):
|
||||||
|
result = cast[ptr NimSeqV2Reimpl](x.value).len
|
||||||
|
else:
|
||||||
let pgenSeq = cast[PGenSeq](cast[ppointer](x.value)[])
|
let pgenSeq = cast[PGenSeq](cast[ppointer](x.value)[])
|
||||||
if isNil(pgenSeq):
|
if isNil(pgenSeq):
|
||||||
result = 0
|
result = 0
|
||||||
|
|
@ -260,20 +310,26 @@ proc isNil*(x: Any): bool =
|
||||||
assert x.rawType.kind in {tyCString, tyRef, tyPtr, tyPointer, tyProc}
|
assert x.rawType.kind in {tyCString, tyRef, tyPtr, tyPointer, tyProc}
|
||||||
result = isNil(cast[ppointer](x.value)[])
|
result = isNil(cast[ppointer](x.value)[])
|
||||||
|
|
||||||
|
const
|
||||||
|
pointerLike = when defined(gcDestructors): {tyCString, tyRef, tyPtr, tyPointer, tyProc}
|
||||||
|
else: {tyString, tyCString, tyRef, tyPtr, tyPointer,
|
||||||
|
tySequence, tyProc}
|
||||||
|
|
||||||
proc getPointer*(x: Any): pointer =
|
proc getPointer*(x: Any): pointer =
|
||||||
## retrieve the pointer value out of `x`. ``x`` needs to be of kind
|
## retrieve the pointer value out of `x`. ``x`` needs to be of kind
|
||||||
## ``akString``, ``akCString``, ``akProc``, ``akRef``, ``akPtr``,
|
## ``akString``, ``akCString``, ``akProc``, ``akRef``, ``akPtr``,
|
||||||
## ``akPointer``, ``akSequence``.
|
## ``akPointer``, ``akSequence``.
|
||||||
assert x.rawType.kind in {tyString, tyCString, tyRef, tyPtr, tyPointer,
|
assert x.rawType.kind in pointerLike
|
||||||
tySequence, tyProc}
|
|
||||||
result = cast[ppointer](x.value)[]
|
result = cast[ppointer](x.value)[]
|
||||||
|
|
||||||
proc setPointer*(x: Any, y: pointer) =
|
proc setPointer*(x: Any, y: pointer) =
|
||||||
## sets the pointer value of `x`. ``x`` needs to be of kind
|
## sets the pointer value of `x`. ``x`` needs to be of kind
|
||||||
## ``akString``, ``akCString``, ``akProc``, ``akRef``, ``akPtr``,
|
## ``akString``, ``akCString``, ``akProc``, ``akRef``, ``akPtr``,
|
||||||
## ``akPointer``, ``akSequence``.
|
## ``akPointer``, ``akSequence``.
|
||||||
assert x.rawType.kind in {tyString, tyCString, tyRef, tyPtr, tyPointer,
|
assert x.rawType.kind in pointerLike
|
||||||
tySequence, tyProc}
|
when defined(gcDestructors):
|
||||||
|
genericAssign(x.value, y, x.rawType)
|
||||||
|
else:
|
||||||
cast[ppointer](x.value)[] = y
|
cast[ppointer](x.value)[] = y
|
||||||
|
|
||||||
proc fieldsAux(p: pointer, n: ptr TNimNode,
|
proc fieldsAux(p: pointer, n: ptr TNimNode,
|
||||||
|
|
@ -607,13 +663,16 @@ proc setBiggestFloat*(x: Any, y: BiggestFloat) =
|
||||||
proc getString*(x: Any): string =
|
proc getString*(x: Any): string =
|
||||||
## retrieve the string value out of `x`. `x` needs to represent a string.
|
## retrieve the string value out of `x`. `x` needs to represent a string.
|
||||||
assert x.rawType.kind == tyString
|
assert x.rawType.kind == tyString
|
||||||
|
when defined(gcDestructors):
|
||||||
|
result = cast[ptr string](x.value)[]
|
||||||
|
else:
|
||||||
if not isNil(cast[ptr pointer](x.value)[]):
|
if not isNil(cast[ptr pointer](x.value)[]):
|
||||||
result = cast[ptr string](x.value)[]
|
result = cast[ptr string](x.value)[]
|
||||||
|
|
||||||
proc setString*(x: Any, y: string) =
|
proc setString*(x: Any, y: string) =
|
||||||
## sets the string value of `x`. `x` needs to represent a string.
|
## sets the string value of `x`. `x` needs to represent a string.
|
||||||
assert x.rawType.kind == tyString
|
assert x.rawType.kind == tyString
|
||||||
cast[ptr string](x.value)[] = y
|
cast[ptr string](x.value)[] = y # also correct for gcDestructors
|
||||||
|
|
||||||
proc getCString*(x: Any): cstring =
|
proc getCString*(x: Any): cstring =
|
||||||
## retrieve the cstring value out of `x`. `x` needs to represent a cstring.
|
## retrieve the cstring value out of `x`. `x` needs to represent a cstring.
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,7 @@
|
||||||
## * `json module <json.html>`_
|
## * `json module <json.html>`_
|
||||||
|
|
||||||
const unsupportedPlatform =
|
const unsupportedPlatform =
|
||||||
when defined(nimV2): "new runtime"
|
when defined(js): "javascript"
|
||||||
elif defined(js): "javascript"
|
|
||||||
elif defined(nimscript): "nimscript"
|
elif defined(nimscript): "nimscript"
|
||||||
else: ""
|
else: ""
|
||||||
|
|
||||||
|
|
@ -60,7 +59,7 @@ when unsupportedPlatform != "":
|
||||||
{.error: "marshal module is not supported in " & unsupportedPlatform & """.
|
{.error: "marshal module is not supported in " & unsupportedPlatform & """.
|
||||||
Please use alternative packages for serialization.
|
Please use alternative packages for serialization.
|
||||||
It is possible to reimplement this module using generics and type traits.
|
It is possible to reimplement this module using generics and type traits.
|
||||||
Please contribute new implementation.""".}
|
Please contribute a new implementation.""".}
|
||||||
|
|
||||||
import streams, typeinfo, json, intsets, tables, unicode
|
import streams, typeinfo, json, intsets, tables, unicode
|
||||||
|
|
||||||
|
|
@ -345,7 +344,7 @@ proc to*[T](data: string): T =
|
||||||
|
|
||||||
|
|
||||||
when not defined(testing) and isMainModule:
|
when not defined(testing) and isMainModule:
|
||||||
template testit(x: untyped) = echo($$to[type(x)]($$x))
|
template testit(x: untyped) = echo($$to[typeof(x)]($$x))
|
||||||
|
|
||||||
var x: array[0..4, array[0..4, string]] = [
|
var x: array[0..4, array[0..4, string]] = [
|
||||||
["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"],
|
["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"],
|
||||||
|
|
|
||||||
|
|
@ -537,7 +537,7 @@ when notJSnotNims and not defined(nimSeqsV2):
|
||||||
template space(s: PGenericSeq): int {.dirty.} =
|
template space(s: PGenericSeq): int {.dirty.} =
|
||||||
s.reserved and not (seqShallowFlag or strlitFlag)
|
s.reserved and not (seqShallowFlag or strlitFlag)
|
||||||
|
|
||||||
when notJSnotNims and not defined(nimV2):
|
when notJSnotNims:
|
||||||
include "system/hti"
|
include "system/hti"
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -1718,16 +1718,16 @@ when not defined(js) and hasThreadSupport and hostOS != "standalone":
|
||||||
|
|
||||||
when not defined(js) and defined(nimV2):
|
when not defined(js) and defined(nimV2):
|
||||||
type
|
type
|
||||||
TNimNode {.compilerproc.} = object # to keep the code generator simple
|
|
||||||
DestructorProc = proc (p: pointer) {.nimcall, benign, raises: [].}
|
DestructorProc = proc (p: pointer) {.nimcall, benign, raises: [].}
|
||||||
TNimType {.compilerproc.} = object
|
TNimTypeV2 {.compilerproc.} = object
|
||||||
destructor: pointer
|
destructor: pointer
|
||||||
size: int
|
size: int
|
||||||
align: int
|
align: int
|
||||||
name: cstring
|
name: cstring
|
||||||
traceImpl: pointer
|
traceImpl: pointer
|
||||||
disposeImpl: pointer
|
disposeImpl: pointer
|
||||||
PNimType = ptr TNimType
|
typeInfoV1: pointer # for backwards compat, usually nil
|
||||||
|
PNimTypeV2 = ptr TNimTypeV2
|
||||||
|
|
||||||
when notJSnotNims and defined(nimSeqsV2):
|
when notJSnotNims and defined(nimSeqsV2):
|
||||||
include "system/strs_v2"
|
include "system/strs_v2"
|
||||||
|
|
@ -2271,7 +2271,6 @@ when notJSnotNims:
|
||||||
else:
|
else:
|
||||||
const GenericSeqSize = (2 * sizeof(int))
|
const GenericSeqSize = (2 * sizeof(int))
|
||||||
|
|
||||||
when not defined(nimV2):
|
|
||||||
proc getDiscriminant(aa: pointer, n: ptr TNimNode): uint =
|
proc getDiscriminant(aa: pointer, n: ptr TNimNode): uint =
|
||||||
sysAssert(n.kind == nkCase, "getDiscriminant: node != nkCase")
|
sysAssert(n.kind == nkCase, "getDiscriminant: node != nkCase")
|
||||||
var d: uint
|
var d: uint
|
||||||
|
|
@ -2305,8 +2304,8 @@ when notJSnotNims and hasAlloc:
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
include "system/strmantle"
|
include "system/strmantle"
|
||||||
when not usesDestructors:
|
|
||||||
include "system/assign"
|
include "system/assign"
|
||||||
|
|
||||||
when not defined(nimV2):
|
when not defined(nimV2):
|
||||||
include "system/repr"
|
include "system/repr"
|
||||||
|
|
||||||
|
|
@ -2862,7 +2861,7 @@ proc locals*(): RootObj {.magic: "Plugin", noSideEffect.} =
|
||||||
## # -> B is 1
|
## # -> B is 1
|
||||||
discard
|
discard
|
||||||
|
|
||||||
when hasAlloc and notJSnotNims and not usesDestructors:
|
when hasAlloc and notJSnotNims:
|
||||||
# XXX how to implement 'deepCopy' is an open problem.
|
# XXX how to implement 'deepCopy' is an open problem.
|
||||||
proc deepCopy*[T](x: var T, y: T) {.noSideEffect, magic: "DeepCopy".} =
|
proc deepCopy*[T](x: var T, y: T) {.noSideEffect, magic: "DeepCopy".} =
|
||||||
## Performs a deep copy of `y` and copies it into `x`.
|
## Performs a deep copy of `y` and copies it into `x`.
|
||||||
|
|
|
||||||
|
|
@ -59,12 +59,6 @@ type
|
||||||
|
|
||||||
Cell = ptr RefHeader
|
Cell = ptr RefHeader
|
||||||
|
|
||||||
template `+!`(p: pointer, s: int): pointer =
|
|
||||||
cast[pointer](cast[int](p) +% s)
|
|
||||||
|
|
||||||
template `-!`(p: pointer, s: int): pointer =
|
|
||||||
cast[pointer](cast[int](p) -% s)
|
|
||||||
|
|
||||||
template head(p: pointer): Cell =
|
template head(p: pointer): Cell =
|
||||||
cast[Cell](cast[int](p) -% sizeof(RefHeader))
|
cast[Cell](cast[int](p) -% sizeof(RefHeader))
|
||||||
|
|
||||||
|
|
@ -132,6 +126,14 @@ proc nimIncRef(p: pointer) {.compilerRtl, inl.} =
|
||||||
when traceCollector:
|
when traceCollector:
|
||||||
cprintf("[INCREF] %p\n", head(p))
|
cprintf("[INCREF] %p\n", head(p))
|
||||||
|
|
||||||
|
proc unsureAsgnRef(dest: ptr pointer, src: pointer) {.inline.} =
|
||||||
|
# This is only used by the old RTTI mechanism and we know
|
||||||
|
# that 'dest[]' is nil and needs no destruction. Which is really handy
|
||||||
|
# as we cannot destroy the object reliably if it's an object of unknown
|
||||||
|
# compile-time type.
|
||||||
|
dest[] = src
|
||||||
|
if src != nil: nimIncRef src
|
||||||
|
|
||||||
when not defined(nimscript) and defined(nimArcDebug):
|
when not defined(nimscript) and defined(nimArcDebug):
|
||||||
proc deallocatedRefId*(p: pointer): int =
|
proc deallocatedRefId*(p: pointer): int =
|
||||||
## Returns the ref's ID if the ref was already deallocated. This
|
## Returns the ref's ID if the ref was already deallocated. This
|
||||||
|
|
@ -165,10 +167,10 @@ template dispose*[T](x: owned(ref T)) = nimRawDispose(cast[pointer](x))
|
||||||
#proc dispose*(x: pointer) = nimRawDispose(x)
|
#proc dispose*(x: pointer) = nimRawDispose(x)
|
||||||
|
|
||||||
proc nimDestroyAndDispose(p: pointer) {.compilerRtl, raises: [].} =
|
proc nimDestroyAndDispose(p: pointer) {.compilerRtl, raises: [].} =
|
||||||
let d = cast[ptr PNimType](p)[].destructor
|
let d = cast[ptr PNimTypeV2](p)[].destructor
|
||||||
if d != nil: cast[DestructorProc](d)(p)
|
if d != nil: cast[DestructorProc](d)(p)
|
||||||
when false:
|
when false:
|
||||||
cstderr.rawWrite cast[ptr PNimType](p)[].name
|
cstderr.rawWrite cast[ptr PNimTypeV2](p)[].name
|
||||||
cstderr.rawWrite "\n"
|
cstderr.rawWrite "\n"
|
||||||
if d == nil:
|
if d == nil:
|
||||||
cstderr.rawWrite "bah, nil\n"
|
cstderr.rawWrite "bah, nil\n"
|
||||||
|
|
@ -226,11 +228,11 @@ template tearDownForeignThreadGc* =
|
||||||
## With ``--gc:arc`` a nop.
|
## With ``--gc:arc`` a nop.
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc isObj(obj: PNimType, subclass: cstring): bool {.compilerRtl, inl.} =
|
proc isObj(obj: PNimTypeV2, subclass: cstring): bool {.compilerRtl, inl.} =
|
||||||
proc strstr(s, sub: cstring): cstring {.header: "<string.h>", importc.}
|
proc strstr(s, sub: cstring): cstring {.header: "<string.h>", importc.}
|
||||||
|
|
||||||
result = strstr(obj.name, subclass) != nil
|
result = strstr(obj.name, subclass) != nil
|
||||||
|
|
||||||
proc chckObj(obj: PNimType, subclass: cstring) {.compilerRtl.} =
|
proc chckObj(obj: PNimTypeV2, subclass: cstring) {.compilerRtl.} =
|
||||||
# checks if obj is of type subclass:
|
# checks if obj is of type subclass:
|
||||||
if not isObj(obj, subclass): sysFatal(ObjectConversionDefect, "invalid object conversion")
|
if not isObj(obj, subclass): sysFatal(ObjectConversionDefect, "invalid object conversion")
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
include seqs_v2_reimpl
|
||||||
|
|
||||||
proc genericResetAux(dest: pointer, n: ptr TNimNode) {.benign.}
|
proc genericResetAux(dest: pointer, n: ptr TNimNode) {.benign.}
|
||||||
|
|
||||||
proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) {.benign.}
|
proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) {.benign.}
|
||||||
|
|
@ -38,6 +40,20 @@ proc genericAssignAux(dest, src: pointer, n: ptr TNimNode,
|
||||||
# echo "ugh memory corruption! ", n.kind
|
# echo "ugh memory corruption! ", n.kind
|
||||||
# quit 1
|
# quit 1
|
||||||
|
|
||||||
|
template deepSeqAssignImpl(operation, additionalArg) {.dirty.} =
|
||||||
|
var d = cast[ptr NimSeqV2Reimpl](dest)
|
||||||
|
var s = cast[ptr NimSeqV2Reimpl](src)
|
||||||
|
d.len = s.len
|
||||||
|
let elem = mt.base
|
||||||
|
d.p = cast[ptr NimSeqPayloadReimpl](newSeqPayload(s.len, elem.size, elem.align))
|
||||||
|
|
||||||
|
let bs = elem.size
|
||||||
|
let ba = elem.align
|
||||||
|
let headerSize = align(sizeof(NimSeqPayloadBase), ba)
|
||||||
|
|
||||||
|
for i in 0..d.len-1:
|
||||||
|
operation(d.p +! (headerSize+i*bs), s.p +! (headerSize+i*bs), mt.base, additionalArg)
|
||||||
|
|
||||||
proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
|
proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
|
||||||
var
|
var
|
||||||
d = cast[ByteAddress](dest)
|
d = cast[ByteAddress](dest)
|
||||||
|
|
@ -45,6 +61,11 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
|
||||||
sysAssert(mt != nil, "genericAssignAux 2")
|
sysAssert(mt != nil, "genericAssignAux 2")
|
||||||
case mt.kind
|
case mt.kind
|
||||||
of tyString:
|
of tyString:
|
||||||
|
when defined(nimSeqsV2):
|
||||||
|
var x = cast[ptr NimStringV2](dest)
|
||||||
|
var s2 = cast[ptr NimStringV2](s)[]
|
||||||
|
nimAsgnStrV2(x[], s2)
|
||||||
|
else:
|
||||||
var x = cast[PPointer](dest)
|
var x = cast[PPointer](dest)
|
||||||
var s2 = cast[PPointer](s)[]
|
var s2 = cast[PPointer](s)[]
|
||||||
if s2 == nil or shallow or (
|
if s2 == nil or shallow or (
|
||||||
|
|
@ -53,6 +74,9 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
|
||||||
else:
|
else:
|
||||||
unsureAsgnRef(x, copyString(cast[NimString](s2)))
|
unsureAsgnRef(x, copyString(cast[NimString](s2)))
|
||||||
of tySequence:
|
of tySequence:
|
||||||
|
when defined(nimSeqsV2):
|
||||||
|
deepSeqAssignImpl(genericAssignAux, shallow)
|
||||||
|
else:
|
||||||
var s2 = cast[PPointer](src)[]
|
var s2 = cast[PPointer](src)[]
|
||||||
var seq = cast[PGenericSeq](s2)
|
var seq = cast[PGenericSeq](s2)
|
||||||
var x = cast[PPointer](dest)
|
var x = cast[PPointer](dest)
|
||||||
|
|
@ -87,6 +111,11 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
|
||||||
genericAssignAux(dest, src, mt.node, shallow)
|
genericAssignAux(dest, src, mt.node, shallow)
|
||||||
# we need to copy m_type field for tyObject, as it could be empty for
|
# we need to copy m_type field for tyObject, as it could be empty for
|
||||||
# sequence reallocations:
|
# sequence reallocations:
|
||||||
|
when defined(nimSeqsV2):
|
||||||
|
var pint = cast[ptr PNimTypeV2](dest)
|
||||||
|
#chckObjAsgn(cast[ptr PNimTypeV2](src)[].typeInfoV2, mt)
|
||||||
|
pint[] = cast[PNimTypeV2](mt.typeInfoV2)
|
||||||
|
else:
|
||||||
var pint = cast[ptr PNimType](dest)
|
var pint = cast[ptr PNimType](dest)
|
||||||
# We need to copy the *static* type not the dynamic type:
|
# We need to copy the *static* type not the dynamic type:
|
||||||
# if p of TB:
|
# if p of TB:
|
||||||
|
|
@ -175,6 +204,10 @@ proc objectInit(dest: pointer, typ: PNimType) =
|
||||||
of tyObject:
|
of tyObject:
|
||||||
# iterate over any structural type
|
# iterate over any structural type
|
||||||
# here we have to init the type field:
|
# here we have to init the type field:
|
||||||
|
when defined(nimSeqsV2):
|
||||||
|
var pint = cast[ptr PNimTypeV2](dest)
|
||||||
|
pint[] = cast[PNimTypeV2](typ.typeInfoV2)
|
||||||
|
else:
|
||||||
var pint = cast[ptr PNimType](dest)
|
var pint = cast[ptr PNimType](dest)
|
||||||
pint[] = typ
|
pint[] = typ
|
||||||
objectInitAux(dest, typ.node)
|
objectInitAux(dest, typ.node)
|
||||||
|
|
@ -204,13 +237,32 @@ proc genericReset(dest: pointer, mt: PNimType) =
|
||||||
var d = cast[ByteAddress](dest)
|
var d = cast[ByteAddress](dest)
|
||||||
sysAssert(mt != nil, "genericReset 2")
|
sysAssert(mt != nil, "genericReset 2")
|
||||||
case mt.kind
|
case mt.kind
|
||||||
of tyString, tyRef, tySequence:
|
of tyRef:
|
||||||
|
unsureAsgnRef(cast[PPointer](dest), nil)
|
||||||
|
of tyString:
|
||||||
|
when defined(nimSeqsV2):
|
||||||
|
var s = cast[ptr NimStringV2](dest)
|
||||||
|
frees(s[])
|
||||||
|
zeroMem(dest, mt.size)
|
||||||
|
else:
|
||||||
|
unsureAsgnRef(cast[PPointer](dest), nil)
|
||||||
|
of tySequence:
|
||||||
|
when defined(nimSeqsV2):
|
||||||
|
var s = cast[ptr NimSeqV2Reimpl](dest)
|
||||||
|
if s.p != nil:
|
||||||
|
deallocShared(s.p)
|
||||||
|
zeroMem(dest, mt.size)
|
||||||
|
else:
|
||||||
unsureAsgnRef(cast[PPointer](dest), nil)
|
unsureAsgnRef(cast[PPointer](dest), nil)
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
genericResetAux(dest, mt.node)
|
genericResetAux(dest, mt.node)
|
||||||
of tyObject:
|
of tyObject:
|
||||||
genericResetAux(dest, mt.node)
|
genericResetAux(dest, mt.node)
|
||||||
# also reset the type field for tyObject, for correct branch switching!
|
# also reset the type field for tyObject, for correct branch switching!
|
||||||
|
when defined(nimSeqsV2):
|
||||||
|
var pint = cast[ptr PNimTypeV2](dest)
|
||||||
|
pint[] = nil
|
||||||
|
else:
|
||||||
var pint = cast[ptr PNimType](dest)
|
var pint = cast[ptr PNimType](dest)
|
||||||
pint[] = nil
|
pint[] = nil
|
||||||
of tyArray, tyArrayConstr:
|
of tyArray, tyArrayConstr:
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,13 @@
|
||||||
# Cell seqs for cyclebreaker and cyclicrefs_v2.
|
# Cell seqs for cyclebreaker and cyclicrefs_v2.
|
||||||
|
|
||||||
type
|
type
|
||||||
CellTuple = (PT, PNimType)
|
CellTuple = (PT, PNimTypeV2)
|
||||||
CellArray = ptr UncheckedArray[CellTuple]
|
CellArray = ptr UncheckedArray[CellTuple]
|
||||||
CellSeq = object
|
CellSeq = object
|
||||||
len, cap: int
|
len, cap: int
|
||||||
d: CellArray
|
d: CellArray
|
||||||
|
|
||||||
proc add(s: var CellSeq, c: PT; t: PNimType) {.inline.} =
|
proc add(s: var CellSeq, c: PT; t: PNimTypeV2) {.inline.} =
|
||||||
if s.len >= s.cap:
|
if s.len >= s.cap:
|
||||||
s.cap = s.cap * 3 div 2
|
s.cap = s.cap * 3 div 2
|
||||||
when defined(useMalloc):
|
when defined(useMalloc):
|
||||||
|
|
@ -51,6 +51,6 @@ proc deinit(s: var CellSeq) =
|
||||||
s.len = 0
|
s.len = 0
|
||||||
s.cap = 0
|
s.cap = 0
|
||||||
|
|
||||||
proc pop(s: var CellSeq): (PT, PNimType) =
|
proc pop(s: var CellSeq): (PT, PNimTypeV2) =
|
||||||
result = s.d[s.len-1]
|
result = s.d[s.len-1]
|
||||||
dec s.len
|
dec s.len
|
||||||
|
|
|
||||||
|
|
@ -78,14 +78,14 @@ type
|
||||||
GcEnv = object
|
GcEnv = object
|
||||||
traceStack: CellSeq
|
traceStack: CellSeq
|
||||||
|
|
||||||
proc trace(p: pointer; desc: PNimType; j: var GcEnv) {.inline.} =
|
proc trace(p: pointer; desc: PNimTypeV2; j: var GcEnv) {.inline.} =
|
||||||
when false:
|
when false:
|
||||||
cprintf("[Trace] desc: %p %p\n", desc, p)
|
cprintf("[Trace] desc: %p %p\n", desc, p)
|
||||||
cprintf("[Trace] trace: %p\n", desc.traceImpl)
|
cprintf("[Trace] trace: %p\n", desc.traceImpl)
|
||||||
if desc.traceImpl != nil:
|
if desc.traceImpl != nil:
|
||||||
cast[TraceProc](desc.traceImpl)(p, addr(j))
|
cast[TraceProc](desc.traceImpl)(p, addr(j))
|
||||||
|
|
||||||
proc nimTraceRef(q: pointer; desc: PNimType; env: pointer) {.compilerRtl.} =
|
proc nimTraceRef(q: pointer; desc: PNimTypeV2; env: pointer) {.compilerRtl.} =
|
||||||
let p = cast[ptr pointer](q)
|
let p = cast[ptr pointer](q)
|
||||||
when traceCollector:
|
when traceCollector:
|
||||||
cprintf("[Trace] raw: %p\n", p)
|
cprintf("[Trace] raw: %p\n", p)
|
||||||
|
|
@ -101,11 +101,11 @@ proc nimTraceRefDyn(q: pointer; env: pointer) {.compilerRtl.} =
|
||||||
cprintf("[TraceDyn] deref: %p\n", p[])
|
cprintf("[TraceDyn] deref: %p\n", p[])
|
||||||
if p[] != nil:
|
if p[] != nil:
|
||||||
var j = cast[ptr GcEnv](env)
|
var j = cast[ptr GcEnv](env)
|
||||||
j.traceStack.add(p, cast[ptr PNimType](p[])[])
|
j.traceStack.add(p, cast[ptr PNimTypeV2](p[])[])
|
||||||
|
|
||||||
var markerGeneration: int
|
var markerGeneration: int
|
||||||
|
|
||||||
proc breakCycles(s: Cell; desc: PNimType) =
|
proc breakCycles(s: Cell; desc: PNimTypeV2) =
|
||||||
let markerColor = if (markerGeneration and 1) == 0: colRed
|
let markerColor = if (markerGeneration and 1) == 0: colRed
|
||||||
else: colYellow
|
else: colYellow
|
||||||
atomicInc markerGeneration
|
atomicInc markerGeneration
|
||||||
|
|
@ -147,7 +147,7 @@ proc thinout*[T](x: ref T) {.inline.} =
|
||||||
## and thus would keep the graph from being freed are `nil`'ed.
|
## and thus would keep the graph from being freed are `nil`'ed.
|
||||||
## This is a form of cycle collection that works well with Nim's ARC
|
## This is a form of cycle collection that works well with Nim's ARC
|
||||||
## and its associated cost model.
|
## and its associated cost model.
|
||||||
proc getDynamicTypeInfo[T](x: T): PNimType {.magic: "GetTypeInfo", noSideEffect, locks: 0.}
|
proc getDynamicTypeInfo[T](x: T): PNimTypeV2 {.magic: "GetTypeInfoV2", noSideEffect, locks: 0.}
|
||||||
|
|
||||||
breakCycles(head(cast[pointer](x)), getDynamicTypeInfo(x[]))
|
breakCycles(head(cast[pointer](x)), getDynamicTypeInfo(x[]))
|
||||||
|
|
||||||
|
|
@ -158,7 +158,7 @@ proc thinout*[T: proc](x: T) {.inline.} =
|
||||||
""".}
|
""".}
|
||||||
|
|
||||||
let p = rawEnv(x)
|
let p = rawEnv(x)
|
||||||
breakCycles(head(p), cast[ptr PNimType](p)[])
|
breakCycles(head(p), cast[ptr PNimTypeV2](p)[])
|
||||||
|
|
||||||
proc nimDecRefIsLastCyclicDyn(p: pointer): bool {.compilerRtl, inl.} =
|
proc nimDecRefIsLastCyclicDyn(p: pointer): bool {.compilerRtl, inl.} =
|
||||||
if p != nil:
|
if p != nil:
|
||||||
|
|
@ -171,7 +171,7 @@ proc nimDecRefIsLastCyclicDyn(p: pointer): bool {.compilerRtl, inl.} =
|
||||||
# According to Lins it's correct to do nothing else here.
|
# According to Lins it's correct to do nothing else here.
|
||||||
#cprintf("[DeCREF] %p\n", p)
|
#cprintf("[DeCREF] %p\n", p)
|
||||||
|
|
||||||
proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimType): bool {.compilerRtl, inl.} =
|
proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimTypeV2): bool {.compilerRtl, inl.} =
|
||||||
if p != nil:
|
if p != nil:
|
||||||
var cell = head(p)
|
var cell = head(p)
|
||||||
if (cell.rc and not rcMask) == 0:
|
if (cell.rc and not rcMask) == 0:
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,11 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
|
||||||
sysAssert(mt != nil, "genericDeepCopyAux 2")
|
sysAssert(mt != nil, "genericDeepCopyAux 2")
|
||||||
case mt.kind
|
case mt.kind
|
||||||
of tyString:
|
of tyString:
|
||||||
|
when defined(nimSeqsV2):
|
||||||
|
var x = cast[ptr NimStringV2](dest)
|
||||||
|
var s2 = cast[ptr NimStringV2](s)[]
|
||||||
|
nimAsgnStrV2(x[], s2)
|
||||||
|
else:
|
||||||
var x = cast[PPointer](dest)
|
var x = cast[PPointer](dest)
|
||||||
var s2 = cast[PPointer](s)[]
|
var s2 = cast[PPointer](s)[]
|
||||||
if s2 == nil:
|
if s2 == nil:
|
||||||
|
|
@ -97,6 +102,9 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
|
||||||
else:
|
else:
|
||||||
unsureAsgnRef(x, copyDeepString(cast[NimString](s2)))
|
unsureAsgnRef(x, copyDeepString(cast[NimString](s2)))
|
||||||
of tySequence:
|
of tySequence:
|
||||||
|
when defined(nimSeqsV2):
|
||||||
|
deepSeqAssignImpl(genericDeepCopyAux, tab)
|
||||||
|
else:
|
||||||
var s2 = cast[PPointer](src)[]
|
var s2 = cast[PPointer](src)[]
|
||||||
var seq = cast[PGenericSeq](s2)
|
var seq = cast[PGenericSeq](s2)
|
||||||
var x = cast[PPointer](dest)
|
var x = cast[PPointer](dest)
|
||||||
|
|
@ -151,7 +159,7 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
|
||||||
sysAssert realType == mt, " types do differ"
|
sysAssert realType == mt, " types do differ"
|
||||||
# this version should work for any possible GC:
|
# this version should work for any possible GC:
|
||||||
let typ = if mt.base.kind == tyObject: cast[ptr PNimType](s2)[] else: mt.base
|
let typ = if mt.base.kind == tyObject: cast[ptr PNimType](s2)[] else: mt.base
|
||||||
let z = newObj(mt, typ.size)
|
let z = when defined(nimSeqsV2): nimNewObj(typ.size) else: newObj(mt, typ.size)
|
||||||
unsureAsgnRef(cast[PPointer](dest), z)
|
unsureAsgnRef(cast[PPointer](dest), z)
|
||||||
tab.put(s2, z)
|
tab.put(s2, z)
|
||||||
genericDeepCopyAux(z, s2, typ, tab)
|
genericDeepCopyAux(z, s2, typ, tab)
|
||||||
|
|
@ -168,11 +176,11 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
|
||||||
copyMem(dest, src, mt.size)
|
copyMem(dest, src, mt.size)
|
||||||
|
|
||||||
proc genericDeepCopy(dest, src: pointer, mt: PNimType) {.compilerproc.} =
|
proc genericDeepCopy(dest, src: pointer, mt: PNimType) {.compilerproc.} =
|
||||||
GC_disable()
|
when not defined(nimSeqsV2): GC_disable()
|
||||||
var tab = initPtrTable()
|
var tab = initPtrTable()
|
||||||
genericDeepCopyAux(dest, src, mt, tab)
|
genericDeepCopyAux(dest, src, mt, tab)
|
||||||
deinit tab
|
deinit tab
|
||||||
GC_enable()
|
when not defined(nimSeqsV2): GC_enable()
|
||||||
|
|
||||||
proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerproc.} =
|
proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerproc.} =
|
||||||
# also invoked for 'string'
|
# also invoked for 'string'
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,8 @@ type
|
||||||
finalizer*: pointer # the finalizer for the type
|
finalizer*: pointer # the finalizer for the type
|
||||||
marker*: proc (p: pointer, op: int) {.nimcall, benign, tags: [], raises: [].} # marker proc for GC
|
marker*: proc (p: pointer, op: int) {.nimcall, benign, tags: [], raises: [].} # marker proc for GC
|
||||||
deepcopy: proc (p: pointer): pointer {.nimcall, benign, tags: [], raises: [].}
|
deepcopy: proc (p: pointer): pointer {.nimcall, benign, tags: [], raises: [].}
|
||||||
|
when defined(nimSeqsV2):
|
||||||
|
typeInfoV2*: pointer
|
||||||
when defined(nimTypeNames):
|
when defined(nimTypeNames):
|
||||||
name: cstring
|
name: cstring
|
||||||
nextType: ptr TNimType
|
nextType: ptr TNimType
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,10 @@ proc growObj(old: pointer, newsize: int): pointer =
|
||||||
proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
|
proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
|
||||||
proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
|
proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
|
||||||
|
|
||||||
proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
|
when not defined(gcDestructors):
|
||||||
|
proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
|
||||||
dest[] = src
|
dest[] = src
|
||||||
|
|
||||||
proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
|
proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
|
||||||
dest[] = src
|
dest[] = src
|
||||||
proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline,
|
proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline,
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ type
|
||||||
toFree: CellSeq
|
toFree: CellSeq
|
||||||
freed, touched: int
|
freed, touched: int
|
||||||
|
|
||||||
proc trace(s: Cell; desc: PNimType; j: var GcEnv) {.inline.} =
|
proc trace(s: Cell; desc: PNimTypeV2; j: var GcEnv) {.inline.} =
|
||||||
if desc.traceImpl != nil:
|
if desc.traceImpl != nil:
|
||||||
var p = s +! sizeof(RefHeader)
|
var p = s +! sizeof(RefHeader)
|
||||||
cast[TraceProc](desc.traceImpl)(p, addr(j))
|
cast[TraceProc](desc.traceImpl)(p, addr(j))
|
||||||
|
|
@ -65,7 +65,7 @@ else:
|
||||||
let p = s +! sizeof(RefHeader)
|
let p = s +! sizeof(RefHeader)
|
||||||
cprintf("[%s] name %s RC %ld\n", str, p, s.rc shr rcShift)
|
cprintf("[%s] name %s RC %ld\n", str, p, s.rc shr rcShift)
|
||||||
|
|
||||||
proc free(s: Cell; desc: PNimType) {.inline.} =
|
proc free(s: Cell; desc: PNimTypeV2) {.inline.} =
|
||||||
when traceCollector:
|
when traceCollector:
|
||||||
cprintf("[From ] %p rc %ld color %ld\n", s, s.rc shr rcShift, s.color)
|
cprintf("[From ] %p rc %ld color %ld\n", s, s.rc shr rcShift, s.color)
|
||||||
let p = s +! sizeof(RefHeader)
|
let p = s +! sizeof(RefHeader)
|
||||||
|
|
@ -89,7 +89,7 @@ proc free(s: Cell; desc: PNimType) {.inline.} =
|
||||||
|
|
||||||
nimRawDispose(p)
|
nimRawDispose(p)
|
||||||
|
|
||||||
proc nimTraceRef(q: pointer; desc: PNimType; env: pointer) {.compilerRtl.} =
|
proc nimTraceRef(q: pointer; desc: PNimTypeV2; env: pointer) {.compilerRtl.} =
|
||||||
let p = cast[ptr pointer](q)
|
let p = cast[ptr pointer](q)
|
||||||
if p[] != nil:
|
if p[] != nil:
|
||||||
var j = cast[ptr GcEnv](env)
|
var j = cast[ptr GcEnv](env)
|
||||||
|
|
@ -99,7 +99,7 @@ proc nimTraceRefDyn(q: pointer; env: pointer) {.compilerRtl.} =
|
||||||
let p = cast[ptr pointer](q)
|
let p = cast[ptr pointer](q)
|
||||||
if p[] != nil:
|
if p[] != nil:
|
||||||
var j = cast[ptr GcEnv](env)
|
var j = cast[ptr GcEnv](env)
|
||||||
j.traceStack.add(head p[], cast[ptr PNimType](p[])[])
|
j.traceStack.add(head p[], cast[ptr PNimTypeV2](p[])[])
|
||||||
|
|
||||||
var
|
var
|
||||||
roots {.threadvar.}: CellSeq
|
roots {.threadvar.}: CellSeq
|
||||||
|
|
@ -115,7 +115,7 @@ proc unregisterCycle(s: Cell) =
|
||||||
roots.d[idx][0].rootIdx = idx
|
roots.d[idx][0].rootIdx = idx
|
||||||
dec roots.len
|
dec roots.len
|
||||||
|
|
||||||
proc scanBlack(s: Cell; desc: PNimType; j: var GcEnv) =
|
proc scanBlack(s: Cell; desc: PNimTypeV2; j: var GcEnv) =
|
||||||
#[
|
#[
|
||||||
proc scanBlack(s: Cell) =
|
proc scanBlack(s: Cell) =
|
||||||
setColor(s, colBlack)
|
setColor(s, colBlack)
|
||||||
|
|
@ -135,7 +135,7 @@ proc scanBlack(s: Cell; desc: PNimType; j: var GcEnv) =
|
||||||
t.setColor colBlack
|
t.setColor colBlack
|
||||||
trace(t, desc, j)
|
trace(t, desc, j)
|
||||||
|
|
||||||
proc markGray(s: Cell; desc: PNimType; j: var GcEnv) =
|
proc markGray(s: Cell; desc: PNimTypeV2; j: var GcEnv) =
|
||||||
#[
|
#[
|
||||||
proc markGray(s: Cell) =
|
proc markGray(s: Cell) =
|
||||||
if s.color != colGray:
|
if s.color != colGray:
|
||||||
|
|
@ -163,7 +163,7 @@ proc markGray(s: Cell; desc: PNimType; j: var GcEnv) =
|
||||||
inc j.touched
|
inc j.touched
|
||||||
trace(t, desc, j)
|
trace(t, desc, j)
|
||||||
|
|
||||||
proc scan(s: Cell; desc: PNimType; j: var GcEnv) =
|
proc scan(s: Cell; desc: PNimTypeV2; j: var GcEnv) =
|
||||||
#[
|
#[
|
||||||
proc scan(s: Cell) =
|
proc scan(s: Cell) =
|
||||||
if s.color == colGray:
|
if s.color == colGray:
|
||||||
|
|
@ -226,7 +226,7 @@ when false:
|
||||||
cfprintf(cstderr, "%s %p root index: %ld; RC: %ld; color: %ld\n",
|
cfprintf(cstderr, "%s %p root index: %ld; RC: %ld; color: %ld\n",
|
||||||
msg, s, s.rootIdx, s.rc shr rcShift, s.color)
|
msg, s, s.rootIdx, s.rc shr rcShift, s.color)
|
||||||
|
|
||||||
proc collectWhite(s: Cell; desc: PNimType; j: var GcEnv) =
|
proc collectWhite(s: Cell; desc: PNimTypeV2; j: var GcEnv) =
|
||||||
#[
|
#[
|
||||||
proc collectWhite(s: Cell) =
|
proc collectWhite(s: Cell) =
|
||||||
if s.color == colWhite and not buffered(s):
|
if s.color == colWhite and not buffered(s):
|
||||||
|
|
@ -315,7 +315,7 @@ proc collectCycles() =
|
||||||
when false:
|
when false:
|
||||||
cfprintf(cstderr, "[collectCycles] freed %ld new threshold %ld\n", j.freed, rootsThreshold)
|
cfprintf(cstderr, "[collectCycles] freed %ld new threshold %ld\n", j.freed, rootsThreshold)
|
||||||
|
|
||||||
proc registerCycle(s: Cell; desc: PNimType) =
|
proc registerCycle(s: Cell; desc: PNimTypeV2) =
|
||||||
if roots.len >= rootsThreshold:
|
if roots.len >= rootsThreshold:
|
||||||
collectCycles()
|
collectCycles()
|
||||||
if roots.d == nil: init(roots)
|
if roots.d == nil: init(roots)
|
||||||
|
|
@ -334,7 +334,7 @@ proc GC_enableMarkAndSweep() =
|
||||||
proc GC_disableMarkAndSweep() =
|
proc GC_disableMarkAndSweep() =
|
||||||
rootsThreshold = high(int)
|
rootsThreshold = high(int)
|
||||||
|
|
||||||
proc rememberCycle(isDestroyAction: bool; s: Cell; desc: PNimType) {.noinline.} =
|
proc rememberCycle(isDestroyAction: bool; s: Cell; desc: PNimTypeV2) {.noinline.} =
|
||||||
if isDestroyAction:
|
if isDestroyAction:
|
||||||
if (s.rc and isCycleCandidate) != 0:
|
if (s.rc and isCycleCandidate) != 0:
|
||||||
s.rc = s.rc and not isCycleCandidate
|
s.rc = s.rc and not isCycleCandidate
|
||||||
|
|
@ -356,9 +356,9 @@ proc nimDecRefIsLastCyclicDyn(p: pointer): bool {.compilerRtl, inl.} =
|
||||||
else:
|
else:
|
||||||
dec cell.rc, rcIncrement
|
dec cell.rc, rcIncrement
|
||||||
#if cell.color == colPurple:
|
#if cell.color == colPurple:
|
||||||
rememberCycle(result, cell, cast[ptr PNimType](p)[])
|
rememberCycle(result, cell, cast[ptr PNimTypeV2](p)[])
|
||||||
|
|
||||||
proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimType): bool {.compilerRtl, inl.} =
|
proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimTypeV2): bool {.compilerRtl, inl.} =
|
||||||
if p != nil:
|
if p != nil:
|
||||||
var cell = head(p)
|
var cell = head(p)
|
||||||
if (cell.rc and not rcMask) == 0:
|
if (cell.rc and not rcMask) == 0:
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,8 @@ type
|
||||||
cap: int
|
cap: int
|
||||||
data: UncheckedArray[T]
|
data: UncheckedArray[T]
|
||||||
|
|
||||||
NimSeqV2*[T] = object
|
NimSeqV2*[T] = object # \
|
||||||
|
# if you change this implementation, also change seqs_v2_reimpl.nim!
|
||||||
len: int
|
len: int
|
||||||
p: ptr NimSeqPayload[T]
|
p: ptr NimSeqPayload[T]
|
||||||
|
|
||||||
|
|
@ -40,12 +41,15 @@ proc newSeqPayload(cap, elemSize, elemAlign: int): pointer {.compilerRtl, raises
|
||||||
else:
|
else:
|
||||||
result = nil
|
result = nil
|
||||||
|
|
||||||
proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {.
|
template `+!`(p: pointer, s: int): pointer =
|
||||||
noSideEffect, raises: [].} =
|
|
||||||
{.noSideEffect.}:
|
|
||||||
template `+!`(p: pointer, s: int): pointer =
|
|
||||||
cast[pointer](cast[int](p) +% s)
|
cast[pointer](cast[int](p) +% s)
|
||||||
|
|
||||||
|
template `-!`(p: pointer, s: int): pointer =
|
||||||
|
cast[pointer](cast[int](p) -% s)
|
||||||
|
|
||||||
|
proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {.
|
||||||
|
noSideEffect, raises: [], compilerRtl.} =
|
||||||
|
{.noSideEffect.}:
|
||||||
let headerSize = align(sizeof(NimSeqPayloadBase), elemAlign)
|
let headerSize = align(sizeof(NimSeqPayloadBase), elemAlign)
|
||||||
if addlen <= 0:
|
if addlen <= 0:
|
||||||
result = p
|
result = p
|
||||||
|
|
|
||||||
17
lib/system/seqs_v2_reimpl.nim
Normal file
17
lib/system/seqs_v2_reimpl.nim
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Nim's Runtime Library
|
||||||
|
# (c) Copyright 2020 Nim contributors
|
||||||
|
#
|
||||||
|
# See the file "copying.txt", included in this
|
||||||
|
# distribution, for details about the copyright.
|
||||||
|
#
|
||||||
|
|
||||||
|
type
|
||||||
|
NimSeqPayloadReimpl = object
|
||||||
|
cap: int
|
||||||
|
data: pointer
|
||||||
|
|
||||||
|
NimSeqV2Reimpl = object
|
||||||
|
len: int
|
||||||
|
p: ptr NimSeqPayloadReimpl
|
||||||
|
|
@ -14,7 +14,7 @@ joinable: false pending https://github.com/nim-lang/Nim/issues/9754
|
||||||
|
|
||||||
import marshal
|
import marshal
|
||||||
|
|
||||||
template testit(x) = discard $$to[type(x)]($$x)
|
template testit(x) = discard $$to[typeof(x)]($$x)
|
||||||
|
|
||||||
var x: array[0..4, array[0..4, string]] = [
|
var x: array[0..4, array[0..4, string]] = [
|
||||||
["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"],
|
["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"],
|
||||||
|
|
@ -89,8 +89,8 @@ var instance1 = Person(name: "Cletus", age: 12,
|
||||||
bio: "Я Cletus",
|
bio: "Я Cletus",
|
||||||
blob: "ABC\x80")
|
blob: "ABC\x80")
|
||||||
echo($$instance1)
|
echo($$instance1)
|
||||||
echo(to[Person]($$instance1).bio == instance1.bio)
|
echo(to[Person]($$instance1).bio == instance1.bio) # true
|
||||||
echo(to[Person]($$instance1).blob == instance1.blob)
|
echo(to[Person]($$instance1).blob == instance1.blob) # true
|
||||||
|
|
||||||
# bug 5757
|
# bug 5757
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue