@@ -143,7 +143,7 @@ LLVMBasedICFG::LLVMBasedICFG(ProjectIRDB &IRDB, CallGraphAnalysisType CGType,
143143 PointsToGraph *PTG = PT->getPointsToGraph (F);
144144 WholeModulePTG.mergeWith (PTG, F);
145145 }
146- constructionWalker (F, Res.get ());
146+ constructionWalker (F, * Res.get ());
147147 }
148148 REG_COUNTER (" WM-PTG Vertices" , WholeModulePTG.getNumOfVertices (),
149149 PAMM_SEVERITY_LEVEL::Full);
@@ -166,29 +166,33 @@ LLVMBasedICFG::~LLVMBasedICFG() {
166166}
167167
168168void LLVMBasedICFG::constructionWalker (const llvm::Function *F,
169- Resolver * Resolver) {
169+ Resolver & Resolver) {
170170 PAMM_GET_INSTANCE;
171171 auto &lg = lg::get ();
172172 LOG_IF_ENABLE (BOOST_LOG_SEV (lg, DEBUG)
173173 << " Walking in function: " << F->getName ().str ());
174- if (VisitedFunctions. count (F ) || F-> isDeclaration () ) {
174+ if (F-> isDeclaration ( ) || !VisitedFunctions. insert (F). second ) {
175175 LOG_IF_ENABLE (BOOST_LOG_SEV (lg, DEBUG)
176176 << " Function already visited or only declaration: "
177177 << F->getName ().str ());
178178 return ;
179179 }
180- VisitedFunctions.insert (F);
181180
182181 // add a node for function F to the call graph (if not present already)
183- if (!FunctionVertexMap.count (F)) {
184- FunctionVertexMap[F] = boost::add_vertex (CallGraph);
185- CallGraph[FunctionVertexMap[F]] = VertexProperties (F);
182+ vertex_t thisFunctionVertexDescriptor;
183+ auto fvmItr = FunctionVertexMap.find (F);
184+ if (fvmItr != FunctionVertexMap.end ())
185+ thisFunctionVertexDescriptor = fvmItr->second ;
186+ else {
187+ thisFunctionVertexDescriptor = boost::add_vertex (VertexProperties (F), CallGraph);
188+ FunctionVertexMap[F] = thisFunctionVertexDescriptor;
186189 }
190+
187191 // iterate all instructions of the current function
188192 for (auto &BB : *F) {
189193 for (auto &I : BB) {
190194 if (llvm::isa<llvm::CallInst>(I) || llvm::isa<llvm::InvokeInst>(I)) {
191- Resolver-> preCall (&I);
195+ Resolver. preCall (&I);
192196
193197 llvm::ImmutableCallSite cs (&I);
194198 set<const llvm::Function *> possible_targets;
@@ -200,10 +204,11 @@ void LLVMBasedICFG::constructionWalker(const llvm::Function *F,
200204 << " " << llvmIRToString (cs.getInstruction ()));
201205 } else {
202206 // still try to resolve the called function statically
203- const llvm::Value *v = cs.getCalledValue ();
204- const llvm::Value *sv = v->stripPointerCasts ();
205- if (sv->hasName () && IRDB.getFunction (sv->getName ())) {
206- possible_targets.insert (IRDB.getFunction (sv->getName ()));
207+ const llvm::Value *sv = cs.getCalledValue ()->stripPointerCasts ();
208+ const llvm::Function *valueFunction =
209+ !sv->hasName () ? nullptr : IRDB.getFunction (sv->getName ());
210+ if (valueFunction) {
211+ possible_targets.insert (valueFunction);
207212 LOG_IF_ENABLE (BOOST_LOG_SEV (lg, DEBUG)
208213 << " Found static call-site: "
209214 << llvmIRToString (cs.getInstruction ()));
@@ -215,9 +220,9 @@ void LLVMBasedICFG::constructionWalker(const llvm::Function *F,
215220 << " " << llvmIRToString (cs.getInstruction ()));
216221 // call the resolve routine
217222 if (isVirtualFunctionCall (cs.getInstruction ())) {
218- possible_targets = Resolver-> resolveVirtualCall (cs);
223+ possible_targets = Resolver. resolveVirtualCall (cs);
219224 } else {
220- possible_targets = Resolver-> resolveFunctionPointer (cs);
225+ possible_targets = Resolver. resolveFunctionPointer (cs);
221226 }
222227 }
223228 }
@@ -226,18 +231,19 @@ void LLVMBasedICFG::constructionWalker(const llvm::Function *F,
226231 << " Found " << possible_targets.size ()
227232 << " possible target(s)" );
228233
229- Resolver-> handlePossibleTargets (cs, possible_targets);
234+ Resolver. handlePossibleTargets (cs, possible_targets);
230235 // Insert possible target inside the graph and add the link with
231236 // the current function
232237 for (auto &possible_target : possible_targets) {
233- auto target = possible_target;
234- if (!FunctionVertexMap.count (target)) {
235- FunctionVertexMap[target] = boost::add_vertex (CallGraph);
236- CallGraph[FunctionVertexMap[target]] =
237- VertexProperties (possible_target);
238+ vertex_t targetVertex;
239+ auto targetFvmItr = FunctionVertexMap.find (possible_target);
240+ if (targetFvmItr != FunctionVertexMap.end ())
241+ targetVertex = targetFvmItr->second ;
242+ else {
243+ targetVertex = boost::add_vertex (VertexProperties (possible_target), CallGraph);
244+ FunctionVertexMap[possible_target] = targetVertex;
238245 }
239-
240- boost::add_edge (FunctionVertexMap[F], FunctionVertexMap[target],
246+ boost::add_edge (thisFunctionVertexDescriptor, targetVertex,
241247 EdgeProperties (cs.getInstruction ()), CallGraph);
242248 }
243249
@@ -246,9 +252,9 @@ void LLVMBasedICFG::constructionWalker(const llvm::Function *F,
246252 constructionWalker (possible_target, Resolver);
247253 }
248254
249- Resolver-> postCall (&I);
255+ Resolver. postCall (&I);
250256 } else {
251- Resolver-> otherInst (&I);
257+ Resolver. otherInst (&I);
252258 }
253259 }
254260 }
@@ -446,23 +452,14 @@ LLVMBasedICFG::getLastInstructionOf(const string &name) {
446452}
447453
448454void LLVMBasedICFG::mergeWith (const LLVMBasedICFG &other) {
449- // Copy other graph into this graph
450- typedef typename boost::property_map<bidigraph_t , boost::vertex_index_t >::type
451- index_map_t ;
452- // For simple adjacency_list<> this type would be more efficient:
453- typedef typename boost::iterator_property_map<
454- typename std::vector<LLVMBasedICFG::vertex_t >::iterator, index_map_t ,
455- LLVMBasedICFG::vertex_t , LLVMBasedICFG::vertex_t &>
456- IsoMap;
457- // For more generic graphs, one can try typedef std::map<vertex_t, vertex_t>
458- // IsoMap;
459- vector<LLVMBasedICFG::vertex_t > orig2copy_data (
460- boost::num_vertices (other.CallGraph ));
461- IsoMap mapV = boost::make_iterator_property_map (
462- orig2copy_data.begin (), get (boost::vertex_index, other.CallGraph ));
463- boost::copy_graph (other.CallGraph , CallGraph,
464- boost::orig_to_copy (mapV)); // means g1 += g2
465- // This vector hols the call-sites that are used to merge the whole-module
455+ typedef bidigraph_t ::vertex_descriptor vertex_t ;
456+ typedef std::map<vertex_t , vertex_t > vertex_map_t ;
457+ vertex_map_t oldToNewVertexMapping;
458+ boost::associative_property_map<vertex_map_t > vertexMapWrapper (
459+ oldToNewVertexMapping);
460+ boost::copy_graph (other.CallGraph , CallGraph, boost::orig_to_copy (vertexMapWrapper));
461+
462+ // This vector holds the call-sites that are used to merge the whole-module
466463 // points-to graphs
467464 vector<pair<llvm::ImmutableCallSite, const llvm::Function *>> Calls;
468465 vertex_iterator vi_v, vi_v_end, vi_u, vi_u_end;
@@ -494,12 +491,16 @@ void LLVMBasedICFG::mergeWith(const LLVMBasedICFG &other) {
494491 }
495492 }
496493 }
497- // Update the FunctionVertexMap
498- FunctionVertexMap.clear ();
499- for (boost::tie (vi_v, vi_v_end) = boost::vertices (CallGraph);
500- vi_v != vi_v_end; ++vi_v) {
501- FunctionVertexMap.insert (make_pair (CallGraph[*vi_v].F , *vi_v));
494+
495+ // Update the FunctionVertexMap:
496+ for (const auto &otherValues : other.FunctionVertexMap ) {
497+ auto mappingIter = oldToNewVertexMapping.find (otherValues.second );
498+ if (mappingIter != oldToNewVertexMapping.end ()) {
499+ FunctionVertexMap.insert (
500+ make_pair (otherValues.first , mappingIter->second ));
501+ }
502502 }
503+
503504 // Merge the already visited functions
504505 VisitedFunctions.insert (other.VisitedFunctions .begin (),
505506 other.VisitedFunctions .end ());
@@ -535,9 +536,44 @@ void LLVMBasedICFG::print(ostream &OS) const {
535536 }
536537}
537538
538- void LLVMBasedICFG::printAsDot (std::ostream &OS) const {
539- boost::write_graphviz (OS, CallGraph, makeCallGraphVertexWriter (CallGraph),
540- makeCallGraphEdgeWriter (CallGraph));
539+ namespace {
540+ template <class graphType >
541+ class VertexWriter {
542+ public:
543+ VertexWriter (const graphType &CGraph) : CGraph(CGraph) {}
544+ template <class VertexOrEdge >
545+ void operator ()(std::ostream &out, const VertexOrEdge &v) const {
546+ out << " [label=\" " << CGraph[v].getFunctionName () << " \" ]" ;
547+ }
548+
549+ private:
550+ const graphType &CGraph;
551+ };
552+
553+ template <class graphType >
554+ class EdgeLabelWriter {
555+ public:
556+ EdgeLabelWriter (const graphType &CGraph) : CGraph(CGraph) {}
557+ template <class VertexOrEdge >
558+ void operator ()(std::ostream &out, const VertexOrEdge &v) const {
559+ out << " [label=\" " << CGraph[v].getCallSiteAsString () << " \" ]" ;
560+ }
561+
562+ private:
563+ const graphType &CGraph;
564+ };
565+ }
566+
567+ void LLVMBasedICFG::printAsDot (std::ostream &OS, bool printEdgeLabels) const {
568+ if (printEdgeLabels) {
569+ boost::write_graphviz (OS, CallGraph,
570+ VertexWriter<bidigraph_t >(CallGraph),
571+ EdgeLabelWriter<bidigraph_t >(CallGraph));
572+ } else {
573+ boost::write_graphviz (OS, CallGraph,
574+ VertexWriter<bidigraph_t >(CallGraph));
575+
576+ }
541577}
542578
543579void LLVMBasedICFG::printInternalPTGAsDot (std::ostream &OS) const {
0 commit comments