summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim19
-rw-r--r--compiler/ccgexprs.nim56
-rw-r--r--compiler/ccgstmts.nim14
-rw-r--r--compiler/ccgthreadvars.nim6
-rw-r--r--compiler/ccgtrav.nim6
-rw-r--r--compiler/ccgtypes.nim4
-rw-r--r--compiler/cgen.nim102
-rw-r--r--compiler/cgendata.nim2
-rw-r--r--compiler/commands.nim270
-rw-r--r--compiler/docgen.nim50
-rw-r--r--compiler/docgen2.nim4
-rw-r--r--compiler/extccomp.nim58
-rw-r--r--compiler/hlo.nim8
-rw-r--r--compiler/importer.nim3
-rw-r--r--compiler/jsgen.nim6
-rw-r--r--compiler/lambdalifting.nim23
-rw-r--r--compiler/lexer.nim6
-rw-r--r--compiler/lookups.nim8
-rw-r--r--compiler/lowerings.nim44
-rw-r--r--compiler/magicsys.nim4
-rw-r--r--compiler/main.nim74
-rw-r--r--compiler/modulegraphs.nim2
-rw-r--r--compiler/modules.nim2
-rw-r--r--compiler/msgs.nim2
-rw-r--r--compiler/nim.nim10
-rw-r--r--compiler/nimconf.nim36
-rw-r--r--compiler/nimfix/nimfix.nim2
-rw-r--r--compiler/options.nim2
-rw-r--r--compiler/passaux.nim2
-rw-r--r--compiler/pragmas.nim31
-rw-r--r--compiler/renderer.nim4
-rw-r--r--compiler/rodread.nim15
-rw-r--r--compiler/rodwrite.nim6
-rw-r--r--compiler/sem.nim10
-rw-r--r--compiler/semdata.nim5
-rw-r--r--compiler/semexprs.nim12
-rw-r--r--compiler/semfold.nim8
-rw-r--r--compiler/semgnrc.nim2
-rw-r--r--compiler/sempass2.nim10
-rw-r--r--compiler/semstmts.nim18
-rw-r--r--compiler/semtypes.nim8
-rw-r--r--compiler/service.nim2
-rw-r--r--compiler/sigmatch.nim4
-rw-r--r--compiler/suggest.nim48
-rw-r--r--compiler/syntaxes.nim2
-rw-r--r--compiler/transf.nim6
46 files changed, 509 insertions, 507 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 6785702f1..5e65fbff9 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -734,7 +734,7 @@ type
     locOther                  # location is something other
   TLocFlag* = enum
     lfIndirect,               # backend introduced a pointer
-    lfFullExternalName, # only used when 'gCmd == cmdPretty': Indicates
+    lfFullExternalName, # only used when 'conf.cmd == cmdPretty': Indicates
       # that the symbol has been imported via 'importc: "fullname"' and
       # no format string.
     lfNoDeepCopy,             # no need for a deep copy
@@ -1078,14 +1078,14 @@ template previouslyInferred*(t: PType): PType =
   if t.sons.len > 1: t.lastSon else: nil
 
 proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
-             info: TLineInfo): PSym =
+             info: TLineInfo; options: TOptions = {}): PSym =
   # generates a symbol and initializes the hash field too
   new(result)
   result.name = name
   result.kind = symKind
   result.flags = {}
   result.info = info
-  result.options = gOptions
+  result.options = options
   result.owner = owner
   result.offset = -1
   result.id = getID()
@@ -1095,7 +1095,7 @@ proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
   #  writeStacktrace()
   #  MessageOut(name.s & " has id: " & toString(result.id))
 
-var emptyNode* = newNode(nkEmpty)
+var emptyNode* = newNode(nkEmpty) # XXX global variable here!
 # There is a single empty node that is shared! Do not overwrite it!
 
 proc isMetaType*(t: PType): bool =
@@ -1325,7 +1325,7 @@ proc copyType*(t: PType, owner: PSym, keepId: bool): PType =
 proc exactReplica*(t: PType): PType = copyType(t, t.owner, true)
 
 proc copySym*(s: PSym, keepId: bool = false): PSym =
-  result = newSym(s.kind, s.name, s.owner, s.info)
+  result = newSym(s.kind, s.name, s.owner, s.info, s.options)
   #result.ast = nil            # BUGFIX; was: s.ast which made problems
   result.typ = s.typ
   if keepId:
@@ -1344,8 +1344,9 @@ proc copySym*(s: PSym, keepId: bool = false): PSym =
   if result.kind in {skVar, skLet, skField}:
     result.guard = s.guard
 
-proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo): PSym =
-  result = newSym(s.kind, newIdent, s.owner, info)
+proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo;
+                        options: TOptions): PSym =
+  result = newSym(s.kind, newIdent, s.owner, info, options)
   # keep ID!
   result.ast = s.ast
   result.id = s.id
@@ -1680,9 +1681,9 @@ proc isException*(t: PType): bool =
     base = base.lastSon
   return false
 
-proc isImportedException*(t: PType): bool =
+proc isImportedException*(t: PType; conf: ConfigRef): bool =
   assert(t != nil)
-  if optNoCppExceptions in gGlobalOptions:
+  if optNoCppExceptions in conf.globalOptions:
     return false
 
   let base = t.skipTypes({tyAlias, tyPtr, tyDistinct, tyGenericInst})
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index dff974ddb..335aa2f84 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -13,7 +13,7 @@
 
 proc int64Literal(i: BiggestInt): Rope =
   if i > low(int64):
-    result = rfmt(nil, "IL64($1)", rope(i))
+    result = "IL64($1)" % [rope(i)]
   else:
     result = ~"(IL64(-9223372036854775807) - IL64(1))"
 
@@ -26,7 +26,7 @@ proc intLiteral(i: BiggestInt): Rope =
     # Nim has the same bug for the same reasons :-)
     result = ~"(-2147483647 -1)"
   elif i > low(int64):
-    result = rfmt(nil, "IL64($1)", rope(i))
+    result = "IL64($1)" % [rope(i)]
   else:
     result = ~"(IL64(-9223372036854775807) - IL64(1))"
 
@@ -834,7 +834,7 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
     if field.loc.r == nil:
       internalError(p.config, e.info, "genCheckedRecordField") # generate the checks:
     genFieldCheck(p, e, r, field)
-    add(r, rfmt(nil, ".$1", field.loc.r))
+    add(r, ropecg(p.module, ".$1", field.loc.r))
     putIntoDest(p, d, e.sons[0], r, a.storage)
   else:
     genRecordField(p, e.sons[0], d)
@@ -862,7 +862,7 @@ proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
         localError(p.config, x.info, "index out of bounds")
   d.inheritLocation(a)
   putIntoDest(p, d, n,
-              rfmt(nil, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.storage)
+              ropecg(p.module, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.storage)
 
 proc genCStringElem(p: BProc, n, x, y: PNode, d: var TLoc) =
   var a, b: TLoc
@@ -871,7 +871,7 @@ proc genCStringElem(p: BProc, n, x, y: PNode, d: var TLoc) =
   var ty = skipTypes(a.t, abstractVarRange)
   inheritLocation(d, a)
   putIntoDest(p, d, n,
-              rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage)
+              ropecg(p.module, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage)
 
 proc genIndexCheck(p: BProc; arr, idx: TLoc) =
   let ty = skipTypes(arr.t, abstractVarRange)
@@ -899,7 +899,7 @@ proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
             rdLoc(b), rdLoc(a)) # BUGFIX: ``>=`` and not ``>``!
   inheritLocation(d, a)
   putIntoDest(p, d, n,
-              rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage)
+              ropecg(p.module, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage)
 
 proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
   var a, b: TLoc
@@ -919,9 +919,9 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
               rdLoc(b), rdLoc(a), lenField(p))
   if d.k == locNone: d.storage = OnHeap
   if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
-    a.r = rfmt(nil, "(*$1)", a.r)
+    a.r = ropecg(p.module, "(*$1)", a.r)
   putIntoDest(p, d, n,
-              rfmt(nil, "$1->data[$2]", rdLoc(a), rdCharLoc(b)), a.storage)
+              ropecg(p.module, "$1->data[$2]", rdLoc(a), rdCharLoc(b)), a.storage)
 
 proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) =
   var ty = skipTypes(n.sons[0].typ, abstractVarRange + tyUserTypeClasses)
@@ -1004,7 +1004,7 @@ proc genEcho(p: BProc, n: PNode) =
       linefmt(p, cpsStmts, "fflush(stdout);$n")
 
 proc gcUsage(conf: ConfigRef; n: PNode) =
-  if gSelectedGC == gcNone: message(conf, n.info, warnGcMem, n.renderTree)
+  if conf.selectedGC == gcNone: message(conf, n.info, warnGcMem, n.renderTree)
 
 proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
   #   <Nim code>
@@ -1033,13 +1033,13 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
     initLocExpr(p, e.sons[i + 1], a)
     if skipTypes(e.sons[i + 1].typ, abstractVarRange).kind == tyChar:
       inc(L)
-      add(appends, rfmt(p.module, "#appendChar($1, $2);$n", tmp.r, rdLoc(a)))
+      add(appends, ropecg(p.module, "#appendChar($1, $2);$n", tmp.r, rdLoc(a)))
     else:
       if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
         inc(L, len(e.sons[i + 1].strVal))
       else:
         addf(lens, "($1 ? $1->$2 : 0) + ", [rdLoc(a), lenField(p)])
-      add(appends, rfmt(p.module, "#appendString($1, $2);$n", tmp.r, rdLoc(a)))
+      add(appends, ropecg(p.module, "#appendString($1, $2);$n", tmp.r, rdLoc(a)))
   linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", tmp.r, lens, rope(L))
   add(p.s(cpsStmts), appends)
   if d.k == locNone:
@@ -1071,14 +1071,14 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
     initLocExpr(p, e.sons[i + 2], a)
     if skipTypes(e.sons[i + 2].typ, abstractVarRange).kind == tyChar:
       inc(L)
-      add(appends, rfmt(p.module, "#appendChar($1, $2);$n",
+      add(appends, ropecg(p.module, "#appendChar($1, $2);$n",
                         rdLoc(dest), rdLoc(a)))
     else:
       if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
         inc(L, len(e.sons[i + 2].strVal))
       else:
         addf(lens, "($1 ? $1->$2 : 0) + ", [rdLoc(a), lenField(p)])
-      add(appends, rfmt(p.module, "#appendString($1, $2);$n",
+      add(appends, ropecg(p.module, "#appendString($1, $2);$n",
                         rdLoc(dest), rdLoc(a)))
   linefmt(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
           rdLoc(dest), lens, rope(L))
@@ -1106,7 +1106,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
   initLoc(dest, locExpr, e.sons[2], OnHeap)
   getIntTemp(p, tmpL)
   lineCg(p, cpsStmts, "$1 = $2->$3++;$n", tmpL.r, rdLoc(a), lenField(p))
-  dest.r = rfmt(nil, "$1->data[$2]", rdLoc(a), tmpL.r)
+  dest.r = ropecg(p.module, "$1->data[$2]", rdLoc(a), tmpL.r)
   genAssignment(p, dest, b, {needToCopy, afDestIsNil})
   gcUsage(p.config, e)
 
@@ -1280,7 +1280,7 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) =
   genNewSeqAux(p, dest[], intLiteral(sonsLen(n)))
   for i in countup(0, sonsLen(n) - 1):
     initLoc(arr, locExpr, n[i], OnHeap)
-    arr.r = rfmt(nil, "$1->data[$2]", rdLoc(dest[]), intLiteral(i))
+    arr.r = ropecg(p.module, "$1->data[$2]", rdLoc(dest[]), intLiteral(i))
     arr.storage = OnHeap            # we know that sequences are on the heap
     expr(p, n[i], arr)
   gcUsage(p.config, n)
@@ -1306,10 +1306,10 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
   if L < 10:
     for i in countup(0, L - 1):
       initLoc(elem, locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap)
-      elem.r = rfmt(nil, "$1->data[$2]", rdLoc(d), intLiteral(i))
+      elem.r = ropecg(p.module, "$1->data[$2]", rdLoc(d), intLiteral(i))
       elem.storage = OnHeap # we know that sequences are on the heap
       initLoc(arr, locExpr, lodeTyp elemType(skipTypes(n.sons[1].typ, abstractInst)), a.storage)
-      arr.r = rfmt(nil, "$1[$2]", rdLoc(a), intLiteral(i))
+      arr.r = ropecg(p.module, "$1[$2]", rdLoc(a), intLiteral(i))
       genAssignment(p, elem, arr, {afDestIsNil, needToCopy})
   else:
     var i: TLoc
@@ -1317,10 +1317,10 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
     let oldCode = p.s(cpsStmts)
     linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",  i.r, L.rope)
     initLoc(elem, locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap)
-    elem.r = rfmt(nil, "$1->data[$2]", rdLoc(d), rdLoc(i))
+    elem.r = ropecg(p.module, "$1->data[$2]", rdLoc(d), rdLoc(i))
     elem.storage = OnHeap # we know that sequences are on the heap
     initLoc(arr, locExpr, lodeTyp elemType(skipTypes(n.sons[1].typ, abstractInst)), a.storage)
-    arr.r = rfmt(nil, "$1[$2]", rdLoc(a), rdLoc(i))
+    arr.r = ropecg(p.module, "$1[$2]", rdLoc(a), rdLoc(i))
     genAssignment(p, elem, arr, {afDestIsNil, needToCopy})
     lineF(p, cpsStmts, "}$n", [])
 
@@ -1356,10 +1356,10 @@ proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo): Rope =
     inc p.module.labels
     let cache = "Nim_OfCheck_CACHE" & p.module.labels.rope
     addf(p.module.s[cfsVars], "static TNimType* $#[2];$n", [cache])
-    result = rfmt(p.module, "#isObjWithCache($#.m_type, $#, $#)", a, ti, cache)
+    result = ropecg(p.module, "#isObjWithCache($#.m_type, $#, $#)", a, ti, cache)
   when false:
     # former version:
-    result = rfmt(p.module, "#isObj($1.m_type, $2)",
+    result = ropecg(p.module, "#isObj($1.m_type, $2)",
                   a, genTypeInfo(p.module, dest, info))
 
 proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
@@ -1372,7 +1372,7 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
   while t.kind in {tyVar, tyLent, tyPtr, tyRef}:
     if t.kind notin {tyVar, tyLent}: nilCheck = r
     if t.kind notin {tyVar, tyLent} or not p.module.compileToCpp:
-      r = rfmt(nil, "(*$1)", r)
+      r = ropecg(p.module, "(*$1)", r)
     t = skipTypes(t.lastSon, typedescInst)
   discard getTypeDesc(p.module, t)
   if not p.module.compileToCpp:
@@ -1383,9 +1383,9 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
     globalError(p.config, x.info,
       "no 'of' operator available for pure objects")
   if nilCheck != nil:
-    r = rfmt(p.module, "(($1) && ($2))", nilCheck, genOfHelper(p, dest, r, x.info))
+    r = ropecg(p.module, "(($1) && ($2))", nilCheck, genOfHelper(p, dest, r, x.info))
   else:
-    r = rfmt(p.module, "($1)", genOfHelper(p, dest, r, x.info))
+    r = ropecg(p.module, "($1)", genOfHelper(p, dest, r, x.info))
   putIntoDest(p, d, x, r, a.storage)
 
 proc genOf(p: BProc, n: PNode, d: var TLoc) =
@@ -1762,11 +1762,11 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
   if a.kind in {nkStrLit..nkTripleStrLit} and a.strVal == "":
     initLocExpr(p, e.sons[2], x)
     putIntoDest(p, d, e,
-      rfmt(nil, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p)))
+      ropecg(p.module, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p)))
   elif b.kind in {nkStrLit..nkTripleStrLit} and b.strVal == "":
     initLocExpr(p, e.sons[1], x)
     putIntoDest(p, d, e,
-      rfmt(nil, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p)))
+      ropecg(p.module, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p)))
   else:
     binaryExpr(p, e, d, "#eqStrings($1, $2)")
 
@@ -1778,7 +1778,7 @@ proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
     assert(e.sons[2].typ != nil)
     initLocExpr(p, e.sons[1], a)
     initLocExpr(p, e.sons[2], b)
-    putIntoDest(p, d, e, rfmt(nil, "(($4)($2) $1 ($4)($3))",
+    putIntoDest(p, d, e, ropecg(p.module, "(($4)($2) $1 ($4)($3))",
                               rope(opr[m]), rdLoc(a), rdLoc(b),
                               getSimpleTypeDesc(p.module, e[1].typ)))
     if optNaNCheck in p.options:
@@ -2295,7 +2295,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
         initLocExpr(p, ex, a)
   of nkAsmStmt: genAsmStmt(p, n)
   of nkTryStmt:
-    if p.module.compileToCpp and optNoCppExceptions notin gGlobalOptions:
+    if p.module.compileToCpp and optNoCppExceptions notin p.config.globalOptions:
       genTryCpp(p, n, d)
     else:
       genTry(p, n, d)
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 0ba85488b..1e0a3c818 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -16,7 +16,7 @@ const
     # above X strings a hash-switch for strings is generated
 
 proc registerGcRoot(p: BProc, v: PSym) =
-  if gSelectedGC in {gcMarkAndSweep, gcGenerational, gcV2, gcRefc} and
+  if p.config.selectedGC in {gcMarkAndSweep, gcGenerational, gcV2, gcRefc} and
       containsGarbageCollectedRef(v.loc.t):
     # we register a specialized marked proc here; this has the advantage
     # that it works out of the box for thread local storage then :-)
@@ -125,7 +125,7 @@ proc endBlock(p: BProc, blockEnd: Rope) =
 proc endBlock(p: BProc) =
   let topBlock = p.blocks.len - 1
   var blockEnd = if p.blocks[topBlock].label != nil:
-      rfmt(nil, "} $1: ;$n", p.blocks[topBlock].label)
+      ropecg(p.module, "} $1: ;$n", p.blocks[topBlock].label)
     else:
       ~"}$n"
   let frameLen = p.blocks[topBlock].frameLen
@@ -337,7 +337,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
 
   for i in countup(1, howManyTrys):
     let tryStmt = p.nestedTryStmts.pop
-    if not p.module.compileToCpp or optNoCppExceptions in gGlobalOptions:
+    if not p.module.compileToCpp or optNoCppExceptions in p.config.globalOptions:
       # Pop safe points generated by try
       if not tryStmt.inExcept:
         linefmt(p, cpsStmts, "#popSafePoint();$n")
@@ -356,7 +356,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
   for i in countdown(howManyTrys-1, 0):
     p.nestedTryStmts.add(stack[i])
 
-  if not p.module.compileToCpp or optNoCppExceptions in gGlobalOptions:
+  if not p.module.compileToCpp or optNoCppExceptions in p.config.globalOptions:
     # Pop exceptions that was handled by the
     # except-blocks we are in
     for i in countdown(howManyExcepts-1, 0):
@@ -571,7 +571,7 @@ proc genRaiseStmt(p: BProc, t: PNode) =
     var e = rdLoc(a)
     var typ = skipTypes(t[0].typ, abstractPtrs)
     genLineDir(p, t)
-    if isImportedException(typ):
+    if isImportedException(typ, p.config):
       lineF(p, cpsStmts, "throw $1;$n", [e])
     else:
       lineCg(p, cpsStmts, "#raiseException((#Exception*)$1, $2);$n",
@@ -579,7 +579,7 @@ proc genRaiseStmt(p: BProc, t: PNode) =
   else:
     genLineDir(p, t)
     # reraise the last exception:
-    if p.module.compileToCpp and optNoCppExceptions notin gGlobalOptions:
+    if p.module.compileToCpp and optNoCppExceptions notin p.config.globalOptions:
       line(p, cpsStmts, ~"throw;$n")
     else:
       linefmt(p, cpsStmts, "#reraiseException();$n")
@@ -1010,7 +1010,7 @@ proc genEmit(p: BProc, t: PNode) =
   if p.prc == nil:
     # top level emit pragma?
     let section = determineSection(t[1])
-    genCLineDir(p.module.s[section], t.info)
+    genCLineDir(p.module.s[section], t.info, p.config)
     add(p.module.s[section], s)
   else:
     genLineDir(p, t)
diff --git a/compiler/ccgthreadvars.nim b/compiler/ccgthreadvars.nim
index c2ffa9651..da5c624b7 100644
--- a/compiler/ccgthreadvars.nim
+++ b/compiler/ccgthreadvars.nim
@@ -13,7 +13,7 @@
 # included from cgen.nim
 
 proc emulatedThreadVars(conf: ConfigRef): bool =
-  result = {optThreads, optTlsEmulation} <= gGlobalOptions
+  result = {optThreads, optTlsEmulation} <= conf.globalOptions
 
 proc accessThreadLocalVar(p: BProc, s: PSym) =
   if emulatedThreadVars(p.config) and not p.threadVarAccessed:
@@ -46,7 +46,7 @@ proc declareThreadVar(m: BModule, s: PSym, isExtern: bool) =
       addf(nimtv, "$1 $2;$n", [getTypeDesc(m, s.loc.t), s.loc.r])
   else:
     if isExtern: add(m.s[cfsVars], "extern ")
-    if optThreads in gGlobalOptions: add(m.s[cfsVars], "NIM_THREADVAR ")
+    if optThreads in m.config.globalOptions: add(m.s[cfsVars], "NIM_THREADVAR ")
     add(m.s[cfsVars], getTypeDesc(m, s.loc.t))
     addf(m.s[cfsVars], " $1;$n", [s.loc.r])
 
@@ -57,7 +57,7 @@ proc generateThreadLocalStorage(m: BModule) =
 
 proc generateThreadVarsSize(m: BModule) =
   if nimtv != nil:
-    let externc = if gCmd == cmdCompileToCpp or
+    let externc = if m.config.cmd == cmdCompileToCpp or
                        sfCompileToCpp in m.module.flags: "extern \"C\" "
                   else: ""
     addf(m.s[cfsProcs],
diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim
index 0e211e239..c265064a1 100644
--- a/compiler/ccgtrav.nim
+++ b/compiler/ccgtrav.nim
@@ -77,7 +77,7 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
     linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
             i.r, arraySize.rope)
     let oldLen = p.s(cpsStmts).len
-    genTraverseProc(c, rfmt(nil, "$1[$2]", accessor, i.r), typ.sons[1])
+    genTraverseProc(c, ropecg(c.p.module, "$1[$2]", accessor, i.r), typ.sons[1])
     if p.s(cpsStmts).len == oldLen:
       # do not emit dummy long loops for faster debug builds:
       p.s(cpsStmts) = oldCode
@@ -92,12 +92,12 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
   of tyTuple:
     let typ = getUniqueType(typ)
     for i in countup(0, sonsLen(typ) - 1):
-      genTraverseProc(c, rfmt(nil, "$1.Field$2", accessor, i.rope), typ.sons[i])
+      genTraverseProc(c, ropecg(c.p.module, "$1.Field$2", accessor, i.rope), typ.sons[i])
   of tyRef, tyString, tySequence:
     lineCg(p, cpsStmts, c.visitorFrmt, accessor)
   of tyProc:
     if typ.callConv == ccClosure:
-      lineCg(p, cpsStmts, c.visitorFrmt, rfmt(nil, "$1.ClE_0", accessor))
+      lineCg(p, cpsStmts, c.visitorFrmt, ropecg(c.p.module, "$1.ClE_0", accessor))
   else:
     discard
 
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index adebb6cd0..7b44cddad 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -915,7 +915,7 @@ template cgDeclFrmt*(s: PSym): string = s.constraint.strVal
 proc genProcHeader(m: BModule, prc: PSym): Rope =
   var
     rettype, params: Rope
-  genCLineDir(result, prc.info)
+  genCLineDir(result, prc.info, m.config)
   # using static is needed for inline procs
   if lfExportLib in prc.loc.flags:
     if isHeaderFile in m.flags:
@@ -1239,7 +1239,7 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
       genTupleInfo(m, x, x, result, info)
   of tySequence, tyRef, tyOptAsRef:
     genTypeInfoAux(m, t, t, result, info)
-    if gSelectedGC >= gcMarkAndSweep:
+    if m.config.selectedGC >= gcMarkAndSweep:
       let markerProc = genTraverseProc(m, origType, sig)
       addf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [result, markerProc])
   of tyPtr, tyRange: genTypeInfoAux(m, t, t, result, info)
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 3a5d66762..133e86cea 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -93,6 +93,7 @@ proc useHeader(m: BModule, sym: PSym) =
 proc cgsym(m: BModule, name: string): Rope
 
 proc ropecg(m: BModule, frmt: FormatStr, args: varargs[Rope]): Rope =
+  assert m != nil
   var i = 0
   var length = len(frmt)
   result = nil
@@ -119,7 +120,7 @@ proc ropecg(m: BModule, frmt: FormatStr, args: varargs[Rope]): Rope =
           internalError(m.config, "ropes: invalid format string $" & $j)
         add(result, args[j-1])
       of 'n':
-        if optLineDir notin gOptions: add(result, rnl)
+        if optLineDir notin m.config.options: add(result, rnl)
         inc(i)
       of 'N':
         add(result, rnl)
@@ -146,9 +147,6 @@ proc ropecg(m: BModule, frmt: FormatStr, args: varargs[Rope]): Rope =
     if i - 1 >= start:
       add(result, substr(frmt, start, i - 1))
 
-template rfmt(m: BModule, fmt: string, args: varargs[Rope]): untyped =
-  ropecg(m, fmt, args)
-
 proc indentLine(p: BProc, r: Rope): Rope =
   result = r
   for i in countup(0, p.blocks.len-1):
@@ -188,14 +186,14 @@ proc safeLineNm(info: TLineInfo): int =
   result = toLinenumber(info)
   if result < 0: result = 0 # negative numbers are not allowed in #line
 
-proc genCLineDir(r: var Rope, filename: string, line: int) =
+proc genCLineDir(r: var Rope, filename: string, line: int; conf: ConfigRef) =
   assert line >= 0
-  if optLineDir in gOptions:
+  if optLineDir in conf.options:
     addf(r, "$N#line $2 $1$N",
         [rope(makeSingleLineCString(filename)), rope(line)])
 
-proc genCLineDir(r: var Rope, info: TLineInfo) =
-  genCLineDir(r, info.toFullPath, info.safeLineNm)
+proc genCLineDir(r: var Rope, info: TLineInfo; conf: ConfigRef) =
+  genCLineDir(r, info.toFullPath, info.safeLineNm, conf)
 
 proc freshLineInfo(p: BProc; info: TLineInfo): bool =
   if p.lastLineInfo.line != info.line or
@@ -212,9 +210,9 @@ proc genLineDir(p: BProc, t: PNode) =
     tt = tt.sons[1]
   let line = tt.info.safeLineNm
 
-  if optEmbedOrigSrc in gGlobalOptions:
+  if optEmbedOrigSrc in p.config.globalOptions:
     add(p.s(cpsStmts), ~"//" & sourceLine(p.config, tt.info) & rnl)
-  genCLineDir(p.s(cpsStmts), tt.info.toFullPath, line)
+  genCLineDir(p.s(cpsStmts), tt.info.toFullPath, line, p.config)
   if ({optStackTrace, optEndb} * p.options == {optStackTrace, optEndb}) and
       (p.prc == nil or sfPure notin p.prc.flags):
     if freshLineInfo(p, tt.info):
@@ -235,7 +233,7 @@ proc emulatedThreadVars(conf: ConfigRef): bool {.inline.}
 proc genProc(m: BModule, prc: PSym)
 
 template compileToCpp(m: BModule): untyped =
-  gCmd == cmdCompileToCpp or sfCompileToCpp in m.module.flags
+  m.config.cmd == cmdCompileToCpp or sfCompileToCpp in m.module.flags
 
 proc getTempName(m: BModule): Rope =
   result = m.tmpBase & rope(m.labels)
@@ -416,7 +414,7 @@ proc assignLocalVar(p: BProc, n: PNode) =
   #assert(s.loc.k == locNone) # not yet assigned
   # this need not be fulfilled for inline procs; they are regenerated
   # for each module that uses them!
-  let nl = if optLineDir in gOptions: "" else: tnl
+  let nl = if optLineDir in p.config.options: "" else: tnl
   let decl = localVarDecl(p, n) & ";" & nl
   line(p, cpsLocals, decl)
   localDebugInfo(p, n.sym)
@@ -510,24 +508,24 @@ proc initFrame(p: BProc, procname, filename: Rope): Rope =
   discard cgsym(p.module, "nimFrame")
   if p.maxFrameLen > 0:
     discard cgsym(p.module, "VarSlot")
-    result = rfmt(nil, "\tnimfrs_($1, $2, $3, $4);$n",
+    result = ropecg(p.module, "\tnimfrs_($1, $2, $3, $4);$n",
                   procname, filename, p.maxFrameLen.rope,
                   p.blocks[0].frameLen.rope)
   else:
-    result = rfmt(nil, "\tnimfr_($1, $2);$n", procname, filename)
+    result = ropecg(p.module, "\tnimfr_($1, $2);$n", procname, filename)
 
 proc initFrameNoDebug(p: BProc; frame, procname, filename: Rope; line: int): Rope =
   discard cgsym(p.module, "nimFrame")
   addf(p.blocks[0].sections[cpsLocals], "TFrame $1;$n", [frame])
-  result = rfmt(nil, "\t$1.procname = $2; $1.filename = $3; " &
+  result = ropecg(p.module, "\t$1.procname = $2; $1.filename = $3; " &
                       " $1.line = $4; $1.len = -1; nimFrame(&$1);$n",
                       frame, procname, filename, rope(line))
 
 proc deinitFrameNoDebug(p: BProc; frame: Rope): Rope =
-  result = rfmt(p.module, "\t#popFrameOfAddr(&$1);$n", frame)
+  result = ropecg(p.module, "\t#popFrameOfAddr(&$1);$n", frame)
 
 proc deinitFrame(p: BProc): Rope =
-  result = rfmt(p.module, "\t#popFrame();$n")
+  result = ropecg(p.module, "\t#popFrame();$n")
 
 include ccgexprs
 
@@ -741,7 +739,7 @@ proc genProcAux(m: BModule, prc: PSym) =
         assignLocalVar(p, resNode)
         assert(res.loc.r != nil)
         initLocalVar(p, res, immediateAsgn=false)
-      returnStmt = rfmt(nil, "\treturn $1;$n", rdLoc(res.loc))
+      returnStmt = ropecg(p.module, "\treturn $1;$n", rdLoc(res.loc))
     else:
       fillResult(resNode)
       assignParam(p, res)
@@ -763,10 +761,10 @@ proc genProcAux(m: BModule, prc: PSym) =
   if sfPure in prc.flags:
     if hasDeclspec in extccomp.CC[extccomp.cCompiler].props:
       header = "__declspec(naked) " & header
-    generatedProc = rfmt(nil, "$N$1 {$n$2$3$4}$N$N",
+    generatedProc = ropecg(p.module, "$N$1 {$n$2$3$4}$N$N",
                          header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts))
   else:
-    generatedProc = rfmt(nil, "$N$1 {$N", header)
+    generatedProc = ropecg(p.module, "$N$1 {$N", header)
     add(generatedProc, initGCFrame(p))
     if optStackTrace in prc.options:
       add(generatedProc, p.s(cpsLocals))
@@ -790,10 +788,10 @@ proc genProcAux(m: BModule, prc: PSym) =
 proc requiresExternC(m: BModule; sym: PSym): bool {.inline.} =
   result = (sfCompileToCpp in m.module.flags and
            sfCompileToCpp notin sym.getModule().flags and
-           gCmd != cmdCompileToCpp) or (
+           m.config.cmd != cmdCompileToCpp) or (
            sym.flags * {sfImportc, sfInfixCall, sfCompilerProc} == {sfImportc} and
            sym.magic == mNone and
-           gCmd == cmdCompileToCpp)
+           m.config.cmd == cmdCompileToCpp)
 
 proc genProcPrototype(m: BModule, sym: PSym) =
   useHeader(m, sym)
@@ -801,7 +799,7 @@ proc genProcPrototype(m: BModule, sym: PSym) =
   if lfDynamicLib in sym.loc.flags:
     if getModule(sym).id != m.module.id and
         not containsOrIncl(m.declaredThings, sym.id):
-      add(m.s[cfsVars], rfmt(nil, "extern $1 $2;$n",
+      add(m.s[cfsVars], ropecg(m, "extern $1 $2;$n",
                         getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym)))
   elif not containsOrIncl(m.declaredProtos, sym.id):
     var header = genProcHeader(m, sym)
@@ -813,7 +811,7 @@ proc genProcPrototype(m: BModule, sym: PSym) =
       header.add(" __attribute__((naked))")
     if sfNoReturn in sym.flags and hasAttribute in CC[cCompiler].props:
       header.add(" __attribute__((noreturn))")
-    add(m.s[cfsProcHeaders], rfmt(nil, "$1;$n", header))
+    add(m.s[cfsProcHeaders], ropecg(m, "$1;$n", header))
 
 proc genProcNoForward(m: BModule, prc: PSym) =
   if lfImportCompilerProc in prc.loc.flags:
@@ -919,14 +917,14 @@ proc genVarPrototype(m: BModule, n: PNode) =
       if sfVolatile in sym.flags: add(m.s[cfsVars], " volatile")
       addf(m.s[cfsVars], " $1;$n", [sym.loc.r])
 
-proc addIntTypes(result: var Rope) {.inline.} =
+proc addIntTypes(result: var Rope; conf: ConfigRef) {.inline.} =
   addf(result, "#define NIM_NEW_MANGLING_RULES" & tnl &
                "#define NIM_INTBITS $1" & tnl, [
     platform.CPU[targetCPU].intSize.rope])
-  if useNimNamespace : result.add("#define USE_NIM_NAMESPACE" & tnl)
+  if optUseNimNamespace in conf.globalOptions: result.add("#define USE_NIM_NAMESPACE" & tnl)
 
 proc getCopyright(conf: ConfigRef; cfile: Cfile): Rope =
-  if optCompileOnly in gGlobalOptions:
+  if optCompileOnly in conf.globalOptions:
     result = ("/* Generated by Nim Compiler v$1 */$N" &
         "/*   (c) " & copyrightYear & " Andreas Rumpf */$N" &
         "/* The generated code is subject to the original license. */$N") %
@@ -945,7 +943,7 @@ proc getCopyright(conf: ConfigRef; cfile: Cfile): Rope =
 
 proc getFileHeader(conf: ConfigRef; cfile: Cfile): Rope =
   result = getCopyright(conf, cfile)
-  addIntTypes(result)
+  addIntTypes(result, conf)
 
 proc genFilenames(m: BModule): Rope =
   discard cgsym(m, "dbgRegisterFilename")
@@ -1050,8 +1048,8 @@ proc genMainProc(m: BModule) =
 
   var nimMain, otherMain: FormatStr
   if platform.targetOS == osWindows and
-      gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}:
-    if optGenGuiApp in gGlobalOptions:
+      m.config.globalOptions * {optGenGuiApp, optGenDynLib} != {}:
+    if optGenGuiApp in m.config.globalOptions:
       nimMain = WinNimMain
       otherMain = WinCMain
     else:
@@ -1061,7 +1059,7 @@ proc genMainProc(m: BModule) =
   elif platform.targetOS == osGenode:
     nimMain = GenodeNimMain
     otherMain = ComponentConstruct
-  elif optGenDynLib in gGlobalOptions:
+  elif optGenDynLib in m.config.globalOptions:
     nimMain = PosixNimDllMain
     otherMain = PosixCDllMain
   elif platform.targetOS == osStandalone:
@@ -1071,11 +1069,11 @@ proc genMainProc(m: BModule) =
     nimMain = PosixNimMain
     otherMain = PosixCMain
   if m.g.breakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint")
-  if optEndb in gOptions:
+  if optEndb in m.config.options:
     m.g.breakpoints.add(m.genFilenames)
 
   let initStackBottomCall =
-    if platform.targetOS == osStandalone or gSelectedGC == gcNone: "".rope
+    if platform.targetOS == osStandalone or m.config.selectedGC == gcNone: "".rope
     else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N")
   inc(m.labels)
   appcg(m, m.s[cfsProcs], PreMainBody, [
@@ -1088,12 +1086,12 @@ proc genMainProc(m: BModule) =
 
   appcg(m, m.s[cfsProcs], nimMain,
         [m.g.mainModInit, initStackBottomCall, rope(m.labels)])
-  if optNoMain notin gGlobalOptions:
-    if useNimNamespace:
+  if optNoMain notin m.config.globalOptions:
+    if optUseNimNamespace in m.config.globalOptions:
       m.s[cfsProcs].add closeNamespaceNim() & "using namespace Nim;" & tnl
 
     appcg(m, m.s[cfsProcs], otherMain, [])
-    if useNimNamespace: m.s[cfsProcs].add openNamespaceNim()
+    if optUseNimNamespace in m.config.globalOptions: m.s[cfsProcs].add openNamespaceNim()
 
 proc getSomeInitName(m: PSym, suffix: string): Rope =
   assert m.kind == skModule
@@ -1201,9 +1199,10 @@ proc genModule(m: BModule, cfile: Cfile): Rope =
     add(result, genSectionStart(i, m.config))
     add(result, m.s[i])
     add(result, genSectionEnd(i, m.config))
-    if useNimNamespace and i == cfsHeaders: result.add openNamespaceNim()
+    if optUseNimNamespace in m.config.globalOptions and i == cfsHeaders:
+      result.add openNamespaceNim()
   add(result, m.s[cfsInitProc])
-  if useNimNamespace: result.add closeNamespaceNim()
+  if optUseNimNamespace in m.config.globalOptions: result.add closeNamespaceNim()
 
 proc newPreInitProc(m: BModule): BProc =
   result = newProc(nil, m)
@@ -1216,10 +1215,12 @@ proc newPostInitProc(m: BModule): BProc =
   result.labels = 200_000
 
 proc initProcOptions(m: BModule): TOptions =
-  if sfSystemModule in m.module.flags: gOptions-{optStackTrace} else: gOptions
+  let opts = m.config.options
+  if sfSystemModule in m.module.flags: opts-{optStackTrace} else: opts
 
 proc rawNewModule(g: BModuleList; module: PSym, filename: string): BModule =
   new(result)
+  result.g = g
   result.tmpBase = rope("TM" & $hashOwner(module) & "_")
   result.headerFiles = @[]
   result.declaredThings = initIntSet()
@@ -1240,14 +1241,13 @@ proc rawNewModule(g: BModuleList; module: PSym, filename: string): BModule =
   result.forwardedProcs = @[]
   result.typeNodesName = getTempName(result)
   result.nimTypesName = getTempName(result)
-  result.g = g
   # no line tracing for the init sections of the system module so that we
   # don't generate a TFrame which can confuse the stack botton initialization:
   if sfSystemModule in module.flags:
     incl result.flags, preventStackTrace
     excl(result.preInitProc.options, optStackTrace)
     excl(result.postInitProc.options, optStackTrace)
-  let ndiName = if optCDebug in gGlobalOptions: changeFileExt(completeCFilePath(g.config, filename), "ndi")
+  let ndiName = if optCDebug in g.config.globalOptions: changeFileExt(completeCFilePath(g.config, filename), "ndi")
                 else: ""
   open(result.ndi, ndiName)
 
@@ -1316,7 +1316,7 @@ template injectG() {.dirty.} =
 proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
   injectG()
   result = newModule(g, module)
-  if optGenIndex in gGlobalOptions and g.generatedHeader == nil:
+  if optGenIndex in graph.config.globalOptions and g.generatedHeader == nil:
     let f = if graph.config.headerFile.len > 0: graph.config.headerFile
             else: graph.config.projectFull
     g.generatedHeader = rawNewModule(g, module,
@@ -1331,7 +1331,7 @@ proc writeHeader(m: BModule) =
 
   var guard = "__$1__" % [m.filename.splitFile.name.rope]
   result.addf("#ifndef $1$n#define $1$n", [guard])
-  addIntTypes(result)
+  addIntTypes(result, m.config)
   generateHeaders(m)
 
   generateThreadLocalStorage(m)
@@ -1339,20 +1339,20 @@ proc writeHeader(m: BModule) =
     add(result, genSectionStart(i, m.config))
     add(result, m.s[i])
     add(result, genSectionEnd(i, m.config))
-    if useNimNamespace and i == cfsHeaders: result.add openNamespaceNim()
+    if optUseNimNamespace in m.config.globalOptions and i == cfsHeaders: result.add openNamespaceNim()
   add(result, m.s[cfsInitProc])
 
-  if optGenDynLib in gGlobalOptions:
+  if optGenDynLib in m.config.globalOptions:
     result.add("N_LIB_IMPORT ")
   result.addf("N_CDECL(void, NimMain)(void);$n", [])
-  if useNimNamespace: result.add closeNamespaceNim()
+  if optUseNimNamespace in m.config.globalOptions: result.add closeNamespaceNim()
   result.addf("#endif /* $1 */$n", [guard])
   writeRope(result, m.filename)
 
 proc getCFile(m: BModule): string =
   let ext =
       if m.compileToCpp: ".cpp"
-      elif gCmd == cmdCompileToOC or sfCompileToObjC in m.module.flags: ".m"
+      elif m.config.cmd == cmdCompileToOC or sfCompileToObjC in m.module.flags: ".m"
       else: ".c"
   result = changeFileExt(completeCFilePath(m.config, withPackageName(m.config, m.cfilename)), ext)
 
@@ -1368,7 +1368,7 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
   var m = BModule(b)
   if passes.skipCodegen(m.config, n): return
   m.initProc.options = initProcOptions(m)
-  softRnl = if optLineDir in gOptions: noRnl else: rnl
+  softRnl = if optLineDir in m.config.options: noRnl else: rnl
   genStmts(m.initProc, n)
 
 proc finishModule(m: BModule) =
@@ -1387,7 +1387,7 @@ proc finishModule(m: BModule) =
 
 proc shouldRecompile(m: BModule; code: Rope, cfile: Cfile): bool =
   result = true
-  if optForceFullMake notin gGlobalOptions:
+  if optForceFullMake notin m.config.globalOptions:
     if not equalsFile(code, cfile.cname):
       if isDefined(m.config, "nimdiff"):
         if fileExists(cfile.cname):
@@ -1412,7 +1412,7 @@ proc writeModule(m: BModule, pending: bool) =
   # generate code for the init statements of the module:
   let cfile = getCFile(m)
 
-  if m.rd == nil or optForceFullMake in gGlobalOptions:
+  if m.rd == nil or optForceFullMake in m.config.globalOptions:
     genInitCode(m)
     finishTypeDescriptions(m)
     if sfMainModule in m.module.flags:
@@ -1423,7 +1423,7 @@ proc writeModule(m: BModule, pending: bool) =
     var cf = Cfile(cname: cfile, obj: completeCFilePath(m.config, toObjFile(m.config, cfile)), flags: {})
     var code = genModule(m, cf)
     when hasTinyCBackend:
-      if gCmd == cmdRun:
+      if conf.cmd == cmdRun:
         tccgen.compileCCode($code)
         return
 
diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim
index 0c310dd7d..ce3fc2f90 100644
--- a/compiler/cgendata.nim
+++ b/compiler/cgendata.nim
@@ -170,7 +170,7 @@ proc newProc*(prc: PSym, module: BModule): BProc =
   result.prc = prc
   result.module = module
   if prc != nil: result.options = prc.options
-  else: result.options = gOptions
+  else: result.options = module.config.options
   newSeq(result.blocks, 1)
   result.nestedTryStmts = @[]
   result.finallySafePoints = @[]
diff --git a/compiler/commands.nim b/compiler/commands.nim
index 328dc2f02..09f63f0f5 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -61,49 +61,49 @@ proc getCommandLineDesc(): string =
                            CPU[platform.hostCPU].name, CompileDate]) &
                            Usage
 
-proc helpOnError(pass: TCmdLinePass) =
+proc helpOnError(conf: ConfigRef; pass: TCmdLinePass) =
   if pass == passCmd1:
-    msgWriteln(getCommandLineDesc(), {msgStdout})
+    msgWriteln(conf, getCommandLineDesc(), {msgStdout})
     msgQuit(0)
 
-proc writeAdvancedUsage(pass: TCmdLinePass) =
+proc writeAdvancedUsage(conf: ConfigRef; pass: TCmdLinePass) =
   if pass == passCmd1:
-    msgWriteln(`%`(HelpMessage, [VersionAsString,
+    msgWriteln(conf, (HelpMessage % [VersionAsString,
                                  platform.OS[platform.hostOS].name,
                                  CPU[platform.hostCPU].name, CompileDate]) &
                                  AdvancedUsage,
                {msgStdout})
     msgQuit(0)
 
-proc writeFullhelp(pass: TCmdLinePass) =
+proc writeFullhelp(conf: ConfigRef; pass: TCmdLinePass) =
   if pass == passCmd1:
-    msgWriteln(`%`(HelpMessage, [VersionAsString,
+    msgWriteln(conf, `%`(HelpMessage, [VersionAsString,
                                  platform.OS[platform.hostOS].name,
                                  CPU[platform.hostCPU].name, CompileDate]) &
                                  Usage & AdvancedUsage,
                {msgStdout})
     msgQuit(0)
 
-proc writeVersionInfo(pass: TCmdLinePass) =
+proc writeVersionInfo(conf: ConfigRef; pass: TCmdLinePass) =
   if pass == passCmd1:
-    msgWriteln(`%`(HelpMessage, [VersionAsString,
+    msgWriteln(conf, `%`(HelpMessage, [VersionAsString,
                                  platform.OS[platform.hostOS].name,
                                  CPU[platform.hostCPU].name, CompileDate]),
                {msgStdout})
 
     const gitHash = gorge("git log -n 1 --format=%H").strip
     when gitHash.len == 40:
-      msgWriteln("git hash: " & gitHash, {msgStdout})
+      msgWriteln(conf, "git hash: " & gitHash, {msgStdout})
 
-    msgWriteln("active boot switches:" & usedRelease &
+    msgWriteln(conf, "active boot switches:" & usedRelease &
       usedTinyC & usedGnuReadline & usedNativeStacktrace &
       usedFFI & usedBoehm & usedMarkAndSweep & usedGenerational & usedGoGC & usedNoGC,
                {msgStdout})
     msgQuit(0)
 
-proc writeCommandLineUsage*(helpWritten: var bool) =
+proc writeCommandLineUsage*(conf: ConfigRef; helpWritten: var bool) =
   if not helpWritten:
-    msgWriteln(getCommandLineDesc(), {msgStdout})
+    msgWriteln(conf, getCommandLineDesc(), {msgStdout})
     helpWritten = true
 
 proc addPrefix(switch: string): string =
@@ -137,24 +137,24 @@ proc splitSwitch(conf: ConfigRef; switch: string, cmd, arg: var string, pass: TC
 proc processOnOffSwitch(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
                         info: TLineInfo) =
   case arg.normalize
-  of "on": gOptions = gOptions + op
-  of "off": gOptions = gOptions - op
+  of "on": conf.options = conf.options + op
+  of "off": conf.options = conf.options - op
   else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
 
 proc processOnOffSwitchOrList(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
                               info: TLineInfo): bool =
   result = false
   case arg.normalize
-  of "on": gOptions = gOptions + op
-  of "off": gOptions = gOptions - op
+  of "on": conf.options = conf.options + op
+  of "off": conf.options = conf.options - op
   of "list": result = true
   else: localError(conf, info, errOnOffOrListExpectedButXFound % arg)
 
 proc processOnOffSwitchG(conf: ConfigRef; op: TGlobalOptions, arg: string, pass: TCmdLinePass,
                          info: TLineInfo) =
   case arg.normalize
-  of "on": gGlobalOptions = gGlobalOptions + op
-  of "off": gGlobalOptions = gGlobalOptions - op
+  of "on": conf.globalOptions = conf.globalOptions + op
+  of "off": conf.globalOptions = conf.globalOptions - op
   else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
 
 proc expectArg(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
@@ -211,30 +211,30 @@ proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo
   case switch.normalize
   of "gc":
     case arg.normalize
-    of "boehm":        result = gSelectedGC == gcBoehm
-    of "refc":         result = gSelectedGC == gcRefc
-    of "v2":           result = gSelectedGC == gcV2
-    of "markandsweep": result = gSelectedGC == gcMarkAndSweep
-    of "generational": result = gSelectedGC == gcGenerational
-    of "go":           result = gSelectedGC == gcGo
-    of "none":         result = gSelectedGC == gcNone
-    of "stack", "regions": result = gSelectedGC == gcRegions
+    of "boehm":        result = conf.selectedGC == gcBoehm
+    of "refc":         result = conf.selectedGC == gcRefc
+    of "v2":           result = conf.selectedGC == gcV2
+    of "markandsweep": result = conf.selectedGC == gcMarkAndSweep
+    of "generational": result = conf.selectedGC == gcGenerational
+    of "go":           result = conf.selectedGC == gcGo
+    of "none":         result = conf.selectedGC == gcNone
+    of "stack", "regions": result = conf.selectedGC == gcRegions
     else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
   of "opt":
     case arg.normalize
-    of "speed": result = contains(gOptions, optOptimizeSpeed)
-    of "size": result = contains(gOptions, optOptimizeSize)
-    of "none": result = gOptions * {optOptimizeSpeed, optOptimizeSize} == {}
+    of "speed": result = contains(conf.options, optOptimizeSpeed)
+    of "size": result = contains(conf.options, optOptimizeSize)
+    of "none": result = conf.options * {optOptimizeSpeed, optOptimizeSize} == {}
     else: localError(conf, info, errNoneSpeedOrSizeExpectedButXFound % arg)
-  of "verbosity": result = $gVerbosity == arg
+  of "verbosity": result = $conf.verbosity == arg
   of "app":
     case arg.normalize
-    of "gui":       result = contains(gGlobalOptions, optGenGuiApp)
-    of "console":   result = not contains(gGlobalOptions, optGenGuiApp)
-    of "lib":       result = contains(gGlobalOptions, optGenDynLib) and
-                      not contains(gGlobalOptions, optGenGuiApp)
-    of "staticlib": result = contains(gGlobalOptions, optGenStaticLib) and
-                      not contains(gGlobalOptions, optGenGuiApp)
+    of "gui":       result = contains(conf.globalOptions, optGenGuiApp)
+    of "console":   result = not contains(conf.globalOptions, optGenGuiApp)
+    of "lib":       result = contains(conf.globalOptions, optGenDynLib) and
+                      not contains(conf.globalOptions, optGenGuiApp)
+    of "staticlib": result = contains(conf.globalOptions, optGenStaticLib) and
+                      not contains(conf.globalOptions, optGenGuiApp)
     else: localError(conf, info, errGuiConsoleOrLibExpectedButXFound % arg)
   of "dynliboverride":
     result = isDynlibOverride(conf, arg)
@@ -242,42 +242,42 @@ proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo
 
 proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool =
   case switch.normalize
-  of "debuginfo": result = contains(gGlobalOptions, optCDebug)
-  of "compileonly", "c": result = contains(gGlobalOptions, optCompileOnly)
-  of "nolinking": result = contains(gGlobalOptions, optNoLinking)
-  of "nomain": result = contains(gGlobalOptions, optNoMain)
-  of "forcebuild", "f": result = contains(gGlobalOptions, optForceFullMake)
-  of "warnings", "w": result = contains(gOptions, optWarns)
-  of "hints": result = contains(gOptions, optHints)
-  of "threadanalysis": result = contains(gGlobalOptions, optThreadAnalysis)
-  of "stacktrace": result = contains(gOptions, optStackTrace)
-  of "linetrace": result = contains(gOptions, optLineTrace)
-  of "debugger": result = contains(gOptions, optEndb)
-  of "profiler": result = contains(gOptions, optProfiler)
-  of "memtracker": result = contains(gOptions, optMemTracker)
-  of "checks", "x": result = gOptions * ChecksOptions == ChecksOptions
+  of "debuginfo": result = contains(conf.globalOptions, optCDebug)
+  of "compileonly", "c": result = contains(conf.globalOptions, optCompileOnly)
+  of "nolinking": result = contains(conf.globalOptions, optNoLinking)
+  of "nomain": result = contains(conf.globalOptions, optNoMain)
+  of "forcebuild", "f": result = contains(conf.globalOptions, optForceFullMake)
+  of "warnings", "w": result = contains(conf.options, optWarns)
+  of "hints": result = contains(conf.options, optHints)
+  of "threadanalysis": result = contains(conf.globalOptions, optThreadAnalysis)
+  of "stacktrace": result = contains(conf.options, optStackTrace)
+  of "linetrace": result = contains(conf.options, optLineTrace)
+  of "debugger": result = contains(conf.options, optEndb)
+  of "profiler": result = contains(conf.options, optProfiler)
+  of "memtracker": result = contains(conf.options, optMemTracker)
+  of "checks", "x": result = conf.options * ChecksOptions == ChecksOptions
   of "floatchecks":
-    result = gOptions * {optNaNCheck, optInfCheck} == {optNaNCheck, optInfCheck}
-  of "infchecks": result = contains(gOptions, optInfCheck)
-  of "nanchecks": result = contains(gOptions, optNaNCheck)
-  of "nilchecks": result = contains(gOptions, optNilCheck)
-  of "objchecks": result = contains(gOptions, optObjCheck)
-  of "fieldchecks": result = contains(gOptions, optFieldCheck)
-  of "rangechecks": result = contains(gOptions, optRangeCheck)
-  of "boundchecks": result = contains(gOptions, optBoundsCheck)
-  of "overflowchecks": result = contains(gOptions, optOverflowCheck)
-  of "movechecks": result = contains(gOptions, optMoveCheck)
-  of "linedir": result = contains(gOptions, optLineDir)
-  of "assertions", "a": result = contains(gOptions, optAssert)
-  of "run", "r": result = contains(gGlobalOptions, optRun)
-  of "symbolfiles": result = gSymbolFiles != disabledSf
-  of "genscript": result = contains(gGlobalOptions, optGenScript)
-  of "threads": result = contains(gGlobalOptions, optThreads)
-  of "taintmode": result = contains(gGlobalOptions, optTaintMode)
-  of "tlsemulation": result = contains(gGlobalOptions, optTlsEmulation)
-  of "implicitstatic": result = contains(gOptions, optImplicitStatic)
-  of "patterns": result = contains(gOptions, optPatterns)
-  of "excessivestacktrace": result = contains(gGlobalOptions, optExcessiveStackTrace)
+    result = conf.options * {optNaNCheck, optInfCheck} == {optNaNCheck, optInfCheck}
+  of "infchecks": result = contains(conf.options, optInfCheck)
+  of "nanchecks": result = contains(conf.options, optNaNCheck)
+  of "nilchecks": result = contains(conf.options, optNilCheck)
+  of "objchecks": result = contains(conf.options, optObjCheck)
+  of "fieldchecks": result = contains(conf.options, optFieldCheck)
+  of "rangechecks": result = contains(conf.options, optRangeCheck)
+  of "boundchecks": result = contains(conf.options, optBoundsCheck)
+  of "overflowchecks": result = contains(conf.options, optOverflowCheck)
+  of "movechecks": result = contains(conf.options, optMoveCheck)
+  of "linedir": result = contains(conf.options, optLineDir)
+  of "assertions", "a": result = contains(conf.options, optAssert)
+  of "run", "r": result = contains(conf.globalOptions, optRun)
+  of "symbolfiles": result = conf.symbolFiles != disabledSf
+  of "genscript": result = contains(conf.globalOptions, optGenScript)
+  of "threads": result = contains(conf.globalOptions, optThreads)
+  of "taintmode": result = contains(conf.globalOptions, optTaintMode)
+  of "tlsemulation": result = contains(conf.globalOptions, optTlsEmulation)
+  of "implicitstatic": result = contains(conf.options, optImplicitStatic)
+  of "patterns": result = contains(conf.options, optPatterns)
+  of "excessivestacktrace": result = contains(conf.globalOptions, optExcessiveStackTrace)
   else: invalidCmdLineOption(conf, passCmd1, switch, info)
 
 proc processPath(conf: ConfigRef; path: string, info: TLineInfo,
@@ -353,7 +353,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
     addPath(conf, if pass == passPP: processCfgPath(conf, arg, info) else: processPath(conf, arg, info), info)
   of "nimblepath", "babelpath":
     # keep the old name for compat
-    if pass in {passCmd2, passPP} and not options.gNoNimblePath:
+    if pass in {passCmd2, passPP} and optNoNimblePath notin conf.globalOptions:
       expectArg(conf, switch, arg, pass, info)
       var path = processPath(conf, arg, info, notRelativeToProj=true)
       let nimbleDir = getEnv("NIMBLE_DIR")
@@ -405,49 +405,49 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
     if pass in {passCmd2, passPP}: addExternalFileToLink(conf, arg)
   of "debuginfo":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optCDebug)
+    incl(conf.globalOptions, optCDebug)
   of "embedsrc":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optEmbedOrigSrc)
+    incl(conf.globalOptions, optEmbedOrigSrc)
   of "compileonly", "c":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optCompileOnly)
+    incl(conf.globalOptions, optCompileOnly)
   of "nolinking":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optNoLinking)
+    incl(conf.globalOptions, optNoLinking)
   of "nomain":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optNoMain)
+    incl(conf.globalOptions, optNoMain)
   of "forcebuild", "f":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optForceFullMake)
+    incl(conf.globalOptions, optForceFullMake)
   of "project":
     expectNoArg(conf, switch, arg, pass, info)
-    gWholeProject = true
+    incl conf.globalOptions, optWholeProject
   of "gc":
     expectArg(conf, switch, arg, pass, info)
     case arg.normalize
     of "boehm":
-      gSelectedGC = gcBoehm
+      conf.selectedGC = gcBoehm
       defineSymbol(conf.symbols, "boehmgc")
     of "refc":
-      gSelectedGC = gcRefc
+      conf.selectedGC = gcRefc
     of "v2":
-      gSelectedGC = gcV2
+      conf.selectedGC = gcV2
     of "markandsweep":
-      gSelectedGC = gcMarkAndSweep
+      conf.selectedGC = gcMarkAndSweep
       defineSymbol(conf.symbols, "gcmarkandsweep")
     of "generational":
-      gSelectedGC = gcGenerational
+      conf.selectedGC = gcGenerational
       defineSymbol(conf.symbols, "gcgenerational")
     of "go":
-      gSelectedGC = gcGo
+      conf.selectedGC = gcGo
       defineSymbol(conf.symbols, "gogc")
     of "none":
-      gSelectedGC = gcNone
+      conf.selectedGC = gcNone
       defineSymbol(conf.symbols, "nogc")
     of "stack", "regions":
-      gSelectedGC= gcRegions
+      conf.selectedGC= gcRegions
       defineSymbol(conf.symbols, "gcregions")
     else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
   of "warnings", "w":
@@ -463,29 +463,29 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
   of "debugger":
     case arg.normalize
     of "on", "endb":
-      gOptions.incl optEndb
+      conf.options.incl optEndb
       defineSymbol(conf.symbols, "endb")
     of "off":
-      gOptions.excl optEndb
+      conf.options.excl optEndb
       undefSymbol(conf.symbols, "endb")
     of "native", "gdb":
-      incl(gGlobalOptions, optCDebug)
-      gOptions = gOptions + {optLineDir} - {optEndb}
+      incl(conf.globalOptions, optCDebug)
+      conf.options = conf.options + {optLineDir} - {optEndb}
       defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
       undefSymbol(conf.symbols, "endb")
     else:
       localError(conf, info, "expected endb|gdb but found " & arg)
   of "profiler":
     processOnOffSwitch(conf, {optProfiler}, arg, pass, info)
-    if optProfiler in gOptions: defineSymbol(conf.symbols, "profiler")
+    if optProfiler in conf.options: defineSymbol(conf.symbols, "profiler")
     else: undefSymbol(conf.symbols, "profiler")
   of "memtracker":
     processOnOffSwitch(conf, {optMemTracker}, arg, pass, info)
-    if optMemTracker in gOptions: defineSymbol(conf.symbols, "memtracker")
+    if optMemTracker in conf.options: defineSymbol(conf.symbols, "memtracker")
     else: undefSymbol(conf.symbols, "memtracker")
   of "hotcodereloading":
     processOnOffSwitch(conf, {optHotCodeReloading}, arg, pass, info)
-    if optHotCodeReloading in gOptions: defineSymbol(conf.symbols, "hotcodereloading")
+    if optHotCodeReloading in conf.options: defineSymbol(conf.symbols, "hotcodereloading")
     else: undefSymbol(conf.symbols, "hotcodereloading")
   of "oldnewlines":
     case arg.normalize
@@ -515,7 +515,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
   of "deadcodeelim": discard # deprecated, dead code elim always on
   of "threads":
     processOnOffSwitchG(conf, {optThreads}, arg, pass, info)
-    #if optThreads in gGlobalOptions: incl(conf.notes, warnGcUnsafe)
+    #if optThreads in conf.globalOptions: incl(conf.notes, warnGcUnsafe)
   of "tlsemulation": processOnOffSwitchG(conf, {optTlsEmulation}, arg, pass, info)
   of "taintmode": processOnOffSwitchG(conf, {optTaintMode}, arg, pass, info)
   of "implicitstatic":
@@ -526,34 +526,34 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
     expectArg(conf, switch, arg, pass, info)
     case arg.normalize
     of "speed":
-      incl(gOptions, optOptimizeSpeed)
-      excl(gOptions, optOptimizeSize)
+      incl(conf.options, optOptimizeSpeed)
+      excl(conf.options, optOptimizeSize)
     of "size":
-      excl(gOptions, optOptimizeSpeed)
-      incl(gOptions, optOptimizeSize)
+      excl(conf.options, optOptimizeSpeed)
+      incl(conf.options, optOptimizeSize)
     of "none":
-      excl(gOptions, optOptimizeSpeed)
-      excl(gOptions, optOptimizeSize)
+      excl(conf.options, optOptimizeSpeed)
+      excl(conf.options, optOptimizeSize)
     else: localError(conf, info, errNoneSpeedOrSizeExpectedButXFound % arg)
   of "app":
     expectArg(conf, switch, arg, pass, info)
     case arg.normalize
     of "gui":
-      incl(gGlobalOptions, optGenGuiApp)
+      incl(conf.globalOptions, optGenGuiApp)
       defineSymbol(conf.symbols, "executable")
       defineSymbol(conf.symbols, "guiapp")
     of "console":
-      excl(gGlobalOptions, optGenGuiApp)
+      excl(conf.globalOptions, optGenGuiApp)
       defineSymbol(conf.symbols, "executable")
       defineSymbol(conf.symbols, "consoleapp")
     of "lib":
-      incl(gGlobalOptions, optGenDynLib)
-      excl(gGlobalOptions, optGenGuiApp)
+      incl(conf.globalOptions, optGenDynLib)
+      excl(conf.globalOptions, optGenGuiApp)
       defineSymbol(conf.symbols, "library")
       defineSymbol(conf.symbols, "dll")
     of "staticlib":
-      incl(gGlobalOptions, optGenStaticLib)
-      excl(gGlobalOptions, optGenGuiApp)
+      incl(conf.globalOptions, optGenStaticLib)
+      excl(conf.globalOptions, optGenGuiApp)
       defineSymbol(conf.symbols, "library")
       defineSymbol(conf.symbols, "staticlib")
     else: localError(conf, info, errGuiConsoleOrLibExpectedButXFound % arg)
@@ -574,7 +574,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
     if pass in {passCmd2, passPP}: cLinkedLibs.add processPath(conf, arg, info)
   of "header":
     if conf != nil: conf.headerFile = arg
-    incl(gGlobalOptions, optGenIndex)
+    incl(conf.globalOptions, optGenIndex)
   of "index":
     processOnOffSwitchG(conf, {optGenIndex}, arg, pass, info)
   of "import":
@@ -585,10 +585,10 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
     if pass in {passCmd2, passPP}: conf.implicitIncludes.add arg
   of "listcmd":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optListCmd)
+    incl(conf.globalOptions, optListCmd)
   of "genmapping":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optGenMapping)
+    incl(conf.globalOptions, optGenMapping)
   of "os":
     expectArg(conf, switch, arg, pass, info)
     if pass in {passCmd1, passPP}:
@@ -605,53 +605,53 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
         setTarget(targetOS, cpu)
   of "run", "r":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optRun)
+    incl(conf.globalOptions, optRun)
   of "verbosity":
     expectArg(conf, switch, arg, pass, info)
-    gVerbosity = parseInt(arg)
-    conf.notes = NotesVerbosity[gVerbosity]
+    conf.verbosity = parseInt(arg)
+    conf.notes = NotesVerbosity[conf.verbosity]
     incl(conf.notes, conf.enableNotes)
     excl(conf.notes, conf.disableNotes)
     conf.mainPackageNotes = conf.notes
   of "parallelbuild":
     expectArg(conf, switch, arg, pass, info)
-    gNumberOfProcessors = parseInt(arg)
+    conf.numberOfProcessors = parseInt(arg)
   of "version", "v":
     expectNoArg(conf, switch, arg, pass, info)
-    writeVersionInfo(pass)
+    writeVersionInfo(conf, pass)
   of "advanced":
     expectNoArg(conf, switch, arg, pass, info)
-    writeAdvancedUsage(pass)
+    writeAdvancedUsage(conf, pass)
   of "fullhelp":
     expectNoArg(conf, switch, arg, pass, info)
-    writeFullhelp(pass)
+    writeFullhelp(conf, pass)
   of "help", "h":
     expectNoArg(conf, switch, arg, pass, info)
-    helpOnError(pass)
+    helpOnError(conf, pass)
   of "symbolfiles":
     case arg.normalize
-    of "on": gSymbolFiles = enabledSf
-    of "off": gSymbolFiles = disabledSf
-    of "writeonly": gSymbolFiles = writeOnlySf
-    of "readonly": gSymbolFiles = readOnlySf
-    of "v2": gSymbolFiles = v2Sf
+    of "on": conf.symbolFiles = enabledSf
+    of "off": conf.symbolFiles = disabledSf
+    of "writeonly": conf.symbolFiles = writeOnlySf
+    of "readonly": conf.symbolFiles = readOnlySf
+    of "v2": conf.symbolFiles = v2Sf
     else: localError(conf, info, "invalid option for --symbolFiles: " & arg)
   of "skipcfg":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optSkipConfigFile)
+    incl(conf.globalOptions, optSkipConfigFile)
   of "skipprojcfg":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optSkipProjConfigFile)
+    incl(conf.globalOptions, optSkipProjConfigFile)
   of "skipusercfg":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optSkipUserConfigFile)
+    incl(conf.globalOptions, optSkipUserConfigFile)
   of "skipparentcfg":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optSkipParentConfigFiles)
+    incl(conf.globalOptions, optSkipParentConfigFiles)
   of "genscript", "gendeps":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optGenScript)
-    incl(gGlobalOptions, optCompileOnly)
+    incl(conf.globalOptions, optGenScript)
+    incl(conf.globalOptions, optCompileOnly)
   of "colors": processOnOffSwitchG(conf, {optUseColors}, arg, pass, info)
   of "lib":
     expectArg(conf, switch, arg, pass, info)
@@ -677,7 +677,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
     conf.ideCmd = ideDef
   of "eval":
     expectArg(conf, switch, arg, pass, info)
-    gEvalExpr = arg
+    conf.evalExpr = arg
   of "context":
     expectNoArg(conf, switch, arg, pass, info)
     conf.ideCmd = ideCon
@@ -686,15 +686,15 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
     conf.ideCmd = ideUse
   of "stdout":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optStdout)
+    incl(conf.globalOptions, optStdout)
   of "listfullpaths":
     expectNoArg(conf, switch, arg, pass, info)
-    gListFullPaths = true
+    incl conf.globalOptions, optListFullPaths
   of "dynliboverride":
     dynlibOverride(conf, switch, arg, pass, info)
   of "dynliboverrideall":
     expectNoArg(conf, switch, arg, pass, info)
-    gDynlibOverrideAll = true
+    incl conf.globalOptions, optDynlibOverrideAll
   of "cs":
     # only supported for compatibility. Does nothing.
     expectArg(conf, switch, arg, pass, info)
@@ -708,7 +708,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
         localError(conf, info, "unknown experimental feature")
   of "nocppexceptions":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(gGlobalOptions, optNoCppExceptions)
+    incl(conf.globalOptions, optNoCppExceptions)
     defineSymbol(conf.symbols, "noCppExceptions")
   of "cppdefine":
     expectArg(conf, switch, arg, pass, info)
@@ -721,7 +721,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
     defineSymbol(conf.symbols, "nimNewRuntime")
   of "cppcompiletonamespace":
     expectNoArg(conf, switch, arg, pass, info)
-    useNimNamespace = true
+    incl conf.globalOptions, optUseNimNamespace
     defineSymbol(conf.symbols, "cppCompileToNamespace")
   else:
     if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg)
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index 7fca27cc9..7ab2f0eee 100644
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -29,7 +29,7 @@ type
     jArray: JsonNode
     types: TStrTable
     isPureRst: bool
-    conf: ConfigRef
+    conf*: ConfigRef
 
   PDoc* = ref TDocumentor ## Alias to type less.
 
@@ -90,7 +90,7 @@ proc newDocumentor*(filename: string, conf: ConfigRef): PDoc =
   declareClosures()
   new(result)
   result.conf = conf
-  initRstGenerator(result[], (if gCmd != cmdRst2tex: outHtml else: outLatex),
+  initRstGenerator(result[], (if conf.cmd != cmdRst2tex: outHtml else: outLatex),
                    conf.configVars, filename, {roSupportRawDirective},
                    docgenFindFile, compilerMsgHandler)
 
@@ -117,8 +117,8 @@ proc newDocumentor*(filename: string, conf: ConfigRef): PDoc =
   result.onTestSnippet = proc (d: var RstGenerator; filename, cmd: string; status: int; content: string) =
     localError(conf, newLineInfo(conf, d.filename, -1, -1), warnUser, "only 'rst2html' supports the ':test:' attribute")
 
-proc dispA(dest: var Rope, xml, tex: string, args: openArray[Rope]) =
-  if gCmd != cmdRst2tex: addf(dest, xml, args)
+proc dispA(conf: ConfigRef; dest: var Rope, xml, tex: string, args: openArray[Rope]) =
+  if conf.cmd != cmdRst2tex: addf(dest, xml, args)
   else: addf(dest, tex, args)
 
 proc getVarIdx(varnames: openArray[string], id: string): int =
@@ -231,37 +231,37 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe
     of tkEof:
       break
     of tkComment:
-      dispA(result, "<span class=\"Comment\">$1</span>", "\\spanComment{$1}",
+      dispA(d.conf, result, "<span class=\"Comment\">$1</span>", "\\spanComment{$1}",
             [rope(esc(d.target, literal))])
     of tokKeywordLow..tokKeywordHigh:
-      dispA(result, "<span class=\"Keyword\">$1</span>", "\\spanKeyword{$1}",
+      dispA(d.conf, result, "<span class=\"Keyword\">$1</span>", "\\spanKeyword{$1}",
             [rope(literal)])
     of tkOpr:
-      dispA(result, "<span class=\"Operator\">$1</span>", "\\spanOperator{$1}",
+      dispA(d.conf, result, "<span class=\"Operator\">$1</span>", "\\spanOperator{$1}",
             [rope(esc(d.target, literal))])
     of tkStrLit..tkTripleStrLit:
-      dispA(result, "<span class=\"StringLit\">$1</span>",
+      dispA(d.conf, result, "<span class=\"StringLit\">$1</span>",
             "\\spanStringLit{$1}", [rope(esc(d.target, literal))])
     of tkCharLit:
-      dispA(result, "<span class=\"CharLit\">$1</span>", "\\spanCharLit{$1}",
+      dispA(d.conf, result, "<span class=\"CharLit\">$1</span>", "\\spanCharLit{$1}",
             [rope(esc(d.target, literal))])
     of tkIntLit..tkUInt64Lit:
-      dispA(result, "<span class=\"DecNumber\">$1</span>",
+      dispA(d.conf, result, "<span class=\"DecNumber\">$1</span>",
             "\\spanDecNumber{$1}", [rope(esc(d.target, literal))])
     of tkFloatLit..tkFloat128Lit:
-      dispA(result, "<span class=\"FloatNumber\">$1</span>",
+      dispA(d.conf, result, "<span class=\"FloatNumber\">$1</span>",
             "\\spanFloatNumber{$1}", [rope(esc(d.target, literal))])
     of tkSymbol:
-      dispA(result, "<span class=\"Identifier\">$1</span>",
+      dispA(d.conf, result, "<span class=\"Identifier\">$1</span>",
             "\\spanIdentifier{$1}", [rope(esc(d.target, literal))])
     of tkSpaces, tkInvalid:
       add(result, literal)
     of tkCurlyDotLe:
-      dispA(result, """<span class="Other pragmabegin">$1</span><div class="pragma">""",
+      dispA(d.conf, result, """<span class="Other pragmabegin">$1</span><div class="pragma">""",
                     "\\spanOther{$1}",
                   [rope(esc(d.target, literal))])
     of tkCurlyDotRi:
-      dispA(result, "</div><span class=\"Other pragmaend\">$1</span>",
+      dispA(d.conf, result, "</div><span class=\"Other pragmaend\">$1</span>",
                     "\\spanOther{$1}",
                   [rope(esc(d.target, literal))])
     of tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi,
@@ -270,7 +270,7 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe
        tkAccent, tkColonColon,
        tkGStrLit, tkGTripleStrLit, tkInfixOpr, tkPrefixOpr, tkPostfixOpr,
        tkBracketLeColon:
-      dispA(result, "<span class=\"Other\">$1</span>", "\\spanOther{$1}",
+      dispA(d.conf, result, "<span class=\"Other\">$1</span>", "\\spanOther{$1}",
             [rope(esc(d.target, literal))])
 
 proc getAllRunnableExamples(d: PDoc; n: PNode; dest: var Rope) =
@@ -278,7 +278,7 @@ proc getAllRunnableExamples(d: PDoc; n: PNode; dest: var Rope) =
   of nkCallKinds:
     if n[0].kind == nkSym and n[0].sym.magic == mRunnableExamples and
         n.len >= 2 and n.lastSon.kind == nkStmtList:
-      dispA(dest, "\n<strong class=\"examples_text\">$1</strong>\n",
+      dispA(d.conf, dest, "\n<strong class=\"examples_text\">$1</strong>\n",
           "\n\\textbf{$1}\n", [rope"Examples:"])
       inc d.listingCounter
       let id = $d.listingCounter
@@ -509,7 +509,7 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
     if gitUrl.len > 0:
       var commit = getConfigVar(d.conf, "git.commit")
       if commit.len == 0: commit = "master"
-      dispA(seeSrcRope, "$1", "", [ropeFormatNamedVars(d.conf, docItemSeeSrc,
+      dispA(d.conf, seeSrcRope, "$1", "", [ropeFormatNamedVars(d.conf, docItemSeeSrc,
           ["path", "line", "url", "commit"], [rope path,
           rope($n.info.line), rope gitUrl,
           rope commit])])
@@ -578,7 +578,7 @@ proc traceDeps(d: PDoc, it: PNode) =
       traceDeps(d, a)
   else:
     if d.section[k] != nil: add(d.section[k], ", ")
-    dispA(d.section[k],
+    dispA(d.conf, d.section[k],
           "<a class=\"reference external\" href=\"$1.html\">$1</a>",
           "$1", [rope(getModuleName(d.conf, it))])
 
@@ -750,7 +750,7 @@ proc genOutFile(d: PDoc): Rope =
       "tableofcontents", "moduledesc", "date", "time", "content"],
       [title.rope, toc, d.modDesc, rope(getDateStr()),
       rope(getClockStr()), code])
-  if optCompileOnly notin gGlobalOptions:
+  if optCompileOnly notin d.conf.globalOptions:
     # XXX what is this hack doing here? 'optCompileOnly' means raw output!?
     code = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.file"), ["title",
         "tableofcontents", "moduledesc", "date", "time",
@@ -763,12 +763,12 @@ proc genOutFile(d: PDoc): Rope =
   result = code
 
 proc generateIndex*(d: PDoc) =
-  if optGenIndex in gGlobalOptions:
+  if optGenIndex in d.conf.globalOptions:
     writeIndexFile(d[], splitFile(d.conf.outFile).dir /
                         splitFile(d.filename).name & IndexExt)
 
 proc getOutFile2(conf: ConfigRef; filename, ext, dir: string): string =
-  if gWholeProject:
+  if optWholeProject in conf.globalOptions:
     let d = if conf.outFile != "": conf.outFile else: dir
     createDir(d)
     result = d / changeFileExt(filename, ext)
@@ -777,7 +777,7 @@ proc getOutFile2(conf: ConfigRef; filename, ext, dir: string): string =
 
 proc writeOutput*(d: PDoc, filename, outExt: string, useWarning = false) =
   var content = genOutFile(d)
-  if optStdout in gGlobalOptions:
+  if optStdout in d.conf.globalOptions:
     writeRope(stdout, content)
   else:
     writeRope(content, getOutFile2(d.conf, filename, outExt, "htmldocs"), useWarning)
@@ -787,7 +787,7 @@ proc writeOutputJson*(d: PDoc, filename, outExt: string,
   let content = %*{"orig": d.filename,
     "nimble": getPackageName(d.conf, d.filename),
     "entries": d.jArray}
-  if optStdout in gGlobalOptions:
+  if optStdout in d.conf.globalOptions:
     write(stdout, $content)
   else:
     var f: File
@@ -857,7 +857,7 @@ proc commandJson*(conf: ConfigRef) =
   let json = d.jArray
   let content = rope(pretty(json))
 
-  if optStdout in gGlobalOptions:
+  if optStdout in d.conf.globalOptions:
     writeRope(stdout, content)
   else:
     #echo getOutFile(gProjectFull, JsonExt)
@@ -872,7 +872,7 @@ proc commandTags*(conf: ConfigRef) =
     content: Rope
   generateTags(d, ast, content)
 
-  if optStdout in gGlobalOptions:
+  if optStdout in d.conf.globalOptions:
     writeRope(stdout, content)
   else:
     #echo getOutFile(gProjectFull, TagsExt)
diff --git a/compiler/docgen2.nim b/compiler/docgen2.nim
index c975e6cc7..d9a73e1cd 100644
--- a/compiler/docgen2.nim
+++ b/compiler/docgen2.nim
@@ -25,8 +25,8 @@ template closeImpl(body: untyped) {.dirty.} =
   var g = PGen(p)
   let useWarning = sfMainModule notin g.module.flags
   #echo g.module.name.s, " ", g.module.owner.id, " ", gMainPackageId
-  if (g.module.owner.id == gMainPackageId and gWholeProject) or
-    sfMainModule in g.module.flags:
+  if (g.module.owner.id == gMainPackageId and optWholeProject in g.doc.conf.globalOptions) or
+      sfMainModule in g.module.flags:
     body
     try:
       generateIndex(g.doc)
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index 8f67a7fb6..3f0e6f611 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -390,7 +390,7 @@ proc getConfigVar(conf: ConfigRef; c: TSystemCC, suffix: string): string =
       suffix
 
   if (platform.hostOS != targetOS or platform.hostCPU != targetCPU) and
-      optCompileOnly notin gGlobalOptions:
+      optCompileOnly notin conf.globalOptions:
     let fullCCname = platform.CPU[targetCPU].name & '.' &
                      platform.OS[targetOS].name & '.' &
                      CC[c].name & fullSuffix
@@ -496,7 +496,7 @@ proc noAbsolutePaths(conf: ConfigRef): bool {.inline.} =
   # really: Cross compilation from Linux to Linux for example is entirely
   # reasonable.
   # `optGenMapping` is included here for niminst.
-  result = gGlobalOptions * {optGenScript, optGenMapping} != {}
+  result = conf.globalOptions * {optGenScript, optGenMapping} != {}
 
 proc cFileSpecificOptions(conf: ConfigRef; cfilename: string): string =
   result = compileOptions
@@ -505,15 +505,15 @@ proc cFileSpecificOptions(conf: ConfigRef; cfilename: string): string =
       addOpt(result, option)
 
   let trunk = splitFile(cfilename).name
-  if optCDebug in gGlobalOptions:
+  if optCDebug in conf.globalOptions:
     let key = trunk & ".debug"
     if existsConfigVar(conf, key): addOpt(result, getConfigVar(conf, key))
     else: addOpt(result, getDebug(conf, cCompiler))
-  if optOptimizeSpeed in gOptions:
+  if optOptimizeSpeed in conf.options:
     let key = trunk & ".speed"
     if existsConfigVar(conf, key): addOpt(result, getConfigVar(conf, key))
     else: addOpt(result, getOptSpeed(conf, cCompiler))
-  elif optOptimizeSize in gOptions:
+  elif optOptimizeSize in conf.options:
     let key = trunk & ".size"
     if existsConfigVar(conf, key): addOpt(result, getConfigVar(conf, key))
     else: addOpt(result, getOptSize(conf, cCompiler))
@@ -531,7 +531,7 @@ proc getLinkOptions(conf: ConfigRef): string =
     result.add(join([CC[cCompiler].linkDirCmd, libDir.quoteShell]))
 
 proc needsExeExt(conf: ConfigRef): bool {.inline.} =
-  result = (optGenScript in gGlobalOptions and targetOS == osWindows) or
+  result = (optGenScript in conf.globalOptions and targetOS == osWindows) or
            (platform.hostOS == osWindows)
 
 proc getCompilerExe(conf: ConfigRef; compiler: TSystemCC; cfile: string): string =
@@ -556,7 +556,7 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile): string =
   if exe.len == 0: exe = getCompilerExe(conf, c, cfile.cname)
 
   if needsExeExt(conf): exe = addFileExt(exe, "exe")
-  if optGenDynLib in gGlobalOptions and
+  if optGenDynLib in conf.globalOptions and
       ospNeedsPIC in platform.OS[targetOS].props:
     add(options, ' ' & CC[c].pic)
 
@@ -628,7 +628,7 @@ proc externalFileChanged(conf: ConfigRef; cfile: Cfile): bool =
       close(f)
 
 proc addExternalFileToCompile*(conf: ConfigRef; c: var Cfile) =
-  if optForceFullMake notin gGlobalOptions and not externalFileChanged(conf, c):
+  if optForceFullMake notin conf.globalOptions and not externalFileChanged(conf, c):
     c.flags.incl CfileFlag.Cached
   toCompile.add(c)
 
@@ -644,16 +644,16 @@ proc compileCFile(conf: ConfigRef; list: CFileList, script: var Rope, cmds: var
     # call the C compiler for the .c file:
     if it.flags.contains(CfileFlag.Cached): continue
     var compileCmd = getCompileCFileCmd(conf, it)
-    if optCompileOnly notin gGlobalOptions:
+    if optCompileOnly notin conf.globalOptions:
       add(cmds, compileCmd)
       let (_, name, _) = splitFile(it.cname)
       add(prettyCmds, "CC: " & name)
-    if optGenScript in gGlobalOptions:
+    if optGenScript in conf.globalOptions:
       add(script, compileCmd)
       add(script, tnl)
 
 proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string =
-  if optGenStaticLib in gGlobalOptions:
+  if optGenStaticLib in conf.globalOptions:
     var libname: string
     if conf.outFile.len > 0:
       libname = conf.outFile.expandTilde
@@ -670,10 +670,10 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string =
     if needsExeExt(conf): linkerExe = addFileExt(linkerExe, "exe")
     if noAbsolutePaths(conf): result = linkerExe
     else: result = joinPath(ccompilerpath, linkerExe)
-    let buildgui = if optGenGuiApp in gGlobalOptions: CC[cCompiler].buildGui
+    let buildgui = if optGenGuiApp in conf.globalOptions: CC[cCompiler].buildGui
                    else: ""
     var exefile, builddll: string
-    if optGenDynLib in gGlobalOptions:
+    if optGenDynLib in conf.globalOptions:
       exefile = platform.OS[targetOS].dllFrmt % splitFile(projectfile).name
       builddll = CC[cCompiler].buildDll
     else:
@@ -687,7 +687,7 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string =
       if not exefile.isAbsolute():
         exefile = joinPath(splitFile(projectfile).dir, exefile)
     when false:
-      if optCDebug in gGlobalOptions:
+      if optCDebug in conf.globalOptions:
         writeDebugInfo(exefile.changeFileExt("ndb"))
     exefile = quoteShell(exefile)
     let linkOptions = getLinkOptions(conf) & " " &
@@ -720,7 +720,7 @@ template tryExceptOSErrorMessage(conf: ConfigRef; errorPrefix: string = "", body
 proc execLinkCmd(conf: ConfigRef; linkCmd: string) =
   tryExceptOSErrorMessage(conf, "invocation of external linker program failed."):
     execExternalProgram(conf, linkCmd,
-      if optListCmd in gGlobalOptions or gVerbosity > 1: hintExecuting else: hintLinking)
+      if optListCmd in conf.globalOptions or conf.verbosity > 1: hintExecuting else: hintLinking)
 
 proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx: int)) =
   let runCb = proc (idx: int, p: Process) =
@@ -729,9 +729,9 @@ proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx:
       rawMessage(conf, errGenerated, "execution of an external compiler program '" &
         cmds[idx] & "' failed with exit code: " & $exitCode & "\n\n" &
         p.outputStream.readAll.strip)
-  if gNumberOfProcessors == 0: gNumberOfProcessors = countProcessors()
+  if conf.numberOfProcessors == 0: conf.numberOfProcessors = countProcessors()
   var res = 0
-  if gNumberOfProcessors <= 1:
+  if conf.numberOfProcessors <= 1:
     for i in countup(0, high(cmds)):
       tryExceptOSErrorMessage(conf, "invocation of external compiler program failed."):
         res = execWithEcho(conf, cmds[i])
@@ -740,24 +740,24 @@ proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx:
           cmds[i])
   else:
     tryExceptOSErrorMessage(conf, "invocation of external compiler program failed."):
-      if optListCmd in gGlobalOptions or gVerbosity > 1:
+      if optListCmd in conf.globalOptions or conf.verbosity > 1:
         res = execProcesses(cmds, {poEchoCmd, poStdErrToStdOut, poUsePath},
-                            gNumberOfProcessors, afterRunEvent=runCb)
-      elif gVerbosity == 1:
+                            conf.numberOfProcessors, afterRunEvent=runCb)
+      elif conf.verbosity == 1:
         res = execProcesses(cmds, {poStdErrToStdOut, poUsePath},
-                            gNumberOfProcessors, prettyCb, afterRunEvent=runCb)
+                            conf.numberOfProcessors, prettyCb, afterRunEvent=runCb)
       else:
         res = execProcesses(cmds, {poStdErrToStdOut, poUsePath},
-                            gNumberOfProcessors, afterRunEvent=runCb)
+                            conf.numberOfProcessors, afterRunEvent=runCb)
   if res != 0:
-    if gNumberOfProcessors <= 1:
+    if conf.numberOfProcessors <= 1:
       rawMessage(conf, errGenerated, "execution of an external program failed: '$1'" %
         cmds.join())
 
 proc callCCompiler*(conf: ConfigRef; projectfile: string) =
   var
     linkCmd: string
-  if gGlobalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}:
+  if conf.globalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}:
     return # speed up that call if only compiling and no script shall be
            # generated
   #var c = cCompiler
@@ -767,9 +767,9 @@ proc callCCompiler*(conf: ConfigRef; projectfile: string) =
   let prettyCb = proc (idx: int) =
     echo prettyCmds[idx]
   compileCFile(conf, toCompile, script, cmds, prettyCmds)
-  if optCompileOnly notin gGlobalOptions:
+  if optCompileOnly notin conf.globalOptions:
     execCmdsInParallel(conf, cmds, prettyCb)
-  if optNoLinking notin gGlobalOptions:
+  if optNoLinking notin conf.globalOptions:
     # call the linker:
     var objfiles = ""
     for it in externalToLink:
@@ -783,11 +783,11 @@ proc callCCompiler*(conf: ConfigRef; projectfile: string) =
       add(objfiles, quoteShell(objFile))
 
     linkCmd = getLinkCmd(conf, projectfile, objfiles)
-    if optCompileOnly notin gGlobalOptions:
+    if optCompileOnly notin conf.globalOptions:
       execLinkCmd(conf, linkCmd)
   else:
     linkCmd = ""
-  if optGenScript in gGlobalOptions:
+  if optGenScript in conf.globalOptions:
     add(script, linkCmd)
     add(script, tnl)
     generateScript(conf, projectfile, script)
@@ -892,7 +892,7 @@ proc genMappingFiles(conf: ConfigRef; list: CFileList): Rope =
     addf(result, "--file:r\"$1\"$N", [rope(it.cname)])
 
 proc writeMapping*(conf: ConfigRef; symbolMapping: Rope) =
-  if optGenMapping notin gGlobalOptions: return
+  if optGenMapping notin conf.globalOptions: return
   var code = rope("[C_Files]\n")
   add(code, genMappingFiles(conf, toCompile))
   add(code, "\n[C_Compiler]\nFlags=")
diff --git a/compiler/hlo.nim b/compiler/hlo.nim
index 76404e49b..8251e3179 100644
--- a/compiler/hlo.nim
+++ b/compiler/hlo.nim
@@ -17,7 +17,7 @@ proc evalPattern(c: PContext, n, orig: PNode): PNode =
   # aweful to semcheck before macro invocation, so we don't and treat
   # templates and macros as immediate in this context.
   var rule: string
-  if optHints in gOptions and hintPattern in c.config.notes:
+  if optHints in c.config.options and hintPattern in c.config.notes:
     rule = renderTree(n, {renderNoComments})
   let s = n.sons[0].sym
   case s.kind
@@ -27,7 +27,7 @@ proc evalPattern(c: PContext, n, orig: PNode): PNode =
     result = semTemplateExpr(c, n, s, {efFromHlo})
   else:
     result = semDirectOp(c, n, {})
-  if optHints in gOptions and hintPattern in c.config.notes:
+  if optHints in c.config.options and hintPattern in c.config.notes:
     message(c.config, orig.info, hintPattern, rule & " --> '" &
       renderTree(result, {renderNoComments}) & "'")
 
@@ -92,12 +92,12 @@ proc hlo(c: PContext, n: PNode): PNode =
 
 proc hloBody(c: PContext, n: PNode): PNode =
   # fast exit:
-  if c.patterns.len == 0 or optPatterns notin gOptions: return n
+  if c.patterns.len == 0 or optPatterns notin c.config.options: return n
   c.hloLoopDetector = 0
   result = hlo(c, n)
 
 proc hloStmt(c: PContext, n: PNode): PNode =
   # fast exit:
-  if c.patterns.len == 0 or optPatterns notin gOptions: return n
+  if c.patterns.len == 0 or optPatterns notin c.config.options: return n
   c.hloLoopDetector = 0
   result = hlo(c, n)
diff --git a/compiler/importer.nim b/compiler/importer.nim
index 4e3aa8d10..ed988cea7 100644
--- a/compiler/importer.nim
+++ b/compiler/importer.nim
@@ -122,7 +122,8 @@ proc importModuleAs(c: PContext; n: PNode, realModule: PSym): PSym =
     localError(c.config, n.info, "module alias must be an identifier")
   elif n.sons[1].ident.id != realModule.name.id:
     # some misguided guy will write 'import abc.foo as foo' ...
-    result = createModuleAlias(realModule, n.sons[1].ident, realModule.info)
+    result = createModuleAlias(realModule, n.sons[1].ident, realModule.info,
+                               c.config.options)
 
 proc myImportModule(c: PContext, n: PNode): PSym =
   var f = checkModuleName(c.config, n)
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 2ec5a068d..25b554f7b 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -245,7 +245,7 @@ proc mangleName(m: BModule, s: PSym): Rope =
         inc i
       result = rope(x)
     if s.name.s != "this" and s.kind != skField:
-      if optHotCodeReloading in gOptions:
+      if optHotCodeReloading in m.config.options:
         # When hot reloading is enabled, we must ensure that the names
         # of functions and types will be preserved across rebuilds:
         add(result, idOrSig(s, m.module.name.s, m.sigConflicts))
@@ -1425,7 +1425,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
     s: Rope
     varCode: string
     varName = mangleName(p.module, v)
-    useReloadingGuard = sfGlobal in v.flags and optHotCodeReloading in gOptions
+    useReloadingGuard = sfGlobal in v.flags and optHotCodeReloading in p.config.options
 
   if v.constraint.isNil:
     if useReloadingGuard:
@@ -1970,7 +1970,7 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
   else:
     result = ~tnl
 
-    if optHotCodeReloading in gOptions:
+    if optHotCodeReloading in p.config.options:
       # Here, we introduce thunks that create the equivalent of a jump table
       # for all global functions, because references to them may be stored
       # in JavaScript variables. The added indirection ensures that such
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 2410f1d36..773e5e29c 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -137,7 +137,7 @@ proc createStateType(g: ModuleGraph; iter: PSym): PType =
   rawAddSon(result, intType)
 
 proc createStateField(g: ModuleGraph; iter: PSym): PSym =
-  result = newSym(skField, getIdent(":state"), iter, iter.info)
+  result = newSym(skField, getIdent(":state"), iter, iter.info, {})
   result.typ = createStateType(g, iter)
 
 proc createEnvObj(g: ModuleGraph; owner: PSym; info: TLineInfo): PType =
@@ -151,7 +151,7 @@ proc getIterResult(iter: PSym): PSym =
     result = iter.ast.sons[resultPos].sym
   else:
     # XXX a bit hacky:
-    result = newSym(skResult, getIdent":result", iter, iter.info)
+    result = newSym(skResult, getIdent":result", iter, iter.info, {})
     result.typ = iter.typ.sons[0]
     incl(result.flags, sfUsed)
     iter.ast.add newSymNode(result)
@@ -228,14 +228,14 @@ proc interestingIterVar(s: PSym): bool {.inline.} =
 template isIterator*(owner: PSym): bool =
   owner.kind == skIterator and owner.typ.callConv == ccClosure
 
-proc liftingHarmful(owner: PSym): bool {.inline.} =
+proc liftingHarmful(conf: ConfigRef; owner: PSym): bool {.inline.} =
   ## lambda lifting can be harmful for JS-like code generators.
   let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro
-  result = gCmd == cmdCompileToJS and not isCompileTime
+  result = conf.cmd == cmdCompileToJS and not isCompileTime
 
 proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
   # transforms  (iter)  to  (let env = newClosure[iter](); (iter, env))
-  if liftingHarmful(owner): return n
+  if liftingHarmful(g.config, owner): return n
   let iter = n.sym
   assert iter.isIterator
 
@@ -811,14 +811,14 @@ proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType): PNo
   fn.typ.callConv = oldCC
 
 proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PNode =
-  # XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs
+  # XXX conf.cmd == cmdCompileToJS does not suffice! The compiletime stuff needs
   # the transformation even when compiling to JS ...
 
   # However we can do lifting for the stuff which is *only* compiletime.
   let isCompileTime = sfCompileTime in fn.flags or fn.kind == skMacro
 
   if body.kind == nkEmpty or (
-      gCmd == cmdCompileToJS and not isCompileTime) or
+      g.config.cmd == cmdCompileToJS and not isCompileTime) or
       fn.skipGenericOwner.kind != skModule:
     # ignore forward declaration:
     result = body
@@ -842,11 +842,8 @@ proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PN
     #  echo renderTree(result, {renderIds})
 
 proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
-  if body.kind == nkEmpty or gCmd == cmdCompileToJS:
-    result = body
-  else:
-    # XXX implement it properly
-    result = body
+  # XXX implement it properly
+  result = body
 
 # ------------------- iterator transformation --------------------------------
 
@@ -878,7 +875,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
         nkBreakState(cl.state)
         ...
     """
-  if liftingHarmful(owner): return body
+  if liftingHarmful(g.config, owner): return body
   var L = body.len
   if not (body.kind == nkForStmt and body[L-2].kind in nkCallKinds):
     localError(g.config, body.info, "ignored invalid for loop")
diff --git a/compiler/lexer.nim b/compiler/lexer.nim
index d01b8c4be..591561987 100644
--- a/compiler/lexer.nim
+++ b/compiler/lexer.nim
@@ -190,8 +190,8 @@ proc prettyTok*(tok: TToken): string =
   if isKeyword(tok.tokType): result = "keyword " & tok.ident.s
   else: result = tokToStr(tok)
 
-proc printTok*(tok: TToken) =
-  msgWriteln($tok.line & ":" & $tok.col & "\t" &
+proc printTok*(conf: ConfigRef; tok: TToken) =
+  msgWriteln(conf, $tok.line & ":" & $tok.col & "\t" &
       TokTypeToStr[tok.tokType] & " " & tokToStr(tok))
 
 proc initToken*(L: var TToken) =
@@ -714,7 +714,7 @@ proc handleCRLF(L: var TLexer, pos: int): int =
     if col > MaxLineLength:
       lexMessagePos(L, hintLineTooLong, pos)
 
-    if optEmbedOrigSrc in gGlobalOptions:
+    if optEmbedOrigSrc in L.config.globalOptions:
       let lineStart = cast[ByteAddress](L.buf) + L.lineStart
       let line = newString(cast[cstring](lineStart), col)
       addSourceLine(L.fileIdx, line)
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index e161d2e11..b6d63d0bd 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -85,7 +85,7 @@ proc skipAlias*(s: PSym; n: PNode; conf: ConfigRef): PSym =
     result = s
   else:
     result = s.owner
-    if gCmd == cmdPretty:
+    if conf.cmd == cmdPretty:
       prettybase.replaceDeprecated(n.info, s, result)
     else:
       message(conf, n.info, warnDeprecated, "use " & result.name.s & " instead; " &
@@ -128,11 +128,11 @@ proc errorSym*(c: PContext, n: PNode): PSym =
       considerQuotedIdent(c.config, m)
     else:
       getIdent("err:" & renderTree(m))
-  result = newSym(skError, ident, getCurrOwner(c), n.info)
+  result = newSym(skError, ident, getCurrOwner(c), n.info, {})
   result.typ = errorType(c)
   incl(result.flags, sfDiscardable)
   # pretend it's imported from some unknown module to prevent cascading errors:
-  if gCmd != cmdInteractive and c.compilesContextId == 0:
+  if c.config.cmd != cmdInteractive and c.compilesContextId == 0:
     c.importTable.addSym(result)
 
 type
@@ -176,7 +176,7 @@ proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope) =
     s = nextIter(it, scope.symbols)
 
 proc wrongRedefinition*(c: PContext; info: TLineInfo, s: string) =
-  if gCmd != cmdInteractive:
+  if c.config.cmd != cmdInteractive:
     localError(c.config, info, "redefinition of '$1'" % s)
 
 proc addDecl*(c: PContext, sym: PSym, info: TLineInfo) =
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index 5b85ab008..13336f00e 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -49,7 +49,7 @@ proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
   let value = n.lastSon
   result = newNodeI(nkStmtList, n.info)
 
-  var temp = newSym(skTemp, getIdent(genPrefix), owner, value.info)
+  var temp = newSym(skTemp, getIdent(genPrefix), owner, value.info, g.config.options)
   temp.typ = skipTypes(value.typ, abstractInst)
   incl(temp.flags, sfFromGeneric)
 
@@ -77,7 +77,7 @@ proc lowerTupleUnpackingForAsgn*(n: PNode; owner: PSym): PNode =
   let value = n.lastSon
   result = newNodeI(nkStmtList, n.info)
 
-  var temp = newSym(skLet, getIdent("_"), owner, value.info)
+  var temp = newSym(skLet, getIdent("_"), owner, value.info, owner.options)
   var v = newNodeI(nkLetSection, value.info)
   let tempAsNode = newSymNode(temp) #newIdentNode(getIdent(genPrefix & $temp.id), value.info)
 
@@ -95,7 +95,7 @@ proc lowerTupleUnpackingForAsgn*(n: PNode; owner: PSym): PNode =
 proc lowerSwap*(n: PNode; owner: PSym): PNode =
   result = newNodeI(nkStmtList, n.info)
   # note: cannot use 'skTemp' here cause we really need the copy for the VM :-(
-  var temp = newSym(skVar, getIdent(genPrefix), owner, n.info)
+  var temp = newSym(skVar, getIdent(genPrefix), owner, n.info, owner.options)
   temp.typ = n.sons[1].typ
   incl(temp.flags, sfFromGeneric)
 
@@ -121,7 +121,7 @@ proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType
     rawAddSon(result, getCompilerProc(g, "RootObj").typ)
   result.n = newNodeI(nkRecList, info)
   let s = newSym(skType, getIdent("Env_" & info.toFilename),
-                  owner, info)
+                  owner, info, owner.options)
   incl s.flags, sfAnon
   s.typ = result
   result.sym = s
@@ -174,7 +174,8 @@ proc lookupInRecord(n: PNode, id: int): PSym =
 proc addField*(obj: PType; s: PSym) =
   # because of 'gensym' support, we have to mangle the name with its ID.
   # This is hacky but the clean solution is much more complex than it looks.
-  var field = newSym(skField, getIdent(s.name.s & $obj.n.len), s.owner, s.info)
+  var field = newSym(skField, getIdent(s.name.s & $obj.n.len), s.owner, s.info,
+                     s.options)
   field.id = -s.id
   let t = skipIntLit(s.typ)
   field.typ = t
@@ -185,7 +186,8 @@ proc addField*(obj: PType; s: PSym) =
 proc addUniqueField*(obj: PType; s: PSym): PSym {.discardable.} =
   result = lookupInRecord(obj.n, s.id)
   if result == nil:
-    var field = newSym(skField, getIdent(s.name.s & $obj.n.len), s.owner, s.info)
+    var field = newSym(skField, getIdent(s.name.s & $obj.n.len), s.owner, s.info,
+                       s.options)
     field.id = -s.id
     let t = skipIntLit(s.typ)
     field.typ = t
@@ -335,7 +337,8 @@ proc typeNeedsNoDeepCopy(t: PType): bool =
 
 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 = newSym(skTemp, getIdent(genPrefix), owner, varSection.info,
+                  owner.options)
   result.typ = typ
   incl(result.flags, sfFromGeneric)
 
@@ -449,7 +452,8 @@ proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;
   t.n.add argsParam.newSymNode
 
   let name = (if f.kind == nkSym: f.sym.name.s else: genPrefix) & "Wrapper"
-  result = newSym(skProc, getIdent(name), argsParam.owner, f.info)
+  result = newSym(skProc, getIdent(name), argsParam.owner, f.info,
+                  argsParam.options)
   result.ast = newProcNode(nkProcDef, f.info, body, params, newSymNode(result))
   result.typ = t
 
@@ -475,7 +479,7 @@ proc setupArgsForConcurrency(g: ModuleGraph; n: PNode; objType: PType; scratchOb
     #  localError(n[i].info, "'spawn'ed function cannot refer to 'ref'/closure")
 
     let fieldname = if i < formals.len: formals[i].sym.name else: tmpName
-    var field = newSym(skField, fieldname, objType.owner, n.info)
+    var field = newSym(skField, fieldname, objType.owner, n.info, g.config.options)
     field.typ = argType
     objType.addField(field)
     result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[i])
@@ -529,7 +533,7 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; scratchOb
     #  localError(n.info, "'spawn'ed function cannot refer to 'ref'/closure")
 
     let fieldname = if i < formals.len: formals[i].sym.name else: tmpName
-    var field = newSym(skField, fieldname, objType.owner, n.info)
+    var field = newSym(skField, fieldname, objType.owner, n.info, g.config.options)
 
     if argType.kind in {tyVarargs, tyOpenArray}:
       # important special case: we always create a zero-copy slice:
@@ -537,7 +541,7 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; scratchOb
       slice.typ = n.typ
       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)
+      var fieldB = newSym(skField, tmpName, objType.owner, n.info, g.config.options)
       fieldB.typ = getSysType(g, n.info, tyInt)
       objType.addField(fieldB)
 
@@ -547,7 +551,7 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; scratchOb
         objType.addField(field)
         result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)
 
-        var fieldA = newSym(skField, tmpName, objType.owner, n.info)
+        var fieldA = newSym(skField, tmpName, objType.owner, n.info, g.config.options)
         fieldA.typ = getSysType(g, n.info, tyInt)
         objType.addField(fieldA)
         result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldA), n[2])
@@ -615,12 +619,12 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P
   if n.kind notin nkCallKinds:
     localError(g.config, n.info, "'spawn' takes a call expression")
     return
-  if optThreadAnalysis in gGlobalOptions:
+  if optThreadAnalysis in g.config.globalOptions:
     if {tfThread, tfNoSideEffect} * n[0].typ.flags == {}:
       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)
+    threadParam = newSym(skParam, getIdent"thread", owner, n.info, g.config.options)
+    argsParam = newSym(skParam, getIdent"args", owner, n.info, g.config.options)
   block:
     let ptrType = getSysType(g, n.info, tyPointer)
     threadParam.typ = ptrType
@@ -631,7 +635,7 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P
   incl(objType.flags, tfFinal)
   let castExpr = createCastExpr(argsParam, objType)
 
-  var scratchObj = newSym(skVar, getIdent"scratch", owner, n.info)
+  var scratchObj = newSym(skVar, getIdent"scratch", owner, n.info, g.config.options)
   block:
     scratchObj.typ = objType
     incl(scratchObj.flags, sfFromGeneric)
@@ -649,7 +653,7 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P
                                                skFunc, skMethod, skConverter}):
     # for indirect calls we pass the function pointer in the scratchObj
     var argType = n[0].typ.skipTypes(abstractInst)
-    var field = newSym(skField, getIdent"fn", owner, n.info)
+    var field = newSym(skField, getIdent"fn", owner, n.info, g.config.options)
     field.typ = argType
     objType.addField(field)
     result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[0])
@@ -673,7 +677,7 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P
   if barrier != nil:
     let typ = newType(tyPtr, owner)
     typ.rawAddSon(magicsys.getCompilerProc(g, "Barrier").typ)
-    var field = newSym(skField, getIdent"barrier", owner, n.info)
+    var field = newSym(skField, getIdent"barrier", owner, n.info, g.config.options)
     field.typ = typ
     objType.addField(field)
     result.add newFastAsgnStmt(newDotExpr(scratchObj, field), barrier)
@@ -681,7 +685,7 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P
 
   var fvField, fvAsExpr: PNode = nil
   if spawnKind == srFlowVar:
-    var field = newSym(skField, getIdent"fv", owner, n.info)
+    var field = newSym(skField, getIdent"fv", owner, n.info, g.config.options)
     field.typ = retType
     objType.addField(field)
     fvField = newDotExpr(scratchObj, field)
@@ -692,7 +696,7 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P
       result.add callCodegenProc(g, "nimFlowVarCreateSemaphore", fvField)
 
   elif spawnKind == srByVar:
-    var field = newSym(skField, getIdent"fv", owner, n.info)
+    var field = newSym(skField, getIdent"fv", owner, n.info, g.config.options)
     field.typ = newType(tyPtr, objType.owner)
     field.typ.rawAddSon(retType)
     objType.addField(field)
diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim
index aabcfd7a6..b5577d961 100644
--- a/compiler/magicsys.nim
+++ b/compiler/magicsys.nim
@@ -29,7 +29,7 @@ proc getSysSym*(g: ModuleGraph; info: TLineInfo; name: string): PSym =
   result = strTableGet(g.systemModule.tab, getIdent(name))
   if result == nil:
     localError(g.config, info, "system module needs: " & name)
-    result = newSym(skError, getIdent(name), g.systemModule, g.systemModule.info)
+    result = newSym(skError, getIdent(name), g.systemModule, g.systemModule.info, {})
     result.typ = newType(tyError, g.systemModule)
   if result.kind == skStub: loadStub(result)
   if result.kind == skAlias: result = result.owner
@@ -57,7 +57,7 @@ proc getSysMagic*(g: ModuleGraph; info: TLineInfo; name: string, m: TMagic): PSy
     r = nextIdentIter(ti, g.systemModule.tab)
   if result != nil: return result
   localError(g.config, info, "system module needs: " & name)
-  result = newSym(skError, id, g.systemModule, g.systemModule.info)
+  result = newSym(skError, id, g.systemModule, g.systemModule.info, {})
   result.typ = newType(tyError, g.systemModule)
 
 proc sysTypeFromName*(g: ModuleGraph; info: TLineInfo; name: string): PType =
diff --git a/compiler/main.nim b/compiler/main.nim
index b9afc6a8d..69b33653b 100644
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -20,8 +20,8 @@ import
 
 from magicsys import resetSysTypes
 
-proc rodPass =
-  if gSymbolFiles in {enabledSf, writeOnlySf}:
+proc rodPass(g: ModuleGraph) =
+  if g.config.symbolFiles in {enabledSf, writeOnlySf}:
     registerPass(rodwritePass)
 
 proc codegenPass =
@@ -56,7 +56,7 @@ proc commandCheck(graph: ModuleGraph; cache: IdentCache) =
   graph.config.errorMax = high(int)  # do not stop after first error
   defineSymbol(graph.config.symbols, "nimcheck")
   semanticPasses()            # use an empty backend for semantic checking only
-  rodPass()
+  rodPass(graph)
   compileProject(graph, cache)
 
 proc commandDoc2(graph: ModuleGraph; cache: IdentCache; json: bool) =
@@ -73,16 +73,16 @@ proc commandCompileToC(graph: ModuleGraph; cache: IdentCache) =
   extccomp.initVars(conf)
   semanticPasses()
   registerPass(cgenPass)
-  rodPass()
+  rodPass(graph)
   #registerPass(cleanupPass())
 
   compileProject(graph, cache)
   cgenWriteModules(graph.backend, conf)
-  if gCmd != cmdRun:
+  if conf.cmd != cmdRun:
     let proj = changeFileExt(conf.projectFull, "")
     extccomp.callCCompiler(conf, proj)
     extccomp.writeJsonBuildInstructions(conf, proj)
-    if optGenScript in gGlobalOptions:
+    if optGenScript in graph.config.globalOptions:
       writeDepsFile(graph, toGeneratedFile(conf, proj, ""))
 
 proc commandJsonScript(graph: ModuleGraph; cache: IdentCache) =
@@ -144,7 +144,7 @@ proc commandScan(cache: IdentCache, config: ConfigRef) =
     openLexer(L, f, stream, cache, config)
     while true:
       rawGetTok(L, tok)
-      printTok(tok)
+      printTok(config, tok)
       if tok.tokType == tkEof: break
     closeLexer(L)
   else:
@@ -159,78 +159,78 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) =
   setupModuleCache()
   # In "nim serve" scenario, each command must reset the registered passes
   clearPasses()
-  gLastCmdTime = epochTime()
+  conf.lastCmdTime = epochTime()
   conf.searchPaths.add(conf.libpath)
   setId(100)
   case conf.command.normalize
   of "c", "cc", "compile", "compiletoc":
     # compile means compileToC currently
-    gCmd = cmdCompileToC
+    conf.cmd = cmdCompileToC
     commandCompileToC(graph, cache)
   of "cpp", "compiletocpp":
-    gCmd = cmdCompileToCpp
+    conf.cmd = cmdCompileToCpp
     defineSymbol(graph.config.symbols, "cpp")
     commandCompileToC(graph, cache)
   of "objc", "compiletooc":
-    gCmd = cmdCompileToOC
+    conf.cmd = cmdCompileToOC
     defineSymbol(graph.config.symbols, "objc")
     commandCompileToC(graph, cache)
   of "run":
-    gCmd = cmdRun
+    conf.cmd = cmdRun
     when hasTinyCBackend:
       extccomp.setCC("tcc")
       commandCompileToC(graph, cache)
     else:
       rawMessage(conf, errGenerated, "'run' command not available; rebuild with -d:tinyc")
   of "js", "compiletojs":
-    gCmd = cmdCompileToJS
+    conf.cmd = cmdCompileToJS
     commandCompileToJS(graph, cache)
   of "doc0":
     wantMainModule(conf)
-    gCmd = cmdDoc
+    conf.cmd = cmdDoc
     loadConfigs(DocConfig, cache)
     commandDoc(conf)
   of "doc2", "doc":
-    gCmd = cmdDoc
+    conf.cmd = cmdDoc
     loadConfigs(DocConfig, cache)
     defineSymbol(conf.symbols, "nimdoc")
     commandDoc2(graph, cache, false)
   of "rst2html":
-    gCmd = cmdRst2html
+    conf.cmd = cmdRst2html
     loadConfigs(DocConfig, cache)
     commandRst2Html(conf)
   of "rst2tex":
-    gCmd = cmdRst2tex
+    conf.cmd = cmdRst2tex
     loadConfigs(DocTexConfig, cache)
     commandRst2TeX(conf)
   of "jsondoc0":
     wantMainModule(conf)
-    gCmd = cmdDoc
+    conf.cmd = cmdDoc
     loadConfigs(DocConfig, cache)
     wantMainModule(conf)
     defineSymbol(conf.symbols, "nimdoc")
     commandJson(conf)
   of "jsondoc2", "jsondoc":
-    gCmd = cmdDoc
+    conf.cmd = cmdDoc
     loadConfigs(DocConfig, cache)
     wantMainModule(conf)
     defineSymbol(conf.symbols, "nimdoc")
     commandDoc2(graph, cache, true)
   of "ctags":
     wantMainModule(conf)
-    gCmd = cmdDoc
+    conf.cmd = cmdDoc
     loadConfigs(DocConfig, cache)
     defineSymbol(conf.symbols, "nimdoc")
     commandTags(conf)
   of "buildindex":
-    gCmd = cmdDoc
+    conf.cmd = cmdDoc
     loadConfigs(DocConfig, cache)
     commandBuildIndex(conf)
   of "gendepend":
-    gCmd = cmdGenDepend
+    conf.cmd = cmdGenDepend
     commandGenDepend(graph, cache)
   of "dump":
-    gCmd = cmdDump
+    conf.cmd = cmdDump
     if getConfigVar(conf, "dump.format") == "json":
       wantMainModule(conf)
 
@@ -247,48 +247,48 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) =
         (key: "lib_paths", val: libpaths)
       ]
 
-      msgWriteln($dumpdata, {msgStdout, msgSkipHook})
+      msgWriteln(conf, $dumpdata, {msgStdout, msgSkipHook})
     else:
-      msgWriteln("-- list of currently defined symbols --",
+      msgWriteln(conf, "-- list of currently defined symbols --",
                  {msgStdout, msgSkipHook})
-      for s in definedSymbolNames(conf.symbols): msgWriteln(s, {msgStdout, msgSkipHook})
-      msgWriteln("-- end of list --", {msgStdout, msgSkipHook})
+      for s in definedSymbolNames(conf.symbols): msgWriteln(conf, s, {msgStdout, msgSkipHook})
+      msgWriteln(conf, "-- end of list --", {msgStdout, msgSkipHook})
 
-      for it in conf.searchPaths: msgWriteln(it)
+      for it in conf.searchPaths: msgWriteln(conf, it)
   of "check":
-    gCmd = cmdCheck
+    conf.cmd = cmdCheck
     commandCheck(graph, cache)
   of "parse":
-    gCmd = cmdParse
+    conf.cmd = cmdParse
     wantMainModule(conf)
     discard parseFile(FileIndex conf.projectMainIdx, cache, conf)
   of "scan":
-    gCmd = cmdScan
+    conf.cmd = cmdScan
     wantMainModule(conf)
     commandScan(cache, conf)
-    msgWriteln("Beware: Indentation tokens depend on the parser's state!")
+    msgWriteln(conf, "Beware: Indentation tokens depend on the parser's state!")
   of "secret":
-    gCmd = cmdInteractive
+    conf.cmd = cmdInteractive
     commandInteractive(graph, cache)
   of "e":
     commandEval(graph, cache, mainCommandArg(conf))
   of "nop", "help":
     # prevent the "success" message:
-    gCmd = cmdDump
+    conf.cmd = cmdDump
   of "jsonscript":
-    gCmd = cmdJsonScript
+    conf.cmd = cmdJsonScript
     commandJsonScript(graph, cache)
   else:
     rawMessage(conf, errGenerated, "invalid command: " & conf.command)
 
   if conf.errorCounter == 0 and
-     gCmd notin {cmdInterpret, cmdRun, cmdDump}:
+     conf.cmd notin {cmdInterpret, cmdRun, cmdDump}:
     when declared(system.getMaxMem):
       let usedMem = formatSize(getMaxMem()) & " peakmem"
     else:
       let usedMem = formatSize(getTotalMem())
     rawMessage(conf, hintSuccessX, [$conf.linesCompiled,
-               formatFloat(epochTime() - gLastCmdTime, ffDecimal, 3),
+               formatFloat(epochTime() - conf.lastCmdTime, ffDecimal, 3),
                usedMem,
                if isDefined(conf, "release"): "Release Build"
                else: "Debug Build"])
diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim
index da3965186..460d0b4a5 100644
--- a/compiler/modulegraphs.nim
+++ b/compiler/modulegraphs.nim
@@ -59,7 +59,7 @@ proc stopCompile*(g: ModuleGraph): bool {.inline.} =
   result = doStopCompile != nil and doStopCompile()
 
 proc createMagic*(g: ModuleGraph; name: string, m: TMagic): PSym =
-  result = newSym(skProc, getIdent(name), nil, unknownLineInfo())
+  result = newSym(skProc, getIdent(name), nil, unknownLineInfo(), {})
   result.magic = m
 
 proc newModuleGraph*(config: ConfigRef = nil): ModuleGraph =
diff --git a/compiler/modules.nim b/compiler/modules.nim
index 3da1bbbc7..7bc32d42c 100644
--- a/compiler/modules.nim
+++ b/compiler/modules.nim
@@ -66,7 +66,7 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; cache: IdentCache, f
       gMainPackageId = result.owner.id
 
     when false:
-      if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}:
+      if conf.cmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}:
         rd = handleSymbolFile(result, cache)
         if result.id < 0:
           internalError("handleSymbolFile should have set the module's ID")
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 6586c9992..774a8b83c 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -313,7 +313,7 @@ proc msgWriteln*(conf: ConfigRef; s: string, flags: MsgFlags = {}) =
 
   ## This is used for 'nim dump' etc. where we don't have nimsuggest
   ## support.
-  #if gCmd == cmdIdeTools and optCDebug notin gGlobalOptions: return
+  #if conf.cmd == cmdIdeTools and optCDebug notin gGlobalOptions: return
 
   if not isNil(writelnHook) and msgSkipHook notin flags:
     writelnHook(s)
diff --git a/compiler/nim.nim b/compiler/nim.nim
index d8402a2af..d3e00017f 100644
--- a/compiler/nim.nim
+++ b/compiler/nim.nim
@@ -40,7 +40,7 @@ proc prependCurDir(f: string): string =
 proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
   condsyms.initDefines(conf.symbols)
   if paramCount() == 0:
-    writeCommandLineUsage(conf.helpWritten)
+    writeCommandLineUsage(conf, conf.helpWritten)
   else:
     # Process command line arguments:
     processCmdLine(passCmd1, "", conf)
@@ -76,14 +76,14 @@ proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
     if conf.command == "":
       rawMessage(conf, errGenerated, "command missing")
     mainCommand(newModuleGraph(conf), cache)
-    if optHints in gOptions and hintGCStats in conf.notes: echo(GC_getStatistics())
+    if optHints in conf.options and hintGCStats in conf.notes: echo(GC_getStatistics())
     #echo(GC_getStatistics())
     if conf.errorCounter == 0:
       when hasTinyCBackend:
-        if gCmd == cmdRun:
+        if conf.cmd == cmdRun:
           tccgen.run(conf.arguments)
-      if optRun in gGlobalOptions:
-        if gCmd == cmdCompileToJS:
+      if optRun in conf.globalOptions:
+        if conf.cmd == cmdCompileToJS:
           var ex: string
           if conf.outFile.len > 0:
             ex = conf.outFile.prependCurDir.quoteShell
diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim
index 6a26f8dc7..379d15ad6 100644
--- a/compiler/nimconf.nim
+++ b/compiler/nimconf.nim
@@ -123,7 +123,7 @@ proc parseDirective(L: var TLexer, tok: var TToken; config: ConfigRef; condStack
   of wEnd: doEnd(L, tok, condStack)
   of wWrite:
     ppGetTok(L, tok)
-    msgs.msgWriteln(strtabs.`%`(tokToStr(tok), config.configVars,
+    msgs.msgWriteln(config, strtabs.`%`(tokToStr(tok), config.configVars,
                                 {useEnvironment, useKey}))
     ppGetTok(L, tok)
   else:
@@ -230,30 +230,30 @@ proc getSystemConfigPath(conf: ConfigRef; filename: string): string =
     if not existsFile(result): result = joinPath([p, "etc", filename])
     if not existsFile(result): result = "/etc/" & filename
 
-proc loadConfigs*(cfg: string; cache: IdentCache; config: ConfigRef = nil) =
-  setDefaultLibpath(config)
+proc loadConfigs*(cfg: string; cache: IdentCache; conf: ConfigRef = nil) =
+  setDefaultLibpath(conf)
 
-  if optSkipConfigFile notin gGlobalOptions:
-    readConfigFile(getSystemConfigPath(config, cfg), cache, config)
+  if optSkipConfigFile notin conf.globalOptions:
+    readConfigFile(getSystemConfigPath(conf, cfg), cache, conf)
 
-  if optSkipUserConfigFile notin gGlobalOptions:
-    readConfigFile(getUserConfigPath(cfg), cache, config)
+  if optSkipUserConfigFile notin conf.globalOptions:
+    readConfigFile(getUserConfigPath(cfg), cache, conf)
 
-  let pd = if config.projectPath.len > 0: config.projectPath else: getCurrentDir()
-  if optSkipParentConfigFiles notin gGlobalOptions:
+  let pd = if conf.projectPath.len > 0: conf.projectPath else: getCurrentDir()
+  if optSkipParentConfigFiles notin conf.globalOptions:
     for dir in parentDirs(pd, fromRoot=true, inclusive=false):
-      readConfigFile(dir / cfg, cache, config)
+      readConfigFile(dir / cfg, cache, conf)
 
-  if optSkipProjConfigFile notin gGlobalOptions:
-    readConfigFile(pd / cfg, cache, config)
+  if optSkipProjConfigFile notin conf.globalOptions:
+    readConfigFile(pd / cfg, cache, conf)
 
-    if config.projectName.len != 0:
+    if conf.projectName.len != 0:
       # new project wide config file:
-      var projectConfig = changeFileExt(config.projectFull, "nimcfg")
+      var projectConfig = changeFileExt(conf.projectFull, "nimcfg")
       if not fileExists(projectConfig):
-        projectConfig = changeFileExt(config.projectFull, "nim.cfg")
-      readConfigFile(projectConfig, cache, config)
+        projectConfig = changeFileExt(conf.projectFull, "nim.cfg")
+      readConfigFile(projectConfig, cache, conf)
 
-proc loadConfigs*(cfg: string; config: ConfigRef) =
+proc loadConfigs*(cfg: string; conf: ConfigRef) =
   # for backwards compatibility only.
-  loadConfigs(cfg, newIdentCache(), config)
+  loadConfigs(cfg, newIdentCache(), conf)
diff --git a/compiler/nimfix/nimfix.nim b/compiler/nimfix/nimfix.nim
index 2ef375b00..c3e29f9a1 100644
--- a/compiler/nimfix/nimfix.nim
+++ b/compiler/nimfix/nimfix.nim
@@ -38,7 +38,7 @@ In addition, all command line options of Nim are supported.
 proc mainCommand =
   registerPass verbosePass
   registerPass semPass
-  gCmd = cmdPretty
+  conf.cmd = cmdPretty
   searchPaths.add options.libpath
   if gProjectFull.len != 0:
     # current path is always looked first for modules
diff --git a/compiler/options.nim b/compiler/options.nim
index c918cac68..56c3dcf0b 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -70,7 +70,7 @@ type                          # please make sure we have under 32 options
     optIdeTerse               # idetools: use terse descriptions
     optNoCppExceptions        # use C exception handling even with CPP
     optExcessiveStackTrace    # fully qualified module filenames
-    opWholeProject            # for 'doc2': output any dependency
+    optWholeProject           # for 'doc2': output any dependency
     optListFullPaths
     optNoNimblePath
     optDynlibOverrideAll
diff --git a/compiler/passaux.nim b/compiler/passaux.nim
index f0d6bd44a..568fb4c23 100644
--- a/compiler/passaux.nim
+++ b/compiler/passaux.nim
@@ -26,7 +26,7 @@ proc verboseOpen(graph: ModuleGraph; s: PSym; cache: IdentCache): PPassContext =
 proc verboseProcess(context: PPassContext, n: PNode): PNode =
   result = n
   let v = VerboseRef(context)
-  if gVerbosity == 3:
+  if v.config.verbosity == 3:
     # system.nim deactivates all hints, for verbosity:3 we want the processing
     # messages nonetheless, so we activate them again unconditionally:
     incl(v.config.notes, hintProcessing)
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 31d3f75a3..1bb10b80e 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -116,7 +116,7 @@ proc setExternName(c: PContext; s: PSym, extname: string, info: TLineInfo) =
       s.loc.r = rope(extname % s.name.s)
     except ValueError:
       localError(c.config, info, "invalid extern name: '" & extname & "'. (Forgot to escape '$'?)")
-  if gCmd == cmdPretty and '$' notin extname:
+  if c.config.cmd == cmdPretty and '$' notin extname:
     # note that '{.importc.}' is transformed into '{.importc: "$1".}'
     s.loc.flags.incl(lfFullExternalName)
 
@@ -140,7 +140,7 @@ proc processImportCpp(c: PContext; s: PSym, extname: string, info: TLineInfo) =
   incl(s.flags, sfImportc)
   incl(s.flags, sfInfixCall)
   excl(s.flags, sfForward)
-  if gCmd == cmdCompileToC:
+  if c.config.cmd == cmdCompileToC:
     let m = s.getModule()
     incl(m.flags, sfCompileToCpp)
   extccomp.gMixedMode = true
@@ -218,8 +218,8 @@ proc isTurnedOn(c: PContext, n: PNode): bool =
   localError(c.config, n.info, "'on' or 'off' expected")
 
 proc onOff(c: PContext, n: PNode, op: TOptions) =
-  if isTurnedOn(c, n): gOptions = gOptions + op
-  else: gOptions = gOptions - op
+  if isTurnedOn(c, n): c.config.options = c.config.options + op
+  else: c.config.options = c.config.options - op
 
 proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) =
   if isTurnedOn(c, n): incl(c.module.flags, flag)
@@ -343,14 +343,14 @@ proc processOption(c: PContext, n: PNode): bool =
       else:
         case n.sons[1].ident.s.normalize
         of "speed":
-          incl(gOptions, optOptimizeSpeed)
-          excl(gOptions, optOptimizeSize)
+          incl(c.config.options, optOptimizeSpeed)
+          excl(c.config.options, optOptimizeSize)
         of "size":
-          excl(gOptions, optOptimizeSpeed)
-          incl(gOptions, optOptimizeSize)
+          excl(c.config.options, optOptimizeSpeed)
+          incl(c.config.options, optOptimizeSize)
         of "none":
-          excl(gOptions, optOptimizeSpeed)
-          excl(gOptions, optOptimizeSize)
+          excl(c.config.options, optOptimizeSpeed)
+          excl(c.config.options, optOptimizeSize)
         else: localError(c.config, n.info, "'none', 'speed' or 'size' expected")
     of wImplicitStatic: onOff(c, n, {optImplicitStatic})
     of wPatterns: onOff(c, n, {optPatterns})
@@ -361,7 +361,7 @@ proc processPush(c: PContext, n: PNode, start: int) =
     localError(c.config, n.info, "'push' cannot have arguments")
   var x = newOptionEntry(c.config)
   var y = c.optionStack[^1]
-  x.options = gOptions
+  x.options = c.config.options
   x.defaultCC = y.defaultCC
   x.dynlib = y.dynlib
   x.notes = c.config.notes
@@ -378,7 +378,7 @@ proc processPop(c: PContext, n: PNode) =
   if c.optionStack.len <= 1:
     localError(c.config, n.info, "{.pop.} without a corresponding {.push.}")
   else:
-    gOptions = c.optionStack[^1].options
+    c.config.options = c.optionStack[^1].options
     c.config.notes = c.optionStack[^1].notes
     c.optionStack.setLen(c.optionStack.len - 1)
 
@@ -557,7 +557,7 @@ proc processPragma(c: PContext, n: PNode, i: int) =
   elif it[0].kind != nkIdent: invalidPragma(c, n)
   elif it[1].kind != nkIdent: invalidPragma(c, n)
 
-  var userPragma = newSym(skTemplate, it[1].ident, nil, it.info)
+  var userPragma = newSym(skTemplate, it[1].ident, nil, it.info, c.config.options)
   userPragma.ast = newNode(nkPragma, n.info, n.sons[i+1..^1])
   strTableAdd(c.userPragmas, userPragma)
 
@@ -635,7 +635,7 @@ proc deprecatedStmt(c: PContext; outerPragma: PNode) =
       if dest == nil or dest.kind in routineKinds:
         localError(c.config, n.info, warnUser, "the .deprecated pragma is unreliable for routines")
       let src = considerQuotedIdent(c.config, n[0])
-      let alias = newSym(skAlias, src, dest, n[0].info)
+      let alias = newSym(skAlias, src, dest, n[0].info, c.config.options)
       incl(alias.flags, sfExported)
       if sfCompilerProc in dest.flags: markCompilerProc(c, alias)
       addInterfaceDecl(c, alias)
@@ -657,7 +657,8 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
       # We return a dummy symbol; later passes over the type will repair it.
       # Generic instantiation needs to know about this too. But we're lazy
       # and perform the lookup on demand instead.
-      result = newSym(skUnknown, considerQuotedIdent(c.config, n), nil, n.info)
+      result = newSym(skUnknown, considerQuotedIdent(c.config, n), nil, n.info,
+        c.config.options)
   else:
     result = qualifiedLookUp(c, n, {checkUndeclared})
 
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index a47c77464..966bed769 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -1456,9 +1456,7 @@ proc renderModule*(n: PNode, infile, outfile: string,
        nkCommentStmt: putNL(g)
     else: discard
   gcoms(g)
-  if optStdout in gGlobalOptions:
-    write(stdout, g.buf)
-  elif open(f, outfile, fmWrite):
+  if open(f, outfile, fmWrite):
     write(f, g.buf)
     close(f)
   else:
diff --git a/compiler/rodread.nim b/compiler/rodread.nim
index f62c24dfd..52e7a924c 100644
--- a/compiler/rodread.nim
+++ b/compiler/rodread.nim
@@ -623,16 +623,16 @@ proc processRodFile(r: PRodReader, hash: SecureHash) =
     of "OPTIONS":
       inc(r.pos)              # skip ':'
       r.options = cast[TOptions](int32(decodeVInt(r.s, r.pos)))
-      if options.gOptions != r.options: r.reason = rrOptions
+      if r.config.options != r.options: r.reason = rrOptions
     of "GOPTIONS":
       inc(r.pos)              # skip ':'
       var dep = cast[TGlobalOptions](int32(decodeVInt(r.s, r.pos)))
-      if gGlobalOptions-harmlessOptions != dep-harmlessOptions:
+      if r.config.globalOptions-harmlessOptions != dep-harmlessOptions:
         r.reason = rrOptions
     of "CMD":
       inc(r.pos)              # skip ':'
       var dep = cast[TCommands](int32(decodeVInt(r.s, r.pos)))
-      if cmdChangeTriggersRecompilation(dep, gCmd): r.reason = rrOptions
+      if cmdChangeTriggersRecompilation(dep, r.config.cmd): r.reason = rrOptions
     of "DEFINES":
       inc(r.pos)              # skip ':'
       d = 0
@@ -907,7 +907,7 @@ proc checkDep(fileIdx: FileIndex; cache: IdentCache; conf: ConfigRef): TReasonFo
           # we cannot break here, because of side-effects of `checkDep`
   if result != rrNone:
     rawMessage(conf, hintProcessing, reasonToFrmt[result] % filename)
-  if result != rrNone or optForceFullMake in gGlobalOptions:
+  if result != rrNone or optForceFullMake in conf.globalOptions:
     # recompilation is necessary:
     if r != nil: memfiles.close(r.memfile)
     r = nil
@@ -915,7 +915,7 @@ proc checkDep(fileIdx: FileIndex; cache: IdentCache; conf: ConfigRef): TReasonFo
   gMods[fileIdx.int32].reason = result  # now we know better
 
 proc handleSymbolFile*(module: PSym; cache: IdentCache; conf: ConfigRef): PRodReader =
-  if gSymbolFiles in {disabledSf, writeOnlySf, v2Sf}:
+  if conf.symbolFiles in {disabledSf, writeOnlySf, v2Sf}:
     module.id = getID()
     return nil
   idgen.loadMaxIds(conf, conf.projectPath / conf.projectName)
@@ -1035,9 +1035,8 @@ proc writeSym(f: File; s: PSym) =
   if s.magic != mNone:
     f.write('@')
     f.write($s.magic)
-  if s.options != gOptions:
-    f.write('!')
-    f.write($s.options)
+  f.write('!')
+  f.write($s.options)
   if s.position != 0:
     f.write('%')
     f.write($s.position)
diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim
index 7dc10bbf5..4686baf2b 100644
--- a/compiler/rodwrite.nim
+++ b/compiler/rodwrite.nim
@@ -71,7 +71,7 @@ proc newRodWriter(hash: SecureHash, module: PSym; cache: IdentCache;
   result.hash = hash
   result.module = module
   result.defines = getDefines(config)
-  result.options = options.gOptions
+  result.options = config.options
   result.files = @[]
   result.inclDeps = ""
   result.modDeps = ""
@@ -509,12 +509,12 @@ proc writeRod(w: PRodWriter) =
   f.write(rodNL)
 
   var goptions = "GOPTIONS:"
-  encodeVInt(cast[int32](gGlobalOptions), goptions)
+  encodeVInt(cast[int32](w.config.globalOptions), goptions)
   f.write(goptions)
   f.write(rodNL)
 
   var cmd = "CMD:"
-  encodeVInt(cast[int32](gCmd), cmd)
+  encodeVInt(cast[int32](w.config.cmd), cmd)
   f.write(cmd)
   f.write(rodNL)
 
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 8cb233a05..c5c3dd99b 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -64,7 +64,7 @@ template semIdeForTemplateOrGeneric(c: PContext; n: PNode;
   # templates perform some quick check whether the cursor is actually in
   # the generic or template.
   when defined(nimsuggest):
-    if gCmd == cmdIdeTools and requiresCheck:
+    if c.config.cmd == cmdIdeTools and requiresCheck:
       #if optIdeDebug in gGlobalOptions:
       #  echo "passing to safeSemExpr: ", renderTree(n)
       discard safeSemExpr(c, n)
@@ -562,9 +562,9 @@ proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
         if result.kind != nkEmpty: addSon(a, result)
         result = a
   result = hloStmt(c, result)
-  if gCmd == cmdInteractive and not isEmptyType(result.typ):
+  if c.config.cmd == cmdInteractive and not isEmptyType(result.typ):
     result = buildEchoStmt(c, result)
-  if gCmd == cmdIdeTools:
+  if c.config.cmd == cmdIdeTools:
     appendToModule(c.module, result)
   result = transformStmt(c.graph, c.module, result)
 
@@ -595,7 +595,7 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
         result = nil
       else:
         result = ast.emptyNode
-      #if gCmd == cmdIdeTools: findSuggest(c, n)
+      #if c.config.cmd == cmdIdeTools: findSuggest(c, n)
   rod.storeNode(c.module, result)
 
 proc testExamples(c: PContext) =
@@ -612,7 +612,7 @@ proc testExamples(c: PContext) =
 
 proc myClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode =
   var c = PContext(context)
-  if gCmd == cmdIdeTools and not c.suggestionsMade:
+  if c.config.cmd == cmdIdeTools and not c.suggestionsMade:
     suggestSentinel(c)
   closeScope(c)         # close module's scope
   rawCloseScope(c)      # imported symbols; don't check for unused ones!
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 6f7a48dae..ad5bdfd49 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -204,7 +204,7 @@ proc considerGenSyms*(c: PContext; n: PNode) =
 
 proc newOptionEntry*(conf: ConfigRef): POptionEntry =
   new(result)
-  result.options = gOptions
+  result.options = conf.options
   result.defaultCC = ccDefault
   result.dynlib = nil
   result.notes = conf.notes
@@ -286,7 +286,8 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType =
 
 proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
   let typedesc = makeTypeDesc(c, typ)
-  let sym = newSym(skType, c.cache.idAnon, getCurrOwner(c), info).linkTo(typedesc)
+  let sym = newSym(skType, c.cache.idAnon, getCurrOwner(c), info,
+                   c.config.options).linkTo(typedesc)
   return newSymNode(sym, info)
 
 proc makeTypeFromExpr*(c: PContext, n: PNode): PType =
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 5fe7a7a69..2a2a8b72a 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -481,7 +481,7 @@ proc isAssignable(c: PContext, n: PNode; isUnsafeAddr=false): TAssignableResult
   result = parampatterns.isAssignable(c.p.owner, n, isUnsafeAddr)
 
 proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
-  if n.kind == nkHiddenDeref and not (gCmd == cmdCompileToCpp or
+  if n.kind == nkHiddenDeref and not (c.config.cmd == cmdCompileToCpp or
                                       sfCompileToCpp in c.module.flags):
     checkSonsLen(n, 1, c.config)
     result = n.sons[0]
@@ -601,7 +601,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
   if {sfNoSideEffect, sfCompileTime} * callee.flags != {} and
      {sfForward, sfImportc} * callee.flags == {} and n.typ != nil:
     if sfCompileTime notin callee.flags and
-        optImplicitStatic notin gOptions: return
+        optImplicitStatic notin c.config.options: return
 
     if callee.magic notin ctfeWhitelist: return
     if callee.kind notin {skProc, skFunc, skConverter} or callee.isGenericRoutine:
@@ -1078,7 +1078,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   # here at all!
   #if isSymChoice(n.sons[1]): return
   when defined(nimsuggest):
-    if gCmd == cmdIdeTools:
+    if c.config.cmd == cmdIdeTools:
       suggestExpr(c, n)
       if exactEquals(gTrackPos, n[1].info): suggestExprNoCheck(c, n)
 
@@ -1931,7 +1931,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
       if callee.magic != mNone:
         result = magicsAfterOverloadResolution(c, result, flags)
   of mRunnableExamples:
-    if gCmd == cmdDoc and n.len >= 2 and n.lastSon.kind == nkStmtList:
+    if c.config.cmd == cmdDoc and n.len >= 2 and n.lastSon.kind == nkStmtList:
       if sfMainModule in c.module.flags:
         let inp = toFullPath(c.module.info)
         if c.runnableExamples == nil:
@@ -2205,7 +2205,7 @@ proc shouldBeBracketExpr(n: PNode): bool =
 
 proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   result = n
-  if gCmd == cmdIdeTools: suggestExpr(c, n)
+  if c.config.cmd == cmdIdeTools: suggestExpr(c, n)
   if nfSem in n.flags: return
   case n.kind
   of nkIdent, nkAccQuoted:
@@ -2290,7 +2290,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     let mode = if nfDotField in n.flags: {} else: {checkUndeclared}
     var s = qualifiedLookUp(c, n.sons[0], mode)
     if s != nil:
-      #if gCmd == cmdPretty and n.sons[0].kind == nkDotExpr:
+      #if c.config.cmd == cmdPretty and n.sons[0].kind == nkDotExpr:
       #  pretty.checkUse(n.sons[0].sons[1].info, s)
       case s.kind
       of skMacro:
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 48a81d110..daf9ce983 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -403,11 +403,11 @@ proc magicCall(m: PSym, n: PNode; g: ModuleGraph): PNode =
   result = evalOp(s.magic, n, a, b, c, g)
 
 proc getAppType(n: PNode; g: ModuleGraph): PNode =
-  if gGlobalOptions.contains(optGenDynLib):
+  if g.config.globalOptions.contains(optGenDynLib):
     result = newStrNodeT("lib", n, g)
-  elif gGlobalOptions.contains(optGenStaticLib):
+  elif g.config.globalOptions.contains(optGenStaticLib):
     result = newStrNodeT("staticlib", n, g)
-  elif gGlobalOptions.contains(optGenGuiApp):
+  elif g.config.globalOptions.contains(optGenGuiApp):
     result = newStrNodeT("gui", n, g)
   else:
     result = newStrNodeT("console", n, g)
@@ -479,7 +479,7 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
     result = newNodeIT(nkCharLit, x.info, n.typ)
     if idx >= 0 and idx < len(x.strVal):
       result.intVal = ord(x.strVal[int(idx)])
-    elif idx == len(x.strVal) and optLaxStrings in gOptions:
+    elif idx == len(x.strVal) and optLaxStrings in g.config.options:
       discard
     else:
       localError(g.config, n.info, "index out of bounds: " & $n)
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index a620c544d..8f06e748e 100644
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -169,7 +169,7 @@ proc semGenericStmt(c: PContext, n: PNode,
   when defined(nimsuggest):
     if withinTypeDesc in flags: inc c.inTypeContext
 
-  #if gCmd == cmdIdeTools: suggestStmt(c, n)
+  #if conf.cmd == cmdIdeTools: suggestStmt(c, n)
   semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody)
 
   case n.kind
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index 015e81b1f..543161524 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -146,7 +146,7 @@ proc guardDotAccess(a: PEffects; n: PNode) =
 
 proc makeVolatile(a: PEffects; s: PSym) {.inline.} =
   template compileToCpp(a): untyped =
-    gCmd == cmdCompileToCpp or sfCompileToCpp in getModule(a.owner).flags
+    a.config.cmd == cmdCompileToCpp or sfCompileToCpp in getModule(a.owner).flags
   if a.inTryStmt > 0 and not compileToCpp(a):
     incl(s.flags, sfVolatile)
 
@@ -186,7 +186,7 @@ proc markGcUnsafe(a: PEffects; reason: PNode) =
         a.owner.gcUnsafetyReason = reason.sym
       else:
         a.owner.gcUnsafetyReason = newSym(skUnknown, getIdent("<unknown>"),
-                                          a.owner, reason.info)
+                                          a.owner, reason.info, {})
 
 when true:
   template markSideEffect(a: PEffects; reason: typed) =
@@ -282,7 +282,7 @@ proc addEffect(a: PEffects, e: PNode, useLineInfo=true) =
   var aa = a.exc
   for i in a.bottom ..< aa.len:
     if sameType(a.graph.excType(aa[i]), a.graph.excType(e)):
-      if not useLineInfo or gCmd == cmdDoc: return
+      if not useLineInfo or a.config.cmd == cmdDoc: return
       elif aa[i].info == e.info: return
   throws(a.exc, e)
 
@@ -290,7 +290,7 @@ proc addTag(a: PEffects, e: PNode, useLineInfo=true) =
   var aa = a.tags
   for i in 0 ..< aa.len:
     if sameType(aa[i].typ.skipTypes(skipPtrs), e.typ.skipTypes(skipPtrs)):
-      if not useLineInfo or gCmd == cmdDoc: return
+      if not useLineInfo or a.config.cmd == cmdDoc: return
       elif aa[i].info == e.info: return
   throws(a.tags, e)
 
@@ -960,7 +960,7 @@ proc trackProc*(g: ModuleGraph; s: PSym, body: PNode) =
     effects.sons[tagEffects] = tagsSpec
 
   if sfThread in s.flags and t.gcUnsafe:
-    if optThreads in gGlobalOptions and optThreadAnalysis in gGlobalOptions:
+    if optThreads in g.config.globalOptions and optThreadAnalysis in g.config.globalOptions:
       #localError(s.info, "'$1' is not GC-safe" % s.name.s)
       listGcUnsafety(s, onlyWarning=false, g.config)
     else:
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 0a51ccee4..7282ea58c 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -139,7 +139,7 @@ proc discardCheck(c: PContext, result: PNode) =
       while n.kind in skipForDiscardable:
         n = n.lastSon
         n.typ = nil
-    elif result.typ.kind != tyError and gCmd != cmdInteractive:
+    elif result.typ.kind != tyError and c.config.cmd != cmdInteractive:
       var n = result
       while n.kind in skipForDiscardable: n = n.lastSon
       var s = "expression '" & $n & "' is of type '" &
@@ -255,7 +255,7 @@ proc semTry(c: PContext, n: PNode): PNode =
     # returns true if exception type is imported type
     let typ = semTypeNode(c, typeNode, nil).toObject()
     var is_imported = false
-    if isImportedException(typ):
+    if isImportedException(typ, c.config):
       is_imported = true
     elif not isException(typ):
       localError(c.config, typeNode.info, errExprCannotBeRaised)
@@ -398,7 +398,7 @@ proc semUsing(c: PContext; n: PNode): PNode =
   if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "using")
   for i in countup(0, sonsLen(n)-1):
     var a = n.sons[i]
-    if gCmd == cmdIdeTools: suggestStmt(c, a)
+    if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
     if a.kind == nkCommentStmt: continue
     if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a, c.config)
     checkMinSonsLen(a, 3, c.config)
@@ -471,7 +471,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
   var hasCompileTime = false
   for i in countup(0, sonsLen(n)-1):
     var a = n.sons[i]
-    if gCmd == cmdIdeTools: suggestStmt(c, a)
+    if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
     if a.kind == nkCommentStmt: continue
     if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a, c.config)
     checkMinSonsLen(a, 3, c.config)
@@ -578,7 +578,7 @@ proc semConst(c: PContext, n: PNode): PNode =
   result = copyNode(n)
   for i in countup(0, sonsLen(n) - 1):
     var a = n.sons[i]
-    if gCmd == cmdIdeTools: suggestStmt(c, a)
+    if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
     if a.kind == nkCommentStmt: continue
     if a.kind != nkConstDef: illFormedAst(a, c.config)
     checkSonsLen(a, 3, c.config)
@@ -756,7 +756,7 @@ proc semRaise(c: PContext, n: PNode): PNode =
   if n[0].kind != nkEmpty:
     n[0] = semExprWithType(c, n[0])
     let typ = n[0].typ
-    if not isImportedException(typ):
+    if not isImportedException(typ, c.config):
       if typ.kind != tyRef or typ.lastSon.kind != tyObject:
         localError(c.config, n.info, errExprCannotBeRaised)
       if not isException(typ.lastSon):
@@ -785,7 +785,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
   for i in countup(0, sonsLen(n) - 1):
     var a = n.sons[i]
     when defined(nimsuggest):
-      if gCmd == cmdIdeTools:
+      if c.config.cmd == cmdIdeTools:
         inc c.inTypeContext
         suggestStmt(c, a)
         dec c.inTypeContext
@@ -1236,7 +1236,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
     s.typ = newProcType(c, n.info)
   if n.sons[pragmasPos].kind != nkEmpty:
     pragma(c, s, n.sons[pragmasPos], lambdaPragmas)
-  s.options = gOptions
+  s.options = c.config.options
   if n.sons[bodyPos].kind != nkEmpty:
     if sfImportc in s.flags:
       localError(c.config, n.sons[bodyPos].info, errImplOfXNotAllowed % s.name.s)
@@ -1565,7 +1565,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
     proto.ast = n             # needed for code generation
     popOwner(c)
     pushOwner(c, s)
-  s.options = gOptions
+  s.options = c.config.options
   if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n)
   if s.name.s[0] in {'.', '('}:
     if s.name.s in [".", ".()", ".="] and {destructor, dotOperators} * c.features == {}:
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index f44d93f20..52afce688 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -451,7 +451,7 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
       else:
         addSon(result.n, newSymNode(field))
         addSonSkipIntLit(result, typ)
-      if gCmd == cmdPretty: styleCheckDef(a.sons[j].info, field)
+      if c.config.cmd == cmdPretty: styleCheckDef(a.sons[j].info, field)
   if result.n.len == 0: result.n = nil
 
 proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
@@ -491,7 +491,7 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
     else: discard
   else:
     result = semIdentVis(c, kind, n, allowed)
-  if gCmd == cmdPretty: styleCheckDef(n.info, result)
+  if c.config.cmd == cmdPretty: styleCheckDef(n.info, result)
 
 proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) =
   let ex = t[branchIndex][currentEx].skipConv
@@ -1062,7 +1062,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
       addSon(result.n, newSymNode(arg))
       rawAddSon(result, finalType)
       addParamOrResult(c, arg, kind)
-      if gCmd == cmdPretty: styleCheckDef(a.sons[j].info, arg)
+      if c.config.cmd == cmdPretty: styleCheckDef(a.sons[j].info, arg)
 
   var r: PType
   if n.sons[0].kind != nkEmpty:
@@ -1354,7 +1354,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
   result = nil
   inc c.inTypeContext
 
-  if gCmd == cmdIdeTools: suggestExpr(c, n)
+  if c.config.cmd == cmdIdeTools: suggestExpr(c, n)
   case n.kind
   of nkEmpty: discard
   of nkTypeOfExpr:
diff --git a/compiler/service.nim b/compiler/service.nim
index 9b45f7bd7..f1a988ae5 100644
--- a/compiler/service.nim
+++ b/compiler/service.nim
@@ -42,7 +42,7 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
     of cmdArgument:
       if processArgument(pass, p, argsCount, config): break
   if pass == passCmd2:
-    if optRun notin gGlobalOptions and config.arguments.len > 0 and config.command.normalize != "run":
+    if optRun notin config.globalOptions and config.arguments.len > 0 and config.command.normalize != "run":
       rawMessage(config, errGenerated, errArgsNeedRunOption)
 
 proc serve*(cache: IdentCache; action: proc (cache: IdentCache){.nimcall.}; config: ConfigRef) =
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 01413f678..74c944d51 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -612,7 +612,7 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
     if tfNoSideEffect in f.flags and tfNoSideEffect notin a.flags:
       return isNone
     elif tfThread in f.flags and a.flags * {tfThread, tfNoSideEffect} == {} and
-        optThreadAnalysis in gGlobalOptions:
+        optThreadAnalysis in c.c.config.globalOptions:
       # noSideEffect implies ``tfThread``!
       return isNone
     elif f.flags * {tfIterator} != a.flags * {tfIterator}:
@@ -686,7 +686,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
       if alreadyBound != nil: typ = alreadyBound
 
       template paramSym(kind): untyped =
-        newSym(kind, typeParamName, typeClass.sym, typeClass.sym.info)
+        newSym(kind, typeParamName, typeClass.sym, typeClass.sym.info, {})
 
       block addTypeParam:
         for prev in typeParams:
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index ba70de1f7..23aecfa71 100644
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -106,7 +106,7 @@ proc cmpSuggestions(a, b: Suggest): int =
   # independent of hashing order:
   result = cmp(a.name.s, b.name.s)
 
-proc symToSuggest(s: PSym, isLocal: bool, section: IdeCmd, info: TLineInfo;
+proc symToSuggest(conf: ConfigRef; s: PSym, isLocal: bool, section: IdeCmd, info: TLineInfo;
                   quality: range[0..100]; prefix: PrefixMatch;
                   inTypeContext: bool; scope: int): Suggest =
   new(result)
@@ -125,7 +125,7 @@ proc symToSuggest(s: PSym, isLocal: bool, section: IdeCmd, info: TLineInfo;
       if u.fileIndex == info.fileIndex: inc c
     result.localUsages = c
   result.symkind = s.kind
-  if optIdeTerse notin gGlobalOptions:
+  if optIdeTerse notin conf.globalOptions:
     result.qualifiedPath = @[]
     if not isLocal and s.kind != skModule:
       let ow = s.owner
@@ -237,7 +237,7 @@ proc fieldVisible*(c: PContext, f: PSym): bool {.inline.} =
 proc suggestField(c: PContext, s: PSym; f: PNode; info: TLineInfo; outputs: var Suggestions) =
   var pm: PrefixMatch
   if filterSym(s, f, pm) and fieldVisible(c, s):
-    outputs.add(symToSuggest(s, isLocal=true, ideSug, info, 100, pm, c.inTypeContext > 0, 0))
+    outputs.add(symToSuggest(c.config, s, isLocal=true, ideSug, info, 100, pm, c.inTypeContext > 0, 0))
 
 proc getQuality(s: PSym): range[0..100] =
   if s.typ != nil and s.typ.len > 1:
@@ -256,7 +256,7 @@ template wholeSymTab(cond, section: untyped) =
       let it {.inject.} = item
       var pm {.inject.}: PrefixMatch
       if cond:
-        outputs.add(symToSuggest(it, isLocal = isLocal, section, info, getQuality(it),
+        outputs.add(symToSuggest(c.config, it, isLocal = isLocal, section, info, getQuality(it),
                                  pm, c.inTypeContext > 0, scopeN))
 
 proc suggestSymList(c: PContext, list, f: PNode; info: TLineInfo, outputs: var Suggestions) =
@@ -330,7 +330,7 @@ proc suggestEverything(c: PContext, n, f: PNode, outputs: var Suggestions) =
     for it in items(scope.symbols):
       var pm: PrefixMatch
       if filterSym(it, f, pm):
-        outputs.add(symToSuggest(it, isLocal = isLocal, ideSug, n.info, 0, pm,
+        outputs.add(symToSuggest(c.config, it, isLocal = isLocal, ideSug, n.info, 0, pm,
                                  c.inTypeContext > 0, scopeN))
     #if scope == c.topLevelScope and f.isNil: break
 
@@ -352,8 +352,8 @@ proc suggestFieldAccess(c: PContext, n, field: PNode, outputs: var Suggestions)
         else:
           for it in items(n.sym.tab):
             if filterSym(it, field, pm):
-              outputs.add(symToSuggest(it, isLocal=false, ideSug, n.info, 100, pm, c.inTypeContext > 0, -100))
-          outputs.add(symToSuggest(m, isLocal=false, ideMod, n.info, 100, PrefixMatch.None,
+              outputs.add(symToSuggest(c.config, it, isLocal=false, ideSug, n.info, 100, pm, c.inTypeContext > 0, -100))
+          outputs.add(symToSuggest(c.config, m, isLocal=false, ideMod, n.info, 100, PrefixMatch.None,
             c.inTypeContext > 0, -99))
 
   if typ == nil:
@@ -363,11 +363,11 @@ proc suggestFieldAccess(c: PContext, n, field: PNode, outputs: var Suggestions)
         # all symbols accessible, because we are in the current module:
         for it in items(c.topLevelScope.symbols):
           if filterSym(it, field, pm):
-            outputs.add(symToSuggest(it, isLocal=false, ideSug, n.info, 100, pm, c.inTypeContext > 0, -99))
+            outputs.add(symToSuggest(c.config, it, isLocal=false, ideSug, n.info, 100, pm, c.inTypeContext > 0, -99))
       else:
         for it in items(n.sym.tab):
           if filterSym(it, field, pm):
-            outputs.add(symToSuggest(it, isLocal=false, ideSug, n.info, 100, pm, c.inTypeContext > 0, -99))
+            outputs.add(symToSuggest(c.config, it, isLocal=false, ideSug, n.info, 100, pm, c.inTypeContext > 0, -99))
     else:
       # fallback:
       suggestEverything(c, n, field, outputs)
@@ -426,29 +426,29 @@ when defined(nimsuggest):
     s.allUsages.add(info)
 
 var
-  lastLineInfo*: TLineInfo
+  lastLineInfo*: TLineInfo # XXX global here
 
-proc findUsages(info: TLineInfo; s: PSym; usageSym: var PSym) =
+proc findUsages(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym) =
   if suggestVersion == 1:
     if usageSym == nil and isTracked(info, s.name.s.len):
       usageSym = s
-      suggestResult(symToSuggest(s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0))
+      suggestResult(symToSuggest(conf, s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0))
     elif s == usageSym:
       if lastLineInfo != info:
-        suggestResult(symToSuggest(s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0))
+        suggestResult(symToSuggest(conf, s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0))
       lastLineInfo = info
 
 when defined(nimsuggest):
-  proc listUsages*(s: PSym) =
+  proc listUsages*(conf: ConfigRef; s: PSym) =
     #echo "usages ", len(s.allUsages)
     for info in s.allUsages:
       let x = if info == s.info and info.col == s.info.col: ideDef else: ideUse
-      suggestResult(symToSuggest(s, isLocal=false, x, info, 100, PrefixMatch.None, false, 0))
+      suggestResult(symToSuggest(conf, s, isLocal=false, x, info, 100, PrefixMatch.None, false, 0))
 
-proc findDefinition(info: TLineInfo; s: PSym) =
+proc findDefinition(conf: ConfigRef; info: TLineInfo; s: PSym) =
   if s.isNil: return
   if isTracked(info, s.name.s.len):
-    suggestResult(symToSuggest(s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0))
+    suggestResult(symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0))
     suggestQuit()
 
 proc ensureIdx[T](x: var T, y: int) =
@@ -467,18 +467,18 @@ proc suggestSym*(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym;
         s.addNoDup(info)
 
     if conf.ideCmd == ideUse:
-      findUsages(info, s, usageSym)
+      findUsages(conf, info, s, usageSym)
     elif conf.ideCmd == ideDef:
-      findDefinition(info, s)
+      findDefinition(conf, info, s)
     elif conf.ideCmd == ideDus and s != nil:
       if isTracked(info, s.name.s.len):
-        suggestResult(symToSuggest(s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0))
-      findUsages(info, s, usageSym)
+        suggestResult(symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0))
+      findUsages(conf, info, s, usageSym)
     elif conf.ideCmd == ideHighlight and info.fileIndex == gTrackPos.fileIndex:
-      suggestResult(symToSuggest(s, isLocal=false, ideHighlight, info, 100, PrefixMatch.None, false, 0))
+      suggestResult(symToSuggest(conf, s, isLocal=false, ideHighlight, info, 100, PrefixMatch.None, false, 0))
     elif conf.ideCmd == ideOutline and info.fileIndex == gTrackPos.fileIndex and
         isDecl:
-      suggestResult(symToSuggest(s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0))
+      suggestResult(symToSuggest(conf, s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0))
 
 proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) =
   if s.kind in routineKinds:
@@ -587,7 +587,7 @@ proc suggestSentinel*(c: PContext) =
     for it in items(scope.symbols):
       var pm: PrefixMatch
       if filterSymNoOpr(it, nil, pm):
-        outputs.add(symToSuggest(it, isLocal = isLocal, ideSug, newLineInfo(gTrackPos.fileIndex, -1, -1), 0, PrefixMatch.None, false, scopeN))
+        outputs.add(symToSuggest(c.config, it, isLocal = isLocal, ideSug, newLineInfo(gTrackPos.fileIndex, -1, -1), 0, PrefixMatch.None, false, scopeN))
 
   dec(c.compilesContextId)
   produceOutput(outputs, c.config)
diff --git a/compiler/syntaxes.nim b/compiler/syntaxes.nim
index 4a6474912..18d68bd2d 100644
--- a/compiler/syntaxes.nim
+++ b/compiler/syntaxes.nim
@@ -119,7 +119,7 @@ proc applyFilter(p: var TParsers, n: PNode, filename: string,
   if f != filtNone:
     if hintCodeBegin in p.config.notes:
       rawMessage(p.config, hintCodeBegin, [])
-      msgWriteln(result.s)
+      msgWriteln(p.config, result.s)
       rawMessage(p.config, hintCodeEnd, [])
 
 proc evalPipe(p: var TParsers, n: PNode, filename: string,
diff --git a/compiler/transf.nim b/compiler/transf.nim
index e49d51b11..a10e8a1e5 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -358,7 +358,7 @@ proc transformYield(c: PTransf, n: PNode): PTransNode =
 
 proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
   result = transformSons(c, n)
-  if gCmd == cmdCompileToCpp or sfCompileToCpp in c.module.flags: return
+  if c.graph.config.cmd == cmdCompileToCpp or sfCompileToCpp in c.module.flags: return
   var n = result.PNode
   case n.sons[0].kind
   of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
@@ -390,7 +390,7 @@ proc generateThunk(c: PTransf; prc: PNode, dest: PType): PNode =
 
   # we cannot generate a proper thunk here for GC-safety reasons
   # (see internal documentation):
-  if gCmd == cmdCompileToJS: return prc
+  if c.graph.config.cmd == cmdCompileToJS: return prc
   result = newNodeIT(nkClosure, prc.info, dest)
   var conv = newNodeIT(nkHiddenSubConv, prc.info, dest)
   conv.add(emptyNode)
@@ -716,7 +716,7 @@ proc transformCall(c: PTransf, n: PNode): PTransNode =
 
 proc transformExceptBranch(c: PTransf, n: PNode): PTransNode =
   result = transformSons(c, n)
-  if n[0].isInfixAs() and (not isImportedException(n[0][1].typ)):
+  if n[0].isInfixAs() and not isImportedException(n[0][1].typ, c.graph.config):
     let excTypeNode = n[0][1]
     let actions = newTransNode(nkStmtListExpr, n[1], 2)
     # Generating `let exc = (excType)(getCurrentException())`