summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim7
-rw-r--r--compiler/ccgexprs.nim151
-rw-r--r--compiler/ccgstmts.nim2
-rw-r--r--compiler/ccgtypes.nim6
-rw-r--r--compiler/cgen.nim12
-rw-r--r--compiler/rodread.nim4
-rw-r--r--compiler/rodwrite.nim4
-rw-r--r--lib/pure/asyncmacro.nim2
8 files changed, 96 insertions, 92 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 92abbb0ab..2b1871bb8 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -747,12 +747,13 @@ type
     OnUnknown,                # location is unknown (stack, heap or static)
     OnStatic,                 # in a static section
     OnStack,                  # location is on hardware stack
-    OnHeap                    # location is on heap or global
+    OnHeap,                   # location is on heap or global
                               # (reference counting needed)
+    OnHeapNew                 # location is on the heap and was just new()'ed
   TLocFlags* = set[TLocFlag]
   TLoc* = object
     k*: TLocKind              # kind of location
-    s*: TStorageLoc
+    storage*: TStorageLoc
     flags*: TLocFlags         # location's flags
     t*: PType                 # type of location
     r*: Rope                  # rope value of location (code generators)
@@ -1261,7 +1262,7 @@ proc newType*(kind: TTypeKind, owner: PSym): PType =
 
 proc mergeLoc(a: var TLoc, b: TLoc) =
   if a.k == low(a.k): a.k = b.k
-  if a.s == low(a.s): a.s = b.s
+  if a.storage == low(a.storage): a.storage = b.storage
   a.flags = a.flags + b.flags
   if a.t == nil: a.t = b.t
   if a.r == nil: a.r = b.r
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index f5c793d29..1064bf998 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -158,9 +158,9 @@ proc getStorageLoc(n: PNode): TStorageLoc =
   else: result = OnUnknown
 
 proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
-  if dest.s == OnStack or not usesNativeGC():
+  if dest.storage == OnStack or not usesNativeGC():
     linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
-  elif dest.s == OnHeap:
+  elif dest.storage in {OnHeap, OnHeapNew}:
     # location is on heap
     # now the writer barrier is inlined for performance:
     #
@@ -202,13 +202,13 @@ proc asgnComplexity(n: PNode): int =
 proc optAsgnLoc(a: TLoc, t: PType, field: Rope): TLoc =
   assert field != nil
   result.k = locField
-  result.s = a.s
+  result.storage = if a.storage == OnHeapNew: OnHeap else: a.storage
   result.t = t
   result.r = rdLoc(a) & "." & field
 
 proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   let newflags =
-    if src.s == OnStatic:
+    if src.storage == OnStatic:
       flags + {needToCopy}
     elif tfShallow in dest.t.flags:
       flags - {needToCopy}
@@ -225,7 +225,7 @@ proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
                       t: PNode, typ: PType) =
   if t == nil: return
   let newflags =
-    if src.s == OnStatic:
+    if src.storage == OnStatic:
       flags + {needToCopy}
     elif tfShallow in dest.t.flags:
       flags - {needToCopy}
@@ -250,7 +250,7 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   # (for objects, etc.):
   if needToCopy notin flags or
       tfShallow in skipTypes(dest.t, abstractVarRange).flags:
-    if dest.s == OnStack or not usesNativeGC():
+    if dest.storage == OnStack or not usesNativeGC():
       useStringh(p.module)
       linefmt(p, cpsStmts,
            "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
@@ -274,18 +274,18 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   of tyRef:
     genRefAssign(p, dest, src, flags)
   of tySequence:
-    if needToCopy notin flags and src.s != OnStatic:
+    if (needToCopy notin flags and src.storage != OnStatic) or src.storage == OnHeapNew:
       genRefAssign(p, dest, src, flags)
     else:
       linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
               addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t))
   of tyString:
-    if needToCopy notin flags and src.s != OnStatic:
+    if (needToCopy notin flags and src.storage != OnStatic) or src.storage == OnHeapNew:
       genRefAssign(p, dest, src, flags)
     else:
-      if dest.s == OnStack or not usesNativeGC():
+      if dest.storage == OnStack or not usesNativeGC():
         linefmt(p, cpsStmts, "$1 = #copyString($2);$n", dest.rdLoc, src.rdLoc)
-      elif dest.s == OnHeap:
+      elif dest.storage in {OnHeap, OnHeapNew}:
         # we use a temporary to care for the dreaded self assignment:
         var tmp: TLoc
         getTemp(p, ty, tmp)
@@ -357,7 +357,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
     linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
   else: internalError("genAssignment: " & $ty.kind)
 
-  if optMemTracker in p.options and dest.s in {OnHeap, OnUnknown}:
+  if optMemTracker in p.options and dest.storage in {OnHeap, OnHeapNew, OnUnknown}:
     #writeStackTrace()
     #echo p.currLineInfo, " requesting"
     linefmt(p, cpsStmts, "#memTrackerWrite((void*)$1, $2, $3, $4);$n",
@@ -662,7 +662,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
     #  message(e.info, warnUser, "CAME HERE " & renderTree(e))
     expr(p, e.sons[0], d)
     if e.sons[0].typ.skipTypes(abstractInst).kind == tyRef:
-      d.s = OnHeap
+      d.storage = OnHeap
   else:
     var a: TLoc
     var typ = skipTypes(e.sons[0].typ, abstractInst)
@@ -675,25 +675,25 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
       initLocExprSingleUse(p, e.sons[0], a)
     if d.k == locNone:
       # dest = *a;  <-- We do not know that 'dest' is on the heap!
-      # It is completely wrong to set 'd.s' here, unless it's not yet
+      # It is completely wrong to set 'd.storage' here, unless it's not yet
       # been assigned to.
       case typ.kind
       of tyRef:
-        d.s = OnHeap
+        d.storage = OnHeap
       of tyVar:
-        d.s = OnUnknown
+        d.storage = OnUnknown
         if tfVarIsPtr notin typ.flags and p.module.compileToCpp and
             e.kind == nkHiddenDeref:
-          putIntoDest(p, d, e.typ, rdLoc(a), a.s)
+          putIntoDest(p, d, e.typ, rdLoc(a), a.storage)
           return
       of tyPtr:
-        d.s = OnUnknown         # BUGFIX!
+        d.storage = OnUnknown         # BUGFIX!
       else:
         internalError(e.info, "genDeref " & $typ.kind)
     elif p.module.compileToCpp:
       if typ.kind == tyVar and tfVarIsPtr notin typ.flags and
            e.kind == nkHiddenDeref:
-        putIntoDest(p, d, e.typ, rdLoc(a), a.s)
+        putIntoDest(p, d, e.typ, rdLoc(a), a.storage)
         return
     if enforceDeref and mt == ctPtrToArray:
       # we lie about the type for better C interop: 'ptr array[3,T]' is
@@ -701,26 +701,26 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
       # See tmissingderef. So we get rid of the deref instead. The codegen
       # ends up using 'memcpy' for the array assignment,
       # so the '&' and '*' cancel out:
-      putIntoDest(p, d, a.t.sons[0], rdLoc(a), a.s)
+      putIntoDest(p, d, a.t.sons[0], rdLoc(a), a.storage)
     else:
-      putIntoDest(p, d, e.typ, "(*$1)" % [rdLoc(a)], a.s)
+      putIntoDest(p, d, e.typ, "(*$1)" % [rdLoc(a)], a.storage)
 
 proc genAddr(p: BProc, e: PNode, d: var TLoc) =
   # careful  'addr(myptrToArray)' needs to get the ampersand:
   if e.sons[0].typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}:
     var a: TLoc
     initLocExpr(p, e.sons[0], a)
-    putIntoDest(p, d, e.typ, "&" & a.r, a.s)
+    putIntoDest(p, d, e.typ, "&" & a.r, a.storage)
     #Message(e.info, warnUser, "HERE NEW &")
   elif mapType(e.sons[0].typ) == ctArray or isCppRef(p, e.sons[0].typ):
     expr(p, e.sons[0], d)
   else:
     var a: TLoc
     initLocExpr(p, e.sons[0], a)
-    putIntoDest(p, d, e.typ, addrLoc(a), a.s)
+    putIntoDest(p, d, e.typ, addrLoc(a), a.storage)
 
 template inheritLocation(d: var TLoc, a: TLoc) =
-  if d.k == locNone: d.s = a.s
+  if d.k == locNone: d.storage = if a.storage == OnHeapNew: OnHeap else: a.storage
 
 proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc) =
   initLocExpr(p, e.sons[0], a)
@@ -742,7 +742,7 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
   of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal)
   else: internalError(e.info, "genTupleElem")
   addf(r, ".Field$1", [rope(i)])
-  putIntoDest(p, d, tupType.sons[i], r, a.s)
+  putIntoDest(p, d, tupType.sons[i], r, a.storage)
 
 proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope;
                       resTyp: ptr PType = nil): PSym =
@@ -769,15 +769,14 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
     # we found a unique tuple type which lacks field information
     # so we use Field$i
     addf(r, ".Field$1", [rope(f.position)])
-    putIntoDest(p, d, f.typ, r, a.s)
+    putIntoDest(p, d, f.typ, r, a.storage)
   else:
     var rtyp: PType
     let field = lookupFieldAgain(p, ty, f, r, addr rtyp)
     if field.loc.r == nil and rtyp != nil: fillObjectFields(p.module, rtyp)
     if field.loc.r == nil: internalError(e.info, "genRecordField 3 " & typeToString(ty))
     addf(r, ".$1", [field.loc.r])
-    putIntoDest(p, d, field.typ, r, a.s)
-  #d.s = a.s
+    putIntoDest(p, d, field.typ, r, a.storage)
 
 proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
 
@@ -827,7 +826,7 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
       internalError(e.info, "genCheckedRecordField") # generate the checks:
     genFieldCheck(p, e, r, field, ty)
     add(r, rfmt(nil, ".$1", field.loc.r))
-    putIntoDest(p, d, field.typ, r, a.s)
+    putIntoDest(p, d, field.typ, r, a.storage)
   else:
     genRecordField(p, e.sons[0], d)
 
@@ -854,16 +853,16 @@ proc genArrayElem(p: BProc, x, y: PNode, d: var TLoc) =
         localError(x.info, errIndexOutOfBounds)
   d.inheritLocation(a)
   putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
-              rfmt(nil, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.s)
+              rfmt(nil, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.storage)
 
 proc genCStringElem(p: BProc, x, y: PNode, d: var TLoc) =
   var a, b: TLoc
   initLocExpr(p, x, a)
   initLocExpr(p, y, b)
   var ty = skipTypes(a.t, abstractVarRange)
-  if d.k == locNone: d.s = a.s
+  inheritLocation(d, a)
   putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
-              rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.s)
+              rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage)
 
 proc genOpenArrayElem(p: BProc, x, y: PNode, d: var TLoc) =
   var a, b: TLoc
@@ -872,9 +871,9 @@ proc genOpenArrayElem(p: BProc, x, y: PNode, d: var TLoc) =
   if optBoundsCheck in p.options:
     linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)) #raiseIndexError();$n",
             rdLoc(b), rdLoc(a)) # BUGFIX: ``>=`` and not ``>``!
-  if d.k == locNone: d.s = a.s
+  inheritLocation(d, a)
   putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
-              rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.s)
+              rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage)
 
 proc genSeqElem(p: BProc, x, y: PNode, d: var TLoc) =
   var a, b: TLoc
@@ -892,11 +891,11 @@ proc genSeqElem(p: BProc, x, y: PNode, d: var TLoc) =
       linefmt(p, cpsStmts,
            "if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
            rdLoc(b), rdLoc(a), lenField(p))
-  if d.k == locNone: d.s = OnHeap
+  if d.k == locNone: d.storage = OnHeap
   if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
     a.r = rfmt(nil, "(*$1)", a.r)
   putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
-              rfmt(nil, "$1->data[$2]", rdLoc(a), rdCharLoc(b)), a.s)
+              rfmt(nil, "$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)
@@ -1088,7 +1087,7 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
   var sizeExpr = sizeExpr
   let typ = a.t
   var b: TLoc
-  initLoc(b, locExpr, a.t, OnHeap)
+  initLoc(b, locExpr, a.t, OnHeapNew)
   let refType = typ.skipTypes(abstractInst)
   assert refType.kind == tyRef
   let bt = refType.lastSon
@@ -1098,7 +1097,7 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
   let args = [getTypeDesc(p.module, typ),
               genTypeInfo(p.module, typ),
               sizeExpr]
-  if a.s == OnHeap and usesNativeGC():
+  if a.storage in {OnHeap, OnHeapNew} and usesNativeGC():
     # use newObjRC1 as an optimization
     if canFormAcycle(a.t):
       linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", a.rdLoc)
@@ -1128,8 +1127,8 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope) =
   let args = [getTypeDesc(p.module, seqtype),
               genTypeInfo(p.module, seqtype), length]
   var call: TLoc
-  initLoc(call, locExpr, dest.t, OnHeap)
-  if dest.s == OnHeap and usesNativeGC():
+  initLoc(call, locExpr, dest.t, OnHeapNew)
+  if dest.storage in {OnHeap, OnHeapNew} and usesNativeGC():
     if canFormAcycle(dest.t):
       linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", dest.rdLoc)
     else:
@@ -1155,6 +1154,7 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
               "($1)#nimNewSeqOfCap($2, $3)", [
               getTypeDesc(p.module, seqtype),
               genTypeInfo(p.module, seqtype), a.rdLoc]))
+  d.storage = OnHeapNew
   gcUsage(e)
 
 proc genConstExpr(p: BProc, n: PNode): Rope
@@ -1206,7 +1206,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
     add(tmp2.r, field.loc.r)
     tmp2.k = locTemp
     tmp2.t = field.loc.t
-    tmp2.s = if isRef: OnHeap else: OnStack
+    tmp2.storage = if isRef: OnHeap else: OnStack
     expr(p, it.sons[1], tmp2)
 
   if d.k == locNone:
@@ -1223,7 +1223,7 @@ proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
   for i in countup(0, sonsLen(t) - 1):
     initLoc(arr, locExpr, elemType(skipTypes(t.typ, typedescInst)), OnHeap)
     arr.r = rfmt(nil, "$1->data[$2]", rdLoc(d), intLiteral(i))
-    arr.s = OnHeap            # we know that sequences are on the heap
+    arr.storage = OnHeap            # we know that sequences are on the heap
     expr(p, t.sons[i], arr)
   gcUsage(t)
 
@@ -1243,8 +1243,8 @@ proc genArrToSeq(p: BProc, t: PNode, d: var TLoc) =
   for i in countup(0, L - 1):
     initLoc(elem, locExpr, elemType(skipTypes(t.typ, abstractInst)), OnHeap)
     elem.r = rfmt(nil, "$1->data[$2]", rdLoc(d), intLiteral(i))
-    elem.s = OnHeap # we know that sequences are on the heap
-    initLoc(arr, locExpr, elemType(skipTypes(t.sons[1].typ, abstractInst)), a.s)
+    elem.storage = OnHeap # we know that sequences are on the heap
+    initLoc(arr, locExpr, elemType(skipTypes(t.sons[1].typ, abstractInst)), a.storage)
     arr.r = rfmt(nil, "$1[$2]", rdLoc(a), intLiteral(i))
     genAssignment(p, elem, arr, {afDestIsNil, needToCopy})
 
@@ -1256,7 +1256,7 @@ proc genNewFinalize(p: BProc, e: PNode) =
   refType = skipTypes(e.sons[1].typ, abstractVarRange)
   initLocExpr(p, e.sons[1], a)
   initLocExpr(p, e.sons[2], f)
-  initLoc(b, locExpr, a.t, OnHeap)
+  initLoc(b, locExpr, a.t, OnHeapNew)
   ti = genTypeInfo(p.module, refType)
   addf(p.module.s[cfsTypeInit3], "$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
   b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [
@@ -1308,7 +1308,7 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
     r = rfmt(p.module, "(($1) && ($2))", nilCheck, genOfHelper(p, dest, r))
   else:
     r = rfmt(p.module, "($1)", genOfHelper(p, dest, r))
-  putIntoDest(p, d, getSysType(tyBool), r, a.s)
+  putIntoDest(p, d, getSysType(tyBool), r, a.storage)
 
 proc genOf(p: BProc, n: PNode, d: var TLoc) =
   genOf(p, n.sons[1], n.sons[2].typ, d)
@@ -1320,46 +1320,47 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
   case t.kind
   of tyInt..tyInt64, tyUInt..tyUInt64:
     putIntoDest(p, d, e.typ,
-                ropecg(p.module, "#reprInt((NI64)$1)", [rdLoc(a)]), a.s)
+                ropecg(p.module, "#reprInt((NI64)$1)", [rdLoc(a)]), a.storage)
   of tyFloat..tyFloat128:
-    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprFloat($1)", [rdLoc(a)]), a.s)
+    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprFloat($1)", [rdLoc(a)]), a.storage)
   of tyBool:
-    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprBool($1)", [rdLoc(a)]), a.s)
+    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprBool($1)", [rdLoc(a)]), a.storage)
   of tyChar:
-    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprChar($1)", [rdLoc(a)]), a.s)
+    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprChar($1)", [rdLoc(a)]), a.storage)
   of tyEnum, tyOrdinal:
     putIntoDest(p, d, e.typ,
                 ropecg(p.module, "#reprEnum((NI)$1, $2)", [
-                rdLoc(a), genTypeInfo(p.module, t)]), a.s)
+                rdLoc(a), genTypeInfo(p.module, t)]), a.storage)
   of tyString:
-    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprStr($1)", [rdLoc(a)]), a.s)
+    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprStr($1)", [rdLoc(a)]), a.storage)
   of tySet:
     putIntoDest(p, d, e.typ, ropecg(p.module, "#reprSet($1, $2)", [
-                addrLoc(a), genTypeInfo(p.module, t)]), a.s)
+                addrLoc(a), genTypeInfo(p.module, t)]), a.storage)
   of tyOpenArray, tyVarargs:
     var b: TLoc
     case a.t.kind
     of tyOpenArray, tyVarargs:
-      putIntoDest(p, b, e.typ, "$1, $1Len_0" % [rdLoc(a)], a.s)
+      putIntoDest(p, b, e.typ, "$1, $1Len_0" % [rdLoc(a)], a.storage)
     of tyString, tySequence:
       putIntoDest(p, b, e.typ,
-                  "$1->data, $1->$2" % [rdLoc(a), lenField(p)], a.s)
+                  "$1->data, $1->$2" % [rdLoc(a), lenField(p)], a.storage)
     of tyArray:
       putIntoDest(p, b, e.typ,
-                  "$1, $2" % [rdLoc(a), rope(lengthOrd(a.t))], a.s)
+                  "$1, $2" % [rdLoc(a), rope(lengthOrd(a.t))], a.storage)
     else: internalError(e.sons[0].info, "genRepr()")
     putIntoDest(p, d, e.typ,
         ropecg(p.module, "#reprOpenArray($1, $2)", [rdLoc(b),
-        genTypeInfo(p.module, elemType(t))]), a.s)
+        genTypeInfo(p.module, elemType(t))]), a.storage)
   of tyCString, tyArray, tyRef, tyPtr, tyPointer, tyNil, tySequence:
     putIntoDest(p, d, e.typ,
                 ropecg(p.module, "#reprAny($1, $2)", [
-                rdLoc(a), genTypeInfo(p.module, t)]), a.s)
+                rdLoc(a), genTypeInfo(p.module, t)]), a.storage)
   of tyEmpty, tyVoid:
     localError(e.info, "'repr' doesn't support 'void' type")
   else:
     putIntoDest(p, d, e.typ, ropecg(p.module, "#reprAny($1, $2)",
-                                   [addrLoc(a), genTypeInfo(p.module, t)]), a.s)
+                                   [addrLoc(a), genTypeInfo(p.module, t)]),
+                                   a.storage)
   gcUsage(e)
 
 proc genGetTypeInfo(p: BProc, e: PNode, d: var TLoc) =
