diff options
author | cooldome <cdome@bk.ru> | 2018-10-18 19:21:25 +0100 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2018-10-18 20:21:25 +0200 |
commit | eaca5be9d6e205e8aa7055306122a6c053ef35a6 (patch) | |
tree | 784c5f2726a94b656e3f85ab231c4dfc377cc167 /compiler | |
parent | 15dbd973dec848f1c429fe7043e53254a501812b (diff) | |
download | Nim-eaca5be9d6e205e8aa7055306122a6c053ef35a6.tar.gz |
Change the order of compilation passes, transformation is made lazy at code gen (#8489)
* Ast no transformation * Add getImplNoTransform to the macros module * progress on delaying transf * Fix methods tranformation * Fix lazy lambdalifting * fix create thread wrapper * transform for lambda lifting * improve getImplTransformed * Fix destructor tests * try to fix nimprof for linux
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 4 | ||||
-rw-r--r-- | compiler/cgen.nim | 13 | ||||
-rw-r--r-- | compiler/cgmeth.nim | 1 | ||||
-rw-r--r-- | compiler/guards.nim | 2 | ||||
-rw-r--r-- | compiler/jsgen.nim | 8 | ||||
-rw-r--r-- | compiler/lambdalifting.nim | 17 | ||||
-rw-r--r-- | compiler/lowerings.nim | 2 | ||||
-rw-r--r-- | compiler/sem.nim | 2 | ||||
-rw-r--r-- | compiler/semfold.nim | 17 | ||||
-rw-r--r-- | compiler/seminst.nim | 5 | ||||
-rw-r--r-- | compiler/sempass2.nim | 16 | ||||
-rw-r--r-- | compiler/semstmts.nim | 12 | ||||
-rw-r--r-- | compiler/semtypinst.nim | 5 | ||||
-rw-r--r-- | compiler/transf.nim | 64 | ||||
-rw-r--r-- | compiler/vm.nim | 11 | ||||
-rw-r--r-- | compiler/vmdef.nim | 1 | ||||
-rw-r--r-- | compiler/vmgen.nim | 5 |
17 files changed, 122 insertions, 63 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index eaf79a190..68c8e7dd2 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -660,7 +660,7 @@ type mNHint, mNWarning, mNError, mInstantiationInfo, mGetTypeInfo, mNimvm, mIntDefine, mStrDefine, mRunnableExamples, - mException, mBuiltinType, mSymOwner, mUncheckedArray + mException, mBuiltinType, mSymOwner, mUncheckedArray, mGetImplTransf # things that we can evaluate safely at compile time, even if not asked for it: const @@ -811,7 +811,7 @@ type of routineKinds: procInstCache*: seq[PInstantiation] gcUnsafetyReason*: PSym # for better error messages wrt gcsafe - #scope*: PScope # the scope where the proc was defined + transformedBody*: PNode # cached body after transf pass of skModule, skPackage: # modules keep track of the generic symbols they use from other modules. # this is because in incremental compilation, when a module is about to diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 86aa7fb45..26d66a0f5 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -14,7 +14,7 @@ import nversion, nimsets, msgs, std / sha1, bitsets, idents, types, ccgutils, os, ropes, math, passes, wordrecg, treetab, cgmeth, condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, - lowerings, semparallel, tables, sets, ndi, lineinfos, pathutils + lowerings, semparallel, tables, sets, ndi, lineinfos, pathutils, transf import strutils except `%` # collides with ropes.`%` @@ -845,6 +845,8 @@ proc genProcAux(m: BModule, prc: PSym) = var header = genProcHeader(m, prc) var returnStmt: Rope = nil assert(prc.ast != nil) + let procBody = transformBody(m.g.graph, prc, cache = false) + if sfPure notin prc.flags and prc.typ.sons[0] != nil: if resultPos >= prc.ast.len: internalError(m.config, prc.info, "proc has no result symbol") @@ -852,7 +854,7 @@ proc genProcAux(m: BModule, prc: PSym) = let res = resNode.sym # get result symbol if not isInvalidReturnType(m.config, prc.typ.sons[0]): if sfNoInit in prc.flags: incl(res.flags, sfNoInit) - if sfNoInit in prc.flags and p.module.compileToCpp and (let val = easyResultAsgn(prc.getBody); val != nil): + if sfNoInit in prc.flags and p.module.compileToCpp and (let val = easyResultAsgn(procBody); val != nil): var decl = localVarDecl(p, resNode) var a: TLoc initLocExprSingleUse(p, val, a) @@ -873,7 +875,7 @@ proc genProcAux(m: BModule, prc: PSym) = # global is either 'nil' or points to valid memory and so the RC operation # succeeds without touching not-initialized memory. if sfNoInit in prc.flags: discard - elif allPathsAsgnResult(prc.getBody) == InitSkippable: discard + elif allPathsAsgnResult(procBody) == InitSkippable: discard else: resetLoc(p, res.loc) if skipTypes(res.typ, abstractInst).kind == tyArray: @@ -885,7 +887,7 @@ proc genProcAux(m: BModule, prc: PSym) = if param.typ.isCompileTimeOnly: continue assignParam(p, param) closureSetup(p, prc) - genStmts(p, prc.getBody) # modifies p.locals, p.init, etc. + genStmts(p, procBody) # modifies p.locals, p.init, etc. var generatedProc: Rope if sfNoReturn in prc.flags: if hasDeclspec in extccomp.CC[p.config.cCompiler].props: @@ -1522,7 +1524,8 @@ proc myProcess(b: PPassContext, n: PNode): PNode = m.initProc.options = initProcOptions(m) #softRnl = if optLineDir in m.config.options: noRnl else: rnl # XXX replicate this logic! - genStmts(m.initProc, n) + let tranformed_n = transformStmt(m.g.graph, m.module, n) + genStmts(m.initProc, tranformed_n) proc finishModule(m: BModule) = var i = 0 diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim index f2ad3dca0..cba07446f 100644 --- a/compiler/cgmeth.nim +++ b/compiler/cgmeth.nim @@ -281,6 +281,7 @@ proc genDispatcher(g: ModuleGraph; methods: TSymSeq, relevantCols: IntSet): PSym else: disp = ret nilchecks.add disp + nilchecks.flags.incl nfTransf # should not be further transformed result.ast.sons[bodyPos] = nilchecks proc generateMethodDispatchers*(g: ModuleGraph): PNode = diff --git a/compiler/guards.nim b/compiler/guards.nim index 99bb51fce..a01c023e4 100644 --- a/compiler/guards.nim +++ b/compiler/guards.nim @@ -70,7 +70,7 @@ proc isLetLocation(m: PNode, isApprox: bool): bool = n = n.sons[0] inc derefs of nkBracketExpr: - if isConstExpr(n.sons[1]) or isLet(n.sons[1]): + if isConstExpr(n.sons[1]) or isLet(n.sons[1]) or isConstExpr(n.sons[1].skipConv): n = n.sons[0] else: return of nkHiddenStdConv, nkHiddenSubConv, nkConv: diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 7ab4a0472..19bbde777 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -32,7 +32,7 @@ import ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options, nversion, nimsets, msgs, std / sha1, bitsets, idents, types, os, tables, times, ropes, math, passes, ccgutils, wordrecg, renderer, - intsets, cgmeth, lowerings, sighashes, lineinfos, rodutils, pathutils + intsets, cgmeth, lowerings, sighashes, lineinfos, rodutils, pathutils, transf from modulegraphs import ModuleGraph, PPassContext @@ -2021,7 +2021,8 @@ proc genProc(oldProc: PProc, prc: PSym): Rope = else: returnStmt = "return $#;$n" % [a.res] - p.nested: genStmt(p, prc.getBody) + let transformed_body = transformBody(oldProc.module.graph, prc, cache = false) + p.nested: genStmt(p, transformed_body) var def: Rope if not prc.constraint.isNil: @@ -2271,7 +2272,8 @@ proc genModule(p: PProc, n: PNode) = add(p.body, frameCreate(p, makeJSString("module " & p.module.module.name.s), makeJSString(toFilename(p.config, p.module.module.info)))) - genStmt(p, n) + let n_transformed = transformStmt(p.module.graph, p.module.module, n) + genStmt(p, n_transformed) if optStackTrace in p.options: add(p.body, frameDestroy(p)) diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 79b44319f..c318421fa 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -11,7 +11,8 @@ import intsets, strutils, options, ast, astalgo, trees, treetab, msgs, - idents, renderer, types, magicsys, lowerings, tables, modulegraphs, lineinfos + idents, renderer, types, magicsys, lowerings, tables, modulegraphs, lineinfos, + transf discard """ The basic approach is that captured vars need to be put on the heap and @@ -257,7 +258,7 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode = # add 'new' statement: result.add newCall(getSysSym(g, n.info, "internalNew"), env) result.add makeClosure(g, iter, env, n.info) - + proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode = let envParam = getHiddenParam(g, owner) let obj = envParam.typ.lastSon @@ -390,7 +391,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) = if innerProc: if s.isIterator: c.somethingToDo = true if not c.processed.containsOrIncl(s.id): - detectCapturedVars(s.getBody, s, c) + let body = transformBody(c.graph, s) + detectCapturedVars(body, s, c) let ow = s.skipGenericOwner if ow == owner: if owner.isIterator: @@ -651,14 +653,17 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass; # echo renderTree(s.getBody, {renderIds}) let oldInContainer = c.inContainer c.inContainer = 0 - var body = liftCapturedVars(s.getBody, s, d, c) + var body = transformBody(d.graph, s) + body = liftCapturedVars(body, s, d, c) if c.envvars.getOrDefault(s.id).isNil: - s.ast.sons[bodyPos] = body + s.transformedBody = body else: - s.ast.sons[bodyPos] = newTree(nkStmtList, rawClosureCreation(s, d, c), body) + s.transformedBody = newTree(nkStmtList, rawClosureCreation(s, d, c), body) c.inContainer = oldInContainer + if s.typ.callConv == ccClosure: result = symToClosure(n, owner, d, c) + elif s.id in d.capturedVars: if s.owner != owner: result = accessViaEnvParam(d.graph, n, owner) diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index dc12e25b7..603def326 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -405,6 +405,8 @@ proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym; varSection, varInit, call, barrier, fv: PNode; spawnKind: TSpawnResult): PSym = var body = newNodeI(nkStmtList, f.info) + body.flags.incl nfTransf # do not transform further + var threadLocalBarrier: PSym if barrier != nil: var varSection2 = newNodeI(nkVarSection, barrier.info) diff --git a/compiler/sem.nim b/compiler/sem.nim index 0d336724c..97a47ceca 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -583,7 +583,7 @@ proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode = result = buildEchoStmt(c, result) if c.config.cmd == cmdIdeTools: appendToModule(c.module, result) - result = transformStmt(c.graph, c.module, result) + trackTopLevelStmt(c.graph, c.module, result) proc recoverContext(c: PContext) = # clean up in case of a semantic error: We clean up the stacks, etc. This is diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 53c9af07a..5565e8ed9 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -413,14 +413,15 @@ proc getAppType(n: PNode; g: ModuleGraph): PNode = result = newStrNodeT("console", n, g) proc rangeCheck(n: PNode, value: BiggestInt; g: ModuleGraph) = - var err = false - if n.typ.skipTypes({tyRange}).kind in {tyUInt..tyUInt64}: - err = value <% firstOrd(g.config, n.typ) or value >% lastOrd(g.config, n.typ, fixedUnsigned=true) - else: - err = value < firstOrd(g.config, n.typ) or value > lastOrd(g.config, n.typ) - if err: - localError(g.config, n.info, "cannot convert " & $value & - " to " & typeToString(n.typ)) + if tfUncheckedArray notin n.typ.flags: + var err = false + if n.typ.skipTypes({tyRange}).kind in {tyUInt..tyUInt64}: + err = value <% firstOrd(g.config, n.typ) or value >% lastOrd(g.config, n.typ, fixedUnsigned=true) + else: + err = value < firstOrd(g.config, n.typ) or value > lastOrd(g.config, n.typ) + if err: + localError(g.config, n.info, "cannot convert " & $value & + " to " & typeToString(n.typ)) proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode = let dstTyp = skipTypes(n.typ, abstractRange) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index b6936d1be..de2e10a9b 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -146,9 +146,8 @@ proc instantiateBody(c: PContext, n, params: PNode, result, orig: PSym) = idTablePut(symMap, params[i].sym, result.typ.n[param.position+1].sym) freshGenSyms(b, result, orig, symMap) b = semProcBody(c, b) - b = hloBody(c, b) - n.sons[bodyPos] = transformBody(c.graph, c.module, b, result) - #echo "code instantiated ", result.name.s + result.ast[bodyPos] = hloBody(c, b) + trackProc(c.graph, result, result.ast[bodyPos]) excl(result.flags, sfForward) dec c.inGenericInst diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 0a9de674b..c1bdb08a8 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -9,7 +9,7 @@ import intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees, - wordrecg, strutils, options, guards, writetracking, lineinfos, + wordrecg, strutils, options, guards, writetracking, lineinfos, semfold, modulegraphs when defined(useDfa): @@ -48,6 +48,7 @@ type tags: PNode # list of tags bottom, inTryStmt: int owner: PSym + owner_module: PSym init: seq[int] # list of initialized variables guards: TModel # nested guards locked: seq[PNode] # locked locations @@ -562,8 +563,10 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) = if op != nil and op.kind == tyProc and n.skipConv.kind != nkNilLit: internalAssert tracked.config, op.n.sons[0].kind == nkEffectList var effectList = op.n.sons[0] - let s = n.skipConv - if s.kind == nkSym and s.sym.kind in routineKinds: + var s = n.skipConv + if s.kind == nkCast and s[1].typ.kind == tyProc: + s = s[1] + if s.kind == nkSym and s.sym.kind in routineKinds and isNoEffectList(effectList): propagateEffects(tracked, n, s.sym) elif isNoEffectList(effectList): if isForwardedProc(n): @@ -709,9 +712,13 @@ proc track(tracked: PEffects, n: PNode) = for i in 0 ..< safeLen(n): track(tracked, n.sons[i]) of nkCallKinds: + if getConstExpr(tracked.owner_module, n, tracked.graph) != nil: + return # p's effects are ours too: - let a = n.sons[0] + var a = n.sons[0] let op = a.typ + if a.kind == nkCast and a[1].typ.kind == tyProc: + a = a[1] # XXX: in rare situations, templates and macros will reach here after # calling getAst(templateOrMacro()). Currently, templates and macros # are indistinguishable from normal procs (both have tyProc type) and @@ -934,6 +941,7 @@ proc initEffects(g: ModuleGraph; effects: PNode; s: PSym; t: var TEffects) = t.exc = effects.sons[exceptionEffects] t.tags = effects.sons[tagEffects] t.owner = s + t.owner_module = s.getModule t.init = @[] t.guards.s = @[] t.guards.o = initOperators(g) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index a286cdc85..b97a56178 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1328,8 +1328,8 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = pushProcCon(c, s) addResult(c, s.typ.sons[0], n.info, skProc) addResultNode(c, n) - let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos])) - n.sons[bodyPos] = transformBody(c.graph, c.module, semBody, s) + s.ast[bodyPos] = hloBody(c, semProcBody(c, n.sons[bodyPos])) + trackProc(c.graph, s, s.ast[bodyPos]) popProcCon(c) elif efOperand notin flags: localError(c.config, n.info, errGenericLambdaNotAllowed) @@ -1369,8 +1369,8 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode = pushProcCon(c, s) addResult(c, n.typ.sons[0], n.info, skProc) addResultNode(c, n) - let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos])) - n.sons[bodyPos] = transformBody(c.graph, c.module, semBody, s) + s.ast[bodyPos] = hloBody(c, semProcBody(c, n.sons[bodyPos])) + trackProc(c.graph, s, s.ast[bodyPos]) popProcCon(c) popOwner(c) closeScope(c) @@ -1683,10 +1683,10 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, if lfDynamicLib notin s.loc.flags: # no semantic checking for importc: - let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos])) + s.ast[bodyPos] = hloBody(c, semProcBody(c, n.sons[bodyPos])) # unfortunately we cannot skip this step when in 'system.compiles' # context as it may even be evaluated in 'system.compiles': - n.sons[bodyPos] = transformBody(c.graph, c.module, semBody, s) + trackProc(c.graph, s, s.ast[bodyPos]) else: if s.typ.sons[0] != nil and kind != skIterator: addDecl(c, newSym(skUnknown, getIdent(c.cache, "result"), nil, n.info)) diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index b05fb37ae..be6ffc586 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -30,6 +30,11 @@ proc checkConstructedType*(conf: ConfigRef; info: TLineInfo, typ: PType) = localError(conf, info, "type 'var var' is not allowed") elif computeSize(conf, t) == szIllegalRecursion: localError(conf, info, "illegal recursion in type '" & typeToString(t) & "'") + + t = typ.skipTypes({tyGenericInst}) + if t.kind == tyArray and tfUncheckedArray in t.flags: + t[0].flags.incl tfUncheckedArray # mark range of unchecked array also unchecked + when false: if t.kind == tyObject and t.sons[0] != nil: if t.sons[0].kind != tyObject or tfFinal in t.sons[0].flags: diff --git a/compiler/transf.nim b/compiler/transf.nim index c2f6c799a..8721661df 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -21,9 +21,13 @@ import intsets, strutils, options, ast, astalgo, trees, treetab, msgs, lookups, idents, renderer, types, passes, semfold, magicsys, cgmeth, - lambdalifting, sempass2, lowerings, destroyer, liftlocals, closureiters, + sempass2, lowerings, destroyer, liftlocals, modulegraphs, lineinfos +proc transformBody*(g: ModuleGraph, prc: PSym, cache = true): PNode + +import closureiters, lambdalifting + type PTransNode* = distinct PNode @@ -62,18 +66,25 @@ proc newTransNode(kind: TNodeKind, n: PNode, var x = newNodeIT(kind, n.info, n.typ) newSeq(x.sons, sons) x.typ = n.typ +# x.flags = n.flags result = x.PTransNode +proc add(a, b: PTransNode) {.inline.} = addSon(PNode(a), PNode(b)) +proc len(a: PTransNode): int {.inline.} = sonsLen(a.PNode) + proc `[]=`(a: PTransNode, i: int, x: PTransNode) {.inline.} = var n = PNode(a) n.sons[i] = PNode(x) +proc `[]=`(a: PTransNode, i: BackwardsIndex, x: PTransNode) {.inline.} = + `[]=`(a, a.len - i.int, x) + proc `[]`(a: PTransNode, i: int): PTransNode {.inline.} = var n = PNode(a) result = n.sons[i].PTransNode -proc add(a, b: PTransNode) {.inline.} = addSon(PNode(a), PNode(b)) -proc len(a: PTransNode): int {.inline.} = result = sonsLen(a.PNode) +proc `[]`(a: PTransNode, i: BackwardsIndex): PTransNode {.inline.} = + `[]`(a, a.len - i.int) proc newTransCon(owner: PSym): PTransCon = assert owner != nil @@ -118,6 +129,8 @@ proc newAsgnStmt(c: PTransf, kind: TNodeKind, le: PNode, ri: PTransNode): PTrans proc transformSymAux(c: PTransf, n: PNode): PNode = let s = n.sym if s.typ != nil and s.typ.callConv == ccClosure: + if s.kind in routineKinds: + discard transformBody(c.graph, s) if s.kind == skIterator: if c.tooEarly: return n else: return liftIterSym(c.graph, n, getCurrOwner(c)) @@ -146,7 +159,7 @@ proc transformSymAux(c: PTransf, n: PNode): PNode = return tc = tc.next result = b - + proc transformSym(c: PTransf, n: PNode): PTransNode = result = PTransNode(transformSymAux(c, n)) @@ -561,9 +574,10 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = c.breakSyms.add(labl) if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or call.sons[0].typ.callConv == ccClosure: - n.sons[length-1] = transformLoopBody(c, n.sons[length-1]).PNode - n.sons[length-2] = transform(c, n.sons[length-2]).PNode - result[1] = lambdalifting.liftForLoop(c.graph, n, getCurrOwner(c)).PTransNode + result[1] = n.PTransNode + result[1][^1] = transformLoopBody(c, n[^1]) + result[1][^2] = transform(c, n[^2]) + result[1] = lambdalifting.liftForLoop(c.graph, result[1].PNode, getCurrOwner(c)).PTransNode discard c.breakSyms.pop return result @@ -617,7 +631,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = add(stmtList, newAsgnStmt(c, nkFastAsgn, temp, arg.PTransNode)) idNodeTablePut(newC.mapping, formal, temp) - var body = iter.getBody.copyTree + let body = transformBody(c.graph, iter).copyTree pushInfoContext(c.graph.config, n.info) # XXX optimize this somehow. But the check "c.inlining" is not correct: var symMap: TIdTable @@ -1040,27 +1054,36 @@ template liftDefer(c, root) = if c.deferDetected: liftDeferAux(root) -proc transformBody*(g: ModuleGraph; module: PSym, n: PNode, prc: PSym): PNode = - if nfTransf in n.flags or prc.kind in {skTemplate}: - result = n +proc transformBody*(g: ModuleGraph, prc: PSym, cache = true): PNode = + assert prc.kind in routineKinds + + if prc.transformedBody != nil: + result = prc.transformedBody + elif nfTransf in prc.ast[bodyPos].flags or prc.kind in {skTemplate}: + result = prc.ast[bodyPos] else: - var c = openTransf(g, module, "") - result = liftLambdas(g, prc, n, c.tooEarly) - #result = n + + prc.transformedBody = newNode(nkEmpty) # protects from recursion + var c = openTransf(g, prc.getModule, "") + result = liftLambdas(g, prc, prc.ast[bodyPos], c.tooEarly) result = processTransf(c, result, prc) liftDefer(c, result) - #result = liftLambdas(prc, result) - when useEffectSystem: trackProc(g, prc, result) result = liftLocalsIfRequested(prc, result, g.cache, g.config) if c.needsDestroyPass: #and newDestructors: result = injectDestructorCalls(g, prc, result) if prc.isIterator: result = g.transformClosureIterator(prc, result) - + incl(result.flags, nfTransf) - #if prc.name.s == "testbody": - # echo renderTree(result) + + let cache = cache or prc.typ.callConv == ccInline + if cache: + # genProc for inline procs will be called multiple times from diffrent modules, + # it is important to transform exactly once to get sym ids and locations right + prc.transformedBody = result + else: + prc.transformedBody = nil proc transformStmt*(g: ModuleGraph; module: PSym, n: PNode): PNode = if nfTransf in n.flags: @@ -1070,9 +1093,6 @@ proc transformStmt*(g: ModuleGraph; module: PSym, n: PNode): PNode = result = processTransf(c, n, module) liftDefer(c, result) #result = liftLambdasForTopLevel(module, result) - when useEffectSystem: trackTopLevelStmt(g, module, result) - #if n.info ?? "temp.nim": - # echo renderTree(result, {renderIds}) if c.needsDestroyPass: result = injectDestructorCalls(g, module, result) incl(result.flags, nfTransf) diff --git a/compiler/vm.nim b/compiler/vm.nim index 4255ba3fc..420934470 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -924,6 +924,17 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = regs[ra].node.flags.incl nfIsRef else: stackTrace(c, tos, pc, "node is not a symbol") + of opcGetImplTransf: + decodeB(rkNode) + let a = regs[rb].node + if a.kind == nkSym: + regs[ra].node = if a.sym.ast.isNil: newNode(nkNilLit) + else: + let ast = a.sym.ast.shallowCopy + for i in 0..<a.sym.ast.len: + ast[i] = a.sym.ast[i] + ast[bodyPos] = transformBody(c.graph, a.sym) + ast.copyTree() of opcSymOwner: decodeB(rkNode) let a = regs[rb].node diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index 17f48da07..875ae5a52 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -107,6 +107,7 @@ type opcEqIdent, opcStrToIdent, opcGetImpl, + opcGetImplTransf opcEcho, opcIndCall, # dest = call regStart, n; where regStart = fn, arg1, ... diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 14d411f9b..c59581aca 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -29,7 +29,7 @@ import strutils, ast, astalgo, types, msgs, renderer, vmdef, - trees, intsets, magicsys, options, lowerings, lineinfos + trees, intsets, magicsys, options, lowerings, lineinfos, transf import platform from os import splitFile @@ -1122,6 +1122,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) = of mStaticExec: genBinaryABCD(c, n, dest, opcGorge) of mNLen: genUnaryABI(c, n, dest, opcLenSeq, nimNodeFlag) of mGetImpl: genUnaryABC(c, n, dest, opcGetImpl) + of mGetImplTransf: genUnaryABC(c, n, dest, opcGetImplTransf) of mSymOwner: genUnaryABC(c, n, dest, opcSymOwner) of mNChild: genBinaryABC(c, n, dest, opcNChild) of mNSetChild: genVoidABC(c, n, dest, opcNSetChild) @@ -2129,7 +2130,7 @@ proc genProc(c: PCtx; s: PSym): int = s.ast.sons[miscPos] = x # thanks to the jmp we can add top level statements easily and also nest # procs easily: - let body = s.getBody + let body = transformBody(c.graph, s, cache = not isCompileTimeProc(s)) let procStart = c.xjmp(body, opcJmp, 0) var p = PProc(blocks: @[], sym: s) let oldPrc = c.prc |