summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2012-04-15 00:38:57 +0300
committerZahary Karadjov <zahary@gmail.com>2012-04-15 01:06:40 +0300
commit567b5b07ea4d7400b4e24822f6d4d6328e9bd2ec (patch)
treed96e2ef33568816d47c62ec2f71f072d1ffc9ad8
parent42e0b082144a2c03ef18e0cabc372c90f1753148 (diff)
downloadNim-567b5b07ea4d7400b4e24822f6d4d6328e9bd2ec.tar.gz
fixes #20 properly
-rw-r--r--compiler/ccgcalls.nim3
-rwxr-xr-xcompiler/ccgstmts.nim10
-rwxr-xr-xcompiler/cgen.nim56
-rwxr-xr-xcompiler/semstmts.nim5
4 files changed, 36 insertions, 38 deletions
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index c1ad8614f..f2fa6a280 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -18,9 +18,6 @@ proc leftAppearsOnRightSide(le, ri: PNode): bool =
 proc hasNoInit(call: PNode): bool {.inline.} =
   result = call.sons[0].kind == nkSym and sfNoInit in call.sons[0].sym.flags
 
-proc resetLoc(p: BProc, d: var TLoc) =
-  zeroVar(p, d, containsGarbageCollectedRef(d.t))
-
 proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) =
   var pl = pl
   var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 8b624fd23..9fd27bfeb 100755
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -101,7 +101,15 @@ proc genSingleVar(p: BProc, a: PNode) =
     if v.owner.kind != skModule:
       targetProc = p.module.preInitProc
     assignGlobalVar(targetProc, v)
-    genObjectInit(targetProc, cpsInit, v.typ, v.loc, true)
+    # XXX: be careful here.
+    # Global variables should not be zeromem-ed within loops 
+    # (see bug #20).
+    # That's why we are doing the construction inside the preInitProc.
+    # genObjectInit relies on the C runtime's guarantees that 
+    # global variables will be initialized to zero.
+    genObjectInit(p.module.preInitProc, cpsInit, v.typ, v.loc, true)
+    # Alternative construction using default constructor (which may zeromem):
+    # if sfImportc notin v.flags: constructLoc(p.module.preInitProc, v.loc)
   else:
     assignLocalVar(p, v)
     initLocalVar(p, v, immediateAsgn)
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index acaa785f8..e8073b555 100755
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -229,45 +229,37 @@ proc isComplexValueType(t: PType): bool {.inline.} =
   result = t.kind in {tyArray, tyArrayConstr, tySet, tyTuple, tyObject} or
     (t.kind == tyProc and t.callConv == ccClosure)
 
-proc zeroVar(p: BProc, loc: TLoc, containsGCref: bool) = 
+proc resetLoc(p: BProc, loc: var TLoc) =
+  let containsGcRef = containsGarbageCollectedRef(loc.t)
   if not isComplexValueType(skipTypes(loc.t, abstractVarRange)):
-    if containsGcref and p.WithInLoop > 0:
-      appf(p.s(cpsInit), "$1 = 0;$n", [rdLoc(loc)])
+    if containsGcRef:
       var nilLoc: TLoc
       initLoc(nilLoc, locTemp, loc.t, onStack)
       nilLoc.r = toRope("NIM_NIL")
-      # puts ``unsureAsgnRef`` etc to ``p.s[cpsStmts]``:
       genRefAssign(p, loc, nilLoc, {afSrcIsNil})
     else:
       appf(p.s(cpsStmts), "$1 = 0;$n", [rdLoc(loc)])
   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)])
+    if loc.s != OnStack:
+      appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
+        [addrLoc(loc), genTypeInfo(p.module, loc.t)])
+      # XXX: generated reset procs should not touch the m_type
+      # field, so disabling this should be safe:
+      genObjectInit(p, cpsStmts, loc.t, loc, true)
     else:
-      appf(p.s(cpsStmts), "memset((void*)$1, 0, sizeof($2));$n", 
-           [addrLoc(loc), rdLoc(loc)])
+      appf(p.s(cpsStmts), "memset((void*)$1, 0, sizeof($2));$n",
+        [addrLoc(loc), rdLoc(loc)])
+      # XXX: We can be extra clever here and call memset only 
+      # on the bytes following the m_type field?
       genObjectInit(p, cpsStmts, loc.t, loc, true)
 
-proc zeroTemp(p: BProc, loc: TLoc) =
+proc constructLoc(p: BProc, loc: TLoc, section = cpsStmts) =
   if not isComplexValueType(skipTypes(loc.t, abstractVarRange)):
-    appf(p.s(cpsStmts), "$1 = 0;$n", [rdLoc(loc)])
-    when false:
-      var nilLoc: TLoc
-      initLoc(nilLoc, locTemp, loc.t, onStack)
-      nilLoc.r = toRope("NIM_NIL")
-      # puts ``unsureAsgnRef`` etc to ``p.s[cpsStmts]``:
-      genRefAssign(p, loc, nilLoc, {afSrcIsNil})
+    appf(p.s(section), "$1 = 0;$n", [rdLoc(loc)])
   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)])
+    appf(p.s(section), "memset((void*)$1, 0, sizeof($2));$n",
+       [addrLoc(loc), rdLoc(loc)])
+    genObjectInit(p, section, loc.t, loc, true)
 
 proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
   if sfNoInit notin v.flags:
@@ -279,11 +271,13 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
     # ``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) = 
+      constructLoc(p, v.loc)
+
+proc initTemp(p: BProc, tmp: var TLoc) =
+  # XXX: This is still suspicious.
+  # Objects should always be constructed?
   if containsGarbageCollectedRef(tmp.t) or isInvalidReturnType(tmp.t):
-    zeroTemp(p, tmp)
+    constructLoc(p, tmp)
 
 proc getTemp(p: BProc, t: PType, result: var TLoc) = 
   inc(p.labels)
@@ -410,7 +404,7 @@ proc assignGlobalVar(p: BProc, s: PSym) =
     appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
   if p.withinLoop > 0:
     # fixes tests/run/tzeroarray:
-    initLocalVar(p, s, false)
+    resetLoc(p, s.loc)
   if p.module.module.options * {optStackTrace, optEndb} ==
                                {optStackTrace, optEndb}: 
     appcg(p.module, p.module.s[cfsDebugInit], 
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index e7051231b..b9b418c98 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -220,9 +220,8 @@ proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
 proc findShadowedVar(c: PContext, v: PSym): PSym =
   for i in countdown(c.tab.tos - 2, 0):
     let shadowed = StrTableGet(c.tab.stack[i], v.name)
-    if shadowed != nil:
-      if shadowed.kind in skLocalVars:
-        return shadowed
+    if shadowed != nil and shadowed.kind in skLocalVars:
+      return shadowed
 
 proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
   if isTopLevel(c):