@@ -1600,13 +1601,13 @@ proc genSomeCast(p: BProc, e: PNode, d: var TLoc) =
   let etyp = skipTypes(e.typ, abstractRange)
   if etyp.kind in ValueTypes and lfIndirect notin a.flags:
     putIntoDest(p, d, e.typ, "(*($1*) ($2))" %
-        [getTypeDesc(p.module, e.typ), addrLoc(a)], a.s)
+        [getTypeDesc(p.module, e.typ), addrLoc(a)], a.storage)
   elif etyp.kind == tyProc and etyp.callConv == ccClosure:
     putIntoDest(p, d, e.typ, "(($1) ($2))" %
-        [getClosureType(p.module, etyp, clHalfWithEnv), rdCharLoc(a)], a.s)
+        [getClosureType(p.module, etyp, clHalfWithEnv), rdCharLoc(a)], a.storage)
   else:
     putIntoDest(p, d, e.typ, "(($1) ($2))" %
-        [getTypeDesc(p.module, e.typ), rdCharLoc(a)], a.s)
+        [getTypeDesc(p.module, e.typ), rdCharLoc(a)], a.storage)
 
 proc genCast(p: BProc, e: PNode, d: var TLoc) =
   const ValueTypes = {tyFloat..tyFloat128, tyTuple, tyObject, tyArray}
@@ -1623,10 +1624,10 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
       getTypeDesc(p.module, e.sons[1].typ), getTypeDesc(p.module, e.typ), lbl)
     tmp.k = locExpr
     tmp.t = srct
-    tmp.s = OnStack
+    tmp.storage = OnStack
     tmp.flags = {}
     expr(p, e.sons[1], tmp)
-    putIntoDest(p, d, e.typ, "LOC$#.dest" % [lbl], tmp.s)
+    putIntoDest(p, d, e.typ, "LOC$#.dest" % [lbl], tmp.storage)
   else:
     # I prefer the shorter cast version for pointer types -> generate less
     # C code; plus it's the right thing to do for closures:
@@ -1640,13 +1641,13 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
                                              {tyUInt..tyUInt64}:
     initLocExpr(p, n.sons[0], a)
     putIntoDest(p, d, n.typ, "(($1) ($2))" %
-        [getTypeDesc(p.module, dest), rdCharLoc(a)], a.s)
+        [getTypeDesc(p.module, dest), rdCharLoc(a)], a.storage)
   else:
     initLocExpr(p, n.sons[0], a)
     putIntoDest(p, d, dest, ropecg(p.module, "(($1)#$5($2, $3, $4))", [
         getTypeDesc(p.module, dest), rdCharLoc(a),
         genLiteral(p, n.sons[1], dest), genLiteral(p, n.sons[2], dest),
-        rope(magic)]), a.s)
+        rope(magic)]), a.storage)
 
 proc genConv(p: BProc, e: PNode, d: var TLoc) =
   let destType = e.typ.skipTypes({tyVar, tyGenericInst, tyAlias})
@@ -1658,13 +1659,15 @@ proc genConv(p: BProc, e: PNode, d: var TLoc) =
 proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) =
   var a: TLoc
   initLocExpr(p, n.sons[0], a)
-  putIntoDest(p, d, skipTypes(n.typ, abstractVar), "$1->data" % [rdLoc(a)], a.s)
+  putIntoDest(p, d, skipTypes(n.typ, abstractVar), "$1->data" % [rdLoc(a)],
+              a.storage)
 
 proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
   var a: TLoc
   initLocExpr(p, n.sons[0], a)
   putIntoDest(p, d, skipTypes(n.typ, abstractVar),
-              ropecg(p.module, "#cstrToNimstr($1)", [rdLoc(a)]), a.s)
+              ropecg(p.module, "#cstrToNimstr($1)", [rdLoc(a)]),
+              a.storage)
   gcUsage(n)
 
 proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
@@ -1872,7 +1875,7 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
     for i in countup(0, sonsLen(n) - 1):
       var it = n.sons[i]
       if it.kind == nkExprColonExpr: it = it.sons[1]
-      initLoc(rec, locExpr, it.typ, d.s)
+      initLoc(rec, locExpr, it.typ, d.storage)
       rec.r = "$1.Field$2" % [rdLoc(d), rope(i)]
       expr(p, it, rec)
 
@@ -1911,7 +1914,7 @@ proc genArrayConstr(p: BProc, n: PNode, d: var TLoc) =
   if not handleConstExpr(p, n, d):
     if d.k == locNone: getTemp(p, n.typ, d)
     for i in countup(0, sonsLen(n) - 1):
-      initLoc(arr, locExpr, elemType(skipTypes(n.typ, abstractInst)), d.s)
+      initLoc(arr, locExpr, elemType(skipTypes(n.typ, abstractInst)), d.storage)
       arr.r = "$1[$2]" % [rdLoc(d), intLiteral(i)]
       expr(p, n.sons[i], arr)
 
@@ -1950,10 +1953,10 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
               r, genTypeInfo(p.module, dest))
   if n.sons[0].typ.kind != tyObject:
     putIntoDest(p, d, n.typ,
-                "(($1) ($2))" % [getTypeDesc(p.module, n.typ), rdLoc(a)], a.s)
+                "(($1) ($2))" % [getTypeDesc(p.module, n.typ), rdLoc(a)], a.storage)
   else:
     putIntoDest(p, d, n.typ, "(*($1*) ($2))" %
-                             [getTypeDesc(p.module, dest), addrLoc(a)], a.s)
+                             [getTypeDesc(p.module, dest), addrLoc(a)], a.storage)
 
 proc downConv(p: BProc, n: PNode, d: var TLoc) =
   if p.module.compileToCpp:
@@ -1985,9 +1988,9 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) =
         linefmt(p, cpsStmts, "$1 = &$2;$n", rdLoc(d), r)
       else:
         r = "&" & r
-        putIntoDest(p, d, n.typ, r, a.s)
+        putIntoDest(p, d, n.typ, r, a.storage)
     else:
-      putIntoDest(p, d, n.typ, r, a.s)
+      putIntoDest(p, d, n.typ, r, a.storage)
 
 proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
   let t = n.typ
@@ -2008,7 +2011,7 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
     # This fixes bug #4551, but we really need better dataflow
     # analysis to make this 100% safe.
     if t.kind notin {tySequence, tyString}:
-      d.s = OnStatic
+      d.storage = OnStatic
 
 proc expr(p: BProc, n: PNode, d: var TLoc) =
   p.currLineInfo = n.info
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 8796dd729..36b225ee5 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -57,7 +57,7 @@ proc genVarTuple(p: BProc, n: PNode) =
     else:
       assignLocalVar(p, v)
       initLocalVar(p, v, immediateAsgn=isAssignedImmediately(n[L-1]))
-    initLoc(field, locExpr, t.sons[i], tup.s)
+    initLoc(field, locExpr, t.sons[i], tup.storage)
     if t.kind == tyTuple:
       field.r = "$1.Field$2" % [rdLoc(tup), rope(i)]
     else:
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 35d73aac0..770c4e468 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -287,7 +287,7 @@ proc fillResult(param: PSym) =
           OnStack)
   if mapReturnType(param.typ) != ctArray and isInvalidReturnType(param.typ):
     incl(param.loc.flags, lfIndirect)
-    param.loc.s = OnUnknown
+    param.loc.storage = OnUnknown
 
 proc typeNameOrLiteral(m: BModule; t: PType, literal: string): Rope =
   if t.sym != nil and sfImportc in t.sym.flags and t.sym.magic == mNone:
@@ -404,7 +404,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
       add(params, getTypeDescWeak(m, param.typ, check))
       add(params, ~"*")
       incl(param.loc.flags, lfIndirect)
-      param.loc.s = OnUnknown
+      param.loc.storage = OnUnknown
     elif weakDep:
       add(params, getTypeDescWeak(m, param.typ, check))
     else:
@@ -417,7 +417,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
     var j = 0
     while arr.kind in {tyOpenArray, tyVarargs}:
       # this fixes the 'sort' bug:
-      if param.typ.kind == tyVar: param.loc.s = OnUnknown
+      if param.typ.kind == tyVar: param.loc.storage = OnUnknown
       # need to pass hidden parameter:
       addf(params, ", NI $1Len_$2", [param.loc.r, j.rope])
       inc(j)
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index b618837c7..6c35a7e18 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -49,7 +49,7 @@ proc findPendingModule(m: BModule, s: PSym): BModule =
 
 proc initLoc(result: var TLoc, k: TLocKind, typ: PType, s: TStorageLoc) =
   result.k = k
-  result.s = s
+  result.storage = s
   result.t = typ
   result.r = nil
   result.flags = {}
@@ -59,7 +59,7 @@ proc fillLoc(a: var TLoc, k: TLocKind, typ: PType, r: Rope, s: TStorageLoc) =
   if a.k == locNone:
     a.k = k
     a.t = typ
-    a.s = s
+    a.storage = s
     if a.r == nil: a.r = r
 
 proc isSimpleConst(typ: PType): bool =
@@ -294,7 +294,7 @@ proc resetLoc(p: BProc, loc: var TLoc) =
   else:
     if optNilCheck in p.options:
       linefmt(p, cpsStmts, "#chckNil((void*)$1);$n", addrLoc(loc))
-    if loc.s != OnStack:
+    if loc.storage != OnStack:
       linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
               addrLoc(loc), genTypeInfo(p.module, loc.t))
       # XXX: generated reset procs should not touch the m_type
@@ -341,7 +341,7 @@ proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
   linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r)
   result.k = locTemp
   result.t = t
-  result.s = OnStack
+  result.storage = OnStack
   result.flags = {}
   constructLoc(p, result, not needsInit)
 
@@ -350,7 +350,7 @@ proc getIntTemp(p: BProc, result: var TLoc) =
   result.r = "T" & rope(p.labels) & "_"
   linefmt(p, cpsLocals, "NI $1;$n", result.r)
   result.k = locTemp
-  result.s = OnStack
+  result.storage = OnStack
   result.t = getSysType(tyInt)
   result.flags = {}
 
@@ -695,7 +695,7 @@ proc genProcAux(m: BModule, prc: PSym) =
       assignParam(p, res)
       if skipTypes(res.typ, abstractInst).kind == tyArray:
         #incl(res.loc.flags, lfIndirect)
-        res.loc.s = OnUnknown
+        res.loc.storage = OnUnknown
 
   for i in countup(1, sonsLen(prc.typ.n) - 1):
     var param = prc.typ.n.sons[i].sym
diff --git a/compiler/rodread.nim b/compiler/rodread.nim
index f7e5a0f84..c06cf3414 100644
--- a/compiler/rodread.nim
+++ b/compiler/rodread.nim
@@ -257,9 +257,9 @@ proc decodeLoc(r: PRodReader, loc: var TLoc, info: TLineInfo) =
       loc.k = low(loc.k)
     if r.s[r.pos] == '*':
       inc(r.pos)
-      loc.s = TStorageLoc(decodeVInt(r.s, r.pos))
+      loc.storage = TStorageLoc(decodeVInt(r.s, r.pos))
     else:
-      loc.s = low(loc.s)
+      loc.storage = low(loc.storage)
     if r.s[r.pos] == '$':
       inc(r.pos)
       loc.flags = cast[TLocFlags](int32(decodeVInt(r.s, r.pos)))
diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim
index d61d817dd..90cafaf1b 100644
--- a/compiler/rodwrite.nim
+++ b/compiler/rodwrite.nim
@@ -175,9 +175,9 @@ proc encodeLoc(w: PRodWriter, loc: TLoc, result: var string) =
   var oldLen = result.len
   result.add('<')
   if loc.k != low(loc.k): encodeVInt(ord(loc.k), result)
-  if loc.s != low(loc.s):
+  if loc.storage != low(loc.storage):
     add(result, '*')
-    encodeVInt(ord(loc.s), result)
+    encodeVInt(ord(loc.storage), result)
   if loc.flags != {}:
     add(result, '$')
     encodeVInt(cast[int32](loc.flags), result)
diff --git a/lib/pure/asyncmacro.nim b/lib/pure/asyncmacro.nim
index 6e7d7993f..8607b4bfc 100644
--- a/lib/pure/asyncmacro.nim
+++ b/lib/pure/asyncmacro.nim
@@ -28,7 +28,7 @@ template createCb(retFutureSym, iteratorNameSym,
                   name, futureVarCompletions: untyped) =
   var nameIterVar = iteratorNameSym
   #{.push stackTrace: off.}
-  proc cb0 {.closure.} =
+  proc cb0 {.closure, gcsafe.} =
     try:
       if not nameIterVar.finished:
         var next = nameIterVar()