summary refs log tree commit diff stats
path: root/compiler/cgen.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/cgen.nim')
-rwxr-xr-xcompiler/cgen.nim29
1 files changed, 19 insertions, 10 deletions
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 2018d7e6d..aa07f40aa 100755
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -14,7 +14,7 @@ import
   options, intsets,
   nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
   times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
-  rodutils, renderer, idgen, cgendata, ccgmerge, semfold
+  rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases
 
 when options.hasTinyCBackend:
   import tccgen
@@ -235,16 +235,17 @@ proc zeroVar(p: BProc, loc: TLoc, containsGCref: bool) =
       genRefAssign(p, loc, nilLoc, {afSrcIsNil})
     else:
       appf(p.s[cpsStmts], "$1 = 0;$n", [rdLoc(loc)])
-  else: 
+  else:
     if containsGcref and p.WithInLoop > 0:
       appf(p.s[cpsInit], "memset((void*)$1, 0, sizeof($2));$n", 
            [addrLoc(loc), rdLoc(loc)])
+      genObjectInit(p, cpsInit, loc.t, loc, true)
       appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n", 
            [addrLoc(loc), genTypeInfo(p.module, loc.t)])
     else:
       appf(p.s[cpsStmts], "memset((void*)$1, 0, sizeof($2));$n", 
            [addrLoc(loc), rdLoc(loc)])
-    genObjectInit(p, cpsInit, loc.t, loc, true)
+      genObjectInit(p, cpsStmts, loc.t, loc, true)
 
 proc zeroTemp(p: BProc, loc: TLoc) = 
   if skipTypes(loc.t, abstractVarRange).Kind notin
@@ -259,15 +260,22 @@ proc zeroTemp(p: BProc, loc: TLoc) =
   else: 
     appf(p.s[cpsStmts], "memset((void*)$1, 0, sizeof($2));$n", 
          [addrLoc(loc), rdLoc(loc)])
+    # XXX no object init necessary for temporaries?
     when false:
       appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n", 
            [addrLoc(loc), genTypeInfo(p.module, loc.t)])
 
-proc initVariable(p: BProc, v: PSym) =
+proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
   if sfNoInit notin v.flags:
-    var b = containsGarbageCollectedRef(v.typ)
-    if b or v.ast == nil:
-      zeroVar(p, v.loc, b)
+    # we know it is a local variable and thus on the stack!
+    # If ``not immediateAsgn`` it is not initialized in a binding like
+    # ``var v = X`` and thus we need to init it. 
+    # If ``v`` contains a GC-ref we may pass it to ``unsureAsgnRef`` somehow
+    # which requires initialization. However this can really only happen if
+    # ``var v = X()`` gets transformed into ``X(&v)``. 
+    # Nowadays the logic in ccgcalls deals with this case however.
+    if not immediateAsgn:
+      zeroVar(p, v.loc, containsGarbageCollectedRef(v.typ))
     
 proc initTemp(p: BProc, tmp: var TLoc) = 
   if containsGarbageCollectedRef(tmp.t) or isInvalidReturnType(tmp.t):
@@ -534,13 +542,14 @@ proc genProcAux(m: BModule, prc: PSym) =
   assert(prc.ast != nil)
   if sfPure notin prc.flags and prc.typ.sons[0] != nil:
     var res = prc.ast.sons[resultPos].sym # get result symbol
-    if not isInvalidReturnType(prc.typ.sons[0]): 
+    if not isInvalidReturnType(prc.typ.sons[0]):
+      if sfNoInit in prc.flags: incl(res.flags, sfNoInit)
       # declare the result symbol:
       assignLocalVar(p, res)
       assert(res.loc.r != nil)
       returnStmt = ropeff("return $1;$n", "ret $1$n", [rdLoc(res.loc)])
-      initVariable(p, res)
-    else: 
+      initLocalVar(p, res, immediateAsgn=false)
+    else:
       fillResult(res)
       assignParam(p, res)
       if skipTypes(res.typ, abstractInst).kind == tyArray: