explicit ID generation for easier IC (#15559)

* refactoring: idents don't need inheritance
* refactoring: adding an IdGenerator (part 1)
* refactoring: adding an IdGenerator (part 2)
* refactoring: adding an IdGenerator (part 3)
* refactoring: adding an IdGenerator (part 4)
* refactoring: adding an IdGenerator (part 5)
* refactoring: adding an IdGenerator (part 5)
* IdGenerator must be a ref type; hello world works again
* make bootstrapping work again
* progress: add back the 'exactReplica' ideas
* added back the missing exactReplica hacks
* make tcompilerapi work again
* make important packages green
* attempt to fix the build for 32 bit machines (probably need a better solution here)
This commit is contained in:
Andreas Rumpf 2020-10-25 08:50:47 +01:00 • committed by GitHub
commit 226595515c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
67 changed files with 853 additions and 903 deletions

View file

@ -27,12 +27,14 @@ type
canRaise: bool
filterDiscriminator: PSym # we generating destructor for case branch
c: PContext # c can be nil, then we are called from lambdalifting!
idgen: IdGenerator
proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode)
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
info: TLineInfo): PSym
info: TLineInfo; idgen: IdGenerator): PSym
proc createTypeBoundOps*(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo)
proc createTypeBoundOps*(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo;
idgen: IdGenerator)
proc at(a, i: PNode, elemType: PType): PNode =
result = newNodeI(nkBracketExpr, a.info, 2)
@ -73,12 +75,12 @@ proc defaultOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
call.typ = t
body.add newAsgnStmt(x, call)
proc genAddr(g: ModuleGraph; x: PNode): PNode =
proc genAddr(c: var TLiftCtx; x: PNode): PNode =
if x.kind == nkHiddenDeref:
checkSonsLen(x, 1, g.config)
checkSonsLen(x, 1, c.g.config)
result = x[0]
else:
result = newNodeIT(nkHiddenAddr, x.info, makeVarType(x.typ.owner, x.typ))
result = newNodeIT(nkHiddenAddr, x.info, makeVarType(x.typ.owner, x.typ, c.idgen))
result.add x
proc genWhileLoop(c: var TLiftCtx; i, dest: PNode): PNode =
@ -92,11 +94,11 @@ proc genWhileLoop(c: var TLiftCtx; i, dest: PNode): PNode =
proc genIf(c: var TLiftCtx; cond, action: PNode): PNode =
result = newTree(nkIfStmt, newTree(nkElifBranch, cond, action))
proc genContainerOf(c: TLiftCtx; objType: PType, field, x: PSym): PNode =
proc genContainerOf(c: var TLiftCtx; objType: PType, field, x: PSym): PNode =
# generate: cast[ptr ObjType](cast[int](addr(x)) - offsetOf(objType.field))
let intType = getSysType(c.g, unknownLineInfo, tyInt)
let addrOf = newNodeIT(nkAddr, c.info, makePtrType(x.owner, x.typ))
let addrOf = newNodeIT(nkAddr, c.info, makePtrType(x.owner, x.typ, c.idgen))
addrOf.add newDeref(newSymNode(x))
let castExpr1 = newNodeIT(nkCast, c.info, intType)
castExpr1.add newNodeIT(nkType, c.info, intType)
@ -113,7 +115,7 @@ proc genContainerOf(c: TLiftCtx; objType: PType, field, x: PSym): PNode =
minusExpr.typ = intType
minusExpr.add offsetOf
let objPtr = makePtrType(objType.owner, objType)
let objPtr = makePtrType(objType.owner, objType, c.idgen)
result = newNodeIT(nkCast, c.info, objPtr)
result.add newNodeIT(nkType, c.info, objPtr)
result.add minusExpr
@ -121,7 +123,7 @@ proc genContainerOf(c: TLiftCtx; objType: PType, field, x: PSym): PNode =
proc destructorCall(c: var TLiftCtx; op: PSym; x: PNode): PNode =
var destroy = newNodeIT(nkCall, x.info, op.typ[0])
destroy.add(newSymNode(op))
destroy.add genAddr(c.g, x)
destroy.add genAddr(c, x)
if sfNeverRaises notin op.flags:
c.canRaise = true
if c.addMemReset:
@ -217,7 +219,7 @@ proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
# for every field (dependent on dest.kind):
# `=` dest.field, src.field
# =destroy(blob)
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.fn, c.info)
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextId c.idgen, c.fn, c.info)
temp.typ = x.typ
incl(temp.flags, sfFromGeneric)
var v = newNodeI(nkVarSection, c.info)
@ -251,7 +253,7 @@ proc newHookCall(c: var TLiftCtx; op: PSym; x, y: PNode): PNode =
if sfNeverRaises notin op.flags:
c.canRaise = true
if op.typ.sons[1].kind == tyVar:
result.add genAddr(c.g, x)
result.add genAddr(c, x)
else:
result.add x
if y != nil:
@ -311,7 +313,7 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
else:
op = field
if op == nil:
op = produceSym(c.g, c.c, t, c.kind, c.info)
op = produceSym(c.g, c.c, t, c.kind, c.info, c.idgen)
if sfError in op.flags:
incl c.fn.flags, sfError
#else:
@ -340,7 +342,7 @@ proc addDestructorCall(c: var TLiftCtx; orig: PType; body, x: PNode) =
t.attachedOps[attachedDestructor] = op
if op == nil and (useNoGc(c, t) or requiresDestructor(c, t)):
op = produceSym(c.g, c.c, t, attachedDestructor, c.info)
op = produceSym(c.g, c.c, t, attachedDestructor, c.info, c.idgen)
doAssert op != nil
doAssert op == t.destructor
@ -381,7 +383,7 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
result = true
proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.fn, c.info)
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextId(c.idgen), c.fn, c.info)
temp.typ = getSysType(c.g, body.info, tyInt)
incl(temp.flags, sfFromGeneric)
@ -452,7 +454,7 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add genBuiltin(c.g, mDestroy, "destroy", x)
proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
createTypeBoundOps(c.g, c.c, t, body.info)
createTypeBoundOps(c.g, c.c, t, body.info, c.idgen)
# recursions are tricky, so we might need to forward the generated
# operation here:
var t = t
@ -493,7 +495,7 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case c.kind
of attachedAsgn, attachedDeepCopy:
body.add callCodegenProc(c.g, "nimAsgnStrV2", c.info, genAddr(c.g, x), y)
body.add callCodegenProc(c.g, "nimAsgnStrV2", c.info, genAddr(c, x), y)
of attachedSink:
let moveCall = genBuiltin(c.g, mMove, "move", x)
moveCall.add y
@ -509,7 +511,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
var actions = newNodeI(nkStmtList, c.info)
let elemType = t.lastSon
createTypeBoundOps(c.g, c.c, elemType, c.info)
createTypeBoundOps(c.g, c.c, elemType, c.info, c.idgen)
if isFinal(elemType):
addDestructorCall(c, elemType, actions, genDeref(x, nkDerefExpr))
@ -548,10 +550,10 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
if isFinal(elemType):
let typInfo = genBuiltin(c.g, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType))
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, c.idgen), typInfo, y)
else:
# If the ref is polymorphic we have to account for this
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(x), y)
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(x, c.idgen), y)
of attachedDispose:
# this is crucial! dispose is like =destroy but we don't follow refs
# as that is dealt within the cycle collector.
@ -593,7 +595,7 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add genIf(c, cond, actions)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace:
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(xenv), y)
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(xenv, c.idgen), y)
of attachedDispose:
# this is crucial! dispose is like =destroy but we don't follow refs
# as that is dealt within the cycle collector.
@ -788,28 +790,30 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of tyOptDeprecated: doAssert false
proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType;
kind: TTypeAttachedOp; info: TLineInfo): PSym =
kind: TTypeAttachedOp; info: TLineInfo;
idgen: IdGenerator): PSym =
assert typ.kind == tyDistinct
let baseType = typ[0]
if baseType.attachedOps[kind] == nil:
discard produceSym(g, c, baseType, kind, info)
discard produceSym(g, c, baseType, kind, info, idgen)
typ.attachedOps[kind] = baseType.attachedOps[kind]
result = typ.attachedOps[kind]
proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp;
info: TLineInfo): PSym =
info: TLineInfo; idgen: IdGenerator): PSym =
let procname = getIdent(g.cache, AttachedOpToStr[kind])
result = newSym(skProc, procname, owner, info)
let dest = newSym(skParam, getIdent(g.cache, "dest"), result, info)
let src = newSym(skParam, getIdent(g.cache, if kind == attachedTrace: "env" else: "src"), result, info)
dest.typ = makeVarType(typ.owner, typ)
result = newSym(skProc, procname, nextId(idgen), owner, info)
let dest = newSym(skParam, getIdent(g.cache, "dest"), nextId(idgen), result, info)
let src = newSym(skParam, getIdent(g.cache, if kind == attachedTrace: "env" else: "src"),
nextId(idgen), result, info)
dest.typ = makeVarType(typ.owner, typ, idgen)
if kind == attachedTrace:
src.typ = getSysType(g, info, tyPointer)
else:
src.typ = typ
result.typ = newProcType(info, owner)
result.typ = newProcType(info, nextId(idgen), owner)
result.typ.addParam dest
if kind notin {attachedDestructor, attachedDispose}:
result.typ.addParam src
@ -825,15 +829,15 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
info: TLineInfo): PSym =
info: TLineInfo; idgen: IdGenerator): PSym =
if typ.kind == tyDistinct:
return produceSymDistinctType(g, c, typ, kind, info)
return produceSymDistinctType(g, c, typ, kind, info, idgen)
result = typ.attachedOps[kind]
if result == nil:
result = symPrototype(g, typ, typ.owner, kind, info)
result = symPrototype(g, typ, typ.owner, kind, info, idgen)
var a = TLiftCtx(info: info, g: g, kind: kind, c: c, asgnForType:typ)
var a = TLiftCtx(info: info, g: g, kind: kind, c: c, asgnForType:typ, idgen: idgen)
a.fn = result
let dest = result.typ.n[1].sym
@ -866,18 +870,19 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
if not a.canRaise: incl result.flags, sfNeverRaises
proc produceDestructorForDiscriminator*(g: ModuleGraph; typ: PType; field: PSym, info: TLineInfo): PSym =
proc produceDestructorForDiscriminator*(g: ModuleGraph; typ: PType; field: PSym,
info: TLineInfo; idgen: IdGenerator): PSym =
assert(typ.skipTypes({tyAlias, tyGenericInst}).kind == tyObject)
result = symPrototype(g, field.typ, typ.owner, attachedDestructor, info)
var a = TLiftCtx(info: info, g: g, kind: attachedDestructor, asgnForType: typ)
result = symPrototype(g, field.typ, typ.owner, attachedDestructor, info, idgen)
var a = TLiftCtx(info: info, g: g, kind: attachedDestructor, asgnForType: typ, idgen: idgen)
a.fn = result
a.asgnForType = typ
a.filterDiscriminator = field
a.addMemReset = true
let discrimantDest = result.typ.n[1].sym
let dst = newSym(skVar, getIdent(g.cache, "dest"), result, info)
dst.typ = makePtrType(typ.owner, typ)
let dst = newSym(skVar, getIdent(g.cache, "dest"), nextId(idgen), result, info)
dst.typ = makePtrType(typ.owner, typ, idgen)
let dstSym = newSymNode(dst)
let d = newDeref(dstSym)
let v = newNodeI(nkVarSection, info)
@ -891,12 +896,12 @@ proc produceDestructorForDiscriminator*(g: ModuleGraph; typ: PType; field: PSym,
template liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) =
discard "now a nop"
proc patchBody(g: ModuleGraph; c: PContext; n: PNode; info: TLineInfo) =
proc patchBody(g: ModuleGraph; c: PContext; n: PNode; info: TLineInfo; idgen: IdGenerator) =
if n.kind in nkCallKinds:
if n[0].kind == nkSym and n[0].sym.magic == mDestroy:
let t = n[1].typ.skipTypes(abstractVar)
if t.destructor == nil:
discard produceSym(g, c, t, attachedDestructor, info)
discard produceSym(g, c, t, attachedDestructor, info, idgen)
if t.destructor != nil:
if t.destructor.ast[genericParamsPos].kind != nkEmpty:
@ -904,9 +909,9 @@ proc patchBody(g: ModuleGraph; c: PContext; n: PNode; info: TLineInfo) =
if t.destructor.magic == mDestroy:
internalError(g.config, info, "patching mDestroy with mDestroy?")
n[0] = newSymNode(t.destructor)
for x in n: patchBody(g, c, x, info)
for x in n: patchBody(g, c, x, info, idgen)
template inst(field, t) =
template inst(field, t, idgen) =
if field.ast != nil and field.ast[genericParamsPos].kind != nkEmpty:
if t.typeInst != nil:
var a: TLiftCtx
@ -914,17 +919,19 @@ template inst(field, t) =
a.g = g
a.kind = k
a.c = c
a.idgen = idgen
field = instantiateGeneric(a, field, t, t.typeInst)
if field.ast != nil:
patchBody(g, c, field.ast, info)
patchBody(g, c, field.ast, info, a.idgen)
else:
localError(g.config, info, "unresolved generic parameter")
proc isTrival(s: PSym): bool {.inline.} =
s == nil or (s.ast != nil and s.ast[bodyPos].len == 0)
proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo) =
proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo;
idgen: IdGenerator) =
## In the semantic pass this is called in strategic places
## to ensure we lift assignment, destructors and moves properly.
## The later 'injectdestructors' pass depends on it.
@ -959,14 +966,14 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf
for k in attachedDestructor..lastAttached:
generics[k] = canon.attachedOps[k] != nil
if not generics[k]:
canon.attachedOps[k] = symPrototype(g, canon, canon.owner, k, info)
canon.attachedOps[k] = symPrototype(g, canon, canon.owner, k, info, idgen)
# we generate the destructor first so that other operators can depend on it:
for k in attachedDestructor..lastAttached:
if not generics[k]:
discard produceSym(g, c, canon, k, info)
discard produceSym(g, c, canon, k, info, idgen)
else:
inst(canon.attachedOps[k], canon)
inst(canon.attachedOps[k], canon, idgen)
if canon != orig:
orig.attachedOps[k] = canon.attachedOps[k]