basic thread analysis working
This commit is contained in:
parent
c019d17561
commit
9f9f0f0818
11 changed files with 179 additions and 44 deletions
|
|
@ -1450,7 +1450,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
|||
of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
|
||||
mInSet:
|
||||
genSetOp(p, e, d, op)
|
||||
of mNewString, mNewStringOfCap, mCopyStr, mCopyStrLast, mExit:
|
||||
of mNewString, mNewStringOfCap, mCopyStr, mCopyStrLast, mExit, mCreateThread:
|
||||
genCall(p, e, d)
|
||||
of mReset: genReset(p, e)
|
||||
of mEcho: genEcho(p, e)
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ Advanced options:
|
|||
--genMapping generate a mapping file containing
|
||||
(Nimrod, mangled) identifier pairs
|
||||
--lineDir:on|off generation of #line directive on|off
|
||||
--checkpoints:on|off turn checkpoints on|off; for debugging Nimrod
|
||||
--threadanalysis:on|off turn thread analysis on|off
|
||||
--skipCfg do not read the general configuration file
|
||||
--skipProjCfg do not read the project's configuration file
|
||||
--gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC
|
||||
|
|
@ -252,7 +252,7 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
|
|||
of wForceBuild, wF: result = contains(gGlobalOptions, optForceFullMake)
|
||||
of wWarnings, wW: result = contains(gOptions, optWarns)
|
||||
of wHints: result = contains(gOptions, optHints)
|
||||
of wCheckpoints: result = contains(gOptions, optCheckpoints)
|
||||
of wThreadAnalysis: result = contains(gGlobalOptions, optThreadAnalysis)
|
||||
of wStackTrace: result = contains(gOptions, optStackTrace)
|
||||
of wLineTrace: result = contains(gOptions, optLineTrace)
|
||||
of wDebugger: result = contains(gOptions, optEndb)
|
||||
|
|
@ -367,7 +367,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
|||
of wWarning: ProcessSpecificNote(arg, wWarning, pass, info)
|
||||
of wHint: ProcessSpecificNote(arg, wHint, pass, info)
|
||||
of wHints: ProcessOnOffSwitch({optHints}, arg, pass, info)
|
||||
of wCheckpoints: ProcessOnOffSwitch({optCheckpoints}, arg, pass, info)
|
||||
of wThreadAnalysis: ProcessOnOffSwitchG({optThreadAnalysis}, arg, pass, info)
|
||||
of wStackTrace: ProcessOnOffSwitch({optStackTrace}, arg, pass, info)
|
||||
of wLineTrace: ProcessOnOffSwitch({optLineTrace}, arg, pass, info)
|
||||
of wDebugger:
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ type # please make sure we have under 32 options
|
|||
optEndb, # embedded debugger
|
||||
optByRef, # use pass by ref for objects
|
||||
# (for interfacing with C)
|
||||
optCheckpoints, # check for checkpoints (used for debugging)
|
||||
optProfiler # profiler turned on
|
||||
TOptions* = set[TOption]
|
||||
TGlobalOption* = enum
|
||||
|
|
@ -46,7 +45,9 @@ type # please make sure we have under 32 options
|
|||
optStdout, # output to stdout
|
||||
optSuggest, # ideTools: 'suggest'
|
||||
optContext, # ideTools: 'context'
|
||||
optDef # ideTools: 'def'
|
||||
optDef, # ideTools: 'def'
|
||||
optThreadAnalysis # thread analysis pass
|
||||
|
||||
TGlobalOptions* = set[TGlobalOption]
|
||||
TCommands* = enum # Nimrod's commands
|
||||
cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
|
||||
|
|
@ -71,7 +72,7 @@ var
|
|||
gOptions*: TOptions = {optObjCheck, optFieldCheck, optRangeCheck,
|
||||
optBoundsCheck, optOverflowCheck, optAssert, optWarns,
|
||||
optHints, optStackTrace, optLineTrace}
|
||||
gGlobalOptions*: TGlobalOptions = {optRefcGC}
|
||||
gGlobalOptions*: TGlobalOptions = {optRefcGC, optThreadAnalysis}
|
||||
gExitcode*: int8
|
||||
searchPaths*: TLinkedList
|
||||
outFile*: string = ""
|
||||
|
|
|
|||
|
|
@ -106,23 +106,23 @@ proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string =
|
|||
else: result = defaultStr
|
||||
|
||||
proc processMagic(c: PContext, n: PNode, s: PSym) =
|
||||
var v: string
|
||||
#if not (sfSystemModule in c.module.flags) then
|
||||
# liMessage(n.info, errMagicOnlyInSystem);
|
||||
#if sfSystemModule notin c.module.flags:
|
||||
# liMessage(n.info, errMagicOnlyInSystem)
|
||||
if n.kind != nkExprColonExpr:
|
||||
LocalError(n.info, errStringLiteralExpected)
|
||||
return
|
||||
var v: string
|
||||
if n.sons[1].kind == nkIdent: v = n.sons[1].ident.s
|
||||
else: v = expectStrLit(c, n)
|
||||
incl(s.flags, sfImportc)
|
||||
# magics don't need an implementation, so we
|
||||
# treat them as imported, instead of modifing a lot of working code
|
||||
# BUGFIX: magic does not imply ``lfNoDecl`` anymore!
|
||||
for m in countup(low(TMagic), high(TMagic)):
|
||||
if substr($m, 1) == v:
|
||||
s.magic = m
|
||||
return
|
||||
Message(n.info, warnUnknownMagic, v)
|
||||
break
|
||||
if s.magic == mNone: Message(n.info, warnUnknownMagic, v)
|
||||
elif s.magic != mCreateThread:
|
||||
# magics don't need an implementation, so we
|
||||
# treat them as imported, instead of modifing a lot of working code:
|
||||
incl(s.flags, sfImportc)
|
||||
|
||||
proc wordToCallConv(sw: TSpecialWord): TCallingConvention =
|
||||
# this assumes that the order of special words and calling conventions is
|
||||
|
|
|
|||
|
|
@ -568,7 +568,8 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
|||
of mEcho: result = semEcho(c, setMs(n, s))
|
||||
of mCreateThread:
|
||||
result = semDirectOp(c, n, flags)
|
||||
if optThreads in gGlobalOptions:
|
||||
if gGlobalOptions * {optThreads, optThreadAnalysis} ==
|
||||
{optThreads, optThreadAnalysis}:
|
||||
# XXX This analysis should be done as late as possible
|
||||
# (forward references!)
|
||||
semthreads.AnalyseThread(result)
|
||||
|
|
|
|||
|
|
@ -170,12 +170,23 @@ proc analyseCall(c: PProcCtx, n: PNode): TThreadOwner =
|
|||
var formal = skipTypes(prc.typ, abstractInst).n.sons[i].sym
|
||||
newCtx.mapping[formal.id] = call.args[i-1]
|
||||
pushInfoContext(n.info)
|
||||
computed[call] = analyse(newCtx, prc.ast.sons[codePos])
|
||||
result = analyse(newCtx, prc.ast.sons[codePos])
|
||||
if prc.typ.sons[0] != nil:
|
||||
if prc.ast.len > resultPos:
|
||||
result = newCtx.mapping[prc.ast.sons[resultPos].sym.id]
|
||||
else:
|
||||
result = toNil
|
||||
else:
|
||||
result = toVoid
|
||||
computed[call] = result
|
||||
popInfoContext()
|
||||
else:
|
||||
# ugh, cycle! We are already computing it but don't know the outcome yet...
|
||||
if prc.typ.sons[0] == nil: result = toVoid
|
||||
else: result = toNil
|
||||
result = computed[call]
|
||||
if result == toUndefined:
|
||||
# ugh, cycle! We are already computing it but don't know the
|
||||
# outcome yet...
|
||||
if prc.typ.sons[0] == nil: result = toVoid
|
||||
else: result = toNil
|
||||
|
||||
proc analyseVarTuple(c: PProcCtx, n: PNode) =
|
||||
if n.kind != nkVarTuple: InternalError(n.info, "analyseVarTuple")
|
||||
|
|
@ -210,28 +221,39 @@ template aggregateOwner(result, ana: expr) =
|
|||
if result == toNil: result = a
|
||||
else: localError(n.info, errDifferentHeaps)
|
||||
|
||||
proc analyseOp(c: PProcCtx, n: PNode): TThreadOwner =
|
||||
if n[0].kind != nkSym or n[0].sym.kind != skProc:
|
||||
Message(n.info, warnAnalysisLoophole, renderTree(n))
|
||||
result = toNil
|
||||
else:
|
||||
var prc = n[0].sym
|
||||
# XXX create thread!?
|
||||
case prc.magic
|
||||
of mNew, mNewFinalize, mNewSeq, mSetLengthStr, mSetLengthSeq,
|
||||
mAppendSeqElem, mReset, mAppendStrCh, mAppendStrStr:
|
||||
writeAccess(c, n[1], toMine)
|
||||
result = toVoid
|
||||
of mSwap:
|
||||
var a = analyse(c, n[2])
|
||||
writeAccess(c, n[1], a)
|
||||
writeAccess(c, n[2], a)
|
||||
result = toVoid
|
||||
of mIntToStr, mInt64ToStr, mFloatToStr, mBoolToStr, mCharToStr,
|
||||
mCStrToStr, mStrToStr, mEnumToStr,
|
||||
mConStrStr, mConArrArr, mConArrT,
|
||||
mConTArr, mConTT, mSlice,
|
||||
mRepr, mArrToSeq, mCopyStr, mCopyStrLast,
|
||||
mNewString, mNewStringOfCap:
|
||||
# XXX no check for effects in the arguments?
|
||||
result = toMine
|
||||
else:
|
||||
result = analyseCall(c, n)
|
||||
|
||||
proc analyse(c: PProcCtx, n: PNode): TThreadOwner =
|
||||
case n.kind
|
||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand,
|
||||
nkCallStrLit, nkHiddenCallConv:
|
||||
if n[0].kind != nkSym or n[0].sym.kind != skProc:
|
||||
Message(n.info, warnAnalysisLoophole, renderTree(n))
|
||||
result = toNil
|
||||
else:
|
||||
var prc = n[0].sym
|
||||
# XXX create thread!?
|
||||
case prc.magic
|
||||
of mNew, mNewFinalize, mNewSeq, mSetLengthStr, mSetLengthSeq,
|
||||
mAppendSeqElem, mReset, mAppendStrCh, mAppendStrStr:
|
||||
writeAccess(c, n[1], toMine)
|
||||
result = toVoid
|
||||
of mSwap:
|
||||
var a = analyse(c, n[2])
|
||||
writeAccess(c, n[1], a)
|
||||
writeAccess(c, n[2], a)
|
||||
result = toVoid
|
||||
else:
|
||||
result = analyseCall(c, n)
|
||||
result = analyseOp(c, n)
|
||||
of nkAsgn, nkFastAsgn:
|
||||
analyseAssign(c, n)
|
||||
result = toVoid
|
||||
|
|
@ -290,7 +312,8 @@ proc analyse(c: PProcCtx, n: PNode): TThreadOwner =
|
|||
of nkVarSection: result = analyseVarSection(c, n)
|
||||
of nkConstSection: result = analyseConstSection(c, n)
|
||||
of nkTypeSection, nkCommentStmt: result = toVoid
|
||||
of nkIfStmt, nkWhileStmt, nkTryStmt, nkCaseStmt, nkStmtList, nkBlockStmt:
|
||||
of nkIfStmt, nkWhileStmt, nkTryStmt, nkCaseStmt, nkStmtList, nkBlockStmt,
|
||||
nkElifBranch, nkElse, nkExceptBranch, nkOfBranch:
|
||||
for i in 0 .. <n.len: discard analyse(c, n[i])
|
||||
result = toVoid
|
||||
of nkBreakStmt, nkContinueStmt: result = toVoid
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ type
|
|||
wPassc, wT, wPassl, wL, wListcmd, wGendoc, wGenmapping, wOs, wCpu,
|
||||
wGenerate, wG, wC, wCpp, wBorrow, wRun, wR, wVerbosity, wV, wHelp, wH,
|
||||
wSymbolFiles, wFieldChecks, wX, wVersion, wAdvanced, wSkipcfg, wSkipProjCfg,
|
||||
wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar,
|
||||
wCc, wGenscript, wCheckPoint, wThreadAnalysis, wNoMain, wSubsChar,
|
||||
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
|
||||
wIndex,
|
||||
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit, wThreads,
|
||||
|
|
@ -100,7 +100,7 @@ const
|
|||
"gui", "passc", "t", "passl", "l", "listcmd", "gendoc", "genmapping", "os",
|
||||
"cpu", "generate", "g", "c", "cpp", "borrow", "run", "r", "verbosity", "v",
|
||||
"help", "h", "symbolfiles", "fieldchecks", "x", "version", "advanced",
|
||||
"skipcfg", "skipprojcfg", "cc", "genscript", "checkpoint", "checkpoints",
|
||||
"skipcfg", "skipprojcfg", "cc", "genscript", "checkpoint", "threadanalysis",
|
||||
"nomain", "subschar", "acyclic", "shallow", "unroll", "linearscanend",
|
||||
"index",
|
||||
"write", "putenv", "prependenv", "appendenv", "threadvar", "emit",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue