implements {.gcsafe.} enforcement as a pragma block

This commit is contained in:
Andreas Rumpf 2017-01-18 12:55:33 +01:00
commit 2f08fdf623
3 changed files with 27 additions and 16 deletions

View file

@ -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)

View file

@ -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,

View file

@ -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: