fixes #20 properly
This commit is contained in:
parent
42e0b08214
commit
567b5b07ea
4 changed files with 36 additions and 38 deletions
|
|
@ -18,9 +18,6 @@ proc leftAppearsOnRightSide(le, ri: PNode): bool =
|
||||||
proc hasNoInit(call: PNode): bool {.inline.} =
|
proc hasNoInit(call: PNode): bool {.inline.} =
|
||||||
result = call.sons[0].kind == nkSym and sfNoInit in call.sons[0].sym.flags
|
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) =
|
proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) =
|
||||||
var pl = pl
|
var pl = pl
|
||||||
var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
|
var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,15 @@ proc genSingleVar(p: BProc, a: PNode) =
|
||||||
if v.owner.kind != skModule:
|
if v.owner.kind != skModule:
|
||||||
targetProc = p.module.preInitProc
|
targetProc = p.module.preInitProc
|
||||||
assignGlobalVar(targetProc, v)
|
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:
|
else:
|
||||||
assignLocalVar(p, v)
|
assignLocalVar(p, v)
|
||||||
initLocalVar(p, v, immediateAsgn)
|
initLocalVar(p, v, immediateAsgn)
|
||||||
|
|
|
||||||
|
|
@ -229,45 +229,37 @@ proc isComplexValueType(t: PType): bool {.inline.} =
|
||||||
result = t.kind in {tyArray, tyArrayConstr, tySet, tyTuple, tyObject} or
|
result = t.kind in {tyArray, tyArrayConstr, tySet, tyTuple, tyObject} or
|
||||||
(t.kind == tyProc and t.callConv == ccClosure)
|
(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 not isComplexValueType(skipTypes(loc.t, abstractVarRange)):
|
||||||
if containsGcref and p.WithInLoop > 0:
|
if containsGcRef:
|
||||||
appf(p.s(cpsInit), "$1 = 0;$n", [rdLoc(loc)])
|
|
||||||
var nilLoc: TLoc
|
var nilLoc: TLoc
|
||||||
initLoc(nilLoc, locTemp, loc.t, onStack)
|
initLoc(nilLoc, locTemp, loc.t, onStack)
|
||||||
nilLoc.r = toRope("NIM_NIL")
|
nilLoc.r = toRope("NIM_NIL")
|
||||||
# puts ``unsureAsgnRef`` etc to ``p.s[cpsStmts]``:
|
|
||||||
genRefAssign(p, loc, nilLoc, {afSrcIsNil})
|
genRefAssign(p, loc, nilLoc, {afSrcIsNil})
|
||||||
else:
|
else:
|
||||||
appf(p.s(cpsStmts), "$1 = 0;$n", [rdLoc(loc)])
|
appf(p.s(cpsStmts), "$1 = 0;$n", [rdLoc(loc)])
|
||||||
else:
|
else:
|
||||||
if containsGcref and p.WithInLoop > 0:
|
if loc.s != OnStack:
|
||||||
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",
|
appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
||||||
[addrLoc(loc), genTypeInfo(p.module, loc.t)])
|
[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:
|
else:
|
||||||
appf(p.s(cpsStmts), "memset((void*)$1, 0, sizeof($2));$n",
|
appf(p.s(cpsStmts), "memset((void*)$1, 0, sizeof($2));$n",
|
||||||
[addrLoc(loc), rdLoc(loc)])
|
[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)
|
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)):
|
if not isComplexValueType(skipTypes(loc.t, abstractVarRange)):
|
||||||
appf(p.s(cpsStmts), "$1 = 0;$n", [rdLoc(loc)])
|
appf(p.s(section), "$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})
|
|
||||||
else:
|
else:
|
||||||
appf(p.s(cpsStmts), "memset((void*)$1, 0, sizeof($2));$n",
|
appf(p.s(section), "memset((void*)$1, 0, sizeof($2));$n",
|
||||||
[addrLoc(loc), rdLoc(loc)])
|
[addrLoc(loc), rdLoc(loc)])
|
||||||
# XXX no object init necessary for temporaries?
|
genObjectInit(p, section, loc.t, loc, true)
|
||||||
when false:
|
|
||||||
appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
|
||||||
[addrLoc(loc), genTypeInfo(p.module, loc.t)])
|
|
||||||
|
|
||||||
proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
|
proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
|
||||||
if sfNoInit notin v.flags:
|
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)``.
|
# ``var v = X()`` gets transformed into ``X(&v)``.
|
||||||
# Nowadays the logic in ccgcalls deals with this case however.
|
# Nowadays the logic in ccgcalls deals with this case however.
|
||||||
if not immediateAsgn:
|
if not immediateAsgn:
|
||||||
zeroVar(p, v.loc, containsGarbageCollectedRef(v.typ))
|
constructLoc(p, v.loc)
|
||||||
|
|
||||||
proc initTemp(p: BProc, tmp: var TLoc) =
|
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):
|
if containsGarbageCollectedRef(tmp.t) or isInvalidReturnType(tmp.t):
|
||||||
zeroTemp(p, tmp)
|
constructLoc(p, tmp)
|
||||||
|
|
||||||
proc getTemp(p: BProc, t: PType, result: var TLoc) =
|
proc getTemp(p: BProc, t: PType, result: var TLoc) =
|
||||||
inc(p.labels)
|
inc(p.labels)
|
||||||
|
|
@ -410,7 +404,7 @@ proc assignGlobalVar(p: BProc, s: PSym) =
|
||||||
appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
|
appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
|
||||||
if p.withinLoop > 0:
|
if p.withinLoop > 0:
|
||||||
# fixes tests/run/tzeroarray:
|
# fixes tests/run/tzeroarray:
|
||||||
initLocalVar(p, s, false)
|
resetLoc(p, s.loc)
|
||||||
if p.module.module.options * {optStackTrace, optEndb} ==
|
if p.module.module.options * {optStackTrace, optEndb} ==
|
||||||
{optStackTrace, optEndb}:
|
{optStackTrace, optEndb}:
|
||||||
appcg(p.module, p.module.s[cfsDebugInit],
|
appcg(p.module, p.module.s[cfsDebugInit],
|
||||||
|
|
|
||||||
|
|
@ -220,9 +220,8 @@ proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
|
||||||
proc findShadowedVar(c: PContext, v: PSym): PSym =
|
proc findShadowedVar(c: PContext, v: PSym): PSym =
|
||||||
for i in countdown(c.tab.tos - 2, 0):
|
for i in countdown(c.tab.tos - 2, 0):
|
||||||
let shadowed = StrTableGet(c.tab.stack[i], v.name)
|
let shadowed = StrTableGet(c.tab.stack[i], v.name)
|
||||||
if shadowed != nil:
|
if shadowed != nil and shadowed.kind in skLocalVars:
|
||||||
if shadowed.kind in skLocalVars:
|
return shadowed
|
||||||
return shadowed
|
|
||||||
|
|
||||||
proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
|
proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
|
||||||
if isTopLevel(c):
|
if isTopLevel(c):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue