45template<
class ICFGGraph,
class CGGraph>
73template<
class ICFGGraph,
class CGGraph>
79 for (
auto nodeIt = CGTraits::nodes_begin(cg),
80 nodeEnd = CGTraits::nodes_end(cg); nodeIt != nodeEnd; ++nodeIt)
106template<
class CGGraph>
115 for (InstSet::iterator it =
lockSites.begin(), eit =
lockSites.end(); it != eit; ++it)
119 if (visited.find(cgnode) == visited.end())
121 worklist.
push(cgnode);
122 visited.insert(cgnode);
129 if (visited.find(cgnode) == visited.end())
131 worklist.
push(cgnode);
132 visited.insert(cgnode);
135 while (!worklist.
empty())
139 std::vector<const CallGraphEdge*> inEdges;
144 if (visited.find(srcNode) == visited.end())
146 visited.insert(srcNode);
147 worklist.
push(srcNode);
157template<
class ICFGGraph>
162 for (InstSet::const_iterator it =
lockSites.begin(), ie =
lockSites.end(); it != ie; ++it)
165 assert(
isCallSite(lockSite) &&
"Lock acquire instruction must be a CallSite");
173 icfg, lockSite, unlockSet, forwardInsts);
175 icfg, unlockSet, backwardInsts);
178 if(forward && backward)
180 else if(forward && !backward)
188template<
class ICFGGraph>
197 worklist.push_back(lockSite);
198 while (!worklist.empty())
200 const ICFGNode *I = worklist.back();
204 if (exitInst ==
nullptr)
210 if (forwardInsts.find(I)!=forwardInsts.end())
212 forwardInsts.insert(I);
222 std::vector<const ICFGNode*> succ;
226 if(dst->getFun() == I->
getFun())
228 worklist.push_back(dst);
240template<
class ICFGGraph>
246 for(InstSet::const_iterator it = unlockSet.begin(), eit = unlockSet.end(); it!=eit; ++it)
250 worklist.push_back(*it);
252 while (!worklist.empty())
254 const ICFGNode *I = worklist.back();
261 if (backwardInsts.find(I)!=backwardInsts.end())
263 backwardInsts.insert(I);
272 std::vector<const ICFGNode*> pred;
276 if(src->getFun() == I->
getFun())
278 worklist.push_back(src);
288template<
class ICFGGraph,
class CGGraph>
292 for (TCT::FunSet::const_iterator it = entryFuncSet.begin(), eit = entryFuncSet.end(); it != eit; ++it)
308 std::vector<const CallGraphEdge*> outEdges;
312 std::vector<const CallICFGNode*> directCalls;
314 cg, cgEdge, directCalls);
318 outs() <<
"\nCollecting CxtLocks: handling direct call:" << *callSite <<
"\t" << cgEdge->getSrcNode()->getFunction()->getName()
319 <<
"-->" << cgEdge->getDstNode()->getFunction()->getName() <<
"\n");
322 std::vector<const CallICFGNode*> indirectCalls;
324 cg, cgEdge, indirectCalls);
328 outs() <<
"\nCollecting CxtLocks: handling indirect call:" << *callSite <<
"\t"
329 << cgEdge->getSrcNode()->getFunction()->getName() <<
"-->" << cgEdge->getDstNode()->getFunction()->getName()
341template<
class ICFGGraph,
class CGGraph>
373template<
class ICFGGraph,
class CGGraph>
378 for (TCT::FunSet::const_iterator it = entryFuncSet.begin(), eit = entryFuncSet.end(); it != eit; ++it)
386 CxtStmt cxtstmt(cxt, frontInst);
398 const bool firstContextVisit =
instToCxtStmtSet[curInst].insert(cts).second;
452 outs() <<
"\nlock sets size = " << lockset.size() <<
"\n";
453 for (CxtLockSet::const_iterator it = lockset.begin(), eit = lockset.end(); it != eit; ++it)
462template<
class ICFGGraph,
class CGGraph>
468 std::vector<const CallGraphEdge*> outEdges;
477 pushCxt(newCxt, call, svfcallee);
480 if (svfInst ==
nullptr)
482 CxtStmt newCts(newCxt, svfInst);
489template<
class ICFGGraph,
class CGGraph>
496 std::vector<const CallGraphEdge*> outEdges;
507 pushCxt(newCxt, call, svfcallee);
510 if (svfInst ==
nullptr)
512 CxtStmt newCts(newCxt, svfInst);
521 if (exitInst ==
nullptr)
523 CxtStmt exitCts(newCxt, exitInst);
529 CxtStmt retCts(curCxt, retNode);
539 const ICFGNode* callsite,
const std::vector<const ICFGNode*>& successors)
543 if (!
matchCxt(callerCxt, call, callee))
546 for (
const ICFGNode* successor : successors)
548 if (successor->getFun() != callsite->
getFun())
553 if (matchingContexts ==
nullptr)
556 for (
const CallStrCxt& callsiteCxt : *matchingContexts)
558 CxtStmt returnCxtStmt(callsiteCxt, successor);
565template<
class ICFGGraph,
class CGGraph>
573 std::vector<const ICFGNode*> succ;
576 std::vector<const CallGraphEdge*> inEdges;
582 std::vector<const CallICFGNode*> directCalls;
584 cg, edgeConst, directCalls);
589 std::vector<const CallICFGNode*> indirectCalls;
591 cg, edgeConst, indirectCalls);
599template<
class ICFGGraph,
class CGGraph>
606 std::vector<const ICFGNode*> succ;
610 if(dst->getFun() == curInst->
getFun())
620 tct->pushCxt(cxt,call,callee);
636 if (
tct->inSameCallGraphSCC(
getTCG()->getCallGraphNode(svfcaller),
getTCG()->getCallGraphNode(callee)) ==
false)
638 if (cxt.back() == csId)
649 return tct->isContextSuffix(lhs,call);
659 bool commonlock =
false;
680 for (InstSet::const_iterator cil1 = lockset1.begin(), ecil1 = lockset1.end(); cil1!=ecil1; ++cil1)
682 for (InstSet::const_iterator cil2=lockset2.begin(), ecil2=lockset2.end(); cil2!=ecil2; ++cil2)
701 return alias(lockset1,lockset2);
713 for (CxtStmtSet::const_iterator cts1 = ctsset1.begin(), ects1 = ctsset1.end(); cts1 != ects1; cts1++)
715 const CxtStmt& cxtStmt1 = *cts1;
716 for (CxtStmtSet::const_iterator cts2 = ctsset2.begin(), ects2 = ctsset2.end(); cts2 != ects2; cts2++)
718 const CxtStmt& cxtStmt2 = *cts2;
719 if(cxtStmt1==cxtStmt2)
746 bool sameSpan =
false;
766 for (InstSet::const_iterator cil1 = lockset1.begin(), ecil1 = lockset1.end(); cil1!=ecil1; ++cil1)
768 for (InstSet::const_iterator cil2=lockset2.begin(), ecil2=lockset2.end(); cil2!=ecil2; ++cil2)
799 for (CxtStmtSet::const_iterator cts1 = ctsset1.begin(), ects1 = ctsset1.end(); cts1 != ects1; cts1++)
801 const CxtStmt& cxtStmt1 = *cts1;
802 for (CxtStmtSet::const_iterator cts2 = ctsset2.begin(), ects2 = ctsset2.end(); cts2 != ects2; cts2++)
804 const CxtStmt& cxtStmt2 = *cts2;
805 if(cxtStmt1==cxtStmt2)
continue;
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
const FunObjVar * getFunction() const
Get function of this call node.
const CallGraphNode * getCallGraphNode(const std::string &name) const
Get call graph node.
CallSiteID getCallSiteID(const CallICFGNode *cs, const FunObjVar *callee) const
Get CallSiteID.
const RetICFGNode * getRetICFGNode() const
Return callsite.
void dump() const
Dump CxtProc.
const CallStrCxt & getContext() const
Return current context.
const FunObjVar * getProc() const
Return current procedure.
void dump() const
Dump CxtStmt.
const CallStrCxt & getContext() const
Return current context.
const ICFGNode * getStmt() const
Return current statement.
bool push(const Data &data)
virtual const FunObjVar * getFunction() const
Get containing function, or null for globals/constants.
const SVFBasicBlock * getEntryBlock() const
bool hasBasicBlock() const
NodeType * getDstNode() const
virtual const FunObjVar * getFun() const
Return the function of this ICFGNode.
Set< CxtLock > CxtLockSet
void analyze(ICFGGraph icfg, CGGraph cg)
bool removeCxtStmtToSpan(CxtStmt &cts, const CxtLock &cl)
Add context-sensitive statement.
CxtStmtWorkList cxtStmtList
context-sensitive statement worklist
bool isProtectedByCommonCILock(const ICFGNode *i1, const ICFGNode *i2)
void handleIntra(ICFGGraph icfg, CGGraph cg, const CxtStmt &cts)
Handle intra.
bool isInSameCSSpan(const ICFGNode *i1, const ICFGNode *i2) const
bool intraBackwardTraverse(ICFGGraph icfg, const InstSet &unlockSet, InstSet &backwardInsts)
bool isProtectedByCommonLock(const ICFGNode *i1, const ICFGNode *i2)
bool isInSameSpan(const ICFGNode *I1, const ICFGNode *I2)
void markCxtStmtFlag(const CxtStmt &tgr, const CxtStmt &src)
Mark thread flags for cxtStmt.
bool isExtCall(const ICFGNode *inst)
Whether it is calling an external function.
Set< CxtStmt > CxtStmtSet
void handleReturnAtCallsite(const CxtStmt &exitCxtStmt, const FunObjVar *callee, const ICFGNode *callsite, const std::vector< const ICFGNode * > &successors)
Propagate a callee-exit lock state to one matching callsite context.
bool alias(const CxtLockSet &lockset1, const CxtLockSet &lockset2)
Return true if two locksets has at least one alias lock.
void handleFork(ICFGGraph icfg, CGGraph cg, const CxtStmt &cts)
Handle fork.
CxtStmt popFromCTSWorkList()
bool isInsideIntraLock(const ICFGNode *stmt) const
Return true if a statement is inside an intra-procedural lock.
const SVFVar * getLockVal(const ICFGNode *call)
Get lock value.
void analyzeLockSpanCxtStmt(ICFGGraph icfg, CGGraph cg)
FunSet lockCandidateFuncSet
Candidate functions which relevant to locks/unlocks.
ThreadCallGraph * getTCG() const
ThreadCallGraph.
bool isInsideCondIntraLock(const ICFGNode *stmt) const
Return true if a statement is inside a partial lock/unlock pair (conditional lock with unconditional ...
Set< CallStrCxt > CallStrCxtSet
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Context helper functions.
bool intraForwardTraverse(ICFGGraph icfg, const ICFGNode *lock, InstSet &unlockSet, InstSet &forwardInsts)
void addCondIntraLock(const ICFGNode *lockSite, const InstSet &stmts)
Add intra-procedural lock.
bool hasCxtLock(const CxtLock &cxtLock) const
Get context-sensitive lock.
bool isTDRelease(const ICFGNode *call)
Whether it is a unlock site.
bool addCxtStmtToSpan(const CxtStmt &cts, const CxtLock &cl)
Add context-sensitive statement.
InstSet lockSites
Record all visited clps.
bool isTDFork(const ICFGNode *call)
Whether it is a lock site.
void handleRet(ICFGGraph icfg, CGGraph cg, const CxtStmt &cts)
Handle return.
bool isProtectedByCommonCxtLock(const ICFGNode *i1, const ICFGNode *i2)
bool pushToCTPWorkList(const CxtLockProc &clp)
WorkList helper functions.
const InstSet & getIntraLockSet(const ICFGNode *stmt) const
void handleCall(ICFGGraph icfg, CGGraph cg, const CxtStmt &cts)
Handle call.
const CxtLockSet & getCxtLockFromCxtStmt(const CxtStmt &cts) const
bool hasCxtStmtFromInst(const ICFGNode *inst) const
Context-sensitive statement and lock spans.
bool pushToCTSWorkList(const CxtStmt &cs)
Worklist operations.
void addIntraLock(const ICFGNode *lockSite, const InstSet &stmts)
Add intra-procedural lock.
void touchCxtStmt(CxtStmt &cts)
Touch this context statement.
Set< const ICFGNode * > InstSet
const CallStrCxtSet * getCallsiteContextsWithSuffix(const ICFGNode *inst, const CallStrCxt &suffix) const
bool isLockCandidateFun(const FunObjVar *fun) const
Return true if it is a candidate function.
void analyzeIntraProceduralLock(ICFGGraph icfg)
void buildCandidateFuncSetForLock(CGGraph cg)
void printLocks(const CxtStmt &cts)
Print locks and spans.
bool isContextSuffix(const CallStrCxt &lhs, const CallStrCxt &call)
If lhs is a suffix of rhs, including equal.
CxtLockProc popFromCTPWorkList()
bool matchCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Match context.
void collectLockUnlockSites(ICFGGraph icfg, CGGraph cg)
void handleCallRelation(ICFGGraph icfg, CGGraph cg, CxtLockProc &clp, const CallGraphEdge *cgEdge, const CallICFGNode *call)
Handle call relations.
const CxtStmtSet & getCxtStmtsFromInst(const ICFGNode *inst) const
bool isInSameCISpan(const ICFGNode *i1, const ICFGNode *i2) const
void collectCxtLock(ICFGGraph icfg, CGGraph cg)
bool isAliasedLocks(const CxtLock &cl1, const CxtLock &cl2)
Return true it a lock matches an unlock.
bool hasCxtLockFromCxtStmt(const CxtStmt &cts) const
InstToCxtStmtSet instToCxtStmtSet
Map a statement to all its context-sensitive statements.
void addCxtLock(const CallStrCxt &cxt, const ICFGNode *inst)
Context-sensitive locks.
bool intersects(const CxtLockSet &lockset1, const CxtLockSet &lockset2) const
Return true if the intersection of two locksets is not empty.
void indexCallsiteContext(const ICFGNode *inst, const CallStrCxt &cxt)
bool isCallSite(const ICFGNode *inst)
Whether it is a callsite.
CxtLockProcVec clpList
Following data structures are used for collecting context-sensitive locks.
bool isTDAcquire(const ICFGNode *call)
Whether it is a lock site.
const std::vector< const ICFGNode * > & getICFGNodeList() const
const ICFGNode * back() const
static double getClk(bool mark=false)
virtual const std::string getSourceLoc() const
OrderedSet< const FunObjVar *, FunObjVarIdCmp > FunSet
Set< const CallGraphNode * > PTACGNodeSet
bool isTDRelease(const CallICFGNode *inst) const
Return true if this call release a lock.
bool isTDAcquire(const CallICFGNode *inst) const
Return true if this call acquire a lock.
ThreadAPI * getThreadAPI() const
Thread API.
std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > cast(const Y &Val)
LLVM_NODISCARD bool isa(const Y &Val)
bool isExtCall(const FunObjVar *fun)
std::ostream & outs()
Overwrite llvm::outs().
LLVM_NODISCARD std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
std::vector< u32_t > CallStrCxt