summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgcalls.nim58
-rw-r--r--compiler/ccgexprs.nim399
-rw-r--r--compiler/ccgstmts.nim83
-rw-r--r--compiler/cgen.nim35
4 files changed, 234 insertions, 341 deletions
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index dca581fad..b446e8360 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -118,8 +118,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
             getTempCpp(p, typ[0], d, pl)
           else:
             if d.k == locNone: getTemp(p, typ[0], d)
-            var list: TLoc
-            initLoc(list, locCall, d.lode, OnUnknown)
+            var list = initLoc(locCall, d.lode, OnUnknown)
             list.r = pl
             genAssignment(p, d, list, {}) # no need for deep copying
             if canRaise: raiseExit(p)
@@ -127,16 +126,14 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
       elif isHarmlessStore(p, canRaise, d):
         if d.k == locNone: getTemp(p, typ[0], d)
         assert(d.t != nil)        # generate an assignment to d:
-        var list: TLoc
-        initLoc(list, locCall, d.lode, OnUnknown)
+        var list = initLoc(locCall, d.lode, OnUnknown)
         list.r = pl
         genAssignment(p, d, list, {}) # no need for deep copying
         if canRaise: raiseExit(p)
       else:
         var tmp: TLoc
         getTemp(p, typ[0], tmp, needsInit=true)
-        var list: TLoc = default(TLoc)
-        initLoc(list, locCall, d.lode, OnUnknown)
+        var list = initLoc(locCall, d.lode, OnUnknown)
         list.r = pl
         genAssignment(p, tmp, list, {}) # no need for deep copying
         if canRaise: raiseExit(p)
@@ -158,10 +155,9 @@ proc reifiedOpenArray(n: PNode): bool {.inline.} =
     result = true
 
 proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType; prepareForMutation = false): (Rope, Rope) =
-  var a, b, c: TLoc = default(TLoc)
-  initLocExpr(p, q[1], a)
-  initLocExpr(p, q[2], b)
-  initLocExpr(p, q[3], c)
+  var a = initLocExpr(p, q[1])
+  var b = initLocExpr(p, q[2])
+  var c = initLocExpr(p, q[3])
   # but first produce the required index checks:
   if optBoundsCheck in p.options:
     genBoundsCheck(p, a, b, c)
@@ -226,8 +222,7 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode; result: var Rope) =
     let (x, y) = genOpenArraySlice(p, q, formalType, n.typ[0])
     result.add x & ", " & y
   else:
-    var a: TLoc = default(TLoc)
-    initLocExpr(p, if n.kind == nkHiddenStdConv: n[1] else: n, a)
+    var a: TLoc = initLocExpr(p, if n.kind == nkHiddenStdConv: n[1] else: n)
     case skipTypes(a.t, abstractVar+{tyStatic}).kind
     of tyOpenArray, tyVarargs:
       if reifiedOpenArray(n):
@@ -283,12 +278,11 @@ proc literalsNeedsTmp(p: BProc, a: TLoc): TLoc =
   genAssignment(p, result, a, {})
 
 proc genArgStringToCString(p: BProc, n: PNode; result: var Rope; needsTmp: bool) {.inline.} =
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, n[0], a)
+  var a: TLoc = initLocExpr(p, n[0])
   appcg(p.module, result, "#nimToCStringConv($1)", [withTmpIfNeeded(p, a, needsTmp).rdLoc])
 
 proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Rope; needsTmp = false) =
-  var a: TLoc = default(TLoc)
+  var a: TLoc
   if n.kind == nkStringToCString:
     genArgStringToCString(p, n, result, needsTmp)
   elif skipTypes(param.typ, abstractVar).kind in {tyOpenArray, tyVarargs}:
@@ -296,14 +290,14 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Rope; need
     openArrayLoc(p, param.typ, n, result)
   elif ccgIntroducedPtr(p.config, param, call[0].typ[0]) and 
     (optByRef notin param.options or not p.module.compileToCpp):
-    initLocExpr(p, n, a)
+    a = initLocExpr(p, n)
     if n.kind in {nkCharLit..nkNilLit}:
       addAddrLoc(p.config, literalsNeedsTmp(p, a), result)
     else:
       addAddrLoc(p.config, withTmpIfNeeded(p, a, needsTmp), result)
   elif p.module.compileToCpp and param.typ.kind in {tyVar} and
       n.kind == nkHiddenAddr:
-    initLocExprSingleUse(p, n[0], a)
+    a = initLocExprSingleUse(p, n[0])
     # if the proc is 'importc'ed but not 'importcpp'ed then 'var T' still
     # means '*T'. See posix.nim for lots of examples that do that in the wild.
     let callee = call[0]
@@ -314,16 +308,16 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Rope; need
     else:
       addRdLoc(a, result)
   else:
-    initLocExprSingleUse(p, n, a)
+    a = initLocExprSingleUse(p, n)
     addRdLoc(withTmpIfNeeded(p, a, needsTmp), result)
   #assert result != nil
 
 proc genArgNoParam(p: BProc, n: PNode; result: var Rope; needsTmp = false) =
-  var a: TLoc = default(TLoc)
+  var a: TLoc
   if n.kind == nkStringToCString:
     genArgStringToCString(p, n, result, needsTmp)
   else:
-    initLocExprSingleUse(p, n, a)
+    a = initLocExprSingleUse(p, n)
     addRdLoc(withTmpIfNeeded(p, a, needsTmp), result)
 
 import aliasanalysis
@@ -423,9 +417,8 @@ proc addActualSuffixForHCR(res: var Rope, module: PSym, sym: PSym) =
     res = res & "_actual".rope
 
 proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
-  var op: TLoc = default(TLoc)
   # this is a hotspot in the compiler
-  initLocExpr(p, ri[0], op)
+  var op: TLoc = initLocExpr(p, ri[0])
   # getUniqueType() is too expensive here:
   var typ = skipTypes(ri[0].typ, abstractInstOwned)
   assert(typ.kind == tyProc)
@@ -447,8 +440,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
   const PatProc = "$1.ClE_0? $1.ClP_0($3$1.ClE_0):(($4)($1.ClP_0))($2)"
   const PatIter = "$1.ClP_0($3$1.ClE_0)" # we know the env exists
 
-  var op: TLoc = default(TLoc)
-  initLocExpr(p, ri[0], op)
+  var op: TLoc = initLocExpr(p, ri[0])
 
   # getUniqueType() is too expensive here:
   var typ = skipTypes(ri[0].typ, abstractInstOwned)
@@ -490,8 +482,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
     elif isHarmlessStore(p, canRaise, d):
       if d.k == locNone: getTemp(p, typ[0], d)
       assert(d.t != nil)        # generate an assignment to d:
-      var list: TLoc = default(TLoc)
-      initLoc(list, locCall, d.lode, OnUnknown)
+      var list: TLoc = initLoc(locCall, d.lode, OnUnknown)
       if tfIterator in typ.flags:
         list.r = PatIter % [rdLoc(op), pl, pl.addComma, rawProc]
       else:
@@ -502,8 +493,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
       var tmp: TLoc
       getTemp(p, typ[0], tmp)
       assert(d.t != nil)        # generate an assignment to d:
-      var list: TLoc = default(TLoc)
-      initLoc(list, locCall, d.lode, OnUnknown)
+      var list: TLoc = initLoc(locCall, d.lode, OnUnknown)
       if tfIterator in typ.flags:
         list.r = PatIter % [rdLoc(op), pl, pl.addComma, rawProc]
       else:
@@ -685,8 +675,7 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType; result: var Ro
         result.add(substr(pat, start, i - 1))
 
 proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
-  var op: TLoc = default(TLoc)
-  initLocExpr(p, ri[0], op)
+  var op: TLoc = initLocExpr(p, ri[0])
   # getUniqueType() is too expensive here:
   var typ = skipTypes(ri[0].typ, abstractInst)
   assert(typ.kind == tyProc)
@@ -710,8 +699,7 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
       else:
         if d.k == locNone: getTemp(p, typ[0], d)
         assert(d.t != nil)        # generate an assignment to d:
-        var list: TLoc
-        initLoc(list, locCall, d.lode, OnUnknown)
+        var list: TLoc = initLoc(locCall, d.lode, OnUnknown)
         list.r = pl
         genAssignment(p, d, list, {}) # no need for deep copying
     else:
@@ -731,8 +719,7 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
 
 proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
   # generates a crappy ObjC call
-  var op: TLoc = default(TLoc)
-  initLocExpr(p, ri[0], op)
+  var op: TLoc = initLocExpr(p, ri[0])
   var pl = "["
   # getUniqueType() is too expensive here:
   var typ = skipTypes(ri[0].typ, abstractInst)
@@ -790,8 +777,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
       pl.add("]")
       if d.k == locNone: getTemp(p, typ[0], d)
       assert(d.t != nil)        # generate an assignment to d:
-      var list: TLoc = default(TLoc)
-      initLoc(list, locCall, ri, OnUnknown)
+      var list: TLoc = initLoc(locCall, ri, OnUnknown)
       list.r = pl
       genAssignment(p, d, list, {}) # no need for deep copying
   else:
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 46a353dce..e46a0470d 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -479,10 +479,9 @@ proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc) =
     d = s # ``d`` is free, so fill it with ``s``
 
 proc putDataIntoDest(p: BProc, d: var TLoc, n: PNode, r: Rope) =
-  var a: TLoc = default(TLoc)
   if d.k != locNone:
+    var a: TLoc = initLoc(locData, n, OnStatic)
     # need to generate an assignment here
-    initLoc(a, locData, n, OnStatic)
     a.r = r
     if lfNoDeepCopy in d.flags: genAssignment(p, d, a, {})
     else: genAssignment(p, d, a, {needToCopy})
@@ -494,10 +493,9 @@ proc putDataIntoDest(p: BProc, d: var TLoc, n: PNode, r: Rope) =
     d.r = r
 
 proc putIntoDest(p: BProc, d: var TLoc, n: PNode, r: Rope; s=OnUnknown) =
-  var a: TLoc = default(TLoc)
   if d.k != locNone:
     # need to generate an assignment here
-    initLoc(a, locExpr, n, s)
+    var a: TLoc = initLoc(locExpr, n, s)
     a.r = r
     if lfNoDeepCopy in d.flags: genAssignment(p, d, a, {})
     else: genAssignment(p, d, a, {needToCopy})
@@ -509,49 +507,42 @@ proc putIntoDest(p: BProc, d: var TLoc, n: PNode, r: Rope; s=OnUnknown) =
     d.r = r
 
 proc binaryStmt(p: BProc, e: PNode, d: var TLoc, op: string) =
-  var a, b: TLoc = default(TLoc)
   if d.k != locNone: internalError(p.config, e.info, "binaryStmt")
-  initLocExpr(p, e[1], a)
-  initLocExpr(p, e[2], b)
+  var a = initLocExpr(p, e[1])
+  var b = initLocExpr(p, e[2])
   lineCg(p, cpsStmts, "$1 $2 $3;$n", [rdLoc(a), op, rdLoc(b)])
 
 proc binaryStmtAddr(p: BProc, e: PNode, d: var TLoc, cpname: string) =
-  var a, b: TLoc = default(TLoc)
   if d.k != locNone: internalError(p.config, e.info, "binaryStmtAddr")
-  initLocExpr(p, e[1], a)
-  initLocExpr(p, e[2], b)
+  var a = initLocExpr(p, e[1])
+  var b = initLocExpr(p, e[2])
   lineCg(p, cpsStmts, "#$1($2, $3);$n", [cpname, byRefLoc(p, a), rdLoc(b)])
 
 template unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
-  var a: TLoc = default(TLoc)
   if d.k != locNone: internalError(p.config, e.info, "unaryStmt")
-  initLocExpr(p, e[1], a)
+  var a: TLoc = initLocExpr(p, e[1])
   lineCg(p, cpsStmts, frmt, [rdLoc(a)])
 
 template binaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) =
-  var a, b: TLoc = default(TLoc)
   assert(e[1].typ != nil)
   assert(e[2].typ != nil)
-  initLocExpr(p, e[1], a)
-  initLocExpr(p, e[2], b)
+  var a = initLocExpr(p, e[1])
+  var b = initLocExpr(p, e[2])
   putIntoDest(p, d, e, ropecg(p.module, frmt, [rdLoc(a), rdLoc(b)]))
 
 template binaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
-  var a, b: TLoc = default(TLoc)
   assert(e[1].typ != nil)
   assert(e[2].typ != nil)
-  initLocExpr(p, e[1], a)
-  initLocExpr(p, e[2], b)
+  var a = initLocExpr(p, e[1])
+  var b = initLocExpr(p, e[2])
   putIntoDest(p, d, e, ropecg(p.module, frmt, [a.rdCharLoc, b.rdCharLoc]))
 
 template unaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) =
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, e[1], a)
+  var a: TLoc = initLocExpr(p, e[1])
   putIntoDest(p, d, e, ropecg(p.module, frmt, [rdLoc(a)]))
 
 template unaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, e[1], a)
+  var a: TLoc = initLocExpr(p, e[1])
   putIntoDest(p, d, e, ropecg(p.module, frmt, [rdCharLoc(a)]))
 
 template binaryArithOverflowRaw(p: BProc, t: PType, a, b: TLoc;
@@ -591,11 +582,10 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
       "nimAddInt64", "nimSubInt64"
     ]
     opr: array[mAddI..mPred, string] = ["+", "-", "*", "/", "%", "+", "-"]
-  var a, b: TLoc = default(TLoc)
   assert(e[1].typ != nil)
   assert(e[2].typ != nil)
-  initLocExpr(p, e[1], a)
-  initLocExpr(p, e[2], b)
+  var a = initLocExpr(p, e[1])
+  var b = initLocExpr(p, e[2])
   # skipping 'range' is correct here as we'll generate a proper range check
   # later via 'chckRange'
   let t = e.typ.skipTypes(abstractRange)
@@ -625,11 +615,9 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
       putIntoDest(p, d, e, res)
 
 proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
-  var
-    a: TLoc = default(TLoc)
-    t: PType
+  var t: PType
   assert(e[1].typ != nil)
-  initLocExpr(p, e[1], a)
+  var a: TLoc = initLocExpr(p, e[1])
   t = skipTypes(e.typ, abstractRange)
   if optOverflowCheck in p.options:
     var first = newRopeAppender()
@@ -651,12 +639,11 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
 
 proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   var
-    a, b: TLoc = default(TLoc)
     s, k: BiggestInt = 0
   assert(e[1].typ != nil)
   assert(e[2].typ != nil)
-  initLocExpr(p, e[1], a)
-  initLocExpr(p, e[2], b)
+  var a = initLocExpr(p, e[1])
+  var b = initLocExpr(p, e[2])
   # BUGFIX: cannot use result-type here, as it may be a boolean
   s = max(getSize(p.config, a.t), getSize(p.config, b.t)) * 8
   k = getSize(p.config, a.t) * 8
@@ -710,11 +697,10 @@ proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     assert(false, $op)
 
 proc genEqProc(p: BProc, e: PNode, d: var TLoc) =
-  var a, b: TLoc = default(TLoc)
   assert(e[1].typ != nil)
   assert(e[2].typ != nil)
-  initLocExpr(p, e[1], a)
-  initLocExpr(p, e[2], b)
+  var a = initLocExpr(p, e[1])
+  var b = initLocExpr(p, e[2])
   if a.t.skipTypes(abstractInstOwned).callConv == ccClosure:
     putIntoDest(p, d, e,
       "($1.ClP_0 == $2.ClP_0 && $1.ClE_0 == $2.ClE_0)" % [rdLoc(a), rdLoc(b)])
@@ -730,10 +716,9 @@ proc genIsNil(p: BProc, e: PNode, d: var TLoc) =
 
 proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   var
-    a: TLoc = default(TLoc)
     t: PType
   assert(e[1].typ != nil)
-  initLocExpr(p, e[1], a)
+  var a = initLocExpr(p, e[1])
   t = skipTypes(e.typ, abstractRange)
 
   template applyFormat(frmt: untyped) =
@@ -767,16 +752,16 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc) =
     if e[0].typ.skipTypes(abstractInstOwned).kind == tyRef:
       d.storage = OnHeap
   else:
-    var a: TLoc = default(TLoc)
+    var a: TLoc
     var typ = e[0].typ
     if typ.kind in {tyUserTypeClass, tyUserTypeClassInst} and typ.isResolvedUserTypeClass:
       typ = typ.lastSon
     typ = typ.skipTypes(abstractInstOwned)
     if typ.kind in {tyVar} and tfVarIsPtr notin typ.flags and p.module.compileToCpp and e[0].kind == nkHiddenAddr:
-      initLocExprSingleUse(p, e[0][0], d)
+      d = initLocExprSingleUse(p, e[0][0])
       return
     else:
-      initLocExprSingleUse(p, e[0], a)
+      a = initLocExprSingleUse(p, e[0])
     if d.k == locNone:
       # dest = *a;  <-- We do not know that 'dest' is on the heap!
       # It is completely wrong to set 'd.storage' here, unless it's not yet
@@ -813,8 +798,7 @@ proc cowBracket(p: BProc; n: PNode) =
   if n.kind == nkBracketExpr and optSeqDestructors in p.config.globalOptions:
     let strCandidate = n[0]
     if strCandidate.typ.skipTypes(abstractInst).kind == tyString:
-      var a: TLoc = default(TLoc)
-      initLocExpr(p, strCandidate, a)
+      var a: TLoc = initLocExpr(p, strCandidate)
       linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
 
 proc cow(p: BProc; n: PNode) {.inline.} =
@@ -823,31 +807,28 @@ proc cow(p: BProc; n: PNode) {.inline.} =
 proc genAddr(p: BProc, e: PNode, d: var TLoc) =
   # careful  'addr(myptrToArray)' needs to get the ampersand:
   if e[0].typ.skipTypes(abstractInstOwned).kind in {tyRef, tyPtr}:
-    var a: TLoc = default(TLoc)
-    initLocExpr(p, e[0], a)
+    var a: TLoc = initLocExpr(p, e[0])
     putIntoDest(p, d, e, "&" & a.r, a.storage)
     #Message(e.info, warnUser, "HERE NEW &")
   elif mapType(p.config, e[0].typ, mapTypeChooser(e[0]) == skParam) == ctArray or isCppRef(p, e.typ):
     expr(p, e[0], d)
   else:
-    var a: TLoc = default(TLoc)
-    initLocExpr(p, e[0], a)
+    var a: TLoc = initLocExpr(p, e[0])
     putIntoDest(p, d, e, addrLoc(p.config, a), a.storage)
 
 template inheritLocation(d: var TLoc, a: TLoc) =
   if d.k == locNone: d.storage = a.storage
 
-proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc) =
-  initLocExpr(p, e[0], a)
+proc genRecordFieldAux(p: BProc, e: PNode, d: var TLoc, a: var TLoc) =
+  a = initLocExpr(p, e[0])
   if e[1].kind != nkSym: internalError(p.config, e.info, "genRecordFieldAux")
   d.inheritLocation(a)
   discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
 
 proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
   var
-    a: TLoc = default(TLoc)
     i: int = 0
-  initLocExpr(p, e[0], a)
+  var a: TLoc = initLocExpr(p, e[0])
   let tupType = a.t.skipTypes(abstractInst+{tyVar})
   assert tupType.kind == tyTuple
   d.inheritLocation(a)
@@ -900,7 +881,7 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
 proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
 
 proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
-  var test, u, v: TLoc = default(TLoc)
+  var test, u, v: TLoc
   for i in 1..<e.len:
     var it = e[i]
     assert(it.kind in nkCallKinds)
@@ -909,9 +890,9 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
     if op.magic == mNot: it = it[1]
     let disc = it[2].skipConv
     assert(disc.kind == nkSym)
-    initLoc(test, locNone, it, OnStack)
-    initLocExpr(p, it[1], u)
-    initLoc(v, locExpr, disc, OnUnknown)
+    test = initLoc(locNone, it, OnStack)
+    u = initLocExpr(p, it[1])
+    v = initLoc(locExpr, disc, OnUnknown)
     v.r = newRopeAppender()
     v.r.add obj
     v.r.add(".")
