implements {.gcsafe.} enforcement as a pragma block
This commit is contained in:
parent
b6b5a11be7
commit
2f08fdf623
3 changed files with 27 additions and 16 deletions
|
|
@ -38,7 +38,7 @@ const
|
||||||
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
|
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
|
||||||
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
|
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
|
||||||
wTags, wLocks, wGcSafe, wExportNims}
|
wTags, wLocks, wGcSafe, wExportNims}
|
||||||
exprPragmas* = {wLine, wLocks, wNoRewrite}
|
exprPragmas* = {wLine, wLocks, wNoRewrite, wGcSafe}
|
||||||
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
|
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
|
||||||
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
|
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
|
||||||
wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
|
wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
|
||||||
|
|
@ -775,9 +775,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||||
if sym.typ.callConv == ccClosure: sym.typ.callConv = ccDefault
|
if sym.typ.callConv == ccClosure: sym.typ.callConv = ccDefault
|
||||||
of wGcSafe:
|
of wGcSafe:
|
||||||
noVal(it)
|
noVal(it)
|
||||||
if sym.kind != skType: incl(sym.flags, sfThread)
|
if sym != nil:
|
||||||
if sym.typ != nil: incl(sym.typ.flags, tfGcSafe)
|
if sym.kind != skType: incl(sym.flags, sfThread)
|
||||||
else: invalidPragma(it)
|
if sym.typ != nil: incl(sym.typ.flags, tfGcSafe)
|
||||||
|
else: invalidPragma(it)
|
||||||
|
else:
|
||||||
|
discard "no checking if used as a code block"
|
||||||
of wPacked:
|
of wPacked:
|
||||||
noVal(it)
|
noVal(it)
|
||||||
if sym.typ == nil: invalidPragma(it)
|
if sym.typ == nil: invalidPragma(it)
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ type
|
||||||
init: seq[int] # list of initialized variables
|
init: seq[int] # list of initialized variables
|
||||||
guards: TModel # nested guards
|
guards: TModel # nested guards
|
||||||
locked: seq[PNode] # locked locations
|
locked: seq[PNode] # locked locations
|
||||||
gcUnsafe, isRecursive, isToplevel, hasSideEffect: bool
|
gcUnsafe, isRecursive, isToplevel, hasSideEffect, inEnforcedGcSafe: bool
|
||||||
maxLockLevel, currLockLevel: TLockLevel
|
maxLockLevel, currLockLevel: TLockLevel
|
||||||
PEffects = var TEffects
|
PEffects = var TEffects
|
||||||
|
|
||||||
|
|
@ -180,17 +180,19 @@ proc warnAboutGcUnsafe(n: PNode) =
|
||||||
message(n.info, warnGcUnsafe, renderTree(n))
|
message(n.info, warnGcUnsafe, renderTree(n))
|
||||||
|
|
||||||
proc markGcUnsafe(a: PEffects; reason: PSym) =
|
proc markGcUnsafe(a: PEffects; reason: PSym) =
|
||||||
a.gcUnsafe = true
|
if not a.inEnforcedGcSafe:
|
||||||
if a.owner.kind in routineKinds: a.owner.gcUnsafetyReason = reason
|
a.gcUnsafe = true
|
||||||
|
if a.owner.kind in routineKinds: a.owner.gcUnsafetyReason = reason
|
||||||
|
|
||||||
proc markGcUnsafe(a: PEffects; reason: PNode) =
|
proc markGcUnsafe(a: PEffects; reason: PNode) =
|
||||||
a.gcUnsafe = true
|
if not a.inEnforcedGcSafe:
|
||||||
if a.owner.kind in routineKinds:
|
a.gcUnsafe = true
|
||||||
if reason.kind == nkSym:
|
if a.owner.kind in routineKinds:
|
||||||
a.owner.gcUnsafetyReason = reason.sym
|
if reason.kind == nkSym:
|
||||||
else:
|
a.owner.gcUnsafetyReason = reason.sym
|
||||||
a.owner.gcUnsafetyReason = newSym(skUnknown, getIdent("<unknown>"),
|
else:
|
||||||
a.owner, reason.info)
|
a.owner.gcUnsafetyReason = newSym(skUnknown, getIdent("<unknown>"),
|
||||||
|
a.owner, reason.info)
|
||||||
|
|
||||||
when true:
|
when true:
|
||||||
template markSideEffect(a: PEffects; reason: typed) =
|
template markSideEffect(a: PEffects; reason: typed) =
|
||||||
|
|
@ -803,10 +805,16 @@ proc track(tracked: PEffects, n: PNode) =
|
||||||
let pragmaList = n.sons[0]
|
let pragmaList = n.sons[0]
|
||||||
let oldLocked = tracked.locked.len
|
let oldLocked = tracked.locked.len
|
||||||
let oldLockLevel = tracked.currLockLevel
|
let oldLockLevel = tracked.currLockLevel
|
||||||
|
var enforcedGcSafety = false
|
||||||
for i in 0 .. <pragmaList.len:
|
for i in 0 .. <pragmaList.len:
|
||||||
if whichPragma(pragmaList.sons[i]) == wLocks:
|
let pragma = whichPragma(pragmaList.sons[i])
|
||||||
|
if pragma == wLocks:
|
||||||
lockLocations(tracked, pragmaList.sons[i])
|
lockLocations(tracked, pragmaList.sons[i])
|
||||||
|
elif pragma == wGcSafe:
|
||||||
|
enforcedGcSafety = true
|
||||||
|
if enforcedGcSafety: tracked.inEnforcedGcSafe = true
|
||||||
track(tracked, n.lastSon)
|
track(tracked, n.lastSon)
|
||||||
|
if enforcedGcSafety: tracked.inEnforcedGcSafe = false
|
||||||
setLen(tracked.locked, oldLocked)
|
setLen(tracked.locked, oldLocked)
|
||||||
tracked.currLockLevel = oldLockLevel
|
tracked.currLockLevel = oldLockLevel
|
||||||
of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,
|
of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,
|
||||||
|
|
|
||||||
|
|
@ -1444,7 +1444,7 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode =
|
||||||
for i in 0 .. <pragmaList.len:
|
for i in 0 .. <pragmaList.len:
|
||||||
case whichPragma(pragmaList.sons[i])
|
case whichPragma(pragmaList.sons[i])
|
||||||
of wLine: setLine(result, pragmaList.sons[i].info)
|
of wLine: setLine(result, pragmaList.sons[i].info)
|
||||||
of wLocks:
|
of wLocks, wGcSafe:
|
||||||
result = n
|
result = n
|
||||||
result.typ = n.sons[1].typ
|
result.typ = n.sons[1].typ
|
||||||
of wNoRewrite:
|
of wNoRewrite:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue