| 44 | } |
| 45 | |
| 46 | void CallGraph::BuildGraphAndGetDepthOfFunctionCalls( |
| 47 | opt::IRContext* context, |
| 48 | std::map<std::pair<uint32_t, uint32_t>, uint32_t>* call_to_max_depth) { |
| 49 | // Consider every function. |
| 50 | for (auto& function : *context->module()) { |
| 51 | // Avoid considering the same callee of this function multiple times by |
| 52 | // recording known callees. |
| 53 | std::set<uint32_t> known_callees; |
| 54 | // Consider every function call instruction in every block. |
| 55 | for (auto& block : function) { |
| 56 | for (auto& instruction : block) { |
| 57 | if (instruction.opcode() != spv::Op::OpFunctionCall) { |
| 58 | continue; |
| 59 | } |
| 60 | // Get the id of the function being called. |
| 61 | uint32_t callee = instruction.GetSingleWordInOperand(0); |
| 62 | |
| 63 | // Get the loop nesting depth of this function call. |
| 64 | uint32_t loop_nesting_depth = |
| 65 | context->GetStructuredCFGAnalysis()->LoopNestingDepth(block.id()); |
| 66 | // If inside a loop header, consider the function call nested inside the |
| 67 | // loop headed by the block. |
| 68 | if (block.IsLoopHeader()) { |
| 69 | loop_nesting_depth++; |
| 70 | } |
| 71 | |
| 72 | // Update the map if we have not seen this pair (caller, callee) |
| 73 | // before or if this function call is from a greater depth. |
| 74 | if (!known_callees.count(callee) || |
| 75 | call_to_max_depth->at({function.result_id(), callee}) < |
| 76 | loop_nesting_depth) { |
| 77 | call_to_max_depth->insert( |
| 78 | {{function.result_id(), callee}, loop_nesting_depth}); |
| 79 | } |
| 80 | |
| 81 | if (known_callees.count(callee)) { |
| 82 | // We have already considered a call to this function - ignore it. |
| 83 | continue; |
| 84 | } |
| 85 | // Increase the callee's in-degree and add an edge to the call graph. |
| 86 | function_in_degree_[callee]++; |
| 87 | call_graph_edges_[function.result_id()].insert(callee); |
| 88 | // Mark the callee as 'known'. |
| 89 | known_callees.insert(callee); |
| 90 | } |
| 91 | } |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | void CallGraph::ComputeTopologicalOrderOfFunctions() { |
| 96 | // This is an implementation of Kahn’s algorithm for topological sorting. |
nothing calls this directly
no test coverage detected