@@ -985,17 +966,15 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
     genRecordField(p, e[0], d)
 
 proc genUncheckedArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
-  var a, b: TLoc = default(TLoc)
-  initLocExpr(p, x, a)
-  initLocExpr(p, y, b)
+  var a = initLocExpr(p, x)
+  var b = initLocExpr(p, y)
   d.inheritLocation(a)
   putIntoDest(p, d, n, ropecg(p.module, "$1[$2]", [rdLoc(a), rdCharLoc(b)]),
               a.storage)
 
 proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
-  var a, b: TLoc = default(TLoc)
-  initLocExpr(p, x, a)
-  initLocExpr(p, y, b)
+  var a = initLocExpr(p, x)
+  var b = initLocExpr(p, y)
   var ty = skipTypes(a.t, abstractVarRange + abstractPtrs + tyUserTypeClasses)
   var first = newRopeAppender()
   intLiteral(firstOrd(p.config, ty), first)
@@ -1028,9 +1007,8 @@ proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
               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 = default(TLoc)
-  initLocExpr(p, x, a)
-  initLocExpr(p, y, b)
+  var a = initLocExpr(p, x)
+  var b = initLocExpr(p, y)
   inheritLocation(d, a)
   putIntoDest(p, d, n,
               ropecg(p.module, "$1[$2]", [rdLoc(a), rdCharLoc(b)]), a.storage)
@@ -1076,9 +1054,8 @@ proc genBoundsCheck(p: BProc; arr, a, b: TLoc) =
   else: discard
 
 proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
-  var a, b: TLoc = default(TLoc)
-  initLocExpr(p, x, a)
-  initLocExpr(p, y, b)
+  var a = initLocExpr(p, x)
+  var b = initLocExpr(p, y)
   if not reifiedOpenArray(x):
     # emit range check:
     if optBoundsCheck in p.options:
@@ -1102,9 +1079,8 @@ proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
                 ropecg(p.module, "$1.Field0[$2]", [rdLoc(a), rdCharLoc(b)]), a.storage)
 
 proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
-  var a, b: TLoc = default(TLoc)
-  initLocExpr(p, x, a)
-  initLocExpr(p, y, b)
+  var a = initLocExpr(p, x)
+  var b = initLocExpr(p, y)
   var ty = skipTypes(a.t, abstractVarRange)
   if ty.kind in {tyRef, tyPtr}:
     ty = skipTypes(ty.lastSon, abstractVarRange) # emit range check:
@@ -1177,11 +1153,10 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
   # a = tmp
   when false:
     #if isSimpleExpr(e) and p.module.compileToCpp:
-    var tmpA, tmpB: TLoc
     #getTemp(p, e.typ, tmpA)
     #getTemp(p, e.typ, tmpB)
-    initLocExprSingleUse(p, e[1], tmpA)
-    initLocExprSingleUse(p, e[2], tmpB)
+    var tmpA = initLocExprSingleUse(p, e[1])
+    var tmpB = initLocExprSingleUse(p, e[2])
     tmpB.k = locExpr
     if m == mOr:
       tmpB.r = "((" & rdLoc(tmpA) & ")||(" & rdLoc(tmpB) & "))"
@@ -1218,12 +1193,12 @@ proc genEcho(p: BProc, n: PNode) =
   if p.config.target.targetOS == osGenode:
     # echo directly to the Genode LOG session
     var args: Rope = ""
-    var a: TLoc = default(TLoc)
+    var a: TLoc
     for i, it in n.sons:
       if it.skipConv.kind == nkNilLit:
         args.add(", \"\"")
       elif n.len != 0:
-        initLocExpr(p, it, a)
+        a = initLocExpr(p, it)
         if i > 0:
           args.add(", ")
         case detectStrVersion(p.module)
@@ -1238,8 +1213,7 @@ proc genEcho(p: BProc, n: PNode) =
     if n.len == 0:
       linefmt(p, cpsStmts, "#echoBinSafe(NIM_NIL, $1);$n", [n.len])
     else:
-      var a: TLoc = default(TLoc)
-      initLocExpr(p, n, a)
+      var a: TLoc = initLocExpr(p, n)
       linefmt(p, cpsStmts, "#echoBinSafe($1, $2);$n", [a.rdLoc, n.len])
     when false:
       p.module.includeHeader("<stdio.h>")
@@ -1273,7 +1247,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
   #    appendChar(tmp0, 'z');
   #    asgn(s, tmp0);
   #  }
-  var a = default(TLoc)
+  var a: TLoc
   var tmp: TLoc
   getTemp(p, e.typ, tmp)
   var L = 0
@@ -1281,7 +1255,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
   var lens: Rope = ""
   for i in 0..<e.len - 1:
     # compute the length expression:
-    initLocExpr(p, e[i + 1], a)
+    a = initLocExpr(p, e[i + 1])
     if skipTypes(e[i + 1].typ, abstractVarRange).kind == tyChar:
       inc(L)
       appends.add(ropecg(p.module, "#appendChar($1, $2);$n", [strLoc(p, tmp), rdLoc(a)]))
@@ -1313,14 +1287,14 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
   #    appendChar(s, 'z');
   #  }
   var
-    a, dest, call: TLoc = default(TLoc)
+    a, call: TLoc
     appends, lens: Rope = ""
   assert(d.k == locNone)
   var L = 0
-  initLocExpr(p, e[1], dest)
+  var dest = initLocExpr(p, e[1])
   for i in 0..<e.len - 2:
     # compute the length expression:
-    initLocExpr(p, e[i + 2], a)
+    a = initLocExpr(p, e[i + 2])
     if skipTypes(e[i + 2].typ, abstractVarRange).kind == tyChar:
       inc(L)
       appends.add(ropecg(p.module, "#appendChar($1, $2);$n",
@@ -1337,7 +1311,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
     linefmt(p, cpsStmts, "#prepareAdd($1, $2$3);$n",
             [byRefLoc(p, dest), lens, L])
   else:
-    initLoc(call, locCall, e, OnHeap)
+    call = initLoc(locCall, e, OnHeap)
     call.r = ropecg(p.module, "#resizeString($1, $2$3)", [rdLoc(dest), lens, L])
     genAssignment(p, dest, call, {})
     gcUsage(p.config, e)
@@ -1347,11 +1321,11 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
   # seq &= x  -->
   #    seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
   #    seq->data[seq->len-1] = x;
-  var a, b, dest, tmpL, call: TLoc = default(TLoc)
-  initLocExpr(p, e[1], a)
-  initLocExpr(p, e[2], b)
+  var tmpL: TLoc = default(TLoc)
+  var a = initLocExpr(p, e[1])
+  var b = initLocExpr(p, e[2])
   let seqType = skipTypes(e[1].typ, {tyVar})
-  initLoc(call, locCall, e, OnHeap)
+  var call = initLoc(locCall, e, OnHeap)
   if not p.module.compileToCpp:
     const seqAppendPattern = "($2) #incrSeqV3((TGenericSeq*)($1), $3)"
     call.r = ropecg(p.module, seqAppendPattern, [rdLoc(a),
@@ -1367,7 +1341,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
   genRefAssign(p, a, call)
   #if bt != b.t:
   #  echo "YES ", e.info, " new: ", typeToString(bt), " old: ", typeToString(b.t)
-  initLoc(dest, locExpr, e[2], OnHeap)
+  var dest = initLoc(locExpr, e[2], OnHeap)
   getIntTemp(p, tmpL)
   lineCg(p, cpsStmts, "$1 = $2->$3++;$n", [tmpL.r, rdLoc(a), lenField(p)])
   dest.r = ropecg(p.module, "$1$3[$2]", [rdLoc(a), tmpL.r, dataField(p)])
@@ -1375,8 +1349,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
   gcUsage(p.config, e)
 
 proc genReset(p: BProc, n: PNode) =
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, n[1], a)
+  var a: TLoc = initLocExpr(p, n[1])
   specializeReset(p, a)
   when false:
     linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
@@ -1390,8 +1363,7 @@ proc genDefault(p: BProc; n: PNode; d: var TLoc) =
 proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) =
   var sizeExpr = sizeExpr
   let typ = a.t
-  var b: TLoc = default(TLoc)
-  initLoc(b, locExpr, a.lode, OnHeap)
+  var b: TLoc = initLoc(locExpr, a.lode, OnHeap)
   let refType = typ.skipTypes(abstractInstOwned)
   assert refType.kind == tyRef
   let bt = refType.lastSon
@@ -1417,8 +1389,7 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) =
         localError(p.module.config, a.lode.info,
           "the destructor that is turned into a finalizer needs " &
           "to have the 'nimcall' calling convention")
-      var f: TLoc = default(TLoc)
-      initLocExpr(p, newSymNode(op), f)
+      var f: TLoc = initLocExpr(p, newSymNode(op))
       p.module.s[cfsTypeInit3].addf("$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
 
     if a.storage == OnHeap and usesWriteBarrier(p.config):
@@ -1443,12 +1414,10 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) =
   genObjectInit(p, cpsStmts, bt, a, constructRefObj)
 
 proc genNew(p: BProc, e: PNode) =
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, e[1], a)
+  var a: TLoc = initLocExpr(p, e[1])
   # 'genNew' also handles 'unsafeNew':
   if e.len == 3:
-    var se: TLoc = default(TLoc)
-    initLocExpr(p, e[2], se)
+    var se: TLoc = initLocExpr(p, e[2])
     rawGenNew(p, a, se.rdLoc, needsInit = true)
   else:
     rawGenNew(p, a, "", needsInit = true)
@@ -1456,8 +1425,7 @@ proc genNew(p: BProc, e: PNode) =
 
 proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope; lenIsZero: bool) =
   let seqtype = skipTypes(dest.t, abstractVarRange)
-  var call: TLoc = default(TLoc)
-  initLoc(call, locExpr, dest.lode, OnHeap)
+  var call: TLoc = initLoc(locExpr, dest.lode, OnHeap)
   if dest.storage == OnHeap and usesWriteBarrier(p.config):
     if canFormAcycle(p.module.g.graph, dest.t):
       linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", [dest.rdLoc])
