implemented 'injectStmt'; more debug support
This commit is contained in:
parent
01661daf76
commit
132b6b3efe
12 changed files with 60 additions and 12 deletions
|
|
@ -290,6 +290,7 @@ proc genCall(p: BProc, e: PNode, d: var TLoc) =
|
||||||
genNamedParamCall(p, e, d)
|
genNamedParamCall(p, e, d)
|
||||||
else:
|
else:
|
||||||
genPrefixCall(p, nil, e, d)
|
genPrefixCall(p, nil, e, d)
|
||||||
|
postStmtActions(p)
|
||||||
when false:
|
when false:
|
||||||
if d.s == onStack and containsGarbageCollectedRef(d.t): keepAlive(p, d)
|
if d.s == onStack and containsGarbageCollectedRef(d.t): keepAlive(p, d)
|
||||||
|
|
||||||
|
|
@ -303,6 +304,7 @@ proc genAsgnCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
genNamedParamCall(p, ri, d)
|
genNamedParamCall(p, ri, d)
|
||||||
else:
|
else:
|
||||||
genPrefixCall(p, le, ri, d)
|
genPrefixCall(p, le, ri, d)
|
||||||
|
postStmtActions(p)
|
||||||
when false:
|
when false:
|
||||||
if d.s == onStack and containsGarbageCollectedRef(d.t): keepAlive(p, d)
|
if d.s == onStack and containsGarbageCollectedRef(d.t): keepAlive(p, d)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -906,7 +906,12 @@ proc genPragma(p: BProc, n: PNode) =
|
||||||
of wEmit: genEmit(p, it)
|
of wEmit: genEmit(p, it)
|
||||||
of wBreakpoint: genBreakPoint(p, it)
|
of wBreakpoint: genBreakPoint(p, it)
|
||||||
of wWatchpoint: genWatchpoint(p, it)
|
of wWatchpoint: genWatchpoint(p, it)
|
||||||
else: nil
|
of wInjectStmt:
|
||||||
|
var p = newProc(nil, p.module)
|
||||||
|
p.options = p.options - {optLineTrace, optStackTrace}
|
||||||
|
genStmts(p, it.sons[1])
|
||||||
|
p.module.injectStmt = p.s(cpsStmts)
|
||||||
|
else: discard
|
||||||
|
|
||||||
proc FieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool =
|
proc FieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool =
|
||||||
if optFieldCheck in p.options:
|
if optFieldCheck in p.options:
|
||||||
|
|
|
||||||
|
|
@ -289,6 +289,9 @@ proc genLineDir(p: BProc, t: PNode) =
|
||||||
linefmt(p, cpsStmts, "nimln($1, $2);$n",
|
linefmt(p, cpsStmts, "nimln($1, $2);$n",
|
||||||
line.toRope, t.info.quotedFilename)
|
line.toRope, t.info.quotedFilename)
|
||||||
|
|
||||||
|
proc postStmtActions(p: BProc) {.inline.} =
|
||||||
|
app(p.s(cpsStmts), p.module.injectStmt)
|
||||||
|
|
||||||
proc accessThreadLocalVar(p: BProc, s: PSym)
|
proc accessThreadLocalVar(p: BProc, s: PSym)
|
||||||
proc emulatedThreadVars(): bool {.inline.}
|
proc emulatedThreadVars(): bool {.inline.}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ type
|
||||||
labels*: natural # for generating unique module-scope names
|
labels*: natural # for generating unique module-scope names
|
||||||
extensionLoaders*: array['0'..'9', PRope] # special procs for the
|
extensionLoaders*: array['0'..'9', PRope] # special procs for the
|
||||||
# OpenGL wrapper
|
# OpenGL wrapper
|
||||||
|
injectStmt*: PRope
|
||||||
|
|
||||||
var
|
var
|
||||||
mainModProcs*, mainModInit*, mainDatInit*: PRope # parts of the main module
|
mainModProcs*, mainModInit*, mainDatInit*: PRope # parts of the main module
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,8 @@ const
|
||||||
wFatal, wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop,
|
wFatal, wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop,
|
||||||
wBreakpoint, wWatchpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated,
|
wBreakpoint, wWatchpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated,
|
||||||
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
|
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
|
||||||
wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto}
|
wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto,
|
||||||
|
wInjectStmt}
|
||||||
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||||
wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
|
wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
|
||||||
wDeprecated, wExtern, wThread, wImportcpp, wImportobjc, wNoStackFrame,
|
wDeprecated, wExtern, wThread, wImportcpp, wImportobjc, wNoStackFrame,
|
||||||
|
|
@ -722,6 +723,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||||
of wOperator:
|
of wOperator:
|
||||||
if sym == nil: invalidPragma(it)
|
if sym == nil: invalidPragma(it)
|
||||||
else: sym.position = expectIntLit(c, it)
|
else: sym.position = expectIntLit(c, it)
|
||||||
|
of wInjectStmt:
|
||||||
|
if it.kind != nkExprColonExpr:
|
||||||
|
localError(it.info, errExprExpected)
|
||||||
|
else:
|
||||||
|
it.sons[1] = c.semExpr(c, it.sons[1])
|
||||||
else: invalidPragma(it)
|
else: invalidPragma(it)
|
||||||
else: invalidPragma(it)
|
else: invalidPragma(it)
|
||||||
else: processNote(c, it)
|
else: processNote(c, it)
|
||||||
|
|
|
||||||
|
|
@ -380,7 +380,8 @@ proc analyseThreadProc*(prc: PSym) =
|
||||||
var formals = skipTypes(prc.typ, abstractInst).n
|
var formals = skipTypes(prc.typ, abstractInst).n
|
||||||
for i in 1 .. formals.len-1:
|
for i in 1 .. formals.len-1:
|
||||||
var formal = formals.sons[i].sym
|
var formal = formals.sons[i].sym
|
||||||
c.mapping[formal.id] = toTheirs # thread receives foreign data!
|
# the input is copied and belongs to the thread:
|
||||||
|
c.mapping[formal.id] = toMine
|
||||||
discard analyse(c, prc.getBody)
|
discard analyse(c, prc.getBody)
|
||||||
|
|
||||||
proc needsGlobalAnalysis*: bool =
|
proc needsGlobalAnalysis*: bool =
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ type
|
||||||
wPassc, wPassl, wBorrow, wDiscardable,
|
wPassc, wPassl, wBorrow, wDiscardable,
|
||||||
wFieldChecks,
|
wFieldChecks,
|
||||||
wWatchPoint, wSubsChar,
|
wWatchPoint, wSubsChar,
|
||||||
wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto,
|
wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, wInjectStmt,
|
||||||
wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit,
|
wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit,
|
||||||
wNoStackFrame,
|
wNoStackFrame,
|
||||||
wImplicitStatic, wGlobal, wCodegenDecl,
|
wImplicitStatic, wGlobal, wCodegenDecl,
|
||||||
|
|
@ -142,7 +142,8 @@ const
|
||||||
"compiletime", "noinit",
|
"compiletime", "noinit",
|
||||||
"passc", "passl", "borrow", "discardable", "fieldchecks",
|
"passc", "passl", "borrow", "discardable", "fieldchecks",
|
||||||
"watchpoint",
|
"watchpoint",
|
||||||
"subschar", "acyclic", "shallow", "unroll", "linearscanend", "computedgoto",
|
"subschar", "acyclic", "shallow", "unroll", "linearscanend",
|
||||||
|
"computedgoto", "injectstmt",
|
||||||
"write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
|
"write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
|
||||||
"nostackframe", "implicitstatic", "global", "codegendecl",
|
"nostackframe", "implicitstatic", "global", "codegendecl",
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5053,6 +5053,18 @@ Note that this pragma is somewhat of a misnomer: Other backends will provide
|
||||||
the same feature under the same name.
|
the same feature under the same name.
|
||||||
|
|
||||||
|
|
||||||
|
Extern pragma
|
||||||
|
-------------
|
||||||
|
Like ``exportc`` or ``importc`` the `extern`:idx: pragma affects name
|
||||||
|
mangling. The string literal passed to ``extern`` can be a format string:
|
||||||
|
|
||||||
|
.. code-block:: Nimrod
|
||||||
|
proc p(s: string) {.extern: "prefix$1".} =
|
||||||
|
echo s
|
||||||
|
|
||||||
|
In the example the external name of ``p`` is set to ``prefixp``.
|
||||||
|
|
||||||
|
|
||||||
Bycopy pragma
|
Bycopy pragma
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -470,6 +470,19 @@ proc is declared in the generated code:
|
||||||
echo "realistic interrupt handler"
|
echo "realistic interrupt handler"
|
||||||
|
|
||||||
|
|
||||||
|
InjectStmt pragma
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
The `injectStmt`:idx: pragma can be used to inject a statement before every
|
||||||
|
other statement in the current module. It is only supposed to be used for
|
||||||
|
debugging:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
{.injectStmt: gcInvariants().}
|
||||||
|
|
||||||
|
# ... complex code here that produces crashes ...
|
||||||
|
|
||||||
|
|
||||||
LineDir option
|
LineDir option
|
||||||
--------------
|
--------------
|
||||||
The `lineDir`:idx: option can be turned on or off. If turned on the
|
The `lineDir`:idx: option can be turned on or off. If turned on the
|
||||||
|
|
|
||||||
|
|
@ -760,7 +760,7 @@ proc getOccupiedMem(a: TMemRegion): int {.inline.} =
|
||||||
# ---------------------- thread memory region -------------------------------
|
# ---------------------- thread memory region -------------------------------
|
||||||
|
|
||||||
template InstantiateForRegion(allocator: expr) =
|
template InstantiateForRegion(allocator: expr) =
|
||||||
when false:
|
when defined(fulldebug):
|
||||||
proc interiorAllocatedPtr*(p: pointer): pointer =
|
proc interiorAllocatedPtr*(p: pointer): pointer =
|
||||||
result = interiorAllocatedPtr(allocator, p)
|
result = interiorAllocatedPtr(allocator, p)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -345,8 +345,9 @@ proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) =
|
||||||
|
|
||||||
proc forAllChildren(cell: PCell, op: TWalkOp) =
|
proc forAllChildren(cell: PCell, op: TWalkOp) =
|
||||||
gcAssert(cell != nil, "forAllChildren: 1")
|
gcAssert(cell != nil, "forAllChildren: 1")
|
||||||
gcAssert(cell.typ != nil, "forAllChildren: 2")
|
gcAssert(isAllocatedPtr(gch.region, cell), "forAllChildren: 2")
|
||||||
gcAssert cell.typ.kind in {tyRef, tySequence, tyString}, "forAllChildren: 3"
|
gcAssert(cell.typ != nil, "forAllChildren: 3")
|
||||||
|
gcAssert cell.typ.kind in {tyRef, tySequence, tyString}, "forAllChildren: 4"
|
||||||
let marker = cell.typ.marker
|
let marker = cell.typ.marker
|
||||||
if marker != nil:
|
if marker != nil:
|
||||||
marker(cellToUsr(cell), op.int)
|
marker(cellToUsr(cell), op.int)
|
||||||
|
|
@ -361,7 +362,7 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
|
||||||
for i in 0..s.len-1:
|
for i in 0..s.len-1:
|
||||||
forAllChildrenAux(cast[pointer](d +% i *% cell.typ.base.size +%
|
forAllChildrenAux(cast[pointer](d +% i *% cell.typ.base.size +%
|
||||||
GenericSeqSize), cell.typ.base, op)
|
GenericSeqSize), cell.typ.base, op)
|
||||||
else: nil
|
else: discard
|
||||||
|
|
||||||
proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
|
proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
|
||||||
# we check the last 8 entries (cache line) for a slot that could be reused.
|
# we check the last 8 entries (cache line) for a slot that could be reused.
|
||||||
|
|
@ -408,8 +409,10 @@ proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
|
||||||
add(gch.zct, res)
|
add(gch.zct, res)
|
||||||
|
|
||||||
{.push stackTrace: off, profiler:off.}
|
{.push stackTrace: off, profiler:off.}
|
||||||
proc gcInvariant*(msg: string) =
|
proc gcInvariant*() =
|
||||||
sysAssert(allocInv(gch.region), msg)
|
sysAssert(allocInv(gch.region), "injected")
|
||||||
|
when defined(markForDebug):
|
||||||
|
markForDebug(gch)
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap): pointer =
|
proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap): pointer =
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@ const
|
||||||
logGC = false
|
logGC = false
|
||||||
traceGC = false # extensive debugging
|
traceGC = false # extensive debugging
|
||||||
alwaysCycleGC = false
|
alwaysCycleGC = false
|
||||||
alwaysGC = false # collect after every memory allocation (for debugging)
|
alwaysGC = defined(fulldebug) # collect after every memory
|
||||||
|
# allocation (for debugging)
|
||||||
leakDetector = false
|
leakDetector = false
|
||||||
overwriteFree = false
|
overwriteFree = false
|
||||||
trackAllocationSource = leakDetector
|
trackAllocationSource = leakDetector
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue