diff options
author | ringabout <43030857+ringabout@users.noreply.github.com> | 2022-09-28 02:07:26 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-27 20:07:26 +0200 |
commit | 80e739f2bf5a3e40df7000566a9cbb9cfab29ac4 (patch) | |
tree | fb7cb6f3e4e275e31b0e253579a15c7df899176c /compiler | |
parent | 3d2f0e2c7ce73299e57f2ebd5ee52822c3543554 (diff) | |
download | Nim-80e739f2bf5a3e40df7000566a9cbb9cfab29ac4.tar.gz |
fixes #19401; fixes #19402; rework Forward declaration and finalizer for ORC (#20295)
* fixes #19401; fixes #19402; rework Forward declaration and finalizer for ORC * add more tests * give it a name * make more tests * fixes tests * hidden addr for cpp * move code to a function
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/semmagic.nim | 72 |
1 files changed, 48 insertions, 24 deletions
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index f7edc5592..48ea69648 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -449,6 +449,53 @@ proc semOld(c: PContext; n: PNode): PNode = localError(c.config, n[1].info, n[1].sym.name.s & " does not belong to " & getCurrOwner(c).name.s) result = n +proc semNewFinalize(c: PContext; n: PNode): PNode = + # Make sure the finalizer procedure refers to a procedure + if n[^1].kind == nkSym and n[^1].sym.kind notin {skProc, skFunc}: + localError(c.config, n.info, "finalizer must be a direct reference to a proc") + elif optTinyRtti in c.config.globalOptions: + let nfin = skipConvCastAndClosure(n[^1]) + let fin = case nfin.kind + of nkSym: nfin.sym + of nkLambda, nkDo: nfin[namePos].sym + else: + localError(c.config, n.info, "finalizer must be a direct reference to a proc") + nil + if fin != nil: + if fin.kind notin {skProc, skFunc}: + # calling convention is checked in codegen + localError(c.config, n.info, "finalizer must be a direct reference to a proc") + + # check if we converted this finalizer into a destructor already: + let t = whereToBindTypeHook(c, fin.typ[1].skipTypes(abstractInst+{tyRef})) + if t != nil and getAttachedOp(c.graph, t, attachedDestructor) != nil and + getAttachedOp(c.graph, t, attachedDestructor).owner == fin: + discard "already turned this one into a finalizer" + else: + if sfForward in fin.flags: + let wrapperSym = newSym(skProc, getIdent(c.graph.cache, fin.name.s & "FinalizerWrapper"), nextSymId c.idgen, fin.owner, fin.info) + let selfSymNode = newSymNode(copySym(fin.ast[paramsPos][1][0].sym, nextSymId c.idgen)) + wrapperSym.flags.incl sfUsed + let wrapper = c.semExpr(c, newProcNode(nkProcDef, fin.info, body = newTree(nkCall, newSymNode(fin), selfSymNode), + params = nkFormalParams.newTree(c.graph.emptyNode, + newTree(nkIdentDefs, selfSymNode, fin.ast[paramsPos][1][1], c.graph.emptyNode) + ), + name = newSymNode(wrapperSym), pattern = c.graph.emptyNode, + genericParams = c.graph.emptyNode, pragmas = c.graph.emptyNode, exceptions = c.graph.emptyNode), {}) + var transFormedSym = turnFinalizerIntoDestructor(c, wrapperSym, wrapper.info) + transFormedSym.owner = fin + if c.config.backend == backendCpp or sfCompileToCpp in c.module.flags: + let origParamType = transFormedSym.ast[bodyPos][1].typ + let selfSymbolType = makePtrType(c, origParamType.skipTypes(abstractPtrs)) + let selfPtr = newNodeI(nkHiddenAddr, transFormedSym.ast[bodyPos][1].info) + selfPtr.add transFormedSym.ast[bodyPos][1] + selfPtr.typ = selfSymbolType + transFormedSym.ast[bodyPos][1] = c.semExpr(c, selfPtr) + bindTypeHook(c, transFormedSym, n, attachedDestructor) + else: + bindTypeHook(c, turnFinalizerIntoDestructor(c, fin, n.info), n, attachedDestructor) + result = n + proc semPrivateAccess(c: PContext, n: PNode): PNode = let t = n[1].typ[0].toObjectFromRefPtrGeneric c.currentScope.allowPrivateAccess.add t.sym @@ -513,30 +560,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, else: result = plugin(c, n) of mNewFinalize: - # Make sure the finalizer procedure refers to a procedure - if n[^1].kind == nkSym and n[^1].sym.kind notin {skProc, skFunc}: - localError(c.config, n.info, "finalizer must be a direct reference to a proc") - elif optTinyRtti in c.config.globalOptions: - let nfin = skipConvCastAndClosure(n[^1]) - let fin = case nfin.kind - of nkSym: nfin.sym - of nkLambda, nkDo: nfin[namePos].sym - else: - localError(c.config, n.info, "finalizer must be a direct reference to a proc") - nil - if fin != nil: - if fin.kind notin {skProc, skFunc}: - # calling convention is checked in codegen - localError(c.config, n.info, "finalizer must be a direct reference to a proc") - - # check if we converted this finalizer into a destructor already: - let t = whereToBindTypeHook(c, fin.typ[1].skipTypes(abstractInst+{tyRef})) - if t != nil and getAttachedOp(c.graph, t, attachedDestructor) != nil and - getAttachedOp(c.graph, t, attachedDestructor).owner == fin: - discard "already turned this one into a finalizer" - else: - bindTypeHook(c, turnFinalizerIntoDestructor(c, fin, n.info), n, attachedDestructor) - result = n + result = semNewFinalize(c, n) of mDestroy: result = n let t = n[1].typ.skipTypes(abstractVar) |