@@ -1482,9 +1450,8 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope; lenIsZero: bool) =
     genAssignment(p, dest, call, {})
 
 proc genNewSeq(p: BProc, e: PNode) =
-  var a, b: TLoc = default(TLoc)
-  initLocExpr(p, e[1], a)
-  initLocExpr(p, e[2], b)
+  var a = initLocExpr(p, e[1])
+  var b = initLocExpr(p, e[2])
   if optSeqDestructors in p.config.globalOptions:
     let seqtype = skipTypes(e[1].typ, abstractVarRange)
     linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3));$n",
@@ -1498,8 +1465,7 @@ proc genNewSeq(p: BProc, e: PNode) =
 
 proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
   let seqtype = skipTypes(e.typ, abstractVarRange)
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, e[1], a)
+  var a: TLoc = initLocExpr(p, e[1])
   if optSeqDestructors in p.config.globalOptions:
     if d.k == locNone: getTemp(p, e.typ, d, needsInit=false)
     linefmt(p, cpsStmts, "$1.len = 0; $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3));$n",
@@ -1602,7 +1568,7 @@ proc lhsDoesAlias(a, b: PNode): bool =
     if isPartOf(a, y) != arNo: return true
 
 proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) =
-  var arr = default(TLoc)
+  var arr: TLoc
   var tmp: TLoc = default(TLoc)
   # bug #668
   let doesAlias = lhsDoesAlias(d.lode, n)
@@ -1623,7 +1589,7 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) =
     # generate call to newSeq before adding the elements per hand:
     genNewSeqAux(p, dest[], lit, n.len == 0)
   for i in 0..<n.len:
-    initLoc(arr, locExpr, n[i], OnHeap)
+    arr = initLoc(locExpr, n[i], OnHeap)
     var lit = newRopeAppender()
     intLiteral(i, lit)
     arr.r = ropecg(p.module, "$1$3[$2]", [rdLoc(dest[]), lit, dataField(p)])
@@ -1637,14 +1603,14 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) =
       genAssignment(p, d, tmp, {})
 
 proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
-  var elem, a, arr: TLoc = default(TLoc)
+  var elem, arr: TLoc
   if n[1].kind == nkBracket:
     n[1].typ = n.typ
     genSeqConstr(p, n[1], d)
     return
   if d.k == locNone:
     getTemp(p, n.typ, d)
-  initLocExpr(p, n[1], a)
+  var a = initLocExpr(p, n[1])
   # generate call to newSeq before adding the elements per hand:
   let L = toInt(lengthOrd(p.config, n[1].typ))
   if optSeqDestructors in p.config.globalOptions:
@@ -1659,22 +1625,22 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
   # bug #5007; do not produce excessive C source code:
   if L < 10:
     for i in 0..<L:
-      initLoc(elem, locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap)
+      elem = initLoc(locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap)
       var lit = newRopeAppender()
       intLiteral(i, lit)
       elem.r = ropecg(p.module, "$1$3[$2]", [rdLoc(d), lit, dataField(p)])
       elem.storage = OnHeap # we know that sequences are on the heap
-      initLoc(arr, locExpr, lodeTyp elemType(skipTypes(n[1].typ, abstractInst)), a.storage)
+      arr = initLoc(locExpr, lodeTyp elemType(skipTypes(n[1].typ, abstractInst)), a.storage)
       arr.r = ropecg(p.module, "$1[$2]", [rdLoc(a), lit])
       genAssignment(p, elem, arr, {needToCopy})
   else:
     var i: TLoc
     getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), i)
     linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",  [i.r, L])
-    initLoc(elem, locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap)
+    elem = initLoc(locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap)
     elem.r = ropecg(p.module, "$1$3[$2]", [rdLoc(d), rdLoc(i), dataField(p)])
     elem.storage = OnHeap # we know that sequences are on the heap
-    initLoc(arr, locExpr, lodeTyp elemType(skipTypes(n[1].typ, abstractInst)), a.storage)
+    arr = initLoc(locExpr, lodeTyp elemType(skipTypes(n[1].typ, abstractInst)), a.storage)
     arr.r = ropecg(p.module, "$1[$2]", [rdLoc(a), rdLoc(i)])
     genAssignment(p, elem, arr, {needToCopy})
     lineF(p, cpsStmts, "}$n", [])
@@ -1682,13 +1648,13 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
 
 proc genNewFinalize(p: BProc, e: PNode) =
   var
-    a, b, f: TLoc = default(TLoc)
+    b: TLoc
     refType, bt: PType
     ti: Rope
   refType = skipTypes(e[1].typ, abstractVarRange)
-  initLocExpr(p, e[1], a)
-  initLocExpr(p, e[2], f)
-  initLoc(b, locExpr, a.lode, OnHeap)
+  var a = initLocExpr(p, e[1])
+  var f = initLocExpr(p, e[2])
+  b = initLoc(locExpr, a.lode, OnHeap)
   ti = genTypeInfo(p.config, p.module, refType, e.info)
   p.module.s[cfsTypeInit3].addf("$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
   b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [
@@ -1718,8 +1684,7 @@ proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo; result: var Ro
       appcg(p.module, result, "#isObjWithCache($#.m_type, $#, $#)", [a, ti, cache])
 
 proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, x, a)
+  var a: TLoc = initLocExpr(p, x)
   var dest = skipTypes(typ, typedescPtrs)
   var r = rdLoc(a)
   var nilCheck: Rope = ""
@@ -1760,8 +1725,7 @@ proc genOf(p: BProc, n: PNode, d: var TLoc) =
 proc genRepr(p: BProc, e: PNode, d: var TLoc) =
   if optTinyRtti in p.config.globalOptions:
     localError(p.config, e.info, "'repr' is not available for --newruntime")
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, e[1], a)
+  var a: TLoc = initLocExpr(p, e[1])
   var t = skipTypes(e[1].typ, abstractVarRange)
   case t.kind
   of tyInt..tyInt64, tyUInt..tyUInt64:
@@ -1841,8 +1805,7 @@ proc genGetTypeInfoV2(p: BProc, e: PNode, d: var TLoc) =
     # ordinary static type information
     putIntoDest(p, d, e, genTypeInfoV2(p.module, t, e.info))
   else:
-    var a: TLoc = default(TLoc)
-    initLocExpr(p, e[1], a)
+    var a: TLoc = initLocExpr(p, e[1])
     var nilCheck = ""
     # use the dynamic type stored at offset 0:
     var rt = newRopeAppender()
@@ -1850,8 +1813,7 @@ proc genGetTypeInfoV2(p: BProc, e: PNode, d: var TLoc) =
     putIntoDest(p, d, e, rt)
 
 proc genAccessTypeField(p: BProc; e: PNode; d: var TLoc) =
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, e[1], a)
+  var a: TLoc = initLocExpr(p, e[1])
   var nilCheck = ""
   # use the dynamic type stored at offset 0:
   var rt = newRopeAppender()
@@ -1859,8 +1821,7 @@ proc genAccessTypeField(p: BProc; e: PNode; d: var TLoc) =
   putIntoDest(p, d, e, rt)
 
 template genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) =
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, n[1], a)
+  var a: TLoc = initLocExpr(p, n[1])
   a.r = ropecg(p.module, frmt, [rdLoc(a)])
   a.flags.excl lfIndirect # this flag should not be propagated here (not just for HCR)
   if d.k == locNone: getTemp(p, n.typ, d)
@@ -1876,11 +1837,9 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     # Bug #9279, len(toOpenArray()) has to work:
     if a.kind in nkCallKinds and a[0].kind == nkSym and a[0].sym.magic == mSlice:
       # magic: pass slice to openArray:
-      var m: TLoc = default(TLoc)
-      var b, c: TLoc = default(TLoc)
-      initLocExpr(p, a[1], m)
-      initLocExpr(p, a[2], b)
-      initLocExpr(p, a[3], c)
+      var m = initLocExpr(p, a[1])
+      var b = initLocExpr(p, a[2])
+      var c = initLocExpr(p, a[3])
       if optBoundsCheck in p.options:
         genBoundsCheck(p, m, b, c)
       if op == mHigh:
@@ -1907,15 +1866,14 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     if op == mHigh: unaryExpr(p, e, d, "($1 ? (#nimCStrLen($1)-1) : -1)")
     else: unaryExpr(p, e, d, "($1 ? #nimCStrLen($1) : 0)")
   of tyString:
-    var a: TLoc = default(TLoc)
-    initLocExpr(p, e[1], a)
+    var a: TLoc = initLocExpr(p, e[1])
     var x = lenExpr(p, a)
     if op == mHigh: x = "($1-1)" % [x]
     putIntoDest(p, d, e, x)
   of tySequence:
     # we go through a temporary here because people write bullshit code.
-    var a, tmp: TLoc = default(TLoc)
-    initLocExpr(p, e[1], a)
+    var tmp: TLoc = default(TLoc)
+    var a = initLocExpr(p, e[1])
     getIntTemp(p, tmp)
     var x = lenExpr(p, a)
     if op == mHigh: x = "($1-1)" % [x]
@@ -1939,15 +1897,14 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
     e[1] = makeAddr(e[1], p.module.idgen)
     genCall(p, e, d)
     return
-  var a, b, call: TLoc = default(TLoc)
   assert(d.k == locNone)
   var x = e[1]
   if x.kind in {nkAddr, nkHiddenAddr}: x = x[0]
-  initLocExpr(p, x, a)
-  initLocExpr(p, e[2], b)
+  var a = initLocExpr(p, x)
+  var b = initLocExpr(p, e[2])
   let t = skipTypes(e[1].typ, {tyVar})
 
-  initLoc(call, locCall, e, OnHeap)
+  var call = initLoc(locCall, e, OnHeap)
   if not p.module.compileToCpp:
     const setLenPattern = "($3) #setLengthSeqV2(($1)?&($1)->Sup:NIM_NIL, $4, $2)"
     call.r = ropecg(p.module, setLenPattern, [
@@ -1967,12 +1924,11 @@ proc genSetLengthStr(p: BProc, e: PNode, d: var TLoc) =
   if optSeqDestructors in p.config.globalOptions:
     binaryStmtAddr(p, e, d, "setLengthStrV2")
   else:
-    var a, b, call: TLoc = default(TLoc)
     if d.k != locNone: internalError(p.config, e.info, "genSetLengthStr")
-    initLocExpr(p, e[1], a)
-    initLocExpr(p, e[2], b)
+    var a = initLocExpr(p, e[1])
+    var b = initLocExpr(p, e[2])
 
-    initLoc(call, locCall, e, OnHeap)
+    var call = initLoc(locCall, e, OnHeap)
     call.r = ropecg(p.module, "#setLengthStr($1, $2)", [
         rdLoc(a), rdLoc(b)])
     genAssignment(p, a, call, {})
@@ -1985,11 +1941,10 @@ proc genSwap(p: BProc, e: PNode, d: var TLoc) =
   # b = temp
   cowBracket(p, e[1])
   cowBracket(p, e[2])
-  var a, b = default(TLoc)
   var tmp: TLoc
   getTemp(p, skipTypes(e[1].typ, abstractVar), tmp)
-  initLocExpr(p, e[1], a) # eval a
-  initLocExpr(p, e[2], b) # eval b
+  var a = initLocExpr(p, e[1]) # eval a
+  var b = initLocExpr(p, e[2]) # eval b
   genAssignment(p, tmp, a, {})
   genAssignment(p, a, b, {})
   genAssignment(p, b, tmp, {})
@@ -2031,16 +1986,15 @@ proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc) =
   else: binaryExprIn(p, e, a, b, d, "(($1[(NU)($2)>>3] &(1U<<((NU)($2)&7U)))!=0)")
 
 template binaryStmtInExcl(p: BProc, e: PNode, d: var TLoc, frmt: string) =
-  var a, b: TLoc = default(TLoc)
   assert(d.k == locNone)
-  initLocExpr(p, e[1], a)
-  initLocExpr(p, e[2], b)
+  var a = initLocExpr(p, e[1])
+  var b = initLocExpr(p, e[2])
   var elem = newRopeAppender()
   rdSetElemLoc(p.config, b, a.t, elem)
   lineF(p, cpsStmts, frmt, [rdLoc(a), elem])
 
 proc genInOp(p: BProc, e: PNode, d: var TLoc) =
-  var a, b, x, y: TLoc = default(TLoc)
+  var a, b, x, y: TLoc
   if (e[1].kind == nkCurly) and fewCmps(p.config, e[1]):
     # a set constructor but not a constant set:
     # do not emit the set, but generate a bunch of comparisons; and if we do
@@ -2050,19 +2004,19 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
                e[2][0]
              else:
                e[2]
-    initLocExpr(p, ea, a)
-    initLoc(b, locExpr, e, OnUnknown)
+    a = initLocExpr(p, ea)
+    b = initLoc(locExpr, e, OnUnknown)
     if e[1].len > 0:
       b.r = rope("(")
       for i in 0..<e[1].len:
         let it = e[1][i]
         if it.kind == nkRange:
-          initLocExpr(p, it[0], x)
-          initLocExpr(p, it[1], y)
+          x = initLocExpr(p, it[0])
+          y = initLocExpr(p, it[1])
           b.r.addf("$1 >= $2 && $1 <= $3",
                [rdCharLoc(a), rdCharLoc(x), rdCharLoc(y)])
         else:
-          initLocExpr(p, it, x)
+          x = initLocExpr(p, it)
           b.r.addf("$1 == $2", [rdCharLoc(a), rdCharLoc(x)])
         if i < e[1].len - 1: b.r.add(" || ")
       b.r.add(")")
@@ -2073,8 +2027,8 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
   else:
     assert(e[1].typ != nil)
     assert(e[2].typ != nil)
-    initLocExpr(p, e[1], a)
-    initLocExpr(p, e[2], b)
+    a = initLocExpr(p, e[1])
+    b = initLocExpr(p, e[2])
     genInExprAux(p, e, a, b, d)
 
 proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
@@ -2090,7 +2044,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
       "&",
       "|",
       "& ~"]
-  var a, b = default(TLoc)
+  var a, b: TLoc
   var i: TLoc
   var setType = skipTypes(e[1].typ, abstractVar)
   var size = int(getSize(p.config, setType))
@@ -2128,13 +2082,12 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     of mIncl: binaryStmtInExcl(p, e, d, "$1[(NU)($2)>>3] |=(1U<<($2&7U));$n")
     of mExcl: binaryStmtInExcl(p, e, d, "$1[(NU)($2)>>3] &= ~(1U<<($2&7U));$n")
     of mCard:
-      var a: TLoc = default(TLoc)
-      initLocExpr(p, e[1], a)
+      var a: TLoc = initLocExpr(p, e[1])
       putIntoDest(p, d, e, ropecg(p.module, "#cardSet($1, $2)", [addrLoc(p.config, a), size]))
     of mLtSet, mLeSet:
       getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), i) # our counter
-      initLocExpr(p, e[1], a)
-      initLocExpr(p, e[2], b)
+      a = initLocExpr(p, e[1])
+      b = initLocExpr(p, e[2])
       if d.k == locNone: getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyBool), d)
       if op == mLtSet:
         linefmt(p, cpsStmts, lookupOpr[mLtSet],
@@ -2143,17 +2096,16 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
         linefmt(p, cpsStmts, lookupOpr[mLeSet],
            [rdLoc(i), size, rdLoc(d), rdLoc(a), rdLoc(b)])
     of mEqSet:
-      var a, b: TLoc = default(TLoc)
       assert(e[1].typ != nil)
       assert(e[2].typ != nil)
-      initLocExpr(p, e[1], a)
-      initLocExpr(p, e[2], b)
+      var a = initLocExpr(p, e[1])
+      var b = initLocExpr(p, e[2])
       putIntoDest(p, d, e, ropecg(p.module, "(#nimCmpMem($1, $2, $3)==0)", [a.rdCharLoc, b.rdCharLoc, size]))
     of mMulSet, mPlusSet, mMinusSet:
       # we inline the simple for loop for better code generation:
       getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), i) # our counter
-      initLocExpr(p, e[1], a)
-      initLocExpr(p, e[2], b)
+      a = initLocExpr(p, e[1])
+      b = initLocExpr(p, e[2])
       if d.k == locNone: getTemp(p, setType, d)
       lineF(p, cpsStmts,
            "for ($1 = 0; $1 < $2; $1++) $n" &
@@ -2171,8 +2123,7 @@ proc genSomeCast(p: BProc, e: PNode, d: var TLoc) =
     ValueTypes = {tyTuple, tyObject, tyArray, tyOpenArray, tyVarargs, tyUncheckedArray}
   # we use whatever C gives us. Except if we have a value-type, we need to go
   # through its address:
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, e[1], a)
+  var a: TLoc = initLocExpr(p, e[1])
   let etyp = skipTypes(e.typ, abstractRange+{tyOwned})
   let srcTyp = skipTypes(e[1].typ, abstractRange)
   if etyp.kind in ValueTypes and lfIndirect notin a.flags:
@@ -2232,9 +2183,8 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
     genSomeCast(p, e, d)
 
 proc genRangeChck(p: BProc, n: PNode, d: var TLoc) =
-  var a: TLoc = default(TLoc)
+  var a: TLoc = initLocExpr(p, n[0])
   var dest = skipTypes(n.typ, abstractVar)
-  initLocExpr(p, n[0], a)
   if optRangeCheck notin p.options or (dest.kind in {tyUInt..tyUInt64} and
       checkUnsignedConversions notin p.config.legacyFeatures):
     discard "no need to generate a check because it was disabled"
@@ -2287,31 +2237,29 @@ proc genConv(p: BProc, e: PNode, d: var TLoc) =
     genSomeCast(p, e, d)
 
 proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) =
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, n[0], a)
+  var a: TLoc = initLocExpr(p, n[0])
   putIntoDest(p, d, n,
               ropecg(p.module, "#nimToCStringConv($1)", [rdLoc(a)]),
 #                "($1 ? $1->data : (NCSTRING)\"\")" % [a.rdLoc],
               a.storage)
 
 proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, n[0], a)
+  var a: TLoc = initLocExpr(p, n[0])
   putIntoDest(p, d, n,
               ropecg(p.module, "#cstrToNimstr($1)", [rdLoc(a)]),
               a.storage)
   gcUsage(p.config, n)
 
 proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
-  var x: TLoc = default(TLoc)
+  var x: TLoc
   var a = e[1]
   var b = e[2]
   if a.kind in {nkStrLit..nkTripleStrLit} and a.strVal == "":
-    initLocExpr(p, e[2], x)
+    x = initLocExpr(p, e[2])
     putIntoDest(p, d, e,
       ropecg(p.module, "($1 == 0)", [lenExpr(p, x)]))
   elif b.kind in {nkStrLit..nkTripleStrLit} and b.strVal == "":
-    initLocExpr(p, e[1], x)
+    x = initLocExpr(p, e[1])
     putIntoDest(p, d, e,
       ropecg(p.module, "($1 == 0)", [lenExpr(p, x)]))
   else:
@@ -2320,11 +2268,10 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
 proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
   if {optNaNCheck, optInfCheck} * p.options != {}:
     const opr: array[mAddF64..mDivF64, string] = ["+", "-", "*", "/"]
-    var a, b: TLoc = default(TLoc)
     assert(e[1].typ != nil)
     assert(e[2].typ != nil)
-    initLocExpr(p, e[1], a)
-    initLocExpr(p, e[2], b)
+    var a = initLocExpr(p, e[1])
+    var b = initLocExpr(p, e[2])
     putIntoDest(p, d, e, ropecg(p.module, "(($4)($2) $1 ($4)($3))",
                               [opr[m], rdLoc(a), rdLoc(b),
                               getSimpleTypeDesc(p.module, e[1].typ)]))
@@ -2345,23 +2292,21 @@ proc skipAddr(n: PNode): PNode =
   result = if n.kind in {nkAddr, nkHiddenAddr}: n[0] else: n
 
 proc genWasMoved(p: BProc; n: PNode) =
-  var a: TLoc = default(TLoc)
+  var a: TLoc
   let n1 = n[1].skipAddr
   if p.withinBlockLeaveActions > 0 and notYetAlive(n1):
     discard
   else:
-    initLocExpr(p, n1, a, {lfEnforceDeref})
+    a = initLocExpr(p, n1, {lfEnforceDeref})
     resetLoc(p, a)
     #linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n",
     #  [addrLoc(p.config, a), getTypeDesc(p.module, a.t)])
 
 proc genMove(p: BProc; n: PNode; d: var TLoc) =
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, n[1].skipAddr, a)
+  var a: TLoc = initLocExpr(p, n[1].skipAddr)
   if n.len == 4:
     # generated by liftdestructors:
-    var src: TLoc = default(TLoc)
-    initLocExpr(p, n[2], src)
+    var src: TLoc = initLocExpr(p, n[2])
     linefmt(p, cpsStmts, "if ($1.p != $2.p) {", [rdLoc(a), rdLoc(src)])
     genStmts(p, n[3])
     linefmt(p, cpsStmts, "}$n$1.len = $2.len; $1.p = $2.p;$n", [rdLoc(a), rdLoc(src)])
@@ -2387,8 +2332,7 @@ proc genDestroy(p: BProc; n: PNode) =
     let t = arg.typ.skipTypes(abstractInst)
     case t.kind
     of tyString:
-      var a: TLoc = default(TLoc)
-      initLocExpr(p, arg, a)
+      var a: TLoc = initLocExpr(p, arg)
       if optThreads in p.config.globalOptions:
         linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
           " #deallocShared($1.p);$n" &
@@ -2398,8 +2342,7 @@ proc genDestroy(p: BProc; n: PNode) =
           " #dealloc($1.p);$n" &
           "}$n", [rdLoc(a)])
     of tySequence:
-      var a: TLoc = default(TLoc)
-      initLocExpr(p, arg, a)
+      var a: TLoc = initLocExpr(p, arg)
       linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
         " #alignedDealloc($1.p, NIM_ALIGNOF($2));$n" &
         "}$n",
@@ -2416,8 +2359,7 @@ proc genDispose(p: BProc; n: PNode) =
   when false:
     let elemType = n[1].typ.skipTypes(abstractVar).lastSon
 
-    var a: TLoc = default(TLoc)
-    initLocExpr(p, n[1].skipAddr, a)
+    var a: TLoc = initLocExpr(p, n[1].skipAddr)
 
     if isFinal(elemType):
       if elemType.destructor != nil:
@@ -2469,11 +2411,10 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     if optOverflowCheck notin p.options or underlying.kind in {tyUInt..tyUInt64}:
       binaryStmt(p, e, d, opr[op])
     else:
-      var a, b: TLoc = default(TLoc)
       assert(e[1].typ != nil)
       assert(e[2].typ != nil)
-      initLocExpr(p, e[1], a)
-      initLocExpr(p, e[2], b)
+      var a = initLocExpr(p, e[1])
+      var b = initLocExpr(p, e[2])
 
       let ranged = skipTypes(e[1].typ, {tyGenericInst, tyAlias, tySink, tyVar, tyLent, tyDistinct})
       let res = binaryArithOverflowRaw(p, ranged, a, b,
@@ -2487,10 +2428,9 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     if optSeqDestructors in p.config.globalOptions:
       binaryStmtAddr(p, e, d, "nimAddCharV1")
     else:
-      var dest, b, call: TLoc = default(TLoc)
-      initLoc(call, locCall, e, OnHeap)
-      initLocExpr(p, e[1], dest)
-      initLocExpr(p, e[2], b)
+      var call = initLoc(locCall, e, OnHeap)
+      var dest = initLocExpr(p, e[1])
+      var b = initLocExpr(p, e[2])
       call.r = ropecg(p.module, "#addChar($1, $2)", [rdLoc(dest), rdLoc(b)])
       genAssignment(p, dest, call, {})
   of mAppendStrStr: genStrAppend(p, e, d)
@@ -2525,8 +2465,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   of mNew: genNew(p, e)
   of mNewFinalize:
     if optTinyRtti in p.config.globalOptions:
-      var a: TLoc = default(TLoc)
-      initLocExpr(p, e[1], a)
+      var a: TLoc = initLocExpr(p, e[1])
       rawGenNew(p, a, "", needsInit = true)
       gcUsage(p.config, e)
     else:
@@ -2620,10 +2559,9 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
       localError(p.config, e.info,
         "for --mm:arc|atomicArc|orc 'deepcopy' support has to be enabled with --deepcopy:on")
 
-    var a, b: TLoc = default(TLoc)
     let x = if e[1].kind in {nkAddr, nkHiddenAddr}: e[1][0] else: e[1]
-    initLocExpr(p, x, a)
-    initLocExpr(p, e[2], b)
+    var a = initLocExpr(p, x)
+    var b = initLocExpr(p, e[2])
     genDeepCopy(p, a, b)
   of mDotDot, mEqCString: genCall(p, e, d)
   of mWasMoved: genWasMoved(p, e)
@@ -2646,7 +2584,7 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
   # nimZeroMem(tmp, sizeof(tmp)); inclRange(tmp, a, b); incl(tmp, c);
   # incl(tmp, d); incl(tmp, e); inclRange(tmp, f, g);
   var
-    a, b = default(TLoc)
+    a, b: TLoc
   var idx: TLoc
   if nfAllConst in e.flags:
     var elem = newRopeAppender()
@@ -2661,8 +2599,8 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
       for it in e.sons:
         if it.kind == nkRange:
           getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), idx) # our counter
-          initLocExpr(p, it[0], a)
-          initLocExpr(p, it[1], b)
+          a = initLocExpr(p, it[0])
+          b = initLocExpr(p, it[1])
           var aa = newRopeAppender()
           rdSetElemLoc(p.config, a, e.typ, aa)
           var bb = newRopeAppender()
@@ -2671,7 +2609,7 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
               "$2[(NU)($1)>>3] |=(1U<<((NU)($1)&7U));$n", [rdLoc(idx), rdLoc(d),
               aa, bb])
         else:
-          initLocExpr(p, it, a)
+          a = initLocExpr(p, it)
           var aa = newRopeAppender()
           rdSetElemLoc(p.config, a, e.typ, aa)
           lineF(p, cpsStmts, "$1[(NU)($2)>>3] |=(1U<<((NU)($2)&7U));$n",
@@ -2683,8 +2621,8 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
       for it in e.sons:
         if it.kind == nkRange:
           getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), idx) # our counter
-          initLocExpr(p, it[0], a)
-          initLocExpr(p, it[1], b)
+          a = initLocExpr(p, it[0])
+          b = initLocExpr(p, it[1])
           var aa = newRopeAppender()
           rdSetElemLoc(p.config, a, e.typ, aa)
           var bb = newRopeAppender()
@@ -2694,7 +2632,7 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
               "$2 |=(($5)(1)<<(($1)%(sizeof($5)*8)));$n", [
               rdLoc(idx), rdLoc(d), aa, bb, rope(ts)])
         else:
-          initLocExpr(p, it, a)
+          a = initLocExpr(p, it)
           var aa = newRopeAppender()
           rdSetElemLoc(p.config, a, e.typ, aa)
           lineF(p, cpsStmts,
@@ -2702,7 +2640,7 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
                [rdLoc(d), aa, rope(ts)])
 
 proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
-  var rec: TLoc = default(TLoc)
+  var rec: TLoc
   if not handleConstExpr(p, n, d):
     let t = n.typ
     discard getTypeDesc(p.module, t) # so that any fields are initialized
@@ -2719,7 +2657,7 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
     for i in 0..<n.len:
       var it = n[i]
       if it.kind == nkExprColonExpr: it = it[1]
-      initLoc(rec, locExpr, it, dest[].storage)
+      rec = initLoc(locExpr, it, dest[].storage)
       rec.r = "$1.Field$2" % [rdLoc(dest[]), rope(i)]
       rec.flags.incl(lfEnforceDeref)
       expr(p, it, rec)
@@ -2747,9 +2685,8 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
     putIntoDest(p, d, n, tmp, OnStatic)
   else:
     var tmp: TLoc
-    var a, b = default(TLoc)
-    initLocExpr(p, n[0], a)
-    initLocExpr(p, n[1], b)
+    var a = initLocExpr(p, n[0])
+    var b = initLocExpr(p, n[1])
     if n[0].skipConv.kind == nkClosure:
       internalError(p.config, n.info, "closure to closure created")
     # tasyncawait.nim breaks with this optimization:
@@ -2764,11 +2701,11 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
       putLocIntoDest(p, d, tmp)
 
 proc genArrayConstr(p: BProc, n: PNode, d: var TLoc) =
-  var arr: TLoc = default(TLoc)
+  var arr: TLoc
   if not handleConstExpr(p, n, d):
     if d.k == locNone: getTemp(p, n.typ, d)
     for i in 0..<n.len:
-      initLoc(arr, locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), d.storage)
+      arr = initLoc(locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), d.storage)
       var lit = newRopeAppender()
       intLiteral(i, lit)
       arr.r = "$1[$2]" % [rdLoc(d), lit]
@@ -2812,8 +2749,7 @@ proc genStmtList(p: BProc, n: PNode) =
 from parampatterns import isLValue
 
 proc upConv(p: BProc, n: PNode, d: var TLoc) =
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, n[0], a)
+  var a: TLoc = initLocExpr(p, n[0])
   let dest = skipTypes(n.typ, abstractPtrs)
   if optObjCheck in p.options and not isObjLackingTypeField(dest):
     var nilCheck = ""
@@ -2864,16 +2800,14 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) =
     # (see bug #837). However sometimes using a temporary is not correct:
     # init(TFigure(my)) # where it is passed to a 'var TFigure'. We test
     # this by ensuring the destination is also a pointer:
-    var a: TLoc = default(TLoc)
-    initLocExpr(p, arg, a)
+    var a: TLoc = initLocExpr(p, arg)
     putIntoDest(p, d, n,
               "(*(($1*) (&($2))))" % [getTypeDesc(p.module, n.typ), rdLoc(a)], a.storage)
   elif p.module.compileToCpp:
     # C++ implicitly downcasts for us
     expr(p, arg, d)
   else:
-    var a: TLoc = default(TLoc)
-    initLocExpr(p, arg, a)
+    var a: TLoc = initLocExpr(p, arg)
     var r = rdLoc(a) & (if isRef: "->Sup" else: ".Sup")
     for i in 2..abs(inheritanceDiff(dest, src)): r.add(".Sup")
     putIntoDest(p, d, n, if isRef: "&" & r else: r, a.storage)
@@ -3156,8 +3090,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
     let ex = n[0]
     if ex.kind != nkEmpty:
       genLineDir(p, n)
-      var a: TLoc = default(TLoc)
-      initLocExprSingleUse(p, ex, a)
+      var a: TLoc = initLocExprSingleUse(p, ex)
       line(p, cpsStmts, "(void)(" & a.r & ");\L")
   of nkAsmStmt: genAsmStmt(p, n)
   of nkTryStmt, nkHiddenTryStmt:
@@ -3478,12 +3411,10 @@ proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; resul
         if n[0].kind == nkNilLit:
           result.add "{NIM_NIL,NIM_NIL}"
         else:
-          var d: TLoc = default(TLoc)
-          initLocExpr(p, n[0], d)
+          var d: TLoc = initLocExpr(p, n[0])
           result.add "{(($1) $2),NIM_NIL}" % [getClosureType(p.module, typ, clHalfWithEnv), rdLoc(d)]
       else:
-        var d: TLoc = default(TLoc)
-        initLocExpr(p, n, d)
+        var d: TLoc = initLocExpr(p, n)
         result.add rdLoc(d)
     of tyArray, tyVarargs:
       genConstSimpleList(p, n, isConst, result)
@@ -3511,10 +3442,8 @@ proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; resul
       if optSeqDestructors in p.config.globalOptions and n.kind != nkNilLit and ty == tyString:
         genStringLiteralV2Const(p.module, n, isConst, result)
       else:
-        var d: TLoc = default(TLoc)
-        initLocExpr(p, n, d)
+        var d: TLoc = initLocExpr(p, n)
         result.add rdLoc(d)
     else:
-      var d: TLoc = default(TLoc)
-      initLocExpr(p, n, d)
+      var d: TLoc = initLocExpr(p, n)
       result.add rdLoc(d)
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 1751321f3..b79eaf346 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -72,7 +72,6 @@ template startBlock(p: BProc, start: FormatStr = "{$n",
 proc endBlock(p: BProc)
 
 proc genVarTuple(p: BProc, n: PNode) =
-  var tup, field: TLoc = default(TLoc)
   if n.kind != nkVarTuple: internalError(p.config, n.info, "genVarTuple")
 
   # if we have a something that's been captured, use the lowering instead:
@@ -96,7 +95,7 @@ proc genVarTuple(p: BProc, n: PNode) =
     startBlock(p)
 
   genLineDir(p, n)
-  initLocExpr(p, n[^1], tup)
+  var tup = initLocExpr(p, n[^1])
   var t = tup.t.skipTypes(abstractInst)
   for i in 0..<n.len-2:
     let vn = n[i]
@@ -109,7 +108,7 @@ proc genVarTuple(p: BProc, n: PNode) =
     else:
       assignLocalVar(p, vn)
       initLocalVar(p, v, immediateAsgn=isAssignedImmediately(p.config, n[^1]))
-    initLoc(field, locExpr, vn, tup.storage)
+    var field = initLoc(locExpr, vn, tup.storage)
     if t.kind == tyTuple:
       field.r = "$1.Field$2" % [rdLoc(tup), rope(i)]
     else:
@@ -245,8 +244,7 @@ proc genGotoState(p: BProc, n: PNode) =
   # switch (x.state) {
   #   case 0: goto STATE0;
   # ...
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, n[0], a)
+  var a: TLoc = initLocExpr(p, n[0])
   lineF(p, cpsStmts, "switch ($1) {$n", [rdLoc(a)])
   p.flags.incl beforeRetNeeded
   lineF(p, cpsStmts, "case -1:$n", [])
@@ -264,14 +262,14 @@ proc genGotoState(p: BProc, n: PNode) =
   lineF(p, cpsStmts, "}$n", [])
 
 proc genBreakState(p: BProc, n: PNode, d: var TLoc) =
-  var a: TLoc = default(TLoc)
-  initLoc(d, locExpr, n, OnUnknown)
+  var a: TLoc
+  d = initLoc(locExpr, n, OnUnknown)
 
   if n[0].kind == nkClosure:
-    initLocExpr(p, n[0][1], a)
+    a = initLocExpr(p, n[0][1])
     d.r = "(((NI*) $1)[1] < 0)" % [rdLoc(a)]
   else:
-    initLocExpr(p, n[0], a)
+    a = initLocExpr(p, n[0])
     # the environment is guaranteed to contain the 'state' field at offset 1:
     d.r = "((((NI*) $1.ClE_0)[1]) < 0)" % [rdLoc(a)]
 
@@ -342,7 +340,7 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
       # Only do this for complex types that may need a call to `objectInit`
       if sfThread in v.flags and emulatedThreadVars(p.config) and
         isComplexValueType(v.typ):
-        initLocExprSingleUse(p.module.preInitProc, vn, loc)
+        loc = initLocExprSingleUse(p.module.preInitProc, vn)
       genObjectInit(p.module.preInitProc, cpsInit, v.typ, loc, constructObj)
     # Alternative construction using default constructor (which may zeromem):
     # if sfImportc notin v.flags: constructLoc(p.module.preInitProc, v.loc)
@@ -358,12 +356,12 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
       # generate better code here: 'Foo f = x;'
       genLineDir(p, vn)
       var decl = localVarDecl(p, vn)
-      var tmp: TLoc = default(TLoc)
+      var tmp: TLoc
       if isCppCtorCall:
         genCppVarForCtor(p, v, vn, value, decl)
         line(p, cpsStmts, decl)
       else:
-        initLocExprSingleUse(p, value, tmp)
+        tmp = initLocExprSingleUse(p, value)
         lineF(p, cpsStmts, "$# = $#;\n", [decl, tmp.rdLoc])
       return
     assignLocalVar(p, vn)
@@ -409,8 +407,7 @@ proc genSingleVar(p: BProc, a: PNode) =
 
 proc genClosureVar(p: BProc, a: PNode) =
   var immediateAsgn = a[2].kind != nkEmpty
-  var v: TLoc
-  initLocExpr(p, a[0], v)
+  var v: TLoc = initLocExpr(p, a[0])
   genLineDir(p, a)
   if immediateAsgn:
     loadInto(p, a[0], a[2], v)
@@ -442,7 +439,7 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
   #  { elsePart }
   #  Lend:
   var
-    a: TLoc = default(TLoc)
+    a: TLoc
     lelse: TLabel
   if not isEmptyType(n.typ) and d.k == locNone:
     getTemp(p, n.typ, d)
@@ -453,7 +450,7 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
     if d.k == locTemp and isEmptyType(n.typ): d.k = locNone
     if it.len == 2:
       startBlock(p)
-      initLocExprSingleUse(p, it[0], a)
+      a = initLocExprSingleUse(p, it[0])
       lelse = getLabel(p)
       inc(p.labels)
       lineF(p, cpsStmts, "if (!$1) goto $2;$n",
@@ -555,8 +552,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
     genStmts(p, n[j])
 
   let caseStmt = n[casePos]
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, caseStmt[0], a)
+  var a: TLoc = initLocExpr(p, caseStmt[0])
   # first goto:
   lineF(p, cpsStmts, "goto *$#[$#];$n", [tmp, a.rdLoc])
 
@@ -594,8 +590,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
       else:
         genStmts(p, it)
 
-    var a: TLoc = default(TLoc)
-    initLocExpr(p, caseStmt[0], a)
+    var a: TLoc = initLocExpr(p, caseStmt[0])
     lineF(p, cpsStmts, "goto *$#[$#];$n", [tmp, a.rdLoc])
     endBlock(p)
 
@@ -607,7 +602,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
   # we don't generate labels here as for example GCC would produce
   # significantly worse code
   var
-    a: TLoc = default(TLoc)
+    a: TLoc
   assert(t.len == 2)
   inc(p.withinLoop)
   genLineDir(p, t)
@@ -623,7 +618,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
     else:
       p.breakIdx = startBlock(p, "while (1) {$n")
       p.blocks[p.breakIdx].isLoop = true
-      initLocExpr(p, t[0], a)
+      a = initLocExpr(p, t[0])
       if (t[0].kind != nkIntLit) or (t[0].intVal == 0):
         lineF(p, cpsStmts, "if (!$1) goto ", [rdLoc(a)])
         assignLabel(p.blocks[p.breakIdx], p.s(cpsStmts))
@@ -662,14 +657,13 @@ proc genParForStmt(p: BProc, t: PNode) =
 
   preserveBreakIdx:
     let forLoopVar = t[0].sym
-    var rangeA, rangeB: TLoc = default(TLoc)
     assignLocalVar(p, t[0])
     #initLoc(forLoopVar.loc, locLocalVar, forLoopVar.typ, onStack)
     #discard mangleName(forLoopVar)
     let call = t[1]
     assert(call.len == 4 or call.len == 5)
-    initLocExpr(p, call[1], rangeA)
-    initLocExpr(p, call[2], rangeB)
+    var rangeA = initLocExpr(p, call[1])
+    var rangeB = initLocExpr(p, call[2])
 
     # $n at the beginning because of #9710
     if call.len == 4: # procName(a, b, annotation)
@@ -686,8 +680,7 @@ proc genParForStmt(p: BProc, t: PNode) =
                     rangeA.rdLoc, rangeB.rdLoc,
                     call[3].getStr.rope])
     else: # `||`(a, b, step, annotation)
-      var step: TLoc = default(TLoc)
-      initLocExpr(p, call[3], step)
+      var step: TLoc = initLocExpr(p, call[3])
       lineF(p, cpsStmts, "$n#pragma omp $5$n" &
                     "for ($1 = $2; $1 <= $3; $1 += $4)",
                     [forLoopVar.loc.rdLoc,
@@ -757,8 +750,7 @@ proc raiseInstr(p: BProc; result: var Rope) =
 
 proc genRaiseStmt(p: BProc, t: PNode) =
   if t[0].kind != nkEmpty:
-    var a: TLoc = default(TLoc)
-    initLocExprSingleUse(p, t[0], a)
+    var a: TLoc = initLocExprSingleUse(p, t[0])
     finallyActions(p)
     var e = rdLoc(a)
     discard getTypeDesc(p.module, t[0].typ)
@@ -785,15 +777,15 @@ proc genRaiseStmt(p: BProc, t: PNode) =
 
 template genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
                           rangeFormat, eqFormat: FormatStr, labl: TLabel) =
-  var x, y: TLoc = default(TLoc)
+  var x, y: TLoc
   for i in 0..<b.len - 1:
     if b[i].kind == nkRange:
-      initLocExpr(p, b[i][0], x)
-      initLocExpr(p, b[i][1], y)
+      x = initLocExpr(p, b[i][0])
+      y = initLocExpr(p, b[i][1])
       lineCg(p, cpsStmts, rangeFormat,
            [rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl])
     else:
-      initLocExpr(p, b[i], x)
+      x = initLocExpr(p, b[i])
       lineCg(p, cpsStmts, eqFormat, [rdCharLoc(e), rdCharLoc(x), labl])
 
 proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc,
@@ -835,18 +827,17 @@ template genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
 
 template genCaseGeneric(p: BProc, t: PNode, d: var TLoc,
                     rangeFormat, eqFormat: FormatStr) =
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, t[0], a)
+  var a: TLoc = initLocExpr(p, t[0])
   var lend = genIfForCaseUntil(p, t, d, rangeFormat, eqFormat, t.len-1, a)
   fixLabel(p, lend)
 
 proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
                          stringKind: TTypeKind,
                          branches: var openArray[Rope]) =
-  var x: TLoc = default(TLoc)
+  var x: TLoc
   for i in 0..<b.len - 1:
     assert(b[i].kind != nkRange)
-    initLocExpr(p, b[i], x)
+    x = initLocExpr(p, b[i])
     var j: int = 0
     case b[i].kind
     of nkStrLit..nkTripleStrLit:
@@ -870,8 +861,7 @@ proc genStringCase(p: BProc, t: PNode, stringKind: TTypeKind, d: var TLoc) =
     var bitMask = math.nextPowerOfTwo(strings) - 1
     var branches: seq[Rope]
     newSeq(branches, bitMask + 1)
-    var a: TLoc = default(TLoc)
-    initLocExpr(p, t[0], a) # fist pass: generate ifs+goto:
+    var a: TLoc = initLocExpr(p, t[0]) # first pass: generate ifs+goto:
     var labId = p.labels
     for i in 1..<t.len:
       inc(p.labels)
@@ -951,8 +941,7 @@ proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
   var splitPoint = ifSwitchSplitPoint(p, n)
 
   # generate if part (might be empty):
-  var a: TLoc = default(TLoc)
-  initLocExpr(p, n[0], a)
+  var a: TLoc = initLocExpr(p, n[0])
   var lend = if splitPoint > 0: genIfForCaseUntil(p, n, d,
                     rangeFormat = "if ($1 >= $2 && $1 <= $3) goto $4;$n",
                     eqFormat = "if ($1 == $2) goto $3;$n",
@@ -1495,8 +1484,7 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false; result: var Rope) =
     of nkSym:
       var sym = it.sym
       if sym.kind in {skProc, skFunc, skIterator, skMethod}:
-        var a: TLoc = default(TLoc)
-        initLocExpr(p, it, a)
+        var a: TLoc = initLocExpr(p, it)
         res.add($rdLoc(a))
       elif sym.kind == skType:
         res.add($getTypeDesc(p.module, sym.typ))
@@ -1508,8 +1496,7 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false; result: var Rope) =
       res.add($getTypeDesc(p.module, it.typ))
     else:
       discard getTypeDesc(p.module, skipTypes(it.typ, abstractPtrs))
-      var a: TLoc = default(TLoc)
-      initLocExpr(p, it, a)
+      var a: TLoc = initLocExpr(p, it)
       res.add($a.rdLoc)
 
   if isAsmStmt and hasGnuAsm in CC[p.config.cCompiler].props:
@@ -1611,11 +1598,10 @@ when false:
     expr(p, call, d)
 
 proc asgnFieldDiscriminant(p: BProc, e: PNode) =
-  var a = default(TLoc)
   var tmp: TLoc
   var dotExpr = e[0]
   if dotExpr.kind == nkCheckedFieldExpr: dotExpr = dotExpr[0]
-  initLocExpr(p, e[0], a)
+  var a = initLocExpr(p, e[0])
   getTemp(p, a.t, tmp)
   expr(p, e[1], tmp)
   if p.inUncheckedAssignSection == 0:
@@ -1634,9 +1620,8 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
   else:
     let le = e[0]
     let ri = e[1]
-    var a: TLoc = default(TLoc)
+    var a: TLoc = initLoc(locNone, le, OnUnknown)
     discard getTypeDesc(p.module, le.typ.skipTypes(skipPtrs), dkVar)
-    initLoc(a, locNone, le, OnUnknown)
     a.flags.incl(lfEnforceDeref)
     a.flags.incl(lfPrepareForMutation)
     genLineDir(p, le) # it can be a nkBracketExpr, which may raise
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index af30f546e..f2483e2de 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -61,12 +61,10 @@ proc findPendingModule(m: BModule, s: PSym): BModule =
     var ms = getModule(s)
     result = m.g.modules[ms.position]
 
-proc initLoc(result: var TLoc, k: TLocKind, lode: PNode, s: TStorageLoc, flags: TLocFlags = {}) =
-  result.k = k
-  result.storage = s
-  result.lode = lode
-  result.r = ""
-  result.flags = flags
+proc initLoc(k: TLocKind, lode: PNode, s: TStorageLoc, flags: TLocFlags = {}): TLoc =
+  result = TLoc(k: k, storage: s, lode: lode,
+               r: "", flags: flags
+  )
 
 proc fillLoc(a: var TLoc, k: TLocKind, lode: PNode, r: Rope, s: TStorageLoc) {.inline.} =
   # fills the loc if it is not already initialized
@@ -483,8 +481,7 @@ proc resetLoc(p: BProc, loc: var TLoc) =
       linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", [rdLoc(loc)])
   elif not isComplexValueType(typ):
     if containsGcRef:
-      var nilLoc: TLoc
-      initLoc(nilLoc, locTemp, loc.lode, OnStack)
+      var nilLoc: TLoc = initLoc(locTemp, loc.lode, OnStack)
       nilLoc.r = rope("NIM_NIL")
       genRefAssign(p, loc, nilLoc)
     else:
@@ -514,8 +511,7 @@ proc constructLoc(p: BProc, loc: var TLoc, isTemp = false) =
     linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", [rdLoc(loc)])
   elif not isComplexValueType(typ):
     if containsGarbageCollectedRef(loc.t):
-      var nilLoc: TLoc
-      initLoc(nilLoc, locTemp, loc.lode, OnStack)
+      var nilLoc: TLoc = initLoc(locTemp, loc.lode, OnStack)
       nilLoc.r = rope("NIM_NIL")
       genRefAssign(p, loc, nilLoc)
     else:
@@ -731,12 +727,12 @@ proc genLiteral(p: BProc, n: PNode; result: var Rope)
 proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType; result: var Rope; argsCounter: var int)
 proc raiseExit(p: BProc)
 
-proc initLocExpr(p: BProc, e: PNode, result: var TLoc, flags: TLocFlags = {}) =
-  initLoc(result, locNone, e, OnUnknown, flags)
+proc initLocExpr(p: BProc, e: PNode, flags: TLocFlags = {}): TLoc =
+  result = initLoc(locNone, e, OnUnknown, flags)
   expr(p, e, result)
 
-proc initLocExprSingleUse(p: BProc, e: PNode, result: var TLoc) =
-  initLoc(result, locNone, e, OnUnknown)
+proc initLocExprSingleUse(p: BProc, e: PNode): TLoc =
+  result = initLoc(locNone, e, OnUnknown)
   if e.kind in nkCallKinds and (e[0].kind != nkSym or e[0].sym.magic == mNone):
     # We cannot check for tfNoSideEffect here because of mutable parameters.
     discard "bug #8202; enforce evaluation order for nested calls for C++ too"
@@ -827,8 +823,7 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
       var p = newProc(nil, m)
       p.options.excl optStackTrace
       p.flags.incl nimErrorFlagDisabled
-      var dest: TLoc
-      initLoc(dest, locTemp, lib.path, OnStack)
+      var dest: TLoc = initLoc(locTemp, lib.path, OnStack)
       dest.r = getTempName(m)
       appcg(m, m.s[cfsDynLibInit],"$1 $2;$n",
            [getTypeDesc(m, lib.path.typ, dkVar), rdLoc(dest)])
@@ -863,11 +858,10 @@ proc symInDynamicLib(m: BModule, sym: PSym) =
   inc(m.labels, 2)
   if isCall:
     let n = lib.path
-    var a: TLoc = default(TLoc)
-    initLocExpr(m.initProc, n[0], a)
+    var a: TLoc = initLocExpr(m.initProc, n[0])
     var params = rdLoc(a) & "("
     for i in 1..<n.len-1:
-      initLocExpr(m.initProc, n[i], a)
+      a = initLocExpr(m.initProc, n[i])
       params.add(rdLoc(a))
       params.add(", ")
     let load = "\t$1 = ($2) ($3$4));$n" %
@@ -1166,8 +1160,7 @@ proc genProcAux*(m: BModule, prc: PSym) =
       if sfNoInit in prc.flags: incl(res.flags, sfNoInit)
       if sfNoInit in prc.flags and p.module.compileToCpp and (let val = easyResultAsgn(procBody); val != nil):
         var decl = localVarDecl(p, resNode)
-        var a: TLoc = default(TLoc)
-        initLocExprSingleUse(p, val, a)
+        var a: TLoc = initLocExprSingleUse(p, val)
         linefmt(p, cpsStmts, "$1 = $2;$n", [decl, rdLoc(a)])
       else:
         # declare the result symbol: