summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/dfa.nim4
-rw-r--r--compiler/lambdalifting.nim175
-rw-r--r--compiler/lowerings.nim124
3 files changed, 154 insertions, 149 deletions
diff --git a/compiler/dfa.nim b/compiler/dfa.nim
index bc9d13870..0784151af 100644
--- a/compiler/dfa.nim
+++ b/compiler/dfa.nim
@@ -102,14 +102,14 @@ proc genLabel(c: Con): TPosition =
 
 proc jmpBack(c: var Con, n: PNode, p = TPosition(0)) =
   let dist = p.int - c.code.len
-  internalAssert(-0x7fff < dist and dist < 0x7fff)
+  doAssert(-0x7fff < dist and dist < 0x7fff)
   c.code.add Instr(n: n, kind: goto, dest: dist)
 
 proc patch(c: var Con, p: TPosition) =
   # patch with current index
   let p = p.int
   let diff = c.code.len - p
-  internalAssert(-0x7fff < diff and diff < 0x7fff)
+  doAssert(-0x7fff < diff and diff < 0x7fff)
   c.code[p].dest = diff
 
 proc popBlock(c: var Con; oldLen: int) =
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 775748425..2410f1d36 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -11,7 +11,8 @@
 
 import
   intsets, strutils, options, ast, astalgo, trees, treetab, msgs, os,
-  idents, renderer, types, magicsys, rodread, lowerings, tables
+  idents, renderer, types, magicsys, rodread, lowerings, tables,
+  modulegraphs
 
 discard """
   The basic approach is that captured vars need to be put on the heap and
@@ -125,25 +126,25 @@ proc newCall(a: PSym, b: PNode): PNode =
   result.add newSymNode(a)
   result.add b
 
-proc createStateType(iter: PSym): PType =
+proc createStateType(g: ModuleGraph; iter: PSym): PType =
   var n = newNodeI(nkRange, iter.info)
   addSon(n, newIntNode(nkIntLit, -1))
   addSon(n, newIntNode(nkIntLit, 0))
   result = newType(tyRange, iter)
   result.n = n
-  var intType = nilOrSysInt()
+  var intType = nilOrSysInt(g)
   if intType.isNil: intType = newType(tyInt, iter)
   rawAddSon(result, intType)
 
-proc createStateField(iter: PSym): PSym =
+proc createStateField(g: ModuleGraph; iter: PSym): PSym =
   result = newSym(skField, getIdent(":state"), iter, iter.info)
-  result.typ = createStateType(iter)
+  result.typ = createStateType(g, iter)
 
-proc createEnvObj(owner: PSym; info: TLineInfo): PType =
+proc createEnvObj(g: ModuleGraph; owner: PSym; info: TLineInfo): PType =
   # YYY meh, just add the state field for every closure for now, it's too
   # hard to figure out if it comes from a closure iterator:
-  result = createObj(owner, info, final=false)
-  rawAddField(result, createStateField(owner))
+  result = createObj(g, owner, info, final=false)
+  rawAddField(result, createStateField(g, owner))
 
 proc getIterResult(iter: PSym): PSym =
   if resultPos < iter.ast.len:
@@ -166,7 +167,7 @@ proc addHiddenParam(routine: PSym, param: PSym) =
   assert sfFromGeneric in param.flags
   #echo "produced environment: ", param.id, " for ", routine.id
 
-proc getHiddenParam(routine: PSym): PSym =
+proc getHiddenParam(g: ModuleGraph; routine: PSym): PSym =
   let params = routine.ast.sons[paramsPos]
   let hidden = lastSon(params)
   if hidden.kind == nkSym and hidden.sym.kind == skParam and hidden.sym.name.s == paramName:
@@ -174,7 +175,7 @@ proc getHiddenParam(routine: PSym): PSym =
     assert sfFromGeneric in result.flags
   else:
     # writeStackTrace()
-    localError(routine.info, "internal error: could not find env param for " & routine.name.s)
+    localError(g.config, routine.info, "internal error: could not find env param for " & routine.name.s)
     result = routine
 
 proc getEnvParam*(routine: PSym): PSym =
@@ -208,14 +209,14 @@ proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode =
   result.sons[0] = le
   result.sons[1] = ri
 
-proc makeClosure*(prc: PSym; env: PNode; info: TLineInfo): PNode =
+proc makeClosure*(g: ModuleGraph; prc: PSym; env: PNode; info: TLineInfo): PNode =
   result = newNodeIT(nkClosure, info, prc.typ)
   result.add(newSymNode(prc))
   if env == nil:
-    result.add(newNodeIT(nkNilLit, info, getSysType(tyNil)))
+    result.add(newNodeIT(nkNilLit, info, getSysType(g, info, tyNil)))
   else:
     if env.skipConv.kind == nkClosure:
-      localError(info, "internal error: taking closure of closure")
+      localError(g.config, info, "internal error: taking closure of closure")
     result.add(env)
 
 proc interestingIterVar(s: PSym): bool {.inline.} =
@@ -232,7 +233,7 @@ proc liftingHarmful(owner: PSym): bool {.inline.} =
   let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro
   result = gCmd == cmdCompileToJS and not isCompileTime
 
-proc liftIterSym*(n: PNode; owner: PSym): PNode =
+proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
   # transforms  (iter)  to  (let env = newClosure[iter](); (iter, env))
   if liftingHarmful(owner): return n
   let iter = n.sym
@@ -240,10 +241,10 @@ proc liftIterSym*(n: PNode; owner: PSym): PNode =
 
   result = newNodeIT(nkStmtListExpr, n.info, n.typ)
 
-  let hp = getHiddenParam(iter)
+  let hp = getHiddenParam(g, iter)
   var env: PNode
   if owner.isIterator:
-    let it = getHiddenParam(owner)
+    let it = getHiddenParam(g, owner)
     addUniqueField(it.typ.sons[0], hp)
     env = indirectAccess(newSymNode(it), hp, hp.info)
   else:
@@ -255,11 +256,11 @@ proc liftIterSym*(n: PNode; owner: PSym): PNode =
     addVar(v, env)
     result.add(v)
   # add 'new' statement:
-  result.add newCall(getSysSym"internalNew", env)
-  result.add makeClosure(iter, env, n.info)
+  result.add newCall(getSysSym(g, n.info, "internalNew"), env)
+  result.add makeClosure(g, iter, env, n.info)
 
-proc freshVarForClosureIter*(s, owner: PSym): PNode =
-  let envParam = getHiddenParam(owner)
+proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode =
+  let envParam = getHiddenParam(g, owner)
   let obj = envParam.typ.lastSon
   addField(obj, s)
 
@@ -269,18 +270,18 @@ proc freshVarForClosureIter*(s, owner: PSym): PNode =
   if field != nil:
     result = rawIndirectAccess(access, field, s.info)
   else:
-    localError(s.info, "internal error: cannot generate fresh variable")
+    localError(g.config, s.info, "internal error: cannot generate fresh variable")
     result = access
 
 # ------------------ new stuff -------------------------------------------
 
-proc markAsClosure(owner: PSym; n: PNode) =
+proc markAsClosure(g: ModuleGraph; owner: PSym; n: PNode) =
   let s = n.sym
   if illegalCapture(s):
-    localError(n.info, "illegal capture '$1' of type <$2> which is declared here: $3" %
+    localError(g.config, n.info, "illegal capture '$1' of type <$2> which is declared here: $3" %
       [s.name.s, typeToString(s.typ), $s.info])
   elif owner.typ.callConv notin {ccClosure, ccDefault}:
-    localError(n.info, "illegal capture '$1' because '$2' has the calling convention: <$3>" %
+    localError(g.config, n.info, "illegal capture '$1' because '$2' has the calling convention: <$3>" %
       [s.name.s, owner.name.s, CallingConvToStr[owner.typ.callConv]])
   incl(owner.typ.flags, tfCapturesEnv)
   owner.typ.callConv = ccClosure
@@ -290,12 +291,14 @@ type
     processed, capturedVars: IntSet
     ownerToType: Table[int, PType]
     somethingToDo: bool
+    graph: ModuleGraph
 
-proc initDetectionPass(fn: PSym): DetectionPass =
+proc initDetectionPass(g: ModuleGraph; fn: PSym): DetectionPass =
   result.processed = initIntSet()
   result.capturedVars = initIntSet()
   result.ownerToType = initTable[int, PType]()
   result.processed.incl(fn.id)
+  result.graph = g
 
 discard """
 proc outer =
@@ -312,7 +315,7 @@ proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym;
   result = c.ownerToType.getOrDefault(owner.id)
   if result.isNil:
     result = newType(tyRef, owner)
-    let obj = createEnvObj(owner, info)
+    let obj = createEnvObj(c.graph, owner, info)
     rawAddSon(result, obj)
     c.ownerToType[owner.id] = result
 
@@ -321,13 +324,13 @@ proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
   let obj = refObj.lastSon
   let fieldType = c.getEnvTypeForOwner(dep, info) #getHiddenParam(dep).typ
   if refObj == fieldType:
-    localError(dep.info, "internal error: invalid up reference computed")
+    localError(c.graph.config, dep.info, "internal error: invalid up reference computed")
 
   let upIdent = getIdent(upName)
   let upField = lookupInRecord(obj.n, upIdent)
   if upField != nil:
     if upField.typ != fieldType:
-      localError(dep.info, "internal error: up references do not agree")
+      localError(c.graph.config, dep.info, "internal error: up references do not agree")
   else:
     let result = newSym(skField, upIdent, obj.owner, obj.owner.info)
     result.typ = fieldType
@@ -369,7 +372,7 @@ proc addClosureParam(c: var DetectionPass; fn: PSym; info: TLineInfo) =
     cp.typ = t
     addHiddenParam(fn, cp)
   elif cp.typ != t and fn.kind != skIterator:
-    localError(fn.info, "internal error: inconsistent environment type")
+    localError(c.graph.config, fn.info, "internal error: inconsistent environment type")
   #echo "adding closure to ", fn.name.s
 
 proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
@@ -395,7 +398,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
         addClosureParam(c, owner, n.info)
         if interestingIterVar(s):
           if not c.capturedVars.containsOrIncl(s.id):
-            let obj = getHiddenParam(owner).typ.lastSon
+            let obj = getHiddenParam(c.graph, owner).typ.lastSon
             #let obj = c.getEnvTypeForOwner(s.owner).lastSon
             addField(obj, s)
       # but always return because the rest of the proc is only relevant when
@@ -415,7 +418,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
       """
       # mark 'owner' as taking a closure:
       c.somethingToDo = true
-      markAsClosure(owner, n)
+      markAsClosure(c.graph, owner, n)
       addClosureParam(c, owner, n.info)
       #echo "capturing ", n.info
       # variable 's' is actually captured:
@@ -440,7 +443,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
           """
           let up = w.skipGenericOwner
           #echo "up for ", w.name.s, " up ", up.name.s
-          markAsClosure(w, n)
+          markAsClosure(c.graph, w, n)
           addClosureParam(c, w, n.info) # , ow
           createUpField(c, w, up, n.info)
           w = up
@@ -467,10 +470,10 @@ proc initLiftingPass(fn: PSym): LiftingPass =
   result.processed.incl(fn.id)
   result.envVars = initTable[int, PNode]()
 
-proc accessViaEnvParam(n: PNode; owner: PSym): PNode =
+proc accessViaEnvParam(g: ModuleGraph; n: PNode; owner: PSym): PNode =
   let s = n.sym
   # Type based expression construction for simplicity:
-  let envParam = getHiddenParam(owner)
+  let envParam = getHiddenParam(g, owner)
   if not envParam.isNil:
     var access = newSymNode(envParam)
     while true:
@@ -482,7 +485,7 @@ proc accessViaEnvParam(n: PNode; owner: PSym): PNode =
       let upField = lookupInRecord(obj.n, getIdent(upName))
       if upField == nil: break
       access = rawIndirectAccess(access, upField, n.info)
-  localError(n.info, "internal error: environment misses: " & s.name.s)
+  localError(g.config, n.info, "internal error: environment misses: " & s.name.s)
   result = n
 
 proc newEnvVar(owner: PSym; typ: PType): PNode =
@@ -501,22 +504,22 @@ proc newEnvVar(owner: PSym; typ: PType): PNode =
 proc setupEnvVar(owner: PSym; d: DetectionPass;
                  c: var LiftingPass): PNode =
   if owner.isIterator:
-    return getHiddenParam(owner).newSymNode
+    return getHiddenParam(d.graph, owner).newSymNode
   result = c.envvars.getOrDefault(owner.id)
   if result.isNil:
     let envVarType = d.ownerToType.getOrDefault(owner.id)
     if envVarType.isNil:
-      localError owner.info, "internal error: could not determine closure type"
+      localError d.graph.config, owner.info, "internal error: could not determine closure type"
     result = newEnvVar(owner, envVarType)
     c.envVars[owner.id] = result
 
-proc getUpViaParam(owner: PSym): PNode =
-  let p = getHiddenParam(owner)
+proc getUpViaParam(g: ModuleGraph; owner: PSym): PNode =
+  let p = getHiddenParam(g, owner)
   result = p.newSymNode
   if owner.isIterator:
     let upField = lookupInRecord(p.typ.lastSon.n, getIdent(upName))
     if upField == nil:
-      localError(owner.info, "could not find up reference for closure iter")
+      localError(g.config, owner.info, "could not find up reference for closure iter")
     else:
       result = rawIndirectAccess(result, upField, p.info)
 
@@ -526,7 +529,7 @@ proc rawClosureCreation(owner: PSym;
 
   var env: PNode
   if owner.isIterator:
-    env = getHiddenParam(owner).newSymNode
+    env = getHiddenParam(d.graph, owner).newSymNode
   else:
     env = setupEnvVar(owner, d, c)
     if env.kind == nkSym:
@@ -534,7 +537,7 @@ proc rawClosureCreation(owner: PSym;
       addVar(v, env)
       result.add(v)
     # add 'new' statement:
-    result.add(newCall(getSysSym"internalNew", env))
+    result.add(newCall(getSysSym(d.graph, env.info, "internalNew"), env))
     # add assignment statements for captured parameters:
     for i in 1..<owner.typ.n.len:
       let local = owner.typ.n[i].sym
@@ -545,7 +548,7 @@ proc rawClosureCreation(owner: PSym;
 
   let upField = lookupInRecord(env.typ.lastSon.n, getIdent(upName))
   if upField != nil:
-    let up = getUpViaParam(owner)
+    let up = getUpViaParam(d.graph, owner)
     if up != nil and upField.typ == up.typ:
       result.add(newAsgnStmt(rawIndirectAccess(env, upField, env.info),
                  up, env.info))
@@ -553,7 +556,7 @@ proc rawClosureCreation(owner: PSym;
     #  result.add(newAsgnStmt(rawIndirectAccess(env, upField, env.info),
     #             oldenv, env.info))
     else:
-      localError(env.info, "internal error: cannot create up reference")
+      localError(d.graph.config, env.info, "internal error: cannot create up reference")
 
 proc closureCreationForIter(iter: PNode;
                             d: DetectionPass; c: var LiftingPass): PNode =
@@ -561,10 +564,10 @@ proc closureCreationForIter(iter: PNode;
   let owner = iter.sym.skipGenericOwner
   var v = newSym(skVar, getIdent(envName), owner, iter.info)
   incl(v.flags, sfShadowed)
-  v.typ = getHiddenParam(iter.sym).typ
+  v.typ = getHiddenParam(d.graph, iter.sym).typ
   var vnode: PNode
   if owner.isIterator:
-    let it = getHiddenParam(owner)
+    let it = getHiddenParam(d.graph, owner)
     addUniqueField(it.typ.sons[0], v)
     vnode = indirectAccess(newSymNode(it), v, v.info)
   else:
@@ -572,7 +575,7 @@ proc closureCreationForIter(iter: PNode;
     var vs = newNodeI(nkVarSection, iter.info)
     addVar(vs, vnode)
     result.add(vs)
-  result.add(newCall(getSysSym"internalNew", vnode))
+  result.add(newCall(getSysSym(d.graph, iter.info, "internalNew"), vnode))
 
   let upField = lookupInRecord(v.typ.lastSon.n, getIdent(upName))
   if upField != nil:
@@ -581,8 +584,8 @@ proc closureCreationForIter(iter: PNode;
       result.add(newAsgnStmt(rawIndirectAccess(vnode, upField, iter.info),
                  u, iter.info))
     else:
-      localError(iter.info, "internal error: cannot create up reference for iter")
-  result.add makeClosure(iter.sym, vnode, iter.info)
+      localError(d.graph.config, iter.info, "internal error: cannot create up reference for iter")
+  result.add makeClosure(d.graph, iter.sym, vnode, iter.info)
 
 proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass;
                      c: var LiftingPass): PNode =
@@ -592,11 +595,11 @@ proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass;
   if field != nil:
     result = rawIndirectAccess(access, field, n.info)
   else:
-    localError(n.info, "internal error: not part of closure object type")
+    localError(d.graph.config, n.info, "internal error: not part of closure object type")
     result = n
 
-proc getStateField(owner: PSym): PSym =
-  getHiddenParam(owner).typ.sons[0].n.sons[0].sym
+proc getStateField(g: ModuleGraph; owner: PSym): PSym =
+  getHiddenParam(g, owner).typ.sons[0].n.sons[0].sym
 
 proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
                       c: var LiftingPass): PNode
@@ -604,8 +607,8 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
 proc transformYield(n: PNode; owner: PSym; d: DetectionPass;
                     c: var LiftingPass): PNode =
   if c.inContainer > 0:
-    localError(n.info, "invalid control flow: 'yield' within a constructor")
-  let state = getStateField(owner)
+    localError(d.graph.config, n.info, "invalid control flow: 'yield' within a constructor")
+  let state = getStateField(d.graph, owner)
   assert state != nil
   assert state.typ != nil
   assert state.typ.n != nil
@@ -615,7 +618,8 @@ proc transformYield(n: PNode; owner: PSym; d: DetectionPass;
   var stateAsgnStmt = newNodeI(nkAsgn, n.info)
   stateAsgnStmt.add(rawIndirectAccess(newSymNode(getEnvParam(owner)),
                     state, n.info))
-  stateAsgnStmt.add(newIntTypeNode(nkIntLit, stateNo, getSysType(tyInt)))
+  stateAsgnStmt.add(newIntTypeNode(nkIntLit, stateNo,
+                    getSysType(d.graph, n.info, tyInt)))
 
   var retStmt = newNodeI(nkReturnStmt, n.info)
   if n.sons[0].kind != nkEmpty:
@@ -628,7 +632,8 @@ proc transformYield(n: PNode; owner: PSym; d: DetectionPass;
     retStmt.add(emptyNode)
 
   var stateLabelStmt = newNodeI(nkState, n.info)
-  stateLabelStmt.add(newIntTypeNode(nkIntLit, stateNo, getSysType(tyInt)))
+  stateLabelStmt.add(newIntTypeNode(nkIntLit, stateNo,
+                     getSysType(d.graph, n.info, tyInt)))
 
   result = newNodeI(nkStmtList, n.info)
   result.add(stateAsgnStmt)
@@ -637,16 +642,16 @@ proc transformYield(n: PNode; owner: PSym; d: DetectionPass;
 
 proc transformReturn(n: PNode; owner: PSym; d: DetectionPass;
                      c: var LiftingPass): PNode =
-  let state = getStateField(owner)
+  let state = getStateField(d.graph, owner)
   result = newNodeI(nkStmtList, n.info)
   var stateAsgnStmt = newNodeI(nkAsgn, n.info)
   stateAsgnStmt.add(rawIndirectAccess(newSymNode(getEnvParam(owner)),
                     state, n.info))
-  stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt)))
+  stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(d.graph, n.info, tyInt)))
   result.add(stateAsgnStmt)
   result.add(n)
 
-proc wrapIterBody(n: PNode; owner: PSym): PNode =
+proc wrapIterBody(g: ModuleGraph; n: PNode; owner: PSym): PNode =
   if not owner.isIterator: return n
   when false:
     # unfortunately control flow is still convoluted and we can end up
@@ -660,7 +665,7 @@ proc wrapIterBody(n: PNode; owner: PSym): PNode =
   let info = n.info
   result = newNodeI(nkStmtList, info)
   var gs = newNodeI(nkGotoState, info)
-  gs.add(rawIndirectAccess(newSymNode(owner.getHiddenParam), getStateField(owner), info))
+  gs.add(rawIndirectAccess(newSymNode(getHiddenParam(g, owner)), getStateField(g, owner), info))
   result.add(gs)
   var state0 = newNodeI(nkState, info)
   state0.add(newIntNode(nkIntLit, 0))
@@ -669,9 +674,9 @@ proc wrapIterBody(n: PNode; owner: PSym): PNode =
   result.add(n)
 
   var stateAsgnStmt = newNodeI(nkAsgn, info)
-  stateAsgnStmt.add(rawIndirectAccess(newSymNode(owner.getHiddenParam),
-                    getStateField(owner), info))
-  stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt)))
+  stateAsgnStmt.add(rawIndirectAccess(newSymNode(getHiddenParam(g, owner)),
+                    getStateField(g, owner), info))
+  stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(g, info, tyInt)))
   result.add(stateAsgnStmt)
 
 proc symToClosure(n: PNode; owner: PSym; d: DetectionPass;
@@ -679,25 +684,25 @@ proc symToClosure(n: PNode; owner: PSym; d: DetectionPass;
   let s = n.sym
   if s == owner:
     # recursive calls go through (lambda, hiddenParam):
-    let available = getHiddenParam(owner)
-    result = makeClosure(s, available.newSymNode, n.info)
+    let available = getHiddenParam(d.graph, owner)
+    result = makeClosure(d.graph, s, available.newSymNode, n.info)
   elif s.isIterator:
     result = closureCreationForIter(n, d, c)
   elif s.skipGenericOwner == owner:
     # direct dependency, so use the outer's env variable:
-    result = makeClosure(s, setupEnvVar(owner, d, c), n.info)
+    result = makeClosure(d.graph, s, setupEnvVar(owner, d, c), n.info)
   else:
-    let available = getHiddenParam(owner)
-    let wanted = getHiddenParam(s).typ
+    let available = getHiddenParam(d.graph, owner)
+    let wanted = getHiddenParam(d.graph, s).typ
     # ugh: call through some other inner proc;
     var access = newSymNode(available)
     while true:
       if access.typ == wanted:
-        return makeClosure(s, access, n.info)
+        return makeClosure(d.graph, s, access, n.info)
       let obj = access.typ.sons[0]
       let upField = lookupInRecord(obj.n, getIdent(upName))
       if upField == nil:
-        localError(n.info, "internal error: no environment found")
+        localError(d.graph.config, n.info, "internal error: no environment found")
         return n
       access = rawIndirectAccess(access, upField, n.info)
 
@@ -713,7 +718,7 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
         #  echo renderTree(s.getBody, {renderIds})
         let oldInContainer = c.inContainer
         c.inContainer = 0
-        let body = wrapIterBody(liftCapturedVars(s.getBody, s, d, c), s)
+        let body = wrapIterBody(d.graph, liftCapturedVars(s.getBody, s, d, c), s)
         if c.envvars.getOrDefault(s.id).isNil:
           s.ast.sons[bodyPos] = body
         else:
@@ -723,9 +728,9 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
         result = symToClosure(n, owner, d, c)
     elif s.id in d.capturedVars:
       if s.owner != owner:
-        result = accessViaEnvParam(n, owner)
+        result = accessViaEnvParam(d.graph, n, owner)
       elif owner.isIterator and interestingIterVar(s):
-        result = accessViaEnvParam(n, owner)
+        result = accessViaEnvParam(d.graph, n, owner)
       else:
         result = accessViaEnvVar(n, owner, d, c)
   of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkComesFrom,
@@ -791,8 +796,8 @@ proc semCaptureSym*(s, owner: PSym) =
     # since the analysis is not entirely correct, we don't set 'tfCapturesEnv'
     # here
 
-proc liftIterToProc*(fn: PSym; body: PNode; ptrType: PType): PNode =
-  var d = initDetectionPass(fn)
+proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType): PNode =
+  var d = initDetectionPass(g, fn)
   var c = initLiftingPass(fn)
   # pretend 'fn' is a closure iterator for the analysis:
   let oldKind = fn.kind
@@ -801,11 +806,11 @@ proc liftIterToProc*(fn: PSym; body: PNode; ptrType: PType): PNode =
   fn.typ.callConv = ccClosure
   d.ownerToType[fn.id] = ptrType
   detectCapturedVars(body, fn, d)
-  result = wrapIterBody(liftCapturedVars(body, fn, d, c), fn)
+  result = wrapIterBody(g, liftCapturedVars(body, fn, d, c), fn)
   fn.kind = oldKind
   fn.typ.callConv = oldCC
 
-proc liftLambdas*(fn: PSym, body: PNode; tooEarly: var bool): PNode =
+proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PNode =
   # XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs
   # the transformation even when compiling to JS ...
 
@@ -819,7 +824,7 @@ proc liftLambdas*(fn: PSym, body: PNode; tooEarly: var bool): PNode =
     result = body
     tooEarly = true
   else:
-    var d = initDetectionPass(fn)
+    var d = initDetectionPass(g, fn)
     detectCapturedVars(body, fn, d)
     if not d.somethingToDo and fn.isIterator:
       addClosureParam(d, fn, body.info)
@@ -829,7 +834,7 @@ proc liftLambdas*(fn: PSym, body: PNode; tooEarly: var bool): PNode =
       var newBody = liftCapturedVars(body, fn, d, c)
       if c.envvars.getOrDefault(fn.id) != nil:
         newBody = newTree(nkStmtList, rawClosureCreation(fn, d, c), newBody)
-      result = wrapIterBody(newBody, fn)
+      result = wrapIterBody(g, newBody, fn)
     else:
       result = body
     #if fn.name.s == "get2":
@@ -845,7 +850,7 @@ proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
 
 # ------------------- iterator transformation --------------------------------
 
-proc liftForLoop*(body: PNode; owner: PSym): PNode =
+proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
   # problem ahead: the iterator could be invoked indirectly, but then
   # we don't know what environment to create here:
   #
@@ -876,7 +881,7 @@ proc liftForLoop*(body: PNode; owner: PSym): PNode =
   if liftingHarmful(owner): return body
   var L = body.len
   if not (body.kind == nkForStmt and body[L-2].kind in nkCallKinds):
-    localError(body.info, "ignored invalid for loop")
+    localError(g.config, body.info, "ignored invalid for loop")
     return body
   var call = body[L-2]
 
@@ -889,7 +894,7 @@ proc liftForLoop*(body: PNode; owner: PSym): PNode =
     # createClosure()
     let iter = op.sym
 
-    let hp = getHiddenParam(iter)
+    let hp = getHiddenParam(g, iter)
     env = newSym(skLet, iter.name, owner, body.info)
     env.typ = hp.typ
     env.flags = hp.flags
@@ -898,7 +903,7 @@ proc liftForLoop*(body: PNode; owner: PSym): PNode =
     addVar(v, newSymNode(env))
     result.add(v)
     # add 'new' statement:
-    result.add(newCall(getSysSym"internalNew", env.newSymNode))
+    result.add(newCall(getSysSym(g, env.info, "internalNew"), env.newSymNode))
   elif op.kind == nkStmtListExpr:
     let closure = op.lastSon
     if closure.kind == nkClosure:
@@ -908,7 +913,7 @@ proc liftForLoop*(body: PNode; owner: PSym): PNode =
 
   var loopBody = newNodeI(nkStmtList, body.info, 3)
   var whileLoop = newNodeI(nkWhileStmt, body.info, 2)
-  whileLoop.sons[0] = newIntTypeNode(nkIntLit, 1, getSysType(tyBool))
+  whileLoop.sons[0] = newIntTypeNode(nkIntLit, 1, getSysType(g, body.info, tyBool))
   whileLoop.sons[1] = loopBody
   result.add whileLoop
 
@@ -923,7 +928,7 @@ proc liftForLoop*(body: PNode; owner: PSym): PNode =
 
   addSon(vpart, ast.emptyNode) # no explicit type
   if not env.isNil:
-    call.sons[0] = makeClosure(call.sons[0].sym, env.newSymNode, body.info)
+    call.sons[0] = makeClosure(g, call.sons[0].sym, env.newSymNode, body.info)
   addSon(vpart, call)
   addSon(v2, vpart)
 
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index 8510bf7ee..5b85ab008 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -12,18 +12,18 @@
 const
   genPrefix* = ":tmp"         # prefix for generated names
 
-import ast, astalgo, types, idents, magicsys, msgs, options
+import ast, astalgo, types, idents, magicsys, msgs, options, modulegraphs
 from trees import getMagic
 
 proc newDeref*(n: PNode): PNode {.inline.} =
   result = newNodeIT(nkHiddenDeref, n.info, n.typ.sons[0])
   addSon(result, n)
 
-proc newTupleAccess*(tup: PNode, i: int): PNode =
+proc newTupleAccess*(g: ModuleGraph; tup: PNode, i: int): PNode =
   result = newNodeIT(nkBracketExpr, tup.info, tup.typ.skipTypes(
                      abstractInst).sons[i])
   addSon(result, copyTree(tup))
-  var lit = newNodeIT(nkIntLit, tup.info, getSysType(tyInt))
+  var lit = newNodeIT(nkIntLit, tup.info, getSysType(g, tup.info, tyInt))
   lit.intVal = i
   addSon(result, lit)
 
@@ -44,7 +44,7 @@ proc newFastAsgnStmt(le, ri: PNode): PNode =
   result.sons[0] = le
   result.sons[1] = ri
 
-proc lowerTupleUnpacking*(n: PNode; owner: PSym): PNode =
+proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
   assert n.kind == nkVarTuple
   let value = n.lastSon
   result = newNodeI(nkStmtList, n.info)
@@ -61,7 +61,7 @@ proc lowerTupleUnpacking*(n: PNode; owner: PSym): PNode =
   result.add newAsgnStmt(tempAsNode, value)
   for i in 0 .. n.len-3:
     if n.sons[i].kind == nkSym: v.addVar(n.sons[i])
-    result.add newAsgnStmt(n.sons[i], newTupleAccess(tempAsNode, i))
+    result.add newAsgnStmt(n.sons[i], newTupleAccess(g, tempAsNode, i))
 
 proc newTupleAccessRaw*(tup: PNode, i: int): PNode =
   result = newNodeI(nkBracketExpr, tup.info)
@@ -112,13 +112,13 @@ proc lowerSwap*(n: PNode; owner: PSym): PNode =
   result.add newFastAsgnStmt(n[1], n[2])
   result.add newFastAsgnStmt(n[2], tempAsNode)
 
-proc createObj*(owner: PSym, info: TLineInfo; final=true): PType =
+proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType =
   result = newType(tyObject, owner)
   if final:
     rawAddSon(result, nil)
     incl result.flags, tfFinal
   else:
-    rawAddSon(result, getCompilerProc("RootObj").typ)
+    rawAddSon(result, getCompilerProc(g, "RootObj").typ)
   result.n = newNodeI(nkRecList, info)
   let s = newSym(skType, getIdent("Env_" & info.toFilename),
                   owner, info)
@@ -218,7 +218,7 @@ proc indirectAccess*(a: PNode, b: int, info: TLineInfo): PNode =
   #if field == nil:
   #  echo "FIELD ", b
   #  debug deref.typ
-  internalAssert field != nil
+  assert field != nil
   addSon(deref, a)
   result = newNodeI(nkDotExpr, info)
   addSon(result, deref)
@@ -242,7 +242,7 @@ proc indirectAccess(a: PNode, b: string, info: TLineInfo): PNode =
   #if field == nil:
   #  echo "FIELD ", b
   #  debug deref.typ
-  internalAssert field != nil
+  assert field != nil
   addSon(deref, a)
   result = newNodeI(nkDotExpr, info)
   addSon(result, deref)
@@ -278,12 +278,12 @@ proc genDeref*(n: PNode): PNode =
                      n.typ.skipTypes(abstractInst).sons[0])
   result.add n
 
-proc callCodegenProc*(name: string, arg1: PNode;
+proc callCodegenProc*(g: ModuleGraph; name: string, arg1: PNode;
                       arg2, arg3, optionalArgs: PNode = nil): PNode =
   result = newNodeI(nkCall, arg1.info)
-  let sym = magicsys.getCompilerProc(name)
+  let sym = magicsys.getCompilerProc(g, name)
   if sym == nil:
-    localError(arg1.info, errSystemNeeds, name)
+    localError(g.config, arg1.info, "system module needs: " & name)
   else:
     result.add newSymNode(sym)
     result.add arg1
@@ -333,7 +333,7 @@ proc typeNeedsNoDeepCopy(t: PType): bool =
   if t.kind in {tyVar, tyLent, tySequence}: t = t.lastSon
   result = not containsGarbageCollectedRef(t)
 
-proc addLocalVar(varSection, varInit: PNode; owner: PSym; typ: PType;
+proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; owner: PSym; typ: PType;
                  v: PNode; useShallowCopy=false): PSym =
   result = newSym(skTemp, getIdent(genPrefix), owner, varSection.info)
   result.typ = typ
@@ -349,7 +349,7 @@ proc addLocalVar(varSection, varInit: PNode; owner: PSym; typ: PType;
       varInit.add newFastAsgnStmt(newSymNode(result), v)
     else:
       let deepCopyCall = newNodeI(nkCall, varInit.info, 3)
-      deepCopyCall.sons[0] = newSymNode(getSysMagic("deepCopy", mDeepCopy))
+      deepCopyCall.sons[0] = newSymNode(getSysMagic(g, varSection.info, "deepCopy", mDeepCopy))
       deepCopyCall.sons[1] = newSymNode(result)
       deepCopyCall.sons[2] = v
       varInit.add deepCopyCall
@@ -384,23 +384,23 @@ stmtList:
 
 """
 
-proc createWrapperProc(f: PNode; threadParam, argsParam: PSym;
+proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;
                        varSection, varInit, call, barrier, fv: PNode;
                        spawnKind: TSpawnResult): PSym =
   var body = newNodeI(nkStmtList, f.info)
   var threadLocalBarrier: PSym
   if barrier != nil:
     var varSection2 = newNodeI(nkVarSection, barrier.info)
-    threadLocalBarrier = addLocalVar(varSection2, nil, argsParam.owner,
+    threadLocalBarrier = addLocalVar(g, varSection2, nil, argsParam.owner,
                                      barrier.typ, barrier)
     body.add varSection2
-    body.add callCodegenProc("barrierEnter", threadLocalBarrier.newSymNode)
+    body.add callCodegenProc(g, "barrierEnter", threadLocalBarrier.newSymNode)
   var threadLocalProm: PSym
   if spawnKind == srByVar:
-    threadLocalProm = addLocalVar(varSection, nil, argsParam.owner, fv.typ, fv)
+    threadLocalProm = addLocalVar(g, varSection, nil, argsParam.owner, fv.typ, fv)
   elif fv != nil:
-    internalAssert fv.typ.kind == tyGenericInst
-    threadLocalProm = addLocalVar(varSection, nil, argsParam.owner, fv.typ, fv)
+    internalAssert g.config, fv.typ.kind == tyGenericInst
+    threadLocalProm = addLocalVar(g, varSection, nil, argsParam.owner, fv.typ, fv)
   body.add varSection
   body.add varInit
   if fv != nil and spawnKind != srByVar:
@@ -409,30 +409,30 @@ proc createWrapperProc(f: PNode; threadParam, argsParam: PSym;
     body.add newAsgnStmt(indirectAccess(threadLocalProm.newSymNode,
       "owner", fv.info), threadParam.newSymNode)
 
-  body.add callCodegenProc("nimArgsPassingDone", threadParam.newSymNode)
+  body.add callCodegenProc(g, "nimArgsPassingDone", threadParam.newSymNode)
   if spawnKind == srByVar:
     body.add newAsgnStmt(genDeref(threadLocalProm.newSymNode), call)
   elif fv != nil:
     let fk = fv.typ.sons[1].flowVarKind
     if fk == fvInvalid:
-      localError(f.info, "cannot create a flowVar of type: " &
+      localError(g.config, f.info, "cannot create a flowVar of type: " &
         typeToString(fv.typ.sons[1]))
     body.add newAsgnStmt(indirectAccess(threadLocalProm.newSymNode,
       if fk == fvGC: "data" else: "blob", fv.info), call)
     if fk == fvGC:
       let incRefCall = newNodeI(nkCall, fv.info, 2)
-      incRefCall.sons[0] = newSymNode(getSysMagic("GCref", mGCref))
+      incRefCall.sons[0] = newSymNode(getSysMagic(g, fv.info, "GCref", mGCref))
       incRefCall.sons[1] = indirectAccess(threadLocalProm.newSymNode,
                                           "data", fv.info)
       body.add incRefCall
     if barrier == nil:
       # by now 'fv' is shared and thus might have beeen overwritten! we need
       # to use the thread-local view instead:
-      body.add callCodegenProc("nimFlowVarSignal", threadLocalProm.newSymNode)
+      body.add callCodegenProc(g, "nimFlowVarSignal", threadLocalProm.newSymNode)
   else:
     body.add call
   if barrier != nil:
-    body.add callCodegenProc("barrierLeave", threadLocalBarrier.newSymNode)
+    body.add callCodegenProc(g, "barrierLeave", threadLocalBarrier.newSymNode)
 
   var params = newNodeI(nkFormalParams, f.info)
   params.add emptyNode
@@ -460,7 +460,7 @@ proc createCastExpr(argsParam: PSym; objType: PType): PNode =
   result.typ = newType(tyPtr, objType.owner)
   result.typ.rawAddSon(objType)
 
-proc setupArgsForConcurrency(n: PNode; objType: PType; scratchObj: PSym,
+proc setupArgsForConcurrency(g: ModuleGraph; n: PNode; objType: PType; scratchObj: PSym,
                              castExpr, call,
                              varSection, varInit, result: PNode) =
   let formals = n[0].typ.n
@@ -470,7 +470,7 @@ proc setupArgsForConcurrency(n: PNode; objType: PType; scratchObj: PSym,
     # 'tyOpenArray':
     var argType = n[i].typ.skipTypes(abstractInst)
     if i < formals.len and formals[i].typ.kind in {tyVar, tyLent}:
-      localError(n[i].info, "'spawn'ed function cannot have a 'var' parameter")
+      localError(g.config, n[i].info, "'spawn'ed function cannot have a 'var' parameter")
     #elif containsTyRef(argType):
     #  localError(n[i].info, "'spawn'ed function cannot refer to 'ref'/closure")
 
@@ -480,7 +480,7 @@ proc setupArgsForConcurrency(n: PNode; objType: PType; scratchObj: PSym,
     objType.addField(field)
     result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[i])
 
-    let temp = addLocalVar(varSection, varInit, objType.owner, argType,
+    let temp = addLocalVar(g, varSection, varInit, objType.owner, argType,
                            indirectAccess(castExpr, field, n.info))
     call.add(newSymNode(temp))
 
@@ -501,20 +501,20 @@ proc getRoot*(n: PNode): PSym =
     if getMagic(n) == mSlice: result = getRoot(n.sons[1])
   else: discard
 
-proc newIntLit*(value: BiggestInt): PNode =
+proc newIntLit*(g: ModuleGraph; info: TLineInfo; value: BiggestInt): PNode =
   result = nkIntLit.newIntNode(value)
-  result.typ = getSysType(tyInt)
+  result.typ = getSysType(g, info, tyInt)
 
-proc genHigh*(n: PNode): PNode =
+proc genHigh*(g: ModuleGraph; n: PNode): PNode =
   if skipTypes(n.typ, abstractVar).kind == tyArray:
-    result = newIntLit(lastOrd(skipTypes(n.typ, abstractVar)))
+    result = newIntLit(g, n.info, lastOrd(skipTypes(n.typ, abstractVar)))
   else:
     result = newNodeI(nkCall, n.info, 2)
-    result.typ = getSysType(tyInt)
-    result.sons[0] = newSymNode(getSysMagic("high", mHigh))
+    result.typ = getSysType(g, n.info, tyInt)
+    result.sons[0] = newSymNode(getSysMagic(g, n.info, "high", mHigh))
     result.sons[1] = n
 
-proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym;
+proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; scratchObj: PSym;
                              castExpr, call,
                              varSection, varInit, result: PNode) =
   let formals = n[0].typ.n
@@ -535,10 +535,10 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym;
       # important special case: we always create a zero-copy slice:
       let slice = newNodeI(nkCall, n.info, 4)
       slice.typ = n.typ
-      slice.sons[0] = newSymNode(createMagic("slice", mSlice))
-      slice.sons[0].typ = getSysType(tyInt) # fake type
+      slice.sons[0] = newSymNode(createMagic(g, "slice", mSlice))
+      slice.sons[0].typ = getSysType(g, n.info, tyInt) # fake type
       var fieldB = newSym(skField, tmpName, objType.owner, n.info)
-      fieldB.typ = getSysType(tyInt)
+      fieldB.typ = getSysType(g, n.info, tyInt)
       objType.addField(fieldB)
 
       if getMagic(n) == mSlice:
@@ -548,12 +548,12 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym;
         result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)
 
         var fieldA = newSym(skField, tmpName, objType.owner, n.info)
-        fieldA.typ = getSysType(tyInt)
+        fieldA.typ = getSysType(g, n.info, tyInt)
         objType.addField(fieldA)
         result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldA), n[2])
         result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), n[3])
 
-        let threadLocal = addLocalVar(varSection,nil, objType.owner, fieldA.typ,
+        let threadLocal = addLocalVar(g, varSection,nil, objType.owner, fieldA.typ,
                                       indirectAccess(castExpr, fieldA, n.info),
                                       useShallowCopy=true)
         slice.sons[2] = threadLocal.newSymNode
@@ -562,13 +562,13 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym;
         field.typ = a.typ
         objType.addField(field)
         result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)
-        result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), genHigh(n))
+        result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), genHigh(g, n))
 
-        slice.sons[2] = newIntLit(0)
+        slice.sons[2] = newIntLit(g, n.info, 0)
       # the array itself does not need to go through a thread local variable:
       slice.sons[1] = genDeref(indirectAccess(castExpr, field, n.info))
 
-      let threadLocal = addLocalVar(varSection,nil, objType.owner, fieldB.typ,
+      let threadLocal = addLocalVar(g, varSection,nil, objType.owner, fieldB.typ,
                                     indirectAccess(castExpr, fieldB, n.info),
                                     useShallowCopy=true)
       slice.sons[3] = threadLocal.newSymNode
@@ -580,7 +580,7 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym;
       field.typ = a.typ
       objType.addField(field)
       result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)
-      let threadLocal = addLocalVar(varSection,nil, objType.owner, field.typ,
+      let threadLocal = addLocalVar(g, varSection,nil, objType.owner, field.typ,
                                     indirectAccess(castExpr, field, n.info),
                                     useShallowCopy=true)
       call.add(genDeref(threadLocal.newSymNode))
@@ -589,13 +589,13 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym;
       field.typ = argType
       objType.addField(field)
       result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n)
-      let threadLocal = addLocalVar(varSection, varInit,
+      let threadLocal = addLocalVar(g, varSection, varInit,
                                     objType.owner, field.typ,
                                     indirectAccess(castExpr, field, n.info),
                                     useShallowCopy=true)
       call.add(threadLocal.newSymNode)
 
-proc wrapProcForSpawn*(owner: PSym; spawnExpr: PNode; retType: PType;
+proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: PType;
                        barrier, dest: PNode = nil): PNode =
   # if 'barrier' != nil, then it is in a 'parallel' section and we
   # generate quite different code
@@ -603,31 +603,31 @@ proc wrapProcForSpawn*(owner: PSym; spawnExpr: PNode; retType: PType;
   let spawnKind = spawnResult(retType, barrier!=nil)
   case spawnKind
   of srVoid:
-    internalAssert dest == nil
+    internalAssert g.config, dest == nil
     result = newNodeI(nkStmtList, n.info)
   of srFlowVar:
-    internalAssert dest == nil
+    internalAssert g.config, dest == nil
     result = newNodeIT(nkStmtListExpr, n.info, retType)
   of srByVar:
-    if dest == nil: localError(n.info, "'spawn' must not be discarded")
+    if dest == nil: localError(g.config, n.info, "'spawn' must not be discarded")
     result = newNodeI(nkStmtList, n.info)
 
   if n.kind notin nkCallKinds:
-    localError(n.info, "'spawn' takes a call expression")
+    localError(g.config, n.info, "'spawn' takes a call expression")
     return
   if optThreadAnalysis in gGlobalOptions:
     if {tfThread, tfNoSideEffect} * n[0].typ.flags == {}:
-      localError(n.info, "'spawn' takes a GC safe call expression")
+      localError(g.config, n.info, "'spawn' takes a GC safe call expression")
   var
     threadParam = newSym(skParam, getIdent"thread", owner, n.info)
     argsParam = newSym(skParam, getIdent"args", owner, n.info)
   block:
-    let ptrType = getSysType(tyPointer)
+    let ptrType = getSysType(g, n.info, tyPointer)
     threadParam.typ = ptrType
     argsParam.typ = ptrType
     argsParam.position = 1
 
-  var objType = createObj(owner, n.info)
+  var objType = createObj(g, owner, n.info)
   incl(objType.flags, tfFinal)
   let castExpr = createCastExpr(argsParam, objType)
 
@@ -644,7 +644,7 @@ proc wrapProcForSpawn*(owner: PSym; spawnExpr: PNode; retType: PType;
   # templates and macros are in fact valid here due to the nature of
   # the transformation:
   if fn.kind == nkClosure:
-    localError(n.info, "closure in spawn environment is not allowed")
+    localError(g.config, n.info, "closure in spawn environment is not allowed")
   if not (fn.kind == nkSym and fn.sym.kind in {skProc, skTemplate, skMacro,
                                                skFunc, skMethod, skConverter}):
     # for indirect calls we pass the function pointer in the scratchObj
@@ -655,24 +655,24 @@ proc wrapProcForSpawn*(owner: PSym; spawnExpr: PNode; retType: PType;
     result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[0])
     fn = indirectAccess(castExpr, field, n.info)
   elif fn.kind == nkSym and fn.sym.kind == skIterator:
-    localError(n.info, "iterator in spawn environment is not allowed")
+    localError(g.config, n.info, "iterator in spawn environment is not allowed")
   elif fn.typ.callConv == ccClosure:
-    localError(n.info, "closure in spawn environment is not allowed")
+    localError(g.config, n.info, "closure in spawn environment is not allowed")
 
   call.add(fn)
   var varSection = newNodeI(nkVarSection, n.info)
   var varInit = newNodeI(nkStmtList, n.info)
   if barrier.isNil:
-    setupArgsForConcurrency(n, objType, scratchObj, castExpr, call,
+    setupArgsForConcurrency(g, n, objType, scratchObj, castExpr, call,
                             varSection, varInit, result)
   else:
-    setupArgsForParallelism(n, objType, scratchObj, castExpr, call,
+    setupArgsForParallelism(g, n, objType, scratchObj, castExpr, call,
                             varSection, varInit, result)
 
   var barrierAsExpr: PNode = nil
   if barrier != nil:
     let typ = newType(tyPtr, owner)
-    typ.rawAddSon(magicsys.getCompilerProc("Barrier").typ)
+    typ.rawAddSon(magicsys.getCompilerProc(g, "Barrier").typ)
     var field = newSym(skField, getIdent"barrier", owner, n.info)
     field.typ = typ
     objType.addField(field)
@@ -689,7 +689,7 @@ proc wrapProcForSpawn*(owner: PSym; spawnExpr: PNode; retType: PType;
     # create flowVar:
     result.add newFastAsgnStmt(fvField, callProc(spawnExpr[^1]))
     if barrier == nil:
-      result.add callCodegenProc("nimFlowVarCreateSemaphore", fvField)
+      result.add callCodegenProc(g, "nimFlowVarCreateSemaphore", fvField)
 
   elif spawnKind == srByVar:
     var field = newSym(skField, getIdent"fv", owner, n.info)
@@ -699,10 +699,10 @@ proc wrapProcForSpawn*(owner: PSym; spawnExpr: PNode; retType: PType;
     fvAsExpr = indirectAccess(castExpr, field, n.info)
     result.add newFastAsgnStmt(newDotExpr(scratchObj, field), genAddrOf(dest))
 
-  let wrapper = createWrapperProc(fn, threadParam, argsParam,
+  let wrapper = createWrapperProc(g, fn, threadParam, argsParam,
                                   varSection, varInit, call,
                                   barrierAsExpr, fvAsExpr, spawnKind)
-  result.add callCodegenProc("nimSpawn" & $spawnExpr.len, wrapper.newSymNode,
+  result.add callCodegenProc(g, "nimSpawn" & $spawnExpr.len, wrapper.newSymNode,
                              genAddrOf(scratchObj.newSymNode), nil, spawnExpr)
 
   if spawnKind == srFlowVar: result.add fvField