58 assert(
tcg !=
nullptr &&
"TCT::TCT: call graph is not a ThreadCallGraph!");
80 assert(inst &&
"null value instruction!!");
86 while(!worklist.
empty())
93 for(CallGraphEdge::CallInstSet::const_iterator cit = (*nit)->directCallsBegin(),
94 ecit = (*nit)->directCallsEnd(); cit!=ecit; ++cit)
96 if(insts.insert(*cit).second)
99 for(CallGraphEdge::CallInstSet::const_iterator cit = (*nit)->indirectCallsBegin(),
100 ecit = (*nit)->indirectCallsEnd(); cit!=ecit; ++cit)
102 if(insts.insert(*cit).second)
110 if(i->getFun()->hasLoopInfo(i->getBB()))
130 while(!worklist.
empty())
133 visits.insert(svffun);
134 if(
tcgSCC->isInCycle(
tcg->getCallGraphNode(svffun)->getId()))
141 for(CallGraphEdge::CallInstSet::const_iterator cit = (*nit)->directCallsBegin(),
142 ecit = (*nit)->directCallsEnd(); cit!=ecit; ++cit)
144 const FunObjVar* caller = (*cit)->getFun();
145 if(visits.find(caller)==visits.end())
146 worklist.
push(caller);
148 for(CallGraphEdge::CallInstSet::const_iterator cit = (*nit)->indirectCallsBegin(),
149 ecit = (*nit)->indirectCallsEnd(); cit!=ecit; ++cit)
151 const FunObjVar* caller = (*cit)->getFun();
152 if(visits.find(caller)==visits.end())
153 worklist.
push(caller);
167 for (ThreadCallGraph::CallSiteSet::const_iterator it =
tcg->forksitesBegin(), eit =
tcg->forksitesEnd(); it != eit; ++it)
169 const FunObjVar* svfun = (*it)->getParent()->getParent();
172 for(ThreadCallGraph::ForkEdgeSet::const_iterator nit =
tcg->getForkEdgeBegin(*it), neit =
tcg->getForkEdgeEnd(*it); nit!=neit; nit++)
180 for (ThreadCallGraph::CallSiteSet::const_iterator it =
tcg->joinsitesBegin(), eit =
tcg->joinsitesEnd(); it != eit; ++it)
182 const FunObjVar* svfun = (*it)->getParent()->getParent();
187 writeWrnMsg(
"We didn't recognize any fork site, this is single thread program?");
198 worklist.
push(cgnode);
199 visited.insert(cgnode);
200 while(!worklist.
empty())
207 if(visited.find(srcNode)==visited.end())
209 visited.insert(srcNode);
210 worklist.
push(srcNode);
222 for (
const auto&
item: *svfirCallGraph)
233 assert(!
entryFuncSet.empty() &&
"Can't find any function in module!");
247 while(!worklist.
empty())
258 for (TCT::ThreadCreateEdgeSet::const_iterator it = node->
getInEdges().begin(), eit = node->
getInEdges().end(); it != eit;
261 if ((*it)->getSrcNode()->isMultiforked())
265 for (TCT::ThreadCreateEdgeSet::const_iterator it = node->
getOutEdges().begin(), eit = node->
getOutEdges().end(); it != eit;
268 worklist.
push((*it)->getDstNode());
311 this->getTCTNode(ctp.
getTid())->getCxtThread().dump();
312 outs() <<
" to thread " << spawneeNode->
getId() <<
" ";
328 assert(!lp.empty() &&
"this is not a loop, empty basic block");
332 assert(loopheadbb->
getParent()==joinbb->
getParent() &&
"should inside same function");
338 if(svffun->
dominate(joinbb,svf_scc_bb)==
false)
352 for(ThreadCallGraph::CallSiteSet::const_iterator it =
tcg->joinsitesBegin(), eit =
tcg->joinsitesEnd(); it!=eit; ++it)
393 std::vector<const SVFBasicBlock*> exitbbs;
394 it->first->getFun()->getExitBlocksOfLoop(it->first->getBB(),exitbbs);
395 while(!exitbbs.empty())
455 for(CallGraphEdge::CallInstSet::const_iterator cit = cgEdge->
directCallsBegin(),
492 cxt.erase(cxt.begin());
518 if(cxt.back() == csId)
533 if (lhs.size() > call.size())
535 bool isSuffix =
true;
536 for (
size_t i = 0; i < lhs.size(); ++i)
538 if (lhs[lhs.size() - 1 - i] != call[call.size() - 1 - i])
554 std::stringstream rawstr(str);
556 for(CallStrCxt::const_iterator it = cxt.begin(), eit = cxt.end(); it!=eit; ++it)
558 rawstr <<
" ' "<< *it <<
" ' ";
559 rawstr << (
tcg->getCallSite(*it))->valueOnlyToString();
560 rawstr <<
" call " <<
tcg->getCallSite(*it)->getCaller()->getName() <<
"-->" <<
tcg->getCalleeOfCallSite(*it)->getName() <<
", \n";
563 outs() <<
"max cxt = " << cxt.size() << rawstr.str() <<
"\n";
581 outs() <<
"TID " << it->first <<
"\t";
582 it->second->getCxtThread().dump();
594 if (outEdge && inEdge)
596 assert(outEdge == inEdge &&
"edges not match");
608 for (TCTEdge::ThreadCreateEdgeSet::const_iterator iter = src->
OutEdgeBegin(); iter != src->
OutEdgeEnd(); ++iter)
636 return "Thread Create Tree";
641 return std::to_string(node->
getId());
649 attr.append(
"shape=record,style=filled,fillcolor=red");
653 attr.append(
"shape=record,style=filled,fillcolor=yellow");
658 template<
class EdgeIter>
664 assert(edge &&
"No edge found!!");
666 return "color=black";
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
CallInstSet::const_iterator indirectCallsBegin() const
CallInstSet::const_iterator directCallsEnd() const
CallInstSet::const_iterator indirectCallsEnd() const
CallInstSet::const_iterator directCallsBegin() const
Iterators for direct and indirect callsites.
const FunObjVar * getFunction() const
Get function of this call node.
const CallStrCxt & getContext() const
Return current context.
const FunObjVar * getProc() const
Return current procedure.
NodeID getTid() const
Return current thread id.
void dump() const
Dump CxtThreadProc.
void dump() const
Dump CxtThread.
bool push(const Data &data)
const SVFBasicBlock * getLoopHeader(const BBList &lp) const
const LoopBBs & getLoopInfo(const SVFBasicBlock *bb) const
bool dominate(const SVFBasicBlock *bbKey, const SVFBasicBlock *bbValue) const
bool loopContainsBB(const BBList &lp, const SVFBasicBlock *bb) const
bool hasLoopInfo(const SVFBasicBlock *bb) const
NodeType * getSrcNode() const
NodeType * getDstNode() const
GEdgeKind getEdgeKind() const
IDToNodeMapTy::const_iterator const_iterator
bool hasIncomingEdge() const
Has incoming/outgoing edge set.
bool hasOutgoingEdge() const
GEdgeSetTy::iterator iterator
const GEdgeSetTy & getOutEdges() const
const GEdgeSetTy & getInEdges() const
iterator OutEdgeBegin()
iterators
GEdgeSetTy::const_iterator const_iterator
static void WriteGraphToFile(SVF::OutStream &O, const std::string &GraphName, const GraphType >, bool simple=false)
virtual const FunObjVar * getFun() const
Return the function of this ICFGNode.
virtual const SVFBasicBlock * getBB() const
Return the basic block of this ICFGNode.
static Option< u32_t > MaxContextLen
static const Option< bool > TCTDotGraph
const FunObjVar * getParent() const
const ICFGNode * back() const
std::vector< const SVFBasicBlock * > getSuccessors() const
const CallGraph * getCallGraph()
Get CG.
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
NodeID getId() const
Get ID.
virtual const std::string & getName() const
const CxtThread & getCxtThread() const
Get thread creation context, <fork site, call string context>.
void setMultiforked(bool value)
bool isInloop() const
inloop, incycle attributes
bool pushToCTPWorkList(const CxtThreadProc &ctp)
WorkList helper functions.
bool isInRecursion(const ICFGNode *inst) const
Whether an instruction is in a recursion.
TCTNode * getTCTNode(NodeID id) const
Get TCT node.
bool isContextSuffix(const CallStrCxt &lhs, const CallStrCxt &call)
If lhs is a suffix of rhs, including equal.
TCTNode * getOrCreateTCTNode(const CallStrCxt &cxt, const ICFGNode *fork, const CxtThreadProc &forkSiteCtp, const FunObjVar *routine)
Get or create a tct node based on CxtThread.
virtual void collectLoopInfoForJoin()
Handle join site in loop.
ThreadCallGraphSCC * tcgSCC
Procedures we care about during call graph traversing when creating TCT.
virtual void collectEntryFunInCallGraph()
Get entry functions that are neither called by other functions nor extern functions.
Set< const CallGraphNode * > PTACGNodeSet
ICFGNode * createDummyForkSite()
Create and get a new dummy fork site for starter routines.
static std::unique_ptr< TCT > create(PointerAnalysis *p)
Construct and build a TCT with the command-line context bound.
DummyForkSiteSet dummyForkSites
set of dummy fork sites for starter routines
InstToLoopMap joinSiteToLoopMap
Map a CxtThread to its start routine function.
virtual ~TCT()
Destructor.
void dump(const std::string &filename)
Dump the graph.
FunSet candidateFuncSet
Procedures that are neither called by other functions nor extern functions.
bool inSameCallGraphSCC(const CallGraphNode *src, const CallGraphNode *dst)
Whether two functions in the same callgraph scc.
TCTEdge * getGraphEdge(TCTNode *src, TCTNode *dst, TCTEdge::CEDGEK kind)
Get call graph edge via nodes.
bool isCandidateFun(const CallGraph::FunctionSet &callees) const
Whether it is a candidate function for indirect call.
CxtThreadProcVec ctpList
Thread call graph SCC.
bool matchAndPopCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Match context.
bool isInLoopInstruction(const ICFGNode *inst)
Multi-forked threads.
bool isJoinMustExecutedInLoop(const LoopBBs &lp, const ICFGNode *join)
Return true if a join instruction must be executed inside a loop.
virtual void markRelProcs()
Mark relevant procedures that are backward reachable from any fork/join site.
Set< const ICFGNode * > inRecurJoinSites
Fork or Join sites in recursions.
void dumpCxt(CallStrCxt &cxt)
Dump calling context.
bool addTCTEdge(TCTNode *src, TCTNode *dst)
Add TCT edge.
TCT(PointerAnalysis *p, u32_t contextLimit)
bool isLoopHeaderOfJoinLoop(const SVFBasicBlock *bb)
Whether a given bb is a loop head of a inloop join site.
virtual void build()
Build TCT.
void print() const
Print TCT information.
virtual void handleCallRelation(CxtThreadProc &ctp, const CallGraphEdge *cgEdge, const CallICFGNode *call)
Handle call relations.
void collectMultiForkedThreads()
CxtThreadProc popFromCTPWorkList()
TCTEdge * hasGraphEdge(TCTNode *src, TCTNode *dst, TCTEdge::CEDGEK kind) const
Whether we have already created this call graph edge.
bool isLoopExitOfJoinLoop(const SVFBasicBlock *bb)
Whether a given bb is an exit of a inloop join site.
SVFLoopAndDomInfo::LoopBBs LoopBBs
const LoopBBs & getLoop(const ICFGNode *inst)
Get loop for an instruction.
virtual void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Context helper functions.
bool isExtCall(const FunObjVar *fun)
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
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::unordered_set< Key, Hash, KeyEqual, Allocator > Set
std::vector< u32_t > CallStrCxt
static std::string getEdgeAttributes(TCTNode *node, EdgeIter EI, TCT *csThreadTree)
NodeType::iterator ChildIteratorType
static std::string getGraphName(TCT *graph)
Return name of the graph.
static std::string getNodeAttributes(TCTNode *node, TCT *tct)
static std::string getNodeLabel(TCTNode *node, TCT *graph)
Return function name;.
DOTGraphTraits(bool isSimple=false)
DefaultDOTGraphTraits(bool simple=false)