diff options
Diffstat (limited to 'compiler/liftdestructors.nim')
-rw-r--r-- | compiler/liftdestructors.nim | 99 |
1 files changed, 53 insertions, 46 deletions
diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index 2735fb417..30094875c 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -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] |