! * Add direct fork edges * As join edge is a special return which is back to join site(s) rather than its fork site * A ThreadJoinEdge is created from the functions where join sites reside in to the start routine function * But we don't invoke addEdge() method to add the edge to src and dst, otherwise it makes a scc cycle */
| 200 | * But we don't invoke addEdge() method to add the edge to src and dst, otherwise it makes a scc cycle |
| 201 | */ |
| 202 | void ThreadCallGraph::addDirectJoinEdge(const CallICFGNode* cs,const CallSiteSet& forkset) |
| 203 | { |
| 204 | |
| 205 | CallGraphNode* joinFunNode = getCallGraphNode(cs->getCaller()); |
| 206 | |
| 207 | for (CallSiteSet::const_iterator it = forkset.begin(), eit = forkset.end(); it != eit; ++it) |
| 208 | { |
| 209 | |
| 210 | const FunObjVar* threadRoutineFun = |
| 211 | SVFUtil::dyn_cast<FunValVar>(tdAPI->getForkedFun(*it))->getFunction(); |
| 212 | assert(threadRoutineFun && "thread routine function does not exist"); |
| 213 | CallGraphNode* threadRoutineFunNode = getCallGraphNode(threadRoutineFun); |
| 214 | CallSiteID csId = addCallSite(cs, threadRoutineFun); |
| 215 | |
| 216 | if (!hasThreadJoinEdge(cs,joinFunNode,threadRoutineFunNode, csId)) |
| 217 | { |
| 218 | assert(cs->getCaller() == joinFunNode->getFunction() && "callee instruction not inside caller??"); |
| 219 | ThreadJoinEdge* edge = new ThreadJoinEdge(joinFunNode,threadRoutineFunNode,csId); |
| 220 | edge->addDirectCallSite(cs); |
| 221 | |
| 222 | addThreadJoinEdgeSetMap(cs, edge); |
| 223 | } |
| 224 | } |
| 225 | } |
nothing calls this directly
no test coverage detected