Static Value-Flow Analysis
Loading...
Searching...
No Matches
TCT.cpp
Go to the documentation of this file.
1//===- TCT.cpp -- Thread creation tree-------------//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-> <Yulei Sui>
6//
7
8// This program is free software: you can redistribute it and/or modify
9// it under the terms of the GNU Affero General Public License as published by
10// the Free Software Foundation, either version 3 of the License, or
11// (at your option) any later version.
12
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU Affero General Public License for more details.
17
18// You should have received a copy of the GNU Affero General Public License
19// along with this program. If not, see <http://www.gnu.org/licenses/>.
20//
21//===----------------------------------------------------------------------===//
22
23
24/*
25 * TCT.cpp
26 *
27 * Created on: Jun 24, 2015
28 * Author: Yulei Sui, Peng Di
29 */
30
31#include "Util/Options.h"
32#include "MTA/TCT.h"
33#include "MTA/MTA.h"
34#include "Graphs/CallGraph.h"
35
36#include <string>
37
38using namespace SVF;
39using namespace SVFUtil;
40
47{
48 assert(inst && "null value instruction!!");
49
52 worklist.push(inst);
53
54 while(!worklist.empty())
55 {
56 const ICFGNode* inst = worklist.pop();
57 insts.insert(inst);
59 for(CallGraphNode::const_iterator nit = cgnode->InEdgeBegin(), neit = cgnode->InEdgeEnd(); nit!=neit; nit++)
60 {
61 for(CallGraphEdge::CallInstSet::const_iterator cit = (*nit)->directCallsBegin(),
62 ecit = (*nit)->directCallsEnd(); cit!=ecit; ++cit)
63 {
64 if(insts.insert(*cit).second)
65 worklist.push(*cit);
66 }
67 for(CallGraphEdge::CallInstSet::const_iterator cit = (*nit)->indirectCallsBegin(),
68 ecit = (*nit)->indirectCallsEnd(); cit!=ecit; ++cit)
69 {
70 if(insts.insert(*cit).second)
71 worklist.push(*cit);
72 }
73 }
74 }
75
76 for(const ICFGNode* i : insts)
77 {
78 if(i->getFun()->hasLoopInfo(i->getBB()))
79 return true;
80 }
81
82
83 return false;
84}
85
91bool TCT::isInRecursion(const ICFGNode* inst) const
92{
93 const FunObjVar* f = inst->getFun();
96 worklist.push(f);
97
98 while(!worklist.empty())
99 {
100 const FunObjVar* svffun = worklist.pop();
101 visits.insert(svffun);
102 if(tcgSCC->isInCycle(tcg->getCallGraphNode(svffun)->getId()))
103 return true;
104
106
107 for(CallGraphNode::const_iterator nit = cgnode->InEdgeBegin(), neit = cgnode->InEdgeEnd(); nit!=neit; nit++)
108 {
109 for(CallGraphEdge::CallInstSet::const_iterator cit = (*nit)->directCallsBegin(),
110 ecit = (*nit)->directCallsEnd(); cit!=ecit; ++cit)
111 {
112 const FunObjVar* caller = (*cit)->getFun();
113 if(visits.find(caller)==visits.end())
114 worklist.push(caller);
115 }
116 for(CallGraphEdge::CallInstSet::const_iterator cit = (*nit)->indirectCallsBegin(),
117 ecit = (*nit)->indirectCallsEnd(); cit!=ecit; ++cit)
118 {
119 const FunObjVar* caller = (*cit)->getFun();
120 if(visits.find(caller)==visits.end())
121 worklist.push(caller);
122 }
123 }
124 }
125
126 return false;
127
128}
129
134{
135 for (ThreadCallGraph::CallSiteSet::const_iterator it = tcg->forksitesBegin(), eit = tcg->forksitesEnd(); it != eit; ++it)
136 {
137 const FunObjVar* svfun = (*it)->getParent()->getParent();
139
140 for(ThreadCallGraph::ForkEdgeSet::const_iterator nit = tcg->getForkEdgeBegin(*it), neit = tcg->getForkEdgeEnd(*it); nit!=neit; nit++)
141 {
142 const CallGraphNode* forkeeNode = (*nit)->getDstNode();
143 candidateFuncSet.insert(forkeeNode->getFunction());
144 }
145
146 }
147
148 for (ThreadCallGraph::CallSiteSet::const_iterator it = tcg->joinsitesBegin(), eit = tcg->joinsitesEnd(); it != eit; ++it)
149 {
150 const FunObjVar* svfun = (*it)->getParent()->getParent();
152 }
153
154 if(candidateFuncSet.empty())
155 writeWrnMsg("We didn't recognize any fork site, this is single thread program?");
156}
157
162{
165 PTACGNodeSet visited;
166 worklist.push(cgnode);
167 visited.insert(cgnode);
168 while(!worklist.empty())
169 {
170 const CallGraphNode* node = worklist.pop();
171 candidateFuncSet.insert(node->getFunction());
173 {
174 const CallGraphNode* srcNode = (*nit)->getSrcNode();
175 if(visited.find(srcNode)==visited.end())
176 {
177 visited.insert(srcNode);
178 worklist.push(srcNode);
179 }
180 }
181 }
182}
183
188{
190 for (const auto& item: *svfirCallGraph)
191 {
192 const FunObjVar* fun = item.second->getFunction();
193 if (SVFUtil::isExtCall(fun))
194 continue;
195 CallGraphNode* node = tcg->getCallGraphNode(fun);
196 if (!node->hasIncomingEdge())
197 {
198 entryFuncSet.insert(fun);
199 }
200 }
201 assert(!entryFuncSet.empty() && "Can't find any function in module!");
202}
203
208{
209 if (this->nodeNum == 0 )
210 return;
211
212 FIFOWorkList<TCTNode*> worklist;
213 worklist.push(getTCTNode(0));
214
215 while(!worklist.empty())
216 {
217 TCTNode* node = worklist.pop();
218 const CxtThread &ct = node->getCxtThread();
219
220 if(ct.isIncycle() || ct.isInloop())
221 {
222 node->setMultiforked(true);
223 }
224 else
225 {
226 for (TCT::ThreadCreateEdgeSet::const_iterator it = node->getInEdges().begin(), eit = node->getInEdges().end(); it != eit;
227 ++it)
228 {
229 if ((*it)->getSrcNode()->isMultiforked())
230 node->setMultiforked(true);
231 }
232 }
233 for (TCT::ThreadCreateEdgeSet::const_iterator it = node->getOutEdges().begin(), eit = node->getOutEdges().end(); it != eit;
234 ++it)
235 {
236 worklist.push((*it)->getDstNode());
237 }
238 }
239}
240
241
246{
247 const FunObjVar* callee = cgEdge->getDstNode()->getFunction();
248
249 CallStrCxt cxt(ctp.getContext());
250 CallStrCxt oldCxt = cxt;
251 const CallICFGNode* callNode = cs;
252
254 if(isCandidateFun(callNode->getFun()) == true)
256
257 if(cgEdge->getEdgeKind() == CallGraphEdge::CallRetEdge)
258 {
259 CxtThreadProc newctp(ctp.getTid(),cxt,callee);
261 {
262 DBOUT(DMTA,outs() << "TCT Process CallRet old ctp --"; ctp.dump());
263 DBOUT(DMTA,outs() << "TCT Process CallRet new ctp --"; newctp.dump());
264 }
265 }
266
267 else if(cgEdge->getEdgeKind() == CallGraphEdge::TDForkEdge)
268 {
272
274 {
276 if(addTCTEdge(this->getGNode(ctp.getTid()), spawneeNode))
277 {
278 DBOUT(DMTA,outs() << "Add TCT Edge from thread " << ctp.getTid() << " ";
279 this->getGNode(ctp.getTid())->getCxtThread().dump();
280 outs() << " to thread " << spawneeNode->getId() << " ";
281 spawneeNode->getCxtThread().dump();
282 outs() << "\n" );
283 }
284 DBOUT(DMTA,outs() << "TCT Process Fork old ctp --"; ctp.dump());
285 DBOUT(DMTA,outs() << "TCT Process Fork new ctp --"; newctp.dump());
286 }
287 }
288}
289
295{
296 assert(!lp.empty() && "this is not a loop, empty basic block");
297 const FunObjVar* svffun = join->getFun();
298 const SVFBasicBlock* loopheadbb = svffun->getLoopHeader(lp);
299 const SVFBasicBlock* joinbb = join->getBB();
300 assert(loopheadbb->getParent()==joinbb->getParent() && "should inside same function");
301
302 for (const SVFBasicBlock* svf_scc_bb : loopheadbb->getSuccessors())
303 {
304 if(svffun->loopContainsBB(lp,svf_scc_bb))
305 {
306 if(svffun->dominate(joinbb,svf_scc_bb)==false)
307 return false;
308 }
309 }
310
311 return true;
312}
313
319{
320 for(ThreadCallGraph::CallSiteSet::const_iterator it = tcg->joinsitesBegin(), eit = tcg->joinsitesEnd(); it!=eit; ++it)
321 {
322 const ICFGNode* join = *it;
323 const FunObjVar* svffun = join->getFun();
324 const SVFBasicBlock* svfbb = join->getBB();
325
326 if(svffun->hasLoopInfo(svfbb))
327 {
328 const LoopBBs& lp = svffun->getLoopInfo(svfbb);
329 if(!lp.empty() && isJoinMustExecutedInLoop(lp,join))
330 {
332 }
333 }
334
336 inRecurJoinSites.insert(join);
337 }
338}
339
344{
345 for(InstToLoopMap::const_iterator it = joinSiteToLoopMap.begin(), eit = joinSiteToLoopMap.end(); it!=eit; ++it)
346 {
347 if(bb->getParent()->getLoopHeader(it->second) == bb)
348 return true;
349 }
350
351 return false;
352}
353
358{
359 for(InstToLoopMap::const_iterator it = joinSiteToLoopMap.begin(), eit = joinSiteToLoopMap.end(); it!=eit; ++it)
360 {
361 std::vector<const SVFBasicBlock*> exitbbs;
362 it->first->getFun()->getExitBlocksOfLoop(it->first->getBB(),exitbbs);
363 while(!exitbbs.empty())
364 {
365 const SVFBasicBlock* eb = exitbbs.back();
366 exitbbs.pop_back();
367 if(eb == bb)
368 return true;
369 }
370 }
371
372 return false;
373}
374
379{
380 const FunObjVar* fun = bb->getParent();
381 return fun->getLoopInfo(bb);
382}
383
388{
389
390 markRelProcs();
391
393
394 // the fork site of main function is initialized with nullptr.
395 // the context of main is initialized with empty
396 // start routine is empty
397
399 for (FunSet::iterator it=entryFuncSet.begin(), eit=entryFuncSet.end(); it!=eit; ++it)
400 {
401 if (!isCandidateFun(*it))
402 continue;
403 CallStrCxt cxt;
404 CxtThreadProc dummyCtp(-1, cxt, nullptr);
406 CxtThreadProc t(mainTCTNode->getId(), cxt, *it);
408 }
409
410 while(!ctpList.empty())
411 {
413 CallGraphNode* cgNode = tcg->getCallGraphNode(ctp.getProc());
414 if(isCandidateFun(cgNode->getFunction()) == false)
415 continue;
416
417 for(CallGraphNode::const_iterator nit = cgNode->OutEdgeBegin(), neit = cgNode->OutEdgeEnd(); nit!=neit; nit++)
418 {
419 const CallGraphEdge* cgEdge = (*nit);
420
421 for(CallGraphEdge::CallInstSet::const_iterator cit = cgEdge->directCallsBegin(),
422 ecit = cgEdge->directCallsEnd(); cit!=ecit; ++cit)
423 {
424 DBOUT(DMTA,outs() << "\nTCT handling direct call:" << **cit << "\t" << cgEdge->getSrcNode()->getFunction()->getName() << "-->" << cgEdge->getDstNode()->getFunction()->getName() << "\n");
426 }
427 for(CallGraphEdge::CallInstSet::const_iterator ind = cgEdge->indirectCallsBegin(),
428 eind = cgEdge->indirectCallsEnd(); ind!=eind; ++ind)
429 {
430 DBOUT(DMTA,outs() << "\nTCT handling indirect call:" << **ind << "\t" << cgEdge->getSrcNode()->getFunction()->getName() << "-->" << cgEdge->getDstNode()->getFunction()->getName() << "\n");
432 }
433 }
434 }
435
437
439 {
440 print();
441 dump("tct");
442 }
443
444}
445
449void TCT::pushCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee)
450{
451 const FunObjVar* caller = call->getFun();
452 CallSiteID csId = tcg->getCallSiteID(call, callee);
453
455 {
456 cxt.push_back(csId);
457 if (cxt.size() > Options::MaxContextLen())
458 cxt.erase(cxt.begin());
459 if (cxt.size() > MaxCxtSize)
460 MaxCxtSize = cxt.size();
461 DBOUT(DMTA,dumpCxt(cxt));
462 }
463}
464
465
470{
471 const FunObjVar* caller = call->getFun();
472 CallSiteID csId = tcg->getCallSiteID(call, callee);
473
475 if(isCandidateFun(caller) == false)
476 return true;
477
479 if(cxt.empty())
480 return true;
481
483 {
484 if(cxt.back() == csId)
485 cxt.pop_back();
486 else
487 return false;
488 DBOUT(DMTA,dumpCxt(cxt));
489 }
490
491 return true;
492}
493
498{
499 if (lhs.size() > call.size())
500 return false;
501 bool isSuffix = true;
502 for (size_t i = 0; i < lhs.size(); ++i)
503 {
504 if (lhs[lhs.size() - 1 - i] != call[call.size() - 1 - i])
505 {
506 isSuffix = false;
507 break;
508 }
509 }
510 return isSuffix;
511}
512
513
518{
519 std::string str;
520 std::stringstream rawstr(str);
521 rawstr << "[:";
522 for(CallStrCxt::const_iterator it = cxt.begin(), eit = cxt.end(); it!=eit; ++it)
523 {
524 rawstr << " ' "<< *it << " ' ";
525 rawstr << (tcg->getCallSite(*it))->valueOnlyToString();
526 rawstr << " call " << tcg->getCallSite(*it)->getCaller()->getName() << "-->" << tcg->getCalleeOfCallSite(*it)->getName() << ", \n";
527 }
528 rawstr << " ]";
529 outs() << "max cxt = " << cxt.size() << rawstr.str() << "\n";
530}
531
535void TCT::dump(const std::string& filename)
536{
538}
539
543void TCT::print() const
544{
545 for(TCT::const_iterator it = this->begin(), eit = this->end(); it!=eit; ++it)
546 {
547 outs() << "TID " << it->first << "\t";
548 it->second->getCxtThread().dump();
549 }
550}
551
556{
557 TCTEdge edge(src, dst, kind);
560 if (outEdge && inEdge)
561 {
562 assert(outEdge == inEdge && "edges not match");
563 return outEdge;
564 }
565 else
566 return nullptr;
567}
568
573{
574 for (TCTEdge::ThreadCreateEdgeSet::const_iterator iter = src->OutEdgeBegin(); iter != src->OutEdgeEnd(); ++iter)
575 {
576 TCTEdge* edge = (*iter);
577 if (edge->getEdgeKind() == kind && edge->getDstID() == dst->getId())
578 return edge;
579 }
580 return nullptr;
581}
582namespace SVF
583{
584
588template<>
590{
591
594 DOTGraphTraits(bool isSimple = false) :
595 DefaultDOTGraphTraits(isSimple)
596 {
597 }
598
600 static std::string getGraphName(TCT *graph)
601 {
602 return "Thread Create Tree";
603 }
605 static std::string getNodeLabel(TCTNode *node, TCT *graph)
606 {
607 return std::to_string(node->getId());
608 }
609
610 static std::string getNodeAttributes(TCTNode *node, TCT *tct)
611 {
612 std::string attr;
613 if (node->isInloop())
614 {
615 attr.append(" style=filled fillcolor=red");
616 }
617 else if (node->isIncycle())
618 {
619 attr.append(" style=filled fillcolor=yellow");
620 }
621 return attr;
622 }
623
624 template<class EdgeIter>
626 {
627
628 TCTEdge* edge = csThreadTree->getGraphEdge(node, *EI, TCTEdge::ThreadCreateEdge);
629 (void)edge; // Suppress warning of unused variable under release build
630 assert(edge && "No edge found!!");
632 return "color=black";
633 }
634};
635} // End namespace llvm
636
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:497
#define DMTA
Definition SVFType.h:518
cJSON * item
Definition cJSON.h:222
const FunObjVar * getFunction() const
Get function of this call node.
Definition CallGraph.h:191
const CallGraphNode * getCallGraphNode(const std::string &name) const
Get call graph node.
const CallICFGNode * getCallSite(CallSiteID id) const
Definition CallGraph.h:396
const FunObjVar * getCalleeOfCallSite(CallSiteID id) const
Definition CallGraph.h:401
CallSiteID getCallSiteID(const CallICFGNode *cs, const FunObjVar *callee) const
Get CallSiteID.
Definition CallGraph.h:377
const FunObjVar * getCaller() const
Return callsite.
Definition ICFGNode.h:442
NodeID getTid() const
Return current thread id.
Definition CxtStmt.h:412
bool push(const Data &data)
Definition WorkList.h:165
bool empty() const
Definition WorkList.h:146
virtual const FunObjVar * getFunction() const
Get containing function, or null for globals/constants.
const SVFBasicBlock * getLoopHeader(const BBList &lp) const
const LoopBBs & getLoopInfo(const SVFBasicBlock *bb) const
iterator begin()
Iterators.
u32_t nodeNum
total num of edge
IDToNodeMapTy::const_iterator const_iterator
NodeType * getGNode(NodeID id) const
Get a node.
bool hasIncomingEdge() const
Has incoming/outgoing edge set.
bool hasOutgoingEdge() const
iterator OutEdgeEnd()
GEdgeSetTy::iterator iterator
const GEdgeSetTy & getOutEdges() const
const GEdgeSetTy & getInEdges() const
iterator OutEdgeBegin()
iterators
GEdgeSetTy::const_iterator const_iterator
iterator InEdgeBegin()
iterator InEdgeEnd()
static void WriteGraphToFile(SVF::OutStream &O, const std::string &GraphName, const GraphType &GT, bool simple=false)
virtual const FunObjVar * getFun() const
Return the function of this ICFGNode.
Definition ICFGNode.h:74
static const Option< u32_t > MaxContextLen
Definition Options.h:82
static const Option< bool > TCTDotGraph
Definition Options.h:163
const FunObjVar * getParent() const
const ICFGNode * back() const
const CallGraph * getCallGraph()
Get CG.
Definition SVFIR.h:178
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:114
NodeID getId() const
Get ID.
Definition SVFValue.h:160
virtual const std::string & getName() const
Definition SVFValue.h:186
@ ThreadCreateEdge
Definition TCT.h:55
const CxtThread & getCxtThread() const
Get thread creation context, <fork site, call string context>
Definition TCT.h:101
void setMultiforked(bool value)
Definition TCT.h:116
bool isIncycle() const
Definition TCT.h:112
bool isInloop() const
inloop, incycle attributes
Definition TCT.h:108
bool pushToCTPWorkList(const CxtThreadProc &ctp)
WorkList helper functions.
Definition TCT.h:563
bool isInRecursion(const ICFGNode *inst) const
Whether an instruction is in a recursion.
Definition TCT.cpp:91
TCTNode * getTCTNode(NodeID id) const
Get TCT node.
Definition TCT.h:200
bool isContextSuffix(const CallStrCxt &lhs, const CallStrCxt &call)
If lhs is a suffix of rhs, including equal.
Definition TCT.cpp:497
FunSet entryFuncSet
Definition TCT.h:583
TCTNode * getOrCreateTCTNode(const CallStrCxt &cxt, const ICFGNode *fork, const CxtThreadProc &forkSiteCtp, const FunObjVar *routine)
Get or create a tct node based on CxtThread.
Definition TCT.h:514
void collectLoopInfoForJoin()
Handle join site in loop.
Definition TCT.cpp:318
ThreadCallGraphSCC * tcgSCC
Procedures we care about during call graph traversing when creating TCT.
Definition TCT.h:585
void collectEntryFunInCallGraph()
Get entry functions that are neither called by other functions nor extern functions.
Definition TCT.cpp:187
Set< const CallGraphNode * > PTACGNodeSet
Definition TCT.h:163
InstToLoopMap joinSiteToLoopMap
Map a CxtThread to its start routine function.
Definition TCT.h:591
void dump(const std::string &filename)
Dump the graph.
Definition TCT.cpp:535
FunSet candidateFuncSet
Procedures that are neither called by other functions nor extern functions.
Definition TCT.h:584
bool inSameCallGraphSCC(const CallGraphNode *src, const CallGraphNode *dst)
Whether two functions in the same callgraph scc.
Definition TCT.h:300
TCTEdge * getGraphEdge(TCTNode *src, TCTNode *dst, TCTEdge::CEDGEK kind)
Get call graph edge via nodes.
Definition TCT.cpp:572
bool isCandidateFun(const CallGraph::FunctionSet &callees) const
Whether it is a candidate function for indirect call.
Definition TCT.h:285
CxtThreadProcVec ctpList
Thread call graph SCC.
Definition TCT.h:586
bool matchAndPopCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Match context.
Definition TCT.cpp:469
bool isInLoopInstruction(const ICFGNode *inst)
Multi-forked threads.
Definition TCT.cpp:46
bool isJoinMustExecutedInLoop(const LoopBBs &lp, const ICFGNode *join)
Return true if a join instruction must be executed inside a loop.
Definition TCT.cpp:294
void markRelProcs()
Mark relevant procedures that are backward reachable from any fork/join site.
Definition TCT.cpp:133
Set< const ICFGNode * > inRecurJoinSites
Fork or Join sites in recursions.
Definition TCT.h:592
void dumpCxt(CallStrCxt &cxt)
Dump calling context.
Definition TCT.cpp:517
bool addTCTEdge(TCTNode *src, TCTNode *dst)
Add TCT edge.
Definition TCT.h:462
u32_t MaxCxtSize
Definition TCT.h:448
bool isLoopHeaderOfJoinLoop(const SVFBasicBlock *bb)
Whether a given bb is a loop head of a inloop join site.
Definition TCT.cpp:343
void build()
Build TCT.
Definition TCT.cpp:387
void print() const
Print TCT information.
Definition TCT.cpp:543
void handleCallRelation(CxtThreadProc &ctp, const CallGraphEdge *cgEdge, const CallICFGNode *call)
Handle call relations.
Definition TCT.cpp:245
ThreadCallGraph * tcg
Definition TCT.h:444
void collectMultiForkedThreads()
Definition TCT.cpp:207
CxtThreadProc popFromCTPWorkList()
Definition TCT.h:572
TCTEdge * hasGraphEdge(TCTNode *src, TCTNode *dst, TCTEdge::CEDGEK kind) const
Whether we have already created this call graph edge.
Definition TCT.cpp:555
bool isLoopExitOfJoinLoop(const SVFBasicBlock *bb)
Whether a given bb is an exit of a inloop join site.
Definition TCT.cpp:357
SVFLoopAndDomInfo::LoopBBs LoopBBs
Definition TCT.h:157
const LoopBBs & getLoop(const ICFGNode *inst)
Get loop for an instruction.
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Context helper functions.
Definition TCT.cpp:449
CallSiteSet::const_iterator forksitesEnd() const
CallSiteSet::const_iterator forksitesBegin() const
Fork sites iterators.
CallSiteSet::const_iterator joinsitesEnd() const
ForkEdgeSet::const_iterator getForkEdgeEnd(const CallICFGNode *cs) const
ForkEdgeSet::const_iterator getForkEdgeBegin(const CallICFGNode *cs) const
CallSiteSet::const_iterator joinsitesBegin() const
Join sites iterators.
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:437
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:68
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
for isBitcode
Definition BasicTypes.h:68
unsigned CallSiteID
Definition GeneralType.h:58
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
std::vector< u32_t > CallStrCxt
static std::string getEdgeAttributes(TCTNode *node, EdgeIter EI, TCT *csThreadTree)
Definition TCT.cpp:625
NodeType::iterator ChildIteratorType
Definition TCT.cpp:593
static std::string getGraphName(TCT *graph)
Return name of the graph.
Definition TCT.cpp:600
static std::string getNodeAttributes(TCTNode *node, TCT *tct)
Definition TCT.cpp:610
static std::string getNodeLabel(TCTNode *node, TCT *graph)
Return function name;.
Definition TCT.cpp:605
DOTGraphTraits(bool isSimple=false)
Definition TCT.cpp:594