diff options
author | Zahary Karadjov <zahary@gmail.com> | 2012-04-15 00:38:57 +0300 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2012-04-15 01:06:40 +0300 |
commit | 567b5b07ea4d7400b4e24822f6d4d6328e9bd2ec (patch) | |
tree | d96e2ef33568816d47c62ec2f71f072d1ffc9ad8 | |
parent | 42e0b082144a2c03ef18e0cabc372c90f1753148 (diff) | |
download | Nim-567b5b07ea4d7400b4e24822f6d4d6328e9bd2ec.tar.gz |
fixes #20 properly
-rw-r--r-- | compiler/ccgcalls.nim | 3 | ||||
-rwxr-xr-x | compiler/ccgstmts.nim | 10 | ||||
-rwxr-xr-x | compiler/cgen.nim | 56 | ||||
-rwxr-xr-x | compiler/semstmts.nim | 5 |
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): |