/*! * get CallGraph edge via nodes */ PTACallGraphEdge* PTACallGraph::getGraphEdge(PTACallGraphNode* src, PTACallGraphNode* dst,PTACallGraphEdge::CEDGEK kind) { for (PTACallGraphEdge::CallGraphEdgeSet::iterator iter = src->OutEdgeBegin(); iter != src->OutEdgeEnd(); ++iter) { PTACallGraphEdge* edge = (*iter); if (edge->getEdgeKind() == kind && edge->getDstID() == dst->getId()) return edge; } return NULL; }
static std::string getEdgeAttributes(PTACallGraphNode *node, EdgeIter EI, PTACallGraph *PTACallGraph) { //TODO: mark indirect call of Fork with different color PTACallGraphEdge* edge = *(EI.getCurrent()); assert(edge && "No edge found!!"); std::string color; if (edge->getEdgeKind() == PTACallGraphEdge::TDJoinEdge) { color = "color=green"; } else if (edge->getEdgeKind() == PTACallGraphEdge::TDForkEdge) { color = "color=blue"; } else { color = "color=black"; } if (0 != edge->getIndirectCalls().size()) { color = "color=red"; } return color; }
/*! * Add indirect call edge to update call graph */ void PTACallGraph::addIndirectCallGraphEdge(const llvm::Instruction* call, const llvm::Function* calleefun) { PTACallGraphNode* caller = getCallGraphNode(call->getParent()->getParent()); PTACallGraphNode* callee = getCallGraphNode(calleefun); numOfResolvedIndCallEdge++; if(PTACallGraphEdge* callEdge = hasGraphEdge(caller,callee, PTACallGraphEdge::CallRetEdge)) { callEdge->addInDirectCallSite(call); addCallGraphEdgeSetMap(call,callEdge); } else { assert(call->getParent()->getParent() == caller->getFunction() && "callee instruction not inside caller??"); PTACallGraphEdge* edge = new PTACallGraphEdge(caller,callee,PTACallGraphEdge::CallRetEdge); edge->addInDirectCallSite(call); addEdge(edge); addCallGraphEdgeSetMap(call,edge); } }
/*! * Add direct call edges */ void PTACallGraph::addDirectCallGraphEdge(const llvm::Instruction* call) { assert(getCallee(call) && "no callee found"); PTACallGraphNode* caller = getCallGraphNode(call->getParent()->getParent()); PTACallGraphNode* callee = getCallGraphNode(getCallee(call)); if(PTACallGraphEdge* callEdge = hasGraphEdge(caller,callee, PTACallGraphEdge::CallRetEdge)) { callEdge->addDirectCallSite(call); addCallGraphEdgeSetMap(call,callEdge); } else { assert(call->getParent()->getParent() == caller->getFunction() && "callee instruction not inside caller??"); PTACallGraphEdge* edge = new PTACallGraphEdge(caller,callee,PTACallGraphEdge::CallRetEdge); edge->addDirectCallSite(call); addEdge(edge); addCallGraphEdgeSetMap(call,edge); } }
void PTAStat::callgraphStat() { PTACallGraph* graph = pta->getPTACallGraph(); PointerAnalysis::CallGraphSCC* callgraphSCC = new PointerAnalysis::CallGraphSCC(graph); callgraphSCC->find(); unsigned totalNode = 0; unsigned totalCycle = 0; unsigned nodeInCycle = 0; unsigned maxNodeInCycle = 0; unsigned totalEdge = 0; unsigned edgeInCycle = 0; std::set<NodeID> sccRepNodeSet; PTACallGraph::iterator it = graph->begin(); PTACallGraph::iterator eit = graph->end(); for (; it != eit; ++it) { totalNode++; if(callgraphSCC->isInCycle(it->first)) { sccRepNodeSet.insert(callgraphSCC->repNode(it->first)); nodeInCycle++; const NodeBS& subNodes = callgraphSCC->subNodes(it->first); if(subNodes.count() > maxNodeInCycle) maxNodeInCycle = subNodes.count(); } PTACallGraphNode::const_iterator edgeIt = it->second->InEdgeBegin(); PTACallGraphNode::const_iterator edgeEit = it->second->InEdgeEnd(); for (; edgeIt != edgeEit; ++edgeIt) { PTACallGraphEdge *edge = *edgeIt; totalEdge+= edge->getDirectCalls().size() + edge->getIndirectCalls().size(); if(callgraphSCC->repNode(edge->getSrcID()) == callgraphSCC->repNode(edge->getDstID())) { edgeInCycle+=edge->getDirectCalls().size() + edge->getIndirectCalls().size(); } } } totalCycle = sccRepNodeSet.size(); PTNumStatMap["TotalNode"] = totalNode; PTNumStatMap["TotalCycle"] = totalCycle; PTNumStatMap["NodeInCycle"] = nodeInCycle; PTNumStatMap["MaxNodeInCycle"] = maxNodeInCycle; PTNumStatMap["TotalEdge"] = totalEdge; PTNumStatMap["CalRetPairInCycle"] = edgeInCycle; std::cout << "\n****CallGraph SCC Stat****\n"; PTAStat::printStat(); PTNumStatMap.clear(); delete callgraphSCC; }
bool PTACallGraphNode::isReachableFromProgEntry() const { std::stack<const PTACallGraphNode*> nodeStack; NodeBS visitedNodes; nodeStack.push(this); visitedNodes.set(getId()); while (nodeStack.empty() == false) { PTACallGraphNode* node = const_cast<PTACallGraphNode*>(nodeStack.top()); nodeStack.pop(); if (analysisUtil::isProgEntryFunction(node->getFunction())) return true; for (const_iterator it = node->InEdgeBegin(), eit = node->InEdgeEnd(); it != eit; ++it) { PTACallGraphEdge* edge = *it; if (visitedNodes.test_and_set(edge->getSrcID())) nodeStack.push(edge->getSrcNode()); } } return false; }
/*! * Call site mod-ref analysis * Compute mod-ref of all callsites invoking this call graph node */ void MRGenerator::modRefAnalysis(PTACallGraphNode* callGraphNode, WorkList& worklist) { /// add ref/mod set of callee to its invocation callsites at caller for(PTACallGraphNode::iterator it = callGraphNode->InEdgeBegin(), eit = callGraphNode->InEdgeEnd(); it!=eit; ++it) { PTACallGraphEdge* edge = *it; /// handle direct callsites for(PTACallGraphEdge::CallInstSet::iterator cit = edge->getDirectCalls().begin(), ecit = edge->getDirectCalls().end(); cit!=ecit; ++cit) { NodeBS mod = getModSideEffectOfFunction(callGraphNode->getFunction()); NodeBS ref = getRefSideEffectOfFunction(callGraphNode->getFunction()); /// ref set include all mods ref |= mod; CallSite cs = analysisUtil::getLLVMCallSite(*cit); // add ref set bool refchanged = addRefSideEffectOfCallSite(cs, ref); // add mod set bool modchanged = addModSideEffectOfCallSite(cs, mod); if(refchanged || modchanged) worklist.push(edge->getSrcID()); } /// handle indirect callsites for(PTACallGraphEdge::CallInstSet::iterator cit = edge->getIndirectCalls().begin(), ecit = edge->getIndirectCalls().end(); cit!=ecit; ++cit) { NodeBS mod = getModSideEffectOfFunction(callGraphNode->getFunction()); NodeBS ref = getRefSideEffectOfFunction(callGraphNode->getFunction()); /// ref set include all mods ref |= mod; CallSite cs = analysisUtil::getLLVMCallSite(*cit); // add ref set bool refchanged = addRefSideEffectOfCallSite(cs, ref); // add mod set bool modchanged = addModSideEffectOfCallSite(cs, mod); if(refchanged || modchanged) worklist.push(edge->getSrcID()); } } }