signature hashing: more progress
This commit is contained in:
parent
72af7e6821
commit
860cbd3107
7 changed files with 301 additions and 300 deletions
|
|
@ -50,7 +50,7 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
|
||||||
of tyUInt64: result = uint64Literal(uint64(n.intVal))
|
of tyUInt64: result = uint64Literal(uint64(n.intVal))
|
||||||
else:
|
else:
|
||||||
result = "(($1) $2)" % [getTypeDesc(p.module,
|
result = "(($1) $2)" % [getTypeDesc(p.module,
|
||||||
skipTypes(ty, abstractVarRange)), intLiteral(n.intVal)]
|
ty), intLiteral(n.intVal)]
|
||||||
of nkNilLit:
|
of nkNilLit:
|
||||||
let t = skipTypes(ty, abstractVarRange)
|
let t = skipTypes(ty, abstractVarRange)
|
||||||
if t.kind == tyProc and t.callConv == ccClosure:
|
if t.kind == tyProc and t.callConv == ccClosure:
|
||||||
|
|
@ -61,7 +61,7 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
|
||||||
inc(p.module.labels)
|
inc(p.module.labels)
|
||||||
addf(p.module.s[cfsData],
|
addf(p.module.s[cfsData],
|
||||||
"static NIM_CONST $1 $2 = {NIM_NIL,NIM_NIL};$n",
|
"static NIM_CONST $1 $2 = {NIM_NIL,NIM_NIL};$n",
|
||||||
[getTypeDesc(p.module, t), result])
|
[getTypeDesc(p.module, ty), result])
|
||||||
else:
|
else:
|
||||||
result = rope("NIM_NIL")
|
result = rope("NIM_NIL")
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
|
|
@ -266,7 +266,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
# little HACK to support the new 'var T' as return type:
|
# little HACK to support the new 'var T' as return type:
|
||||||
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
||||||
return
|
return
|
||||||
var ty = skipTypes(dest.t, abstractRange)
|
let ty = skipTypes(dest.t, abstractRange)
|
||||||
case ty.kind
|
case ty.kind
|
||||||
of tyRef:
|
of tyRef:
|
||||||
genRefAssign(p, dest, src, flags)
|
genRefAssign(p, dest, src, flags)
|
||||||
|
|
@ -315,8 +315,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
genGenericAsgn(p, dest, src, flags)
|
genGenericAsgn(p, dest, src, flags)
|
||||||
elif needsComplexAssignment(ty):
|
elif needsComplexAssignment(ty):
|
||||||
if ty.sons[0].isNil and asgnComplexity(ty.n) <= 4:
|
if ty.sons[0].isNil and asgnComplexity(ty.n) <= 4:
|
||||||
discard getTypeDesc(p.module, ty)
|
discard getTypeDesc(p.module, dest.t)
|
||||||
ty = getUniqueType(ty)
|
|
||||||
internalAssert ty.n != nil
|
internalAssert ty.n != nil
|
||||||
genOptAsgnObject(p, dest, src, flags, ty.n)
|
genOptAsgnObject(p, dest, src, flags, ty.n)
|
||||||
else:
|
else:
|
||||||
|
|
@ -330,7 +329,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
useStringh(p.module)
|
useStringh(p.module)
|
||||||
linefmt(p, cpsStmts,
|
linefmt(p, cpsStmts,
|
||||||
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
|
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
|
||||||
rdLoc(dest), rdLoc(src), getTypeDesc(p.module, ty))
|
rdLoc(dest), rdLoc(src), getTypeDesc(p.module, dest.t))
|
||||||
of tyOpenArray, tyVarargs:
|
of tyOpenArray, tyVarargs:
|
||||||
# open arrays are always on the stack - really? What if a sequence is
|
# open arrays are always on the stack - really? What if a sequence is
|
||||||
# passed to an open array?
|
# passed to an open array?
|
||||||
|
|
@ -494,12 +493,12 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||||
# later via 'chckRange'
|
# later via 'chckRange'
|
||||||
let t = e.typ.skipTypes(abstractRange)
|
let t = e.typ.skipTypes(abstractRange)
|
||||||
if optOverflowCheck notin p.options:
|
if optOverflowCheck notin p.options:
|
||||||
let res = opr[m] % [getTypeDesc(p.module, t), rdLoc(a), rdLoc(b)]
|
let res = opr[m] % [getTypeDesc(p.module, e.typ), rdLoc(a), rdLoc(b)]
|
||||||
putIntoDest(p, d, e.typ, res)
|
putIntoDest(p, d, e.typ, res)
|
||||||
else:
|
else:
|
||||||
let res = binaryArithOverflowRaw(p, t, a, b,
|
let res = binaryArithOverflowRaw(p, t, a, b,
|
||||||
if t.kind == tyInt64: prc64[m] else: prc[m])
|
if t.kind == tyInt64: prc64[m] else: prc[m])
|
||||||
putIntoDest(p, d, e.typ, "($#)($#)" % [getTypeDesc(p.module, t), res])
|
putIntoDest(p, d, e.typ, "($#)($#)" % [getTypeDesc(p.module, e.typ), res])
|
||||||
|
|
||||||
proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||||
const
|
const
|
||||||
|
|
@ -700,12 +699,11 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
template inheritLocation(d: var TLoc, a: TLoc) =
|
template inheritLocation(d: var TLoc, a: TLoc) =
|
||||||
if d.k == locNone: d.s = a.s
|
if d.k == locNone: d.s = a.s
|
||||||
|
|
||||||
proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc): PType =
|
proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc) =
|
||||||
initLocExpr(p, e.sons[0], a)
|
initLocExpr(p, e.sons[0], a)
|
||||||
if e.sons[1].kind != nkSym: internalError(e.info, "genRecordFieldAux")
|
if e.sons[1].kind != nkSym: internalError(e.info, "genRecordFieldAux")
|
||||||
d.inheritLocation(a)
|
d.inheritLocation(a)
|
||||||
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
||||||
result = a.t.getUniqueType
|
|
||||||
|
|
||||||
proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
|
proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var
|
var
|
||||||
|
|
@ -714,13 +712,12 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
|
||||||
initLocExpr(p, e.sons[0], a)
|
initLocExpr(p, e.sons[0], a)
|
||||||
d.inheritLocation(a)
|
d.inheritLocation(a)
|
||||||
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
||||||
var ty = a.t.getUniqueType
|
|
||||||
var r = rdLoc(a)
|
var r = rdLoc(a)
|
||||||
case e.sons[1].kind
|
case e.sons[1].kind
|
||||||
of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal)
|
of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal)
|
||||||
else: internalError(e.info, "genTupleElem")
|
else: internalError(e.info, "genTupleElem")
|
||||||
addf(r, ".Field$1", [rope(i)])
|
addf(r, ".Field$1", [rope(i)])
|
||||||
putIntoDest(p, d, ty.sons[i], r, a.s)
|
putIntoDest(p, d, a.t.sons[i], r, a.s)
|
||||||
|
|
||||||
proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope): PSym =
|
proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope): PSym =
|
||||||
var ty = ty
|
var ty = ty
|
||||||
|
|
@ -731,14 +728,15 @@ proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope): PSym =
|
||||||
result = lookupInRecord(ty.n, field.name)
|
result = lookupInRecord(ty.n, field.name)
|
||||||
if result != nil: break
|
if result != nil: break
|
||||||
if not p.module.compileToCpp: add(r, ".Sup")
|
if not p.module.compileToCpp: add(r, ".Sup")
|
||||||
ty = getUniqueType(ty.sons[0])
|
ty = ty.sons[0]
|
||||||
if result == nil: internalError(field.info, "genCheckedRecordField")
|
if result == nil: internalError(field.info, "genCheckedRecordField")
|
||||||
|
|
||||||
proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
var ty = genRecordFieldAux(p, e, d, a)
|
genRecordFieldAux(p, e, d, a)
|
||||||
var r = rdLoc(a)
|
var r = rdLoc(a)
|
||||||
var f = e.sons[1].sym
|
var f = e.sons[1].sym
|
||||||
|
let ty = skipTypes(a.t, abstractInst)
|
||||||
if ty.kind == tyTuple:
|
if ty.kind == tyTuple:
|
||||||
# we found a unique tuple type which lacks field information
|
# we found a unique tuple type which lacks field information
|
||||||
# so we use Field$i
|
# so we use Field$i
|
||||||
|
|
@ -746,7 +744,7 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
putIntoDest(p, d, f.typ, r, a.s)
|
putIntoDest(p, d, f.typ, r, a.s)
|
||||||
else:
|
else:
|
||||||
let field = lookupFieldAgain(p, ty, f, r)
|
let field = lookupFieldAgain(p, ty, f, r)
|
||||||
if field.loc.r == nil: internalError(e.info, "genRecordField 3")
|
if field.loc.r == nil: internalError(e.info, "genRecordField 3 " & typeToString(ty))
|
||||||
addf(r, ".$1", [field.loc.r])
|
addf(r, ".$1", [field.loc.r])
|
||||||
putIntoDest(p, d, field.typ, r, a.s)
|
putIntoDest(p, d, field.typ, r, a.s)
|
||||||
#d.s = a.s
|
#d.s = a.s
|
||||||
|
|
@ -789,7 +787,8 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym;
|
||||||
proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
if optFieldCheck in p.options:
|
if optFieldCheck in p.options:
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
let ty = genRecordFieldAux(p, e.sons[0], d, a)
|
genRecordFieldAux(p, e.sons[0], d, a)
|
||||||
|
let ty = skipTypes(a.t, abstractInst)
|
||||||
var r = rdLoc(a)
|
var r = rdLoc(a)
|
||||||
let f = e.sons[0].sons[1].sym
|
let f = e.sons[0].sons[1].sym
|
||||||
let field = lookupFieldAgain(p, ty, f, r)
|
let field = lookupFieldAgain(p, ty, f, r)
|
||||||
|
|
@ -1029,10 +1028,10 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var a, b, dest: TLoc
|
var a, b, dest: TLoc
|
||||||
initLocExpr(p, e.sons[1], a)
|
initLocExpr(p, e.sons[1], a)
|
||||||
initLocExpr(p, e.sons[2], b)
|
initLocExpr(p, e.sons[2], b)
|
||||||
let bt = skipTypes(e.sons[2].typ, abstractVar)
|
let bt = skipTypes(e.sons[2].typ, {tyVar})
|
||||||
lineCg(p, cpsStmts, seqAppendPattern, [
|
lineCg(p, cpsStmts, seqAppendPattern, [
|
||||||
rdLoc(a),
|
rdLoc(a),
|
||||||
getTypeDesc(p.module, skipTypes(e.sons[1].typ, abstractVar)),
|
getTypeDesc(p.module, e.sons[1].typ),
|
||||||
getTypeDesc(p.module, bt)])
|
getTypeDesc(p.module, bt)])
|
||||||
#if bt != b.t:
|
#if bt != b.t:
|
||||||
# echo "YES ", e.info, " new: ", typeToString(bt), " old: ", typeToString(b.t)
|
# echo "YES ", e.info, " new: ", typeToString(bt), " old: ", typeToString(b.t)
|
||||||
|
|
@ -1046,16 +1045,17 @@ proc genReset(p: BProc, n: PNode) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
initLocExpr(p, n.sons[1], a)
|
initLocExpr(p, n.sons[1], a)
|
||||||
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
||||||
addrLoc(a), genTypeInfo(p.module, skipTypes(a.t, abstractVarRange)))
|
addrLoc(a), genTypeInfo(p.module, skipTypes(a.t, {tyVar})))
|
||||||
|
|
||||||
proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
|
proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
|
||||||
var sizeExpr = sizeExpr
|
var sizeExpr = sizeExpr
|
||||||
let refType = skipTypes(a.t, abstractVarRange)
|
let refType = a.t
|
||||||
var b: TLoc
|
var b: TLoc
|
||||||
initLoc(b, locExpr, a.t, OnHeap)
|
initLoc(b, locExpr, a.t, OnHeap)
|
||||||
|
let bt = refType.lastSon
|
||||||
if sizeExpr.isNil:
|
if sizeExpr.isNil:
|
||||||
sizeExpr = "sizeof($1)" %
|
sizeExpr = "sizeof($1)" %
|
||||||
[getTypeDesc(p.module, skipTypes(refType.sons[0], abstractRange))]
|
[getTypeDesc(p.module, bt)]
|
||||||
let args = [getTypeDesc(p.module, refType),
|
let args = [getTypeDesc(p.module, refType),
|
||||||
genTypeInfo(p.module, refType),
|
genTypeInfo(p.module, refType),
|
||||||
sizeExpr]
|
sizeExpr]
|
||||||
|
|
@ -1070,7 +1070,6 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
|
||||||
else:
|
else:
|
||||||
b.r = ropecg(p.module, "($1) #newObj($2, $3)", args)
|
b.r = ropecg(p.module, "($1) #newObj($2, $3)", args)
|
||||||
genAssignment(p, a, b, {}) # set the object type:
|
genAssignment(p, a, b, {}) # set the object type:
|
||||||
let bt = skipTypes(refType.sons[0], abstractRange)
|
|
||||||
genObjectInit(p, cpsStmts, bt, a, false)
|
genObjectInit(p, cpsStmts, bt, a, false)
|
||||||
|
|
||||||
proc genNew(p: BProc, e: PNode) =
|
proc genNew(p: BProc, e: PNode) =
|
||||||
|
|
@ -1122,7 +1121,7 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
|
||||||
proc genConstExpr(p: BProc, n: PNode): Rope
|
proc genConstExpr(p: BProc, n: PNode): Rope
|
||||||
proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
|
proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
|
||||||
if d.k == locNone and n.len > ord(n.kind == nkObjConstr) and n.isDeepConstExpr:
|
if d.k == locNone and n.len > ord(n.kind == nkObjConstr) and n.isDeepConstExpr:
|
||||||
var t = getUniqueType(n.typ)
|
let t = n.typ
|
||||||
discard getTypeDesc(p.module, t) # so that any fields are initialized
|
discard getTypeDesc(p.module, t) # so that any fields are initialized
|
||||||
let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels)
|
let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels)
|
||||||
fillLoc(d, locData, t, p.module.tmpBase & rope(id), OnStatic)
|
fillLoc(d, locData, t, p.module.tmpBase & rope(id), OnStatic)
|
||||||
|
|
@ -1322,7 +1321,7 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
gcUsage(e)
|
gcUsage(e)
|
||||||
|
|
||||||
proc genGetTypeInfo(p: BProc, e: PNode, d: var TLoc) =
|
proc genGetTypeInfo(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var t = skipTypes(e.sons[1].typ, abstractVarRange)
|
let t = e.sons[1].typ
|
||||||
putIntoDest(p, d, e.typ, genTypeInfo(p.module, t))
|
putIntoDest(p, d, e.typ, genTypeInfo(p.module, t))
|
||||||
|
|
||||||
proc genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) =
|
proc genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) =
|
||||||
|
|
@ -1336,7 +1335,7 @@ proc genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) =
|
||||||
proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
var a = e.sons[1]
|
var a = e.sons[1]
|
||||||
if a.kind == nkHiddenAddr: a = a.sons[0]
|
if a.kind == nkHiddenAddr: a = a.sons[0]
|
||||||
var typ = skipTypes(a.typ, abstractVar)
|
let typ = skipTypes(a.typ, abstractVar)
|
||||||
case typ.kind
|
case typ.kind
|
||||||
of tyOpenArray, tyVarargs:
|
of tyOpenArray, tyVarargs:
|
||||||
if op == mHigh: unaryExpr(p, e, d, "($1Len0-1)")
|
if op == mHigh: unaryExpr(p, e, d, "($1Len0-1)")
|
||||||
|
|
@ -1363,7 +1362,7 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
|
||||||
assert(d.k == locNone)
|
assert(d.k == locNone)
|
||||||
initLocExpr(p, e.sons[1], a)
|
initLocExpr(p, e.sons[1], a)
|
||||||
initLocExpr(p, e.sons[2], b)
|
initLocExpr(p, e.sons[2], b)
|
||||||
var t = skipTypes(e.sons[1].typ, abstractVar)
|
let t = skipTypes(e.sons[1].typ, {tyVar})
|
||||||
let setLenPattern = if not p.module.compileToCpp:
|
let setLenPattern = if not p.module.compileToCpp:
|
||||||
"$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n"
|
"$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n"
|
||||||
else:
|
else:
|
||||||
|
|
@ -1371,7 +1370,7 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
|
||||||
|
|
||||||
lineCg(p, cpsStmts, setLenPattern, [
|
lineCg(p, cpsStmts, setLenPattern, [
|
||||||
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
|
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
|
||||||
getTypeDesc(p.module, t.sons[0])])
|
getTypeDesc(p.module, t.skipTypes(abstractInst).sons[0])])
|
||||||
gcUsage(e)
|
gcUsage(e)
|
||||||
|
|
||||||
proc genSetLengthStr(p: BProc, e: PNode, d: var TLoc) =
|
proc genSetLengthStr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
|
|
@ -1562,7 +1561,7 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var tmp: TLoc
|
var tmp: TLoc
|
||||||
tmp.r = "LOC$1.source" % [lbl]
|
tmp.r = "LOC$1.source" % [lbl]
|
||||||
linefmt(p, cpsLocals, "union { $1 source; $2 dest; } LOC$3;$n",
|
linefmt(p, cpsLocals, "union { $1 source; $2 dest; } LOC$3;$n",
|
||||||
getTypeDesc(p.module, srct), getTypeDesc(p.module, destt), lbl)
|
getTypeDesc(p.module, e.sons[1].typ), getTypeDesc(p.module, e.typ), lbl)
|
||||||
tmp.k = locExpr
|
tmp.k = locExpr
|
||||||
tmp.t = srct
|
tmp.t = srct
|
||||||
tmp.s = OnStack
|
tmp.s = OnStack
|
||||||
|
|
@ -1796,7 +1795,7 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
|
proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
var rec: TLoc
|
var rec: TLoc
|
||||||
if not handleConstExpr(p, n, d):
|
if not handleConstExpr(p, n, d):
|
||||||
var t = getUniqueType(n.typ)
|
let t = n.typ
|
||||||
discard getTypeDesc(p.module, t) # so that any fields are initialized
|
discard getTypeDesc(p.module, t) # so that any fields are initialized
|
||||||
if d.k == locNone: getTemp(p, t, d)
|
if d.k == locNone: getTemp(p, t, d)
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
|
|
@ -1805,11 +1804,6 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
initLoc(rec, locExpr, it.typ, d.s)
|
initLoc(rec, locExpr, it.typ, d.s)
|
||||||
rec.r = "$1.Field$2" % [rdLoc(d), rope(i)]
|
rec.r = "$1.Field$2" % [rdLoc(d), rope(i)]
|
||||||
expr(p, it, rec)
|
expr(p, it, rec)
|
||||||
when false:
|
|
||||||
initLoc(rec, locExpr, it.typ, d.s)
|
|
||||||
if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genTupleConstr")
|
|
||||||
rec.r = "$1.$2" % [rdLoc(d), mangleRecFieldName(t.n.sons[i].sym, t)]
|
|
||||||
expr(p, it, rec)
|
|
||||||
|
|
||||||
proc isConstClosure(n: PNode): bool {.inline.} =
|
proc isConstClosure(n: PNode): bool {.inline.} =
|
||||||
result = n.sons[0].kind == nkSym and isRoutine(n.sons[0].sym) and
|
result = n.sons[0].kind == nkSym and isRoutine(n.sons[0].sym) and
|
||||||
|
|
@ -1863,7 +1857,7 @@ proc genStmtListExpr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
proc upConv(p: BProc, n: PNode, d: var TLoc) =
|
proc upConv(p: BProc, n: PNode, d: var TLoc) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
initLocExpr(p, n.sons[0], a)
|
initLocExpr(p, n.sons[0], a)
|
||||||
var dest = skipTypes(n.typ, abstractPtrs)
|
let dest = skipTypes(n.typ, abstractPtrs)
|
||||||
if optObjCheck in p.options and not isObjLackingTypeField(dest):
|
if optObjCheck in p.options and not isObjLackingTypeField(dest):
|
||||||
var r = rdLoc(a)
|
var r = rdLoc(a)
|
||||||
var nilCheck: Rope = nil
|
var nilCheck: Rope = nil
|
||||||
|
|
@ -1925,7 +1919,7 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) =
|
||||||
putIntoDest(p, d, n.typ, r, a.s)
|
putIntoDest(p, d, n.typ, r, a.s)
|
||||||
|
|
||||||
proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
|
proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
|
||||||
var t = getUniqueType(n.typ)
|
let t = n.typ
|
||||||
discard getTypeDesc(p.module, t) # so that any fields are initialized
|
discard getTypeDesc(p.module, t) # so that any fields are initialized
|
||||||
let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels)
|
let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels)
|
||||||
let tmp = p.module.tmpBase & rope(id)
|
let tmp = p.module.tmpBase & rope(id)
|
||||||
|
|
@ -2161,13 +2155,14 @@ proc genConstSeq(p: BProc, n: PNode, t: PType): Rope =
|
||||||
data.add("}")
|
data.add("}")
|
||||||
|
|
||||||
result = getTempName(p.module)
|
result = getTempName(p.module)
|
||||||
|
let base = t.skipTypes(abstractInst).sons[0]
|
||||||
|
|
||||||
appcg(p.module, cfsData,
|
appcg(p.module, cfsData,
|
||||||
"NIM_CONST struct {$n" &
|
"NIM_CONST struct {$n" &
|
||||||
" #TGenericSeq Sup;$n" &
|
" #TGenericSeq Sup;$n" &
|
||||||
" $1 data[$2];$n" &
|
" $1 data[$2];$n" &
|
||||||
"} $3 = $4;$n", [
|
"} $3 = $4;$n", [
|
||||||
getTypeDesc(p.module, t.sons[0]), n.len.rope, result, data])
|
getTypeDesc(p.module, base), n.len.rope, result, data])
|
||||||
|
|
||||||
result = "(($1)&$2)" % [getTypeDesc(p.module, t), result]
|
result = "(($1)&$2)" % [getTypeDesc(p.module, t), result]
|
||||||
|
|
||||||
|
|
@ -2182,7 +2177,7 @@ proc genConstExpr(p: BProc, n: PNode): Rope =
|
||||||
of nkBracket, nkPar, nkClosure, nkObjConstr:
|
of nkBracket, nkPar, nkClosure, nkObjConstr:
|
||||||
var t = skipTypes(n.typ, abstractInst)
|
var t = skipTypes(n.typ, abstractInst)
|
||||||
if t.kind == tySequence:
|
if t.kind == tySequence:
|
||||||
result = genConstSeq(p, n, t)
|
result = genConstSeq(p, n, n.typ)
|
||||||
else:
|
else:
|
||||||
result = genConstSimpleList(p, n)
|
result = genConstSimpleList(p, n)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, ropes, options, strutils, nimlexbase, msgs, cgendata, rodutils,
|
ast, astalgo, ropes, options, strutils, nimlexbase, msgs, cgendata, rodutils,
|
||||||
intsets, platform, llstream
|
intsets, platform, llstream, tables, sighashes
|
||||||
|
|
||||||
# Careful! Section marks need to contain a tabulator so that they cannot
|
# Careful! Section marks need to contain a tabulator so that they cannot
|
||||||
# be part of C string literals.
|
# be part of C string literals.
|
||||||
|
|
@ -69,7 +69,7 @@ proc genSectionEnd*(ps: TCProcSection): Rope =
|
||||||
if compilationCachePresent:
|
if compilationCachePresent:
|
||||||
result = rope(NimMergeEndMark & tnl)
|
result = rope(NimMergeEndMark & tnl)
|
||||||
|
|
||||||
proc writeTypeCache(a: TIdTable, s: var string) =
|
proc writeTypeCache(a: TypeCache, s: var string) =
|
||||||
var i = 0
|
var i = 0
|
||||||
for id, value in pairs(a):
|
for id, value in pairs(a):
|
||||||
if i == 10:
|
if i == 10:
|
||||||
|
|
@ -77,9 +77,9 @@ proc writeTypeCache(a: TIdTable, s: var string) =
|
||||||
s.add(tnl)
|
s.add(tnl)
|
||||||
else:
|
else:
|
||||||
s.add(' ')
|
s.add(' ')
|
||||||
encodeVInt(id, s)
|
encodeStr($id, s)
|
||||||
s.add(':')
|
s.add(':')
|
||||||
encodeStr($Rope(value), s)
|
encodeStr($value, s)
|
||||||
inc i
|
inc i
|
||||||
s.add('}')
|
s.add('}')
|
||||||
|
|
||||||
|
|
@ -103,6 +103,7 @@ proc genMergeInfo*(m: BModule): Rope =
|
||||||
writeTypeCache(m.typeCache, s)
|
writeTypeCache(m.typeCache, s)
|
||||||
s.add("declared:{")
|
s.add("declared:{")
|
||||||
writeIntSet(m.declaredThings, s)
|
writeIntSet(m.declaredThings, s)
|
||||||
|
when false:
|
||||||
s.add("typeInfo:{")
|
s.add("typeInfo:{")
|
||||||
writeIntSet(m.typeInfoMarker, s)
|
writeIntSet(m.typeInfoMarker, s)
|
||||||
s.add("labels:")
|
s.add("labels:")
|
||||||
|
|
@ -185,18 +186,17 @@ proc newFakeType(id: int): PType =
|
||||||
new(result)
|
new(result)
|
||||||
result.id = id
|
result.id = id
|
||||||
|
|
||||||
proc readTypeCache(L: var TBaseLexer, result: var TIdTable) =
|
proc readTypeCache(L: var TBaseLexer, result: var TypeCache) =
|
||||||
if ^L.bufpos != '{': internalError("ccgmerge: '{' expected")
|
if ^L.bufpos != '{': internalError("ccgmerge: '{' expected")
|
||||||
inc L.bufpos
|
inc L.bufpos
|
||||||
while ^L.bufpos != '}':
|
while ^L.bufpos != '}':
|
||||||
skipWhite(L)
|
skipWhite(L)
|
||||||
var key = decodeVInt(L.buf, L.bufpos)
|
var key = decodeStr(L.buf, L.bufpos)
|
||||||
if ^L.bufpos != ':': internalError("ccgmerge: ':' expected")
|
if ^L.bufpos != ':': internalError("ccgmerge: ':' expected")
|
||||||
inc L.bufpos
|
inc L.bufpos
|
||||||
var value = decodeStr(L.buf, L.bufpos)
|
var value = decodeStr(L.buf, L.bufpos)
|
||||||
# XXX little hack: we create a "fake" type object with the correct Id
|
# XXX implement me
|
||||||
# better would be to adapt the data structure to not even store the
|
when false:
|
||||||
# object as key, but only the Id
|
|
||||||
idTablePut(result, newFakeType(key), value.rope)
|
idTablePut(result, newFakeType(key), value.rope)
|
||||||
inc L.bufpos
|
inc L.bufpos
|
||||||
|
|
||||||
|
|
@ -220,7 +220,8 @@ proc processMergeInfo(L: var TBaseLexer, m: BModule) =
|
||||||
case k
|
case k
|
||||||
of "typeCache": readTypeCache(L, m.typeCache)
|
of "typeCache": readTypeCache(L, m.typeCache)
|
||||||
of "declared": readIntSet(L, m.declaredThings)
|
of "declared": readIntSet(L, m.declaredThings)
|
||||||
of "typeInfo": readIntSet(L, m.typeInfoMarker)
|
of "typeInfo":
|
||||||
|
when false: readIntSet(L, m.typeInfoMarker)
|
||||||
of "labels": m.labels = decodeVInt(L.buf, L.bufpos)
|
of "labels": m.labels = decodeVInt(L.buf, L.bufpos)
|
||||||
of "flags":
|
of "flags":
|
||||||
m.flags = cast[set[CodegenFlag]](decodeVInt(L.buf, L.bufpos) != 0)
|
m.flags = cast[set[CodegenFlag]](decodeVInt(L.buf, L.bufpos) != 0)
|
||||||
|
|
|
||||||
|
|
@ -43,15 +43,9 @@ proc idOrSig(m: BModule; s: PSym): Rope =
|
||||||
# signatures for exported routines are reliable enough to
|
# signatures for exported routines are reliable enough to
|
||||||
# produce a unique name and this means produced C++ is more stable wrt
|
# produce a unique name and this means produced C++ is more stable wrt
|
||||||
# Nim changes:
|
# Nim changes:
|
||||||
when false:
|
|
||||||
let h = hashType(s.typ, {considerParamNames})
|
|
||||||
if m.hashConflicts.containsOrIncl(cast[int](h)):
|
|
||||||
result = s.id
|
|
||||||
else:
|
|
||||||
result = BiggestInt(h)
|
|
||||||
result = rope($hashProc(s))
|
result = rope($hashProc(s))
|
||||||
else:
|
else:
|
||||||
result = rope s.id
|
result = "_" & rope s.id
|
||||||
|
|
||||||
proc mangleName(m: BModule; s: PSym): Rope =
|
proc mangleName(m: BModule; s: PSym): Rope =
|
||||||
result = s.loc.r
|
result = s.loc.r
|
||||||
|
|
@ -102,7 +96,6 @@ proc mangleName(m: BModule; s: PSym): Rope =
|
||||||
if keepOrigName:
|
if keepOrigName:
|
||||||
result.add "0"
|
result.add "0"
|
||||||
else:
|
else:
|
||||||
add(result, ~"_")
|
|
||||||
add(result, m.idOrSig(s))
|
add(result, m.idOrSig(s))
|
||||||
#add(result, ~"_")
|
#add(result, ~"_")
|
||||||
#add(result, rope(hashOwner(s).BiggestInt))
|
#add(result, rope(hashOwner(s).BiggestInt))
|
||||||
|
|
@ -112,24 +105,12 @@ proc typeName(typ: PType): Rope =
|
||||||
result = if typ.sym != nil: typ.sym.name.s.mangle.rope
|
result = if typ.sym != nil: typ.sym.name.s.mangle.rope
|
||||||
else: ~"TY"
|
else: ~"TY"
|
||||||
|
|
||||||
proc getTypeName(m: BModule; typ: PType): Rope =
|
proc getTypeName(m: BModule; typ: PType; sig: SigHash): Rope =
|
||||||
if typ.sym != nil and {sfImportc, sfExportc} * typ.sym.flags != {}:
|
if typ.sym != nil and {sfImportc, sfExportc} * typ.sym.flags != {}:
|
||||||
result = typ.sym.loc.r
|
result = typ.sym.loc.r
|
||||||
else:
|
else:
|
||||||
if typ.loc.r == nil:
|
if typ.loc.r == nil:
|
||||||
when false:
|
typ.loc.r = typ.typeName & $sig
|
||||||
# doesn't work yet and would require bigger rewritings
|
|
||||||
let h = hashType(typ, {considerParamNames})# and 0x0fff_ffffu32
|
|
||||||
let sig =
|
|
||||||
if m.hashConflicts.containsOrIncl(cast[int](h)) and false:
|
|
||||||
BiggestInt typ.id
|
|
||||||
else:
|
|
||||||
BiggestInt h
|
|
||||||
else:
|
|
||||||
let sig = BiggestInt typ.id
|
|
||||||
typ.loc.r = typ.typeName & sig.rope #& ("_" & m.module.name.s)
|
|
||||||
#if typ.kind != tySet:
|
|
||||||
# typ.loc.r.add "_" & m.module.name.s
|
|
||||||
result = typ.loc.r
|
result = typ.loc.r
|
||||||
if result == nil: internalError("getTypeName: " & $typ.kind)
|
if result == nil: internalError("getTypeName: " & $typ.kind)
|
||||||
|
|
||||||
|
|
@ -196,7 +177,7 @@ proc isImportedType(t: PType): bool =
|
||||||
proc isImportedCppType(t: PType): bool =
|
proc isImportedCppType(t: PType): bool =
|
||||||
result = t.sym != nil and sfInfixCall in t.sym.flags
|
result = t.sym != nil and sfInfixCall in t.sym.flags
|
||||||
|
|
||||||
proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope
|
proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope
|
||||||
proc needsComplexAssignment(typ: PType): bool =
|
proc needsComplexAssignment(typ: PType): bool =
|
||||||
result = containsGarbageCollectedRef(typ)
|
result = containsGarbageCollectedRef(typ)
|
||||||
|
|
||||||
|
|
@ -229,11 +210,11 @@ const
|
||||||
# but one can #define it to what one wants
|
# but one can #define it to what one wants
|
||||||
"N_INLINE", "N_NOINLINE", "N_FASTCALL", "N_CLOSURE", "N_NOCONV"]
|
"N_INLINE", "N_NOINLINE", "N_FASTCALL", "N_CLOSURE", "N_NOCONV"]
|
||||||
|
|
||||||
proc cacheGetType(tab: TIdTable, key: PType): Rope =
|
proc cacheGetType(tab: TypeCache; sig: SigHash): Rope =
|
||||||
# returns nil if we need to declare this type
|
# returns nil if we need to declare this type
|
||||||
# since types are now unique via the ``getUniqueType`` mechanism, this slow
|
# since types are now unique via the ``getUniqueType`` mechanism, this slow
|
||||||
# linear search is not necessary anymore:
|
# linear search is not necessary anymore:
|
||||||
result = Rope(idTableGet(tab, key))
|
result = tab.getOrDefault(sig)
|
||||||
|
|
||||||
proc getTempName(m: BModule): Rope =
|
proc getTempName(m: BModule): Rope =
|
||||||
result = m.tmpBase & rope(m.labels)
|
result = m.tmpBase & rope(m.labels)
|
||||||
|
|
@ -266,7 +247,7 @@ proc fillResult(param: PSym) =
|
||||||
|
|
||||||
proc typeNameOrLiteral(m: BModule; t: PType, literal: string): Rope =
|
proc typeNameOrLiteral(m: BModule; t: PType, literal: string): Rope =
|
||||||
if t.sym != nil and sfImportc in t.sym.flags and t.sym.magic == mNone:
|
if t.sym != nil and sfImportc in t.sym.flags and t.sym.magic == mNone:
|
||||||
result = getTypeName(m, t)
|
result = t.sym.loc.r
|
||||||
else:
|
else:
|
||||||
result = rope(literal)
|
result = rope(literal)
|
||||||
|
|
||||||
|
|
@ -299,11 +280,11 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
|
||||||
proc pushType(m: BModule, typ: PType) =
|
proc pushType(m: BModule, typ: PType) =
|
||||||
add(m.typeStack, typ)
|
add(m.typeStack, typ)
|
||||||
|
|
||||||
proc getTypePre(m: BModule, typ: PType): Rope =
|
proc getTypePre(m: BModule, typ: PType; sig: SigHash): Rope =
|
||||||
if typ == nil: result = rope("void")
|
if typ == nil: result = rope("void")
|
||||||
else:
|
else:
|
||||||
result = getSimpleTypeDesc(m, typ)
|
result = getSimpleTypeDesc(m, typ)
|
||||||
if result == nil: result = cacheGetType(m.typeCache, typ)
|
if result == nil: result = cacheGetType(m.typeCache, sig)
|
||||||
|
|
||||||
proc structOrUnion(t: PType): Rope =
|
proc structOrUnion(t: PType): Rope =
|
||||||
(if tfUnion in t.flags: rope("union") else: rope("struct"))
|
(if tfUnion in t.flags: rope("union") else: rope("struct"))
|
||||||
|
|
@ -312,42 +293,44 @@ proc getForwardStructFormat(m: BModule): string =
|
||||||
if m.compileToCpp: result = "$1 $2;$n"
|
if m.compileToCpp: result = "$1 $2;$n"
|
||||||
else: result = "typedef $1 $2 $2;$n"
|
else: result = "typedef $1 $2 $2;$n"
|
||||||
|
|
||||||
proc getTypeForward(m: BModule, typ: PType): Rope =
|
proc getTypeForward(m: BModule, typ: PType; sig: SigHash): Rope =
|
||||||
result = cacheGetType(m.forwTypeCache, typ)
|
result = cacheGetType(m.forwTypeCache, sig)
|
||||||
if result != nil: return
|
if result != nil: return
|
||||||
result = getTypePre(m, typ)
|
result = getTypePre(m, typ, sig)
|
||||||
if result != nil: return
|
if result != nil: return
|
||||||
case typ.kind
|
case typ.skipTypes(abstractInst).kind
|
||||||
of tySequence, tyTuple, tyObject:
|
of tySequence, tyTuple, tyObject:
|
||||||
result = getTypeName(m, typ)
|
result = getTypeName(m, typ, sig)
|
||||||
|
m.forwTypeCache[sig] = result
|
||||||
if not isImportedType(typ):
|
if not isImportedType(typ):
|
||||||
|
addf(m.s[cfsForwardTypes], "/* getTypeForward: $1 $2 $3 */", [rope typeToString typ,
|
||||||
|
rope typ.id, rope m.module.id])
|
||||||
addf(m.s[cfsForwardTypes], getForwardStructFormat(m),
|
addf(m.s[cfsForwardTypes], getForwardStructFormat(m),
|
||||||
[structOrUnion(typ), result])
|
[structOrUnion(typ), result])
|
||||||
idTablePut(m.forwTypeCache, typ, result)
|
doAssert m.forwTypeCache[sig] == result
|
||||||
else: internalError("getTypeForward(" & $typ.kind & ')')
|
else: internalError("getTypeForward(" & $typ.kind & ')')
|
||||||
|
|
||||||
proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): Rope =
|
proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): Rope =
|
||||||
## like getTypeDescAux but creates only a *weak* dependency. In other words
|
## like getTypeDescAux but creates only a *weak* dependency. In other words
|
||||||
## we know we only need a pointer to it so we only generate a struct forward
|
## we know we only need a pointer to it so we only generate a struct forward
|
||||||
## declaration:
|
## declaration:
|
||||||
var etB = t.skipTypes(abstractInst)
|
let etB = t.skipTypes(abstractInst)
|
||||||
case etB.kind
|
case etB.kind
|
||||||
of tyObject, tyTuple:
|
of tyObject, tyTuple:
|
||||||
if isImportedCppType(etB) and t.kind == tyGenericInst:
|
if isImportedCppType(etB) and t.kind == tyGenericInst:
|
||||||
result = getTypeDescAux(m, t, check)
|
result = getTypeDescAux(m, t, check)
|
||||||
else:
|
else:
|
||||||
let x = getUniqueType(etB)
|
result = getTypeForward(m, t, hashType(t))
|
||||||
result = getTypeForward(m, x)
|
pushType(m, t)
|
||||||
pushType(m, x)
|
|
||||||
of tySequence:
|
of tySequence:
|
||||||
let x = getUniqueType(etB)
|
result = getTypeForward(m, t, hashType(t)) & "*"
|
||||||
result = getTypeForward(m, x) & "*"
|
pushType(m, t)
|
||||||
pushType(m, x)
|
|
||||||
else:
|
else:
|
||||||
result = getTypeDescAux(m, t, check)
|
result = getTypeDescAux(m, t, check)
|
||||||
|
|
||||||
proc paramStorageLoc(param: PSym): TStorageLoc =
|
proc paramStorageLoc(param: PSym): TStorageLoc =
|
||||||
if param.typ.skipTypes({tyVar, tyTypeDesc}).kind notin {tyArray, tyOpenArray, tyVarargs, tyArrayConstr}:
|
if param.typ.skipTypes({tyVar, tyTypeDesc}).kind notin {
|
||||||
|
tyArray, tyOpenArray, tyVarargs, tyArrayConstr}:
|
||||||
result = OnStack
|
result = OnStack
|
||||||
else:
|
else:
|
||||||
result = OnUnknown
|
result = OnUnknown
|
||||||
|
|
@ -419,10 +402,6 @@ proc mangleRecFieldName(field: PSym, rectype: PType): Rope =
|
||||||
proc genRecordFieldsAux(m: BModule, n: PNode,
|
proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||||
accessExpr: Rope, rectype: PType,
|
accessExpr: Rope, rectype: PType,
|
||||||
check: var IntSet): Rope =
|
check: var IntSet): Rope =
|
||||||
var
|
|
||||||
ae, uname, sname, a: Rope
|
|
||||||
k: PNode
|
|
||||||
field: PSym
|
|
||||||
result = nil
|
result = nil
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
|
|
@ -431,17 +410,17 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
if n.sons[0].kind != nkSym: internalError(n.info, "genRecordFieldsAux")
|
if n.sons[0].kind != nkSym: internalError(n.info, "genRecordFieldsAux")
|
||||||
add(result, genRecordFieldsAux(m, n.sons[0], accessExpr, rectype, check))
|
add(result, genRecordFieldsAux(m, n.sons[0], accessExpr, rectype, check))
|
||||||
uname = rope(mangle(n.sons[0].sym.name.s) & 'U')
|
let uname = rope(mangle(n.sons[0].sym.name.s) & 'U')
|
||||||
if accessExpr != nil: ae = "$1.$2" % [accessExpr, uname]
|
let ae = if accessExpr != nil: "$1.$2" % [accessExpr, uname]
|
||||||
else: ae = uname
|
else: uname
|
||||||
var unionBody: Rope = nil
|
var unionBody: Rope = nil
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
case n.sons[i].kind
|
case n.sons[i].kind
|
||||||
of nkOfBranch, nkElse:
|
of nkOfBranch, nkElse:
|
||||||
k = lastSon(n.sons[i])
|
let k = lastSon(n.sons[i])
|
||||||
if k.kind != nkSym:
|
if k.kind != nkSym:
|
||||||
sname = "S" & rope(i)
|
let sname = "S" & rope(i)
|
||||||
a = genRecordFieldsAux(m, k, "$1.$2" % [ae, sname], rectype,
|
let a = genRecordFieldsAux(m, k, "$1.$2" % [ae, sname], rectype,
|
||||||
check)
|
check)
|
||||||
if a != nil:
|
if a != nil:
|
||||||
add(unionBody, "struct {")
|
add(unionBody, "struct {")
|
||||||
|
|
@ -453,12 +432,12 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||||
if unionBody != nil:
|
if unionBody != nil:
|
||||||
addf(result, "union{$n$1} $2;$n", [unionBody, uname])
|
addf(result, "union{$n$1} $2;$n", [unionBody, uname])
|
||||||
of nkSym:
|
of nkSym:
|
||||||
field = n.sym
|
let field = n.sym
|
||||||
if field.typ.kind == tyVoid: return
|
if field.typ.kind == tyVoid: return
|
||||||
#assert(field.ast == nil)
|
#assert(field.ast == nil)
|
||||||
sname = mangleRecFieldName(field, rectype)
|
let sname = mangleRecFieldName(field, rectype)
|
||||||
if accessExpr != nil: ae = "$1.$2" % [accessExpr, sname]
|
let ae = if accessExpr != nil: "$1.$2" % [accessExpr, sname]
|
||||||
else: ae = sname
|
else: sname
|
||||||
fillLoc(field.loc, locField, field.typ, ae, OnUnknown)
|
fillLoc(field.loc, locField, field.typ, ae, OnUnknown)
|
||||||
# for importcpp'ed objects, we only need to set field.loc, but don't
|
# for importcpp'ed objects, we only need to set field.loc, but don't
|
||||||
# have to recurse via 'getTypeDescAux'. And not doing so prevents problems
|
# have to recurse via 'getTypeDescAux'. And not doing so prevents problems
|
||||||
|
|
@ -558,24 +537,29 @@ proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
|
||||||
result = if result.kind == tyGenericInst: result.sons[1]
|
result = if result.kind == tyGenericInst: result.sons[1]
|
||||||
else: result.elemType
|
else: result.elemType
|
||||||
|
|
||||||
proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
|
const
|
||||||
|
irrelevantForBackend = {tyGenericBody, tyGenericInst, tyGenericInvocation,
|
||||||
|
tyDistinct, tyRange, tyStatic}
|
||||||
|
|
||||||
|
proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
|
||||||
# returns only the type's name
|
# returns only the type's name
|
||||||
var t = getUniqueType(typ)
|
var t = origTyp.skipTypes(irrelevantForBackend)
|
||||||
if t == nil: internalError("getTypeDescAux: t == nil")
|
|
||||||
if t.sym != nil: useHeader(m, t.sym)
|
if t.sym != nil: useHeader(m, t.sym)
|
||||||
result = getTypePre(m, t)
|
if t != origTyp and origTyp.sym != nil: useHeader(m, origTyp.sym)
|
||||||
|
let sig = hashType(origTyp)
|
||||||
|
result = getTypePre(m, t, sig)
|
||||||
if result != nil: return
|
if result != nil: return
|
||||||
if containsOrIncl(check, t.id):
|
if containsOrIncl(check, t.id):
|
||||||
if not (isImportedCppType(typ) or isImportedCppType(t)):
|
if not (isImportedCppType(origTyp) or isImportedCppType(t)):
|
||||||
internalError("cannot generate C type for: " & typeToString(typ))
|
internalError("cannot generate C type for: " & typeToString(origTyp))
|
||||||
# XXX: this BUG is hard to fix -> we need to introduce helper structs,
|
# XXX: this BUG is hard to fix -> we need to introduce helper structs,
|
||||||
# but determining when this needs to be done is hard. We should split
|
# but determining when this needs to be done is hard. We should split
|
||||||
# C type generation into an analysis and a code generation phase somehow.
|
# C type generation into an analysis and a code generation phase somehow.
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyRef, tyPtr, tyVar:
|
of tyRef, tyPtr, tyVar:
|
||||||
var star = if t.kind == tyVar and tfVarIsPtr notin typ.flags and
|
var star = if t.kind == tyVar and tfVarIsPtr notin origTyp.flags and
|
||||||
compileToCpp(m): "&" else: "*"
|
compileToCpp(m): "&" else: "*"
|
||||||
var et = typ.skipTypes(abstractInst).lastSon
|
var et = origTyp.skipTypes(abstractInst).lastSon
|
||||||
var etB = et.skipTypes(abstractInst)
|
var etB = et.skipTypes(abstractInst)
|
||||||
if etB.kind in {tyArrayConstr, tyArray, tyOpenArray, tyVarargs}:
|
if etB.kind in {tyArrayConstr, tyArray, tyOpenArray, tyVarargs}:
|
||||||
# this is correct! sets have no proper base type, so we treat
|
# this is correct! sets have no proper base type, so we treat
|
||||||
|
|
@ -589,33 +573,30 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
|
||||||
result = getTypeDescAux(m, et, check) & star
|
result = getTypeDescAux(m, et, check) & star
|
||||||
else:
|
else:
|
||||||
# no restriction! We have a forward declaration for structs
|
# no restriction! We have a forward declaration for structs
|
||||||
let x = getUniqueType(etB)
|
let name = getTypeForward(m, et, hashType et)
|
||||||
let name = getTypeForward(m, x)
|
|
||||||
result = name & star
|
result = name & star
|
||||||
idTablePut(m.typeCache, t, result)
|
m.typeCache[sig] = result
|
||||||
pushType(m, x)
|
pushType(m, et)
|
||||||
of tySequence:
|
of tySequence:
|
||||||
# no restriction! We have a forward declaration for structs
|
# no restriction! We have a forward declaration for structs
|
||||||
let x = getUniqueType(etB)
|
let name = getTypeForward(m, et, hashType et)
|
||||||
let name = getTypeForward(m, x)
|
|
||||||
result = name & "*" & star
|
result = name & "*" & star
|
||||||
idTablePut(m.typeCache, t, result)
|
m.typeCache[sig] = result
|
||||||
pushType(m, x)
|
pushType(m, et)
|
||||||
else:
|
else:
|
||||||
# else we have a strong dependency :-(
|
# else we have a strong dependency :-(
|
||||||
result = getTypeDescAux(m, et, check) & star
|
result = getTypeDescAux(m, et, check) & star
|
||||||
idTablePut(m.typeCache, t, result)
|
m.typeCache[sig] = result
|
||||||
of tyOpenArray, tyVarargs:
|
of tyOpenArray, tyVarargs:
|
||||||
result = getTypeDescWeak(m, t.sons[0], check) & "*"
|
result = getTypeDescWeak(m, t.sons[0], check) & "*"
|
||||||
idTablePut(m.typeCache, t, result)
|
m.typeCache[sig] = result
|
||||||
of tyRange, tyEnum:
|
of tyEnum:
|
||||||
let t = if t.kind == tyRange: t.lastSon else: t
|
result = cacheGetType(m.typeCache, sig)
|
||||||
result = cacheGetType(m.typeCache, t)
|
|
||||||
if result == nil:
|
if result == nil:
|
||||||
result = getTypeName(m, t)
|
result = getTypeName(m, t, sig)
|
||||||
if not (isImportedCppType(t) or
|
if not (isImportedCppType(t) or
|
||||||
(sfImportc in t.sym.flags and t.sym.magic == mNone)):
|
(sfImportc in t.sym.flags and t.sym.magic == mNone)):
|
||||||
idTablePut(m.typeCache, t, result)
|
m.typeCache[sig] = result
|
||||||
var size: int
|
var size: int
|
||||||
if firstOrd(t) < 0:
|
if firstOrd(t) < 0:
|
||||||
addf(m.s[cfsTypes], "typedef NI32 $1;$n", [result])
|
addf(m.s[cfsTypes], "typedef NI32 $1;$n", [result])
|
||||||
|
|
@ -639,8 +620,8 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
|
||||||
gDebugInfo.registerEnum(EnumDesc(size: size, owner: owner, id: t.sym.id,
|
gDebugInfo.registerEnum(EnumDesc(size: size, owner: owner, id: t.sym.id,
|
||||||
name: t.sym.name.s, values: vals))
|
name: t.sym.name.s, values: vals))
|
||||||
of tyProc:
|
of tyProc:
|
||||||
result = getTypeName(m, t)
|
result = getTypeName(m, origTyp, sig)
|
||||||
idTablePut(m.typeCache, t, result)
|
m.typeCache[sig] = result
|
||||||
var rettype, desc: Rope
|
var rettype, desc: Rope
|
||||||
genProcParams(m, t, rettype, desc, check, true, true)
|
genProcParams(m, t, rettype, desc, check, true, true)
|
||||||
if not isImportedType(t):
|
if not isImportedType(t):
|
||||||
|
|
@ -655,15 +636,15 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
|
||||||
of tySequence:
|
of tySequence:
|
||||||
# we cannot use getTypeForward here because then t would be associated
|
# we cannot use getTypeForward here because then t would be associated
|
||||||
# with the name of the struct, not with the pointer to the struct:
|
# with the name of the struct, not with the pointer to the struct:
|
||||||
result = cacheGetType(m.forwTypeCache, t)
|
result = cacheGetType(m.forwTypeCache, sig)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
result = getTypeName(m, t)
|
result = getTypeName(m, origTyp, sig)
|
||||||
if not isImportedType(t):
|
if not isImportedType(t):
|
||||||
addf(m.s[cfsForwardTypes], getForwardStructFormat(m),
|
addf(m.s[cfsForwardTypes], getForwardStructFormat(m),
|
||||||
[structOrUnion(t), result])
|
[structOrUnion(t), result])
|
||||||
idTablePut(m.forwTypeCache, t, result)
|
m.forwTypeCache[sig] = result
|
||||||
assert(cacheGetType(m.typeCache, t) == nil)
|
assert(cacheGetType(m.typeCache, sig) == nil)
|
||||||
idTablePut(m.typeCache, t, result & "*")
|
m.typeCache[sig] = result & "*"
|
||||||
if not isImportedType(t):
|
if not isImportedType(t):
|
||||||
if skipTypes(t.sons[0], typedescInst).kind != tyEmpty:
|
if skipTypes(t.sons[0], typedescInst).kind != tyEmpty:
|
||||||
const
|
const
|
||||||
|
|
@ -677,20 +658,20 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
|
||||||
else:
|
else:
|
||||||
result = rope("TGenericSeq")
|
result = rope("TGenericSeq")
|
||||||
add(result, "*")
|
add(result, "*")
|
||||||
of tyArrayConstr, tyArray:
|
of tyArray:
|
||||||
var n: BiggestInt = lengthOrd(t)
|
var n: BiggestInt = lengthOrd(t)
|
||||||
if n <= 0: n = 1 # make an array of at least one element
|
if n <= 0: n = 1 # make an array of at least one element
|
||||||
result = getTypeName(m, t)
|
result = getTypeName(m, origTyp, sig)
|
||||||
idTablePut(m.typeCache, t, result)
|
m.typeCache[sig] = result
|
||||||
if not isImportedType(t):
|
if not isImportedType(t):
|
||||||
let foo = getTypeDescAux(m, t.sons[1], check)
|
let foo = getTypeDescAux(m, t.sons[1], check)
|
||||||
addf(m.s[cfsTypes], "typedef $1 $2[$3];$n",
|
addf(m.s[cfsTypes], "typedef $1 $2[$3];$n",
|
||||||
[foo, result, rope(n)])
|
[foo, result, rope(n)])
|
||||||
of tyObject, tyTuple:
|
of tyObject, tyTuple:
|
||||||
if isImportedCppType(t) and typ.kind == tyGenericInst:
|
if isImportedCppType(t) and origTyp.kind == tyGenericInst:
|
||||||
# for instantiated templates we do not go through the type cache as the
|
# for instantiated templates we do not go through the type cache as the
|
||||||
# the type cache is not aware of 'tyGenericInst'.
|
# the type cache is not aware of 'tyGenericInst'.
|
||||||
let cppName = getTypeName(m, t)
|
let cppName = getTypeName(m, t, sig)
|
||||||
var i = 0
|
var i = 0
|
||||||
var chunkStart = 0
|
var chunkStart = 0
|
||||||
while i < cppName.data.len:
|
while i < cppName.data.len:
|
||||||
|
|
@ -701,7 +682,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
|
||||||
result.add cppName.data.substr(chunkStart, chunkEnd)
|
result.add cppName.data.substr(chunkStart, chunkEnd)
|
||||||
chunkStart = i
|
chunkStart = i
|
||||||
|
|
||||||
let typeInSlot = resolveStarsInCppType(typ, idx + 1, stars)
|
let typeInSlot = resolveStarsInCppType(origTyp, idx + 1, stars)
|
||||||
if typeInSlot == nil or typeInSlot.kind == tyVoid:
|
if typeInSlot == nil or typeInSlot.kind == tyVoid:
|
||||||
result.add(~"void")
|
result.add(~"void")
|
||||||
else:
|
else:
|
||||||
|
|
@ -713,28 +694,44 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
|
||||||
result.add cppName.data.substr(chunkStart)
|
result.add cppName.data.substr(chunkStart)
|
||||||
else:
|
else:
|
||||||
result = cppName & "<"
|
result = cppName & "<"
|
||||||
for i in 1 .. typ.len-2:
|
for i in 1 .. origTyp.len-2:
|
||||||
if i > 1: result.add(" COMMA ")
|
if i > 1: result.add(" COMMA ")
|
||||||
result.add(getTypeDescAux(m, typ.sons[i], check))
|
result.add(getTypeDescAux(m, origTyp.sons[i], check))
|
||||||
result.add("> ")
|
result.add("> ")
|
||||||
# always call for sideeffects:
|
# always call for sideeffects:
|
||||||
assert t.kind != tyTuple
|
assert t.kind != tyTuple
|
||||||
discard getRecordDesc(m, t, result, check)
|
discard getRecordDesc(m, t, result, check)
|
||||||
else:
|
else:
|
||||||
result = cacheGetType(m.forwTypeCache, t)
|
when false:
|
||||||
|
if t.sym != nil and t.sym.name.s == "KeyValuePair":
|
||||||
|
if t == origTyp:
|
||||||
|
echo "wtf: came here"
|
||||||
|
writeStackTrace()
|
||||||
|
quit 1
|
||||||
|
result = cacheGetType(m.forwTypeCache, sig)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
result = getTypeName(m, t)
|
when false:
|
||||||
|
if t.sym != nil and t.sym.name.s == "KeyValuePair":
|
||||||
|
# or {sfImportc, sfExportc} * t.sym.flags == {}:
|
||||||
|
if t.loc.r != nil:
|
||||||
|
echo t.kind, " ", hashType t
|
||||||
|
echo origTyp.kind, " ", sig
|
||||||
|
assert t.loc.r == nil
|
||||||
|
result = getTypeName(m, origTyp, sig)
|
||||||
|
m.forwTypeCache[sig] = result
|
||||||
if not isImportedType(t):
|
if not isImportedType(t):
|
||||||
|
addf(m.s[cfsForwardTypes], "/* tyObject: $1 $2 $3 */", [rope typeToString t,
|
||||||
|
rope t.id, rope m.module.id])
|
||||||
addf(m.s[cfsForwardTypes], getForwardStructFormat(m),
|
addf(m.s[cfsForwardTypes], getForwardStructFormat(m),
|
||||||
[structOrUnion(t), result])
|
[structOrUnion(t), result])
|
||||||
idTablePut(m.forwTypeCache, t, result)
|
doAssert m.forwTypeCache[sig] == result
|
||||||
idTablePut(m.typeCache, t, result) # always call for sideeffects:
|
m.typeCache[sig] = result # always call for sideeffects:
|
||||||
let recdesc = if t.kind != tyTuple: getRecordDesc(m, t, result, check)
|
let recdesc = if t.kind != tyTuple: getRecordDesc(m, t, result, check)
|
||||||
else: getTupleDesc(m, t, result, check)
|
else: getTupleDesc(m, t, result, check)
|
||||||
if not isImportedType(t): add(m.s[cfsTypes], recdesc)
|
if not isImportedType(t): add(m.s[cfsTypes], recdesc)
|
||||||
of tySet:
|
of tySet:
|
||||||
result = getTypeName(m, t.lastSon) & "Set"
|
result = getTypeName(m, t.lastSon, hashType t.lastSon) & "Set"
|
||||||
idTablePut(m.typeCache, t, result)
|
m.typeCache[sig] = result
|
||||||
if not isImportedType(t):
|
if not isImportedType(t):
|
||||||
let s = int(getSize(t))
|
let s = int(getSize(t))
|
||||||
case s
|
case s
|
||||||
|
|
@ -822,8 +819,7 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType; name, base: Rope) =
|
||||||
|
|
||||||
var size: Rope
|
var size: Rope
|
||||||
if tfIncompleteStruct in typ.flags: size = rope"void*"
|
if tfIncompleteStruct in typ.flags: size = rope"void*"
|
||||||
elif m.compileToCpp: size = getTypeDesc(m, origType)
|
else: size = getTypeDesc(m, origType)
|
||||||
else: size = getTypeDesc(m, typ)
|
|
||||||
addf(m.s[cfsTypeInit3],
|
addf(m.s[cfsTypeInit3],
|
||||||
"$1.size = sizeof($2);$n" & "$1.kind = $3;$n" & "$1.base = $4;$n",
|
"$1.size = sizeof($2);$n" & "$1.kind = $3;$n" & "$1.base = $4;$n",
|
||||||
[name, size, rope(nimtypeKind), base])
|
[name, size, rope(nimtypeKind), base])
|
||||||
|
|
@ -855,26 +851,26 @@ proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): Rope =
|
||||||
objtype = objtype.sons[0]
|
objtype = objtype.sons[0]
|
||||||
if objtype.sym == nil:
|
if objtype.sym == nil:
|
||||||
internalError(d.info, "anonymous obj with discriminator")
|
internalError(d.info, "anonymous obj with discriminator")
|
||||||
result = "NimDT_$1_$2" % [rope(objtype.id), rope(d.name.s.mangle)]
|
result = "NimDT_$1_$2" % [rope($hashType(objtype)), rope(d.name.s.mangle)]
|
||||||
|
|
||||||
proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): Rope =
|
proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): Rope =
|
||||||
discard cgsym(m, "TNimNode")
|
discard cgsym(m, "TNimNode")
|
||||||
var tmp = discriminatorTableName(m, objtype, d)
|
var tmp = discriminatorTableName(m, objtype, d)
|
||||||
result = "TNimNode* $1[$2];$n" % [tmp, rope(lengthOrd(d.typ)+1)]
|
result = "TNimNode* $1[$2];$n" % [tmp, rope(lengthOrd(d.typ)+1)]
|
||||||
|
|
||||||
proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: Rope) =
|
proc genObjectFields(m: BModule, typ, origType: PType, n: PNode, expr: Rope) =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
var L = sonsLen(n)
|
var L = sonsLen(n)
|
||||||
if L == 1:
|
if L == 1:
|
||||||
genObjectFields(m, typ, n.sons[0], expr)
|
genObjectFields(m, typ, origType, n.sons[0], expr)
|
||||||
elif L > 0:
|
elif L > 0:
|
||||||
var tmp = getTempName(m)
|
var tmp = getTempName(m)
|
||||||
addf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", [tmp, rope(L)])
|
addf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", [tmp, rope(L)])
|
||||||
for i in countup(0, L-1):
|
for i in countup(0, L-1):
|
||||||
var tmp2 = getNimNode(m)
|
var tmp2 = getNimNode(m)
|
||||||
addf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, rope(i), tmp2])
|
addf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, rope(i), tmp2])
|
||||||
genObjectFields(m, typ, n.sons[i], tmp2)
|
genObjectFields(m, typ, origType, n.sons[i], tmp2)
|
||||||
addf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
|
addf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
|
||||||
[expr, rope(L), tmp])
|
[expr, rope(L), tmp])
|
||||||
else:
|
else:
|
||||||
|
|
@ -888,7 +884,7 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: Rope) =
|
||||||
addf(m.s[cfsTypeInit3], "$1.kind = 3;$n" &
|
addf(m.s[cfsTypeInit3], "$1.kind = 3;$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" & "$1.sons = &$6[0];$n" &
|
"$1.name = $5;$n" & "$1.sons = &$6[0];$n" &
|
||||||
"$1.len = $7;$n", [expr, getTypeDesc(m, typ), field.loc.r,
|
"$1.len = $7;$n", [expr, getTypeDesc(m, origType), field.loc.r,
|
||||||
genTypeInfo(m, field.typ),
|
genTypeInfo(m, field.typ),
|
||||||
makeCString(field.name.s),
|
makeCString(field.name.s),
|
||||||
tmp, rope(L)])
|
tmp, rope(L)])
|
||||||
|
|
@ -896,7 +892,7 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: Rope) =
|
||||||
for i in countup(1, sonsLen(n)-1):
|
for i in countup(1, sonsLen(n)-1):
|
||||||
var b = n.sons[i] # branch
|
var b = n.sons[i] # branch
|
||||||
var tmp2 = getNimNode(m)
|
var tmp2 = getNimNode(m)
|
||||||
genObjectFields(m, typ, lastSon(b), tmp2)
|
genObjectFields(m, typ, origType, lastSon(b), tmp2)
|
||||||
case b.kind
|
case b.kind
|
||||||
of nkOfBranch:
|
of nkOfBranch:
|
||||||
if sonsLen(b) < 2:
|
if sonsLen(b) < 2:
|
||||||
|
|
@ -920,7 +916,7 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: Rope) =
|
||||||
if field.bitsize == 0:
|
if field.bitsize == 0:
|
||||||
addf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
|
addf(m.s[cfsTypeInit3], "$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, typ),
|
"$1.name = $5;$n", [expr, getTypeDesc(m, origType),
|
||||||
field.loc.r, genTypeInfo(m, field.typ), makeCString(field.name.s)])
|
field.loc.r, genTypeInfo(m, field.typ), makeCString(field.name.s)])
|
||||||
else: internalError(n.info, "genObjectFields")
|
else: internalError(n.info, "genObjectFields")
|
||||||
|
|
||||||
|
|
@ -929,7 +925,7 @@ proc genObjectInfo(m: BModule, typ, origType: PType, name: Rope) =
|
||||||
else: genTypeInfoAuxBase(m, typ, origType, name, rope("0"))
|
else: genTypeInfoAuxBase(m, typ, origType, name, rope("0"))
|
||||||
var tmp = getNimNode(m)
|
var tmp = getNimNode(m)
|
||||||
if not isImportedCppType(typ):
|
if not isImportedCppType(typ):
|
||||||
genObjectFields(m, typ, typ.n, tmp)
|
genObjectFields(m, typ, origType, typ.n, tmp)
|
||||||
addf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [name, tmp])
|
addf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [name, tmp])
|
||||||
var t = typ.sons[0]
|
var t = typ.sons[0]
|
||||||
while t != nil:
|
while t != nil:
|
||||||
|
|
@ -937,7 +933,7 @@ proc genObjectInfo(m: BModule, typ, origType: PType, name: Rope) =
|
||||||
t.flags.incl tfObjHasKids
|
t.flags.incl tfObjHasKids
|
||||||
t = t.sons[0]
|
t = t.sons[0]
|
||||||
|
|
||||||
proc genTupleInfo(m: BModule, typ: PType, name: Rope) =
|
proc genTupleInfo(m: BModule, typ, origType: PType, name: Rope) =
|
||||||
genTypeInfoAuxBase(m, typ, typ, name, rope("0"))
|
genTypeInfoAuxBase(m, typ, typ, name, rope("0"))
|
||||||
var expr = getNimNode(m)
|
var expr = getNimNode(m)
|
||||||
var length = sonsLen(typ)
|
var length = sonsLen(typ)
|
||||||
|
|
@ -952,7 +948,7 @@ proc genTupleInfo(m: BModule, typ: PType, name: Rope) =
|
||||||
"$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, typ), rope(i), genTypeInfo(m, a)])
|
[tmp2, getTypeDesc(m, origType), rope(i), genTypeInfo(m, a)])
|
||||||
addf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
|
addf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
|
||||||
[expr, rope(length), tmp])
|
[expr, rope(length), tmp])
|
||||||
else:
|
else:
|
||||||
|
|
@ -1034,27 +1030,20 @@ proc genDeepCopyProc(m: BModule; s: PSym; result: Rope) =
|
||||||
|
|
||||||
proc genTypeInfo(m: BModule, t: PType): Rope =
|
proc genTypeInfo(m: BModule, t: PType): Rope =
|
||||||
let origType = t
|
let origType = t
|
||||||
var t = getUniqueType(t)
|
var t = skipTypes(origType, irrelevantForBackend)
|
||||||
|
|
||||||
when false:
|
let sig = hashType(origType)
|
||||||
let h = hashType(t, {considerParamNames})
|
result = m.typeInfoMarker.getOrDefault(sig)
|
||||||
let tid = if m.hashConflicts.containsOrIncl(cast[int](h)):
|
if result != nil:
|
||||||
BiggestInt t.id
|
|
||||||
else:
|
|
||||||
BiggestInt h
|
|
||||||
else:
|
|
||||||
let tid = t.id
|
|
||||||
|
|
||||||
result = "NTI$1" % [rope(tid)]
|
|
||||||
if containsOrIncl(m.typeInfoMarker, t.id):
|
|
||||||
return "(&".rope & result & ")".rope
|
return "(&".rope & result & ")".rope
|
||||||
|
|
||||||
# getUniqueType doesn't skip tyDistinct when that has an overriden operation:
|
result = "NTI$1" % [rope($sig)]
|
||||||
while t.kind == tyDistinct: t = t.lastSon
|
m.typeInfoMarker[sig] = result
|
||||||
|
|
||||||
let owner = t.skipTypes(typedescPtrs).owner.getModule
|
let owner = t.skipTypes(typedescPtrs).owner.getModule
|
||||||
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
|
||||||
discard genTypeInfo(owner.bmod, t)
|
discard genTypeInfo(owner.bmod, origType)
|
||||||
# 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")
|
||||||
|
|
@ -1072,7 +1061,8 @@ proc genTypeInfo(m: BModule, t: PType): Rope =
|
||||||
if t.callConv != ccClosure:
|
if t.callConv != ccClosure:
|
||||||
genTypeInfoAuxBase(m, t, t, result, rope"0")
|
genTypeInfoAuxBase(m, t, t, result, rope"0")
|
||||||
else:
|
else:
|
||||||
genTupleInfo(m, fakeClosureType(t.owner), result)
|
let x = fakeClosureType(t.owner)
|
||||||
|
genTupleInfo(m, x, x, result)
|
||||||
of tySequence, tyRef:
|
of tySequence, tyRef:
|
||||||
genTypeInfoAux(m, t, t, result)
|
genTypeInfoAux(m, t, t, result)
|
||||||
if gSelectedGC >= gcMarkAndSweep:
|
if gSelectedGC >= gcMarkAndSweep:
|
||||||
|
|
@ -1088,7 +1078,7 @@ proc genTypeInfo(m: BModule, t: PType): Rope =
|
||||||
# else:
|
# else:
|
||||||
# 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, result)
|
genTupleInfo(m, t, origType, result)
|
||||||
else: internalError("genTypeInfo(" & $t.kind & ')')
|
else: internalError("genTypeInfo(" & $t.kind & ')')
|
||||||
if t.deepCopy != nil:
|
if t.deepCopy != nil:
|
||||||
genDeepCopyProc(m, t.deepCopy, result)
|
genDeepCopyProc(m, t.deepCopy, result)
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,8 @@ proc slowSearch(key: PType; k: TTypeKind): PType =
|
||||||
|
|
||||||
proc getUniqueType*(key: PType): PType =
|
proc getUniqueType*(key: PType): PType =
|
||||||
# this is a hotspot in the compiler!
|
# this is a hotspot in the compiler!
|
||||||
|
result = key
|
||||||
|
when false:
|
||||||
if key == nil: return
|
if key == nil: return
|
||||||
var k = key.kind
|
var k = key.kind
|
||||||
case k
|
case k
|
||||||
|
|
@ -155,18 +157,6 @@ proc getUniqueType*(key: PType): PType =
|
||||||
result = slowSearch(key, k)
|
result = slowSearch(key, k)
|
||||||
of tyUnused, tyUnused0, tyUnused1, tyUnused2: internalError("getUniqueType")
|
of tyUnused, tyUnused0, tyUnused1, tyUnused2: internalError("getUniqueType")
|
||||||
|
|
||||||
proc tableGetType*(tab: TIdTable, key: PType): RootRef =
|
|
||||||
# returns nil if we need to declare this type
|
|
||||||
result = idTableGet(tab, key)
|
|
||||||
if (result == nil) and (tab.counter > 0):
|
|
||||||
# we have to do a slow linear search because types may need
|
|
||||||
# to be compared by their structure:
|
|
||||||
for h in countup(0, high(tab.data)):
|
|
||||||
var t = PType(tab.data[h].key)
|
|
||||||
if t != nil:
|
|
||||||
if sameType(t, key):
|
|
||||||
return tab.data[h].val
|
|
||||||
|
|
||||||
proc makeSingleLineCString*(s: string): string =
|
proc makeSingleLineCString*(s: string): string =
|
||||||
result = "\""
|
result = "\""
|
||||||
for c in items(s):
|
for c in items(s):
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import
|
||||||
nversion, nimsets, msgs, securehash, bitsets, idents, lists, types,
|
nversion, nimsets, msgs, securehash, bitsets, idents, lists, types,
|
||||||
ccgutils, os, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
|
ccgutils, os, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
|
||||||
condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases,
|
condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases,
|
||||||
lowerings, semparallel
|
lowerings, semparallel, tables
|
||||||
|
|
||||||
from modulegraphs import ModuleGraph
|
from modulegraphs import ModuleGraph
|
||||||
|
|
||||||
|
|
@ -263,6 +263,7 @@ type
|
||||||
proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags)
|
proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags)
|
||||||
|
|
||||||
proc isComplexValueType(t: PType): bool {.inline.} =
|
proc isComplexValueType(t: PType): bool {.inline.} =
|
||||||
|
let t = t.skipTypes(abstractInst)
|
||||||
result = t.kind in {tyArray, tyArrayConstr, tySet, tyTuple, tyObject} or
|
result = t.kind in {tyArray, tyArrayConstr, tySet, tyTuple, tyObject} or
|
||||||
(t.kind == tyProc and t.callConv == ccClosure)
|
(t.kind == tyProc and t.callConv == ccClosure)
|
||||||
|
|
||||||
|
|
@ -296,7 +297,7 @@ proc resetLoc(p: BProc, loc: var TLoc) =
|
||||||
genObjectInit(p, cpsStmts, loc.t, loc, true)
|
genObjectInit(p, cpsStmts, loc.t, loc, true)
|
||||||
|
|
||||||
proc constructLoc(p: BProc, loc: TLoc, isTemp = false) =
|
proc constructLoc(p: BProc, loc: TLoc, isTemp = false) =
|
||||||
let typ = skipTypes(loc.t, abstractRange)
|
let typ = loc.t
|
||||||
if not isComplexValueType(typ):
|
if not isComplexValueType(typ):
|
||||||
linefmt(p, cpsStmts, "$1 = ($2)0;$n", rdLoc(loc),
|
linefmt(p, cpsStmts, "$1 = ($2)0;$n", rdLoc(loc),
|
||||||
getTypeDesc(p.module, typ))
|
getTypeDesc(p.module, typ))
|
||||||
|
|
@ -325,13 +326,9 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
|
||||||
proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
|
proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
|
||||||
inc(p.labels)
|
inc(p.labels)
|
||||||
result.r = "LOC" & rope(p.labels)
|
result.r = "LOC" & rope(p.labels)
|
||||||
#addf(p.blocks[0].sections[cpsLocals],
|
|
||||||
# "$1 $2;$n", [getTypeDesc(p.module, t), result.r])
|
|
||||||
linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r)
|
linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r)
|
||||||
result.k = locTemp
|
result.k = locTemp
|
||||||
#result.a = - 1
|
|
||||||
result.t = t
|
result.t = t
|
||||||
#result.t = getUniqueType(t)
|
|
||||||
result.s = OnStack
|
result.s = OnStack
|
||||||
result.flags = {}
|
result.flags = {}
|
||||||
constructLoc(p, result, not needsInit)
|
constructLoc(p, result, not needsInit)
|
||||||
|
|
@ -1094,10 +1091,10 @@ proc rawNewModule(module: PSym, filename: string): BModule =
|
||||||
result.declaredProtos = initIntSet()
|
result.declaredProtos = initIntSet()
|
||||||
result.cfilename = filename
|
result.cfilename = filename
|
||||||
result.filename = filename
|
result.filename = filename
|
||||||
initIdTable(result.typeCache)
|
result.typeCache = initTable[SigHash, Rope]()
|
||||||
initIdTable(result.forwTypeCache)
|
result.forwTypeCache = initTable[SigHash, Rope]()
|
||||||
result.module = module
|
result.module = module
|
||||||
result.typeInfoMarker = initIntSet()
|
result.typeInfoMarker = initTable[SigHash, Rope]()
|
||||||
result.initProc = newProc(nil, result)
|
result.initProc = newProc(nil, result)
|
||||||
result.initProc.options = initProcOptions(result)
|
result.initProc.options = initProcOptions(result)
|
||||||
result.preInitProc = newPreInitProc(result)
|
result.preInitProc = newPreInitProc(result)
|
||||||
|
|
@ -1107,7 +1104,6 @@ proc rawNewModule(module: PSym, filename: string): BModule =
|
||||||
result.forwardedProcs = @[]
|
result.forwardedProcs = @[]
|
||||||
result.typeNodesName = getTempName(result)
|
result.typeNodesName = getTempName(result)
|
||||||
result.nimTypesName = getTempName(result)
|
result.nimTypesName = getTempName(result)
|
||||||
result.hashConflicts = initIntSet()
|
|
||||||
# no line tracing for the init sections of the system module so that we
|
# no line tracing for the init sections of the system module so that we
|
||||||
# don't generate a TFrame which can confuse the stack botton initialization:
|
# don't generate a TFrame which can confuse the stack botton initialization:
|
||||||
if sfSystemModule in module.flags:
|
if sfSystemModule in module.flags:
|
||||||
|
|
@ -1124,7 +1120,7 @@ proc resetModule*(m: BModule) =
|
||||||
# away all the data that was written to disk
|
# away all the data that was written to disk
|
||||||
initLinkedList(m.headerFiles)
|
initLinkedList(m.headerFiles)
|
||||||
m.declaredProtos = initIntSet()
|
m.declaredProtos = initIntSet()
|
||||||
initIdTable(m.forwTypeCache)
|
m.forwTypeCache = initTable[SigHash, Rope]()
|
||||||
m.initProc = newProc(nil, m)
|
m.initProc = newProc(nil, m)
|
||||||
m.initProc.options = initProcOptions(m)
|
m.initProc.options = initProcOptions(m)
|
||||||
m.preInitProc = newPreInitProc(m)
|
m.preInitProc = newPreInitProc(m)
|
||||||
|
|
@ -1141,7 +1137,6 @@ proc resetModule*(m: BModule) =
|
||||||
nullify m.s
|
nullify m.s
|
||||||
m.typeNodes = 0
|
m.typeNodes = 0
|
||||||
m.nimTypes = 0
|
m.nimTypes = 0
|
||||||
m.hashConflicts = initIntSet()
|
|
||||||
nullify m.extensionLoaders
|
nullify m.extensionLoaders
|
||||||
|
|
||||||
# indicate that this is now cached module
|
# indicate that this is now cached module
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@
|
||||||
## This module contains the data structures for the C code generation phase.
|
## This module contains the data structures for the C code generation phase.
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, ropes, passes, options, intsets, lists, platform
|
ast, astalgo, ropes, passes, options, intsets, lists, platform, sighashes,
|
||||||
|
tables
|
||||||
|
|
||||||
from msgs import TLineInfo
|
from msgs import TLineInfo
|
||||||
|
|
||||||
|
|
@ -92,6 +93,7 @@ type
|
||||||
gcFrameType*: Rope # the struct {} we put the GC markers into
|
gcFrameType*: Rope # the struct {} we put the GC markers into
|
||||||
|
|
||||||
TTypeSeq* = seq[PType]
|
TTypeSeq* = seq[PType]
|
||||||
|
TypeCache* = Table[SigHash, Rope]
|
||||||
|
|
||||||
Codegenflag* = enum
|
Codegenflag* = enum
|
||||||
preventStackTrace, # true if stack traces need to be prevented
|
preventStackTrace, # true if stack traces need to be prevented
|
||||||
|
|
@ -109,12 +111,12 @@ type
|
||||||
cfilename*: string # filename of the module (including path,
|
cfilename*: string # filename of the module (including path,
|
||||||
# without extension)
|
# without extension)
|
||||||
tmpBase*: Rope # base for temp identifier generation
|
tmpBase*: Rope # base for temp identifier generation
|
||||||
typeCache*: TIdTable # cache the generated types
|
typeCache*: TypeCache # cache the generated types
|
||||||
forwTypeCache*: TIdTable # cache for forward declarations of types
|
forwTypeCache*: TypeCache # cache for forward declarations of types
|
||||||
declaredThings*: IntSet # things we have declared in this .c file
|
declaredThings*: IntSet # things we have declared in this .c file
|
||||||
declaredProtos*: IntSet # prototypes we have declared in this .c file
|
declaredProtos*: IntSet # prototypes we have declared in this .c file
|
||||||
headerFiles*: TLinkedList # needed headers to include
|
headerFiles*: TLinkedList # needed headers to include
|
||||||
typeInfoMarker*: IntSet # needed for generating type information
|
typeInfoMarker*: TypeCache # needed for generating type information
|
||||||
initProc*: BProc # code for init procedure
|
initProc*: BProc # code for init procedure
|
||||||
postInitProc*: BProc # code to be executed after the init proc
|
postInitProc*: BProc # code to be executed after the init proc
|
||||||
preInitProc*: BProc # code executed before the init proc
|
preInitProc*: BProc # code executed before the init proc
|
||||||
|
|
@ -127,7 +129,6 @@ type
|
||||||
extensionLoaders*: array['0'..'9', Rope] # special procs for the
|
extensionLoaders*: array['0'..'9', Rope] # special procs for the
|
||||||
# OpenGL wrapper
|
# OpenGL wrapper
|
||||||
injectStmt*: Rope
|
injectStmt*: Rope
|
||||||
hashConflicts*: IntSet
|
|
||||||
|
|
||||||
var
|
var
|
||||||
mainModProcs*, mainModInit*, otherModsInit*, mainDatInit*: Rope
|
mainModProcs*, mainModInit*, otherModsInit*, mainDatInit*: Rope
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,10 @@
|
||||||
## Computes hash values for routine (proc, method etc) signatures.
|
## Computes hash values for routine (proc, method etc) signatures.
|
||||||
|
|
||||||
import ast, md5
|
import ast, md5
|
||||||
export md5.`==`
|
from hashes import Hash
|
||||||
|
from astalgo import debug
|
||||||
|
from types import typeToString
|
||||||
|
from strutils import startsWith
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
type
|
type
|
||||||
|
|
@ -25,7 +28,7 @@ when false:
|
||||||
|
|
||||||
else:
|
else:
|
||||||
type
|
type
|
||||||
SigHash* = Md5Digest
|
SigHash* = distinct Md5Digest
|
||||||
|
|
||||||
const
|
const
|
||||||
cb64 = [
|
cb64 = [
|
||||||
|
|
@ -39,6 +42,7 @@ else:
|
||||||
proc toBase64a(s: cstring, len: int): string =
|
proc toBase64a(s: cstring, len: int): string =
|
||||||
## encodes `s` into base64 representation.
|
## encodes `s` into base64 representation.
|
||||||
result = newStringOfCap(((len + 2) div 3) * 4)
|
result = newStringOfCap(((len + 2) div 3) * 4)
|
||||||
|
result.add '_'
|
||||||
var i = 0
|
var i = 0
|
||||||
while i < len - 2:
|
while i < len - 2:
|
||||||
let a = ord(s[i])
|
let a = ord(s[i])
|
||||||
|
|
@ -65,6 +69,15 @@ else:
|
||||||
proc `&=`(c: var MD5Context, s: string) = md5Update(c, s, s.len)
|
proc `&=`(c: var MD5Context, s: string) = md5Update(c, s, s.len)
|
||||||
proc `&=`(c: var MD5Context, ch: char) = md5Update(c, unsafeAddr ch, 1)
|
proc `&=`(c: var MD5Context, ch: char) = md5Update(c, unsafeAddr ch, 1)
|
||||||
|
|
||||||
|
proc `==`*(a, b: SigHash): bool =
|
||||||
|
# {.borrow.}
|
||||||
|
result = equalMem(unsafeAddr a, unsafeAddr b, sizeof(a))
|
||||||
|
|
||||||
|
proc hash*(u: SigHash): Hash =
|
||||||
|
result = 0
|
||||||
|
for x in 0..3:
|
||||||
|
result = (result shl 8) or u.MD5Digest[x].int
|
||||||
|
|
||||||
proc hashSym(c: var MD5Context, s: PSym) =
|
proc hashSym(c: var MD5Context, s: PSym) =
|
||||||
if sfAnon in s.flags or s.kind == skGenericParam:
|
if sfAnon in s.flags or s.kind == skGenericParam:
|
||||||
c &= ":anon"
|
c &= ":anon"
|
||||||
|
|
@ -105,28 +118,46 @@ proc hashTree(c: var MD5Context, n: PNode) =
|
||||||
|
|
||||||
type
|
type
|
||||||
ConsiderFlag* = enum
|
ConsiderFlag* = enum
|
||||||
considerParamNames
|
CoProc
|
||||||
|
CoType
|
||||||
|
|
||||||
proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
|
proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
|
||||||
# modelled after 'typeToString'
|
|
||||||
if t == nil:
|
if t == nil:
|
||||||
c &= "\254"
|
c &= "\254"
|
||||||
return
|
return
|
||||||
|
|
||||||
c &= char(t.kind)
|
c &= char(t.kind)
|
||||||
|
|
||||||
# Every cyclic type in Nim need to be constructed via some 't.sym', so this
|
case t.kind
|
||||||
# is actually safe without an infinite recursion check:
|
of tyGenericInst:
|
||||||
if t.sym != nil and sfAnon notin t.sym.flags:
|
var x = t.lastSon
|
||||||
# t.n for literals, but not for e.g. objects!
|
if x.kind == tyGenericBody: x = x.lastSon
|
||||||
if t.kind in {tyFloat, tyInt}: c.hashTree(t.n)
|
if x.kind == tyTuple:
|
||||||
|
c.hashType x, flags
|
||||||
|
return
|
||||||
|
for i in countup(0, sonsLen(t) - 2):
|
||||||
|
c.hashType t.sons[i], flags
|
||||||
|
return
|
||||||
|
of tyGenericInvocation:
|
||||||
|
for i in countup(0, sonsLen(t) - 1):
|
||||||
|
c.hashType t.sons[i], flags
|
||||||
|
return
|
||||||
|
of tyDistinct:
|
||||||
|
if CoType in flags:
|
||||||
|
c.hashType t.lastSon, flags
|
||||||
|
else:
|
||||||
c.hashSym(t.sym)
|
c.hashSym(t.sym)
|
||||||
return
|
return
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyGenericBody, tyGenericInst, tyGenericInvocation:
|
of tyObject, tyEnum:
|
||||||
for i in countup(0, sonsLen(t) - 1 - ord(t.kind != tyGenericInvocation)):
|
# Every cyclic type in Nim need to be constructed via some 't.sym', so this
|
||||||
c.hashType t.sons[i], flags
|
# is actually safe without an infinite recursion check:
|
||||||
|
c.hashSym(t.sym)
|
||||||
|
of tyRef, tyPtr, tyGenericBody:
|
||||||
|
c.hashType t.lastSon, flags
|
||||||
of tyUserTypeClass:
|
of tyUserTypeClass:
|
||||||
if t.sym != nil and t.sym.owner != nil:
|
if t.sym != nil and t.sym.owner != nil:
|
||||||
c &= t.sym.owner.name.s
|
c &= t.sym.owner.name.s
|
||||||
|
|
@ -139,11 +170,8 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
|
||||||
c.hashType t.sons[i], flags
|
c.hashType t.sons[i], flags
|
||||||
of tyFromExpr, tyFieldAccessor:
|
of tyFromExpr, tyFieldAccessor:
|
||||||
c.hashTree(t.n)
|
c.hashTree(t.n)
|
||||||
of tyArrayConstr:
|
|
||||||
c.hashTree(t.sons[0].n)
|
|
||||||
c.hashType(t.sons[1], flags)
|
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
if t.n != nil:
|
if t.n != nil and CoType notin flags:
|
||||||
assert(sonsLen(t.n) == sonsLen(t))
|
assert(sonsLen(t.n) == sonsLen(t))
|
||||||
for i in countup(0, sonsLen(t.n) - 1):
|
for i in countup(0, sonsLen(t.n) - 1):
|
||||||
assert(t.n.sons[i].kind == nkSym)
|
assert(t.n.sons[i].kind == nkSym)
|
||||||
|
|
@ -154,11 +182,11 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
|
||||||
else:
|
else:
|
||||||
for i in countup(0, sonsLen(t) - 1): c.hashType t.sons[i], flags
|
for i in countup(0, sonsLen(t) - 1): c.hashType t.sons[i], flags
|
||||||
of tyRange:
|
of tyRange:
|
||||||
c.hashTree(t.n)
|
if CoType notin flags: c.hashTree(t.n)
|
||||||
c.hashType(t.sons[0], flags)
|
c.hashType(t.sons[0], flags)
|
||||||
of tyProc:
|
of tyProc:
|
||||||
c &= (if tfIterator in t.flags: "iterator " else: "proc ")
|
c &= (if tfIterator in t.flags: "iterator " else: "proc ")
|
||||||
if considerParamNames in flags and t.n != nil:
|
if CoProc in flags and t.n != nil:
|
||||||
let params = t.n
|
let params = t.n
|
||||||
for i in 1..<params.len:
|
for i in 1..<params.len:
|
||||||
let param = params[i].sym
|
let param = params[i].sym
|
||||||
|
|
@ -170,22 +198,23 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
|
||||||
else:
|
else:
|
||||||
for i in 0.. <t.len: c.hashType(t.sons[i], flags)
|
for i in 0.. <t.len: c.hashType(t.sons[i], flags)
|
||||||
c &= char(t.callConv)
|
c &= char(t.callConv)
|
||||||
|
if CoType notin flags:
|
||||||
if tfNoSideEffect in t.flags: c &= ".noSideEffect"
|
if tfNoSideEffect in t.flags: c &= ".noSideEffect"
|
||||||
if tfThread in t.flags: c &= ".thread"
|
if tfThread in t.flags: c &= ".thread"
|
||||||
else:
|
else:
|
||||||
for i in 0.. <t.len: c.hashType(t.sons[i], flags)
|
for i in 0.. <t.len: c.hashType(t.sons[i], flags)
|
||||||
if tfNotNil in t.flags: c &= "not nil"
|
if tfNotNil in t.flags and CoType notin flags: c &= "not nil"
|
||||||
|
|
||||||
proc hashType*(t: PType; flags: set[ConsiderFlag]): SigHash =
|
proc hashType*(t: PType; flags: set[ConsiderFlag] = {CoType}): SigHash =
|
||||||
var c: MD5Context
|
var c: MD5Context
|
||||||
md5Init c
|
md5Init c
|
||||||
hashType c, t, flags
|
hashType c, t, flags
|
||||||
md5Final c, result
|
md5Final c, result.Md5Digest
|
||||||
|
|
||||||
proc hashProc*(s: PSym): SigHash =
|
proc hashProc*(s: PSym): SigHash =
|
||||||
var c: MD5Context
|
var c: MD5Context
|
||||||
md5Init c
|
md5Init c
|
||||||
hashType c, s.typ, {considerParamNames}
|
hashType c, s.typ, {CoProc}
|
||||||
|
|
||||||
var m = s
|
var m = s
|
||||||
while m.kind != skModule: m = m.owner
|
while m.kind != skModule: m = m.owner
|
||||||
|
|
@ -195,7 +224,7 @@ proc hashProc*(s: PSym): SigHash =
|
||||||
c &= "."
|
c &= "."
|
||||||
c &= m.name.s
|
c &= m.name.s
|
||||||
|
|
||||||
md5Final c, result
|
md5Final c, result.Md5Digest
|
||||||
|
|
||||||
proc hashOwner*(s: PSym): SigHash =
|
proc hashOwner*(s: PSym): SigHash =
|
||||||
var c: MD5Context
|
var c: MD5Context
|
||||||
|
|
@ -208,4 +237,4 @@ proc hashOwner*(s: PSym): SigHash =
|
||||||
c &= "."
|
c &= "."
|
||||||
c &= m.name.s
|
c &= m.name.s
|
||||||
|
|
||||||
md5Final c, result
|
md5Final c, result.Md5Digest
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue