Path: blob/main/contrib/llvm-project/llvm/lib/Analysis/CallGraph.cpp
35232 views
//===- CallGraph.cpp - Build a Module's call graph ------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/Analysis/CallGraph.h"9#include "llvm/ADT/SCCIterator.h"10#include "llvm/ADT/STLExtras.h"11#include "llvm/ADT/SmallVector.h"12#include "llvm/Config/llvm-config.h"13#include "llvm/IR/AbstractCallSite.h"14#include "llvm/IR/Function.h"15#include "llvm/IR/IntrinsicInst.h"16#include "llvm/IR/Module.h"17#include "llvm/IR/PassManager.h"18#include "llvm/InitializePasses.h"19#include "llvm/Pass.h"20#include "llvm/Support/Compiler.h"21#include "llvm/Support/Debug.h"22#include "llvm/Support/raw_ostream.h"23#include <cassert>2425using namespace llvm;2627//===----------------------------------------------------------------------===//28// Implementations of the CallGraph class methods.29//3031CallGraph::CallGraph(Module &M)32: M(M), ExternalCallingNode(getOrInsertFunction(nullptr)),33CallsExternalNode(std::make_unique<CallGraphNode>(this, nullptr)) {34// Add every interesting function to the call graph.35for (Function &F : M)36if (!isDbgInfoIntrinsic(F.getIntrinsicID()))37addToCallGraph(&F);38}3940CallGraph::CallGraph(CallGraph &&Arg)41: M(Arg.M), FunctionMap(std::move(Arg.FunctionMap)),42ExternalCallingNode(Arg.ExternalCallingNode),43CallsExternalNode(std::move(Arg.CallsExternalNode)) {44Arg.FunctionMap.clear();45Arg.ExternalCallingNode = nullptr;4647// Update parent CG for all call graph's nodes.48CallsExternalNode->CG = this;49for (auto &P : FunctionMap)50P.second->CG = this;51}5253CallGraph::~CallGraph() {54// CallsExternalNode is not in the function map, delete it explicitly.55if (CallsExternalNode)56CallsExternalNode->allReferencesDropped();5758// Reset all node's use counts to zero before deleting them to prevent an59// assertion from firing.60#ifndef NDEBUG61for (auto &I : FunctionMap)62I.second->allReferencesDropped();63#endif64}6566bool CallGraph::invalidate(Module &, const PreservedAnalyses &PA,67ModuleAnalysisManager::Invalidator &) {68// Check whether the analysis, all analyses on functions, or the function's69// CFG have been preserved.70auto PAC = PA.getChecker<CallGraphAnalysis>();71return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Module>>());72}7374void CallGraph::addToCallGraph(Function *F) {75CallGraphNode *Node = getOrInsertFunction(F);7677// If this function has external linkage or has its address taken and78// it is not a callback, then anything could call it.79if (!F->hasLocalLinkage() ||80F->hasAddressTaken(nullptr, /*IgnoreCallbackUses=*/true,81/* IgnoreAssumeLikeCalls */ true,82/* IgnoreLLVMUsed */ false))83ExternalCallingNode->addCalledFunction(nullptr, Node);8485populateCallGraphNode(Node);86}8788void CallGraph::populateCallGraphNode(CallGraphNode *Node) {89Function *F = Node->getFunction();9091// If this function is not defined in this translation unit, it could call92// anything.93if (F->isDeclaration() && !F->hasFnAttribute(Attribute::NoCallback))94Node->addCalledFunction(nullptr, CallsExternalNode.get());9596// Look for calls by this function.97for (BasicBlock &BB : *F)98for (Instruction &I : BB) {99if (auto *Call = dyn_cast<CallBase>(&I)) {100const Function *Callee = Call->getCalledFunction();101if (!Callee)102Node->addCalledFunction(Call, CallsExternalNode.get());103else if (!isDbgInfoIntrinsic(Callee->getIntrinsicID()))104Node->addCalledFunction(Call, getOrInsertFunction(Callee));105106// Add reference to callback functions.107forEachCallbackFunction(*Call, [=](Function *CB) {108Node->addCalledFunction(nullptr, getOrInsertFunction(CB));109});110}111}112}113114void CallGraph::print(raw_ostream &OS) const {115// Print in a deterministic order by sorting CallGraphNodes by name. We do116// this here to avoid slowing down the non-printing fast path.117118SmallVector<CallGraphNode *, 16> Nodes;119Nodes.reserve(FunctionMap.size());120121for (const auto &I : *this)122Nodes.push_back(I.second.get());123124llvm::sort(Nodes, [](CallGraphNode *LHS, CallGraphNode *RHS) {125if (Function *LF = LHS->getFunction())126if (Function *RF = RHS->getFunction())127return LF->getName() < RF->getName();128129return RHS->getFunction() != nullptr;130});131132for (CallGraphNode *CN : Nodes)133CN->print(OS);134}135136#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)137LLVM_DUMP_METHOD void CallGraph::dump() const { print(dbgs()); }138#endif139140void CallGraph::ReplaceExternalCallEdge(CallGraphNode *Old,141CallGraphNode *New) {142for (auto &CR : ExternalCallingNode->CalledFunctions)143if (CR.second == Old) {144CR.second->DropRef();145CR.second = New;146CR.second->AddRef();147}148}149150// removeFunctionFromModule - Unlink the function from this module, returning151// it. Because this removes the function from the module, the call graph node152// is destroyed. This is only valid if the function does not call any other153// functions (ie, there are no edges in it's CGN). The easiest way to do this154// is to dropAllReferences before calling this.155//156Function *CallGraph::removeFunctionFromModule(CallGraphNode *CGN) {157assert(CGN->empty() && "Cannot remove function from call "158"graph if it references other functions!");159Function *F = CGN->getFunction(); // Get the function for the call graph node160FunctionMap.erase(F); // Remove the call graph node from the map161162M.getFunctionList().remove(F);163return F;164}165166// getOrInsertFunction - This method is identical to calling operator[], but167// it will insert a new CallGraphNode for the specified function if one does168// not already exist.169CallGraphNode *CallGraph::getOrInsertFunction(const Function *F) {170auto &CGN = FunctionMap[F];171if (CGN)172return CGN.get();173174assert((!F || F->getParent() == &M) && "Function not in current module!");175CGN = std::make_unique<CallGraphNode>(this, const_cast<Function *>(F));176return CGN.get();177}178179//===----------------------------------------------------------------------===//180// Implementations of the CallGraphNode class methods.181//182183void CallGraphNode::print(raw_ostream &OS) const {184if (Function *F = getFunction())185OS << "Call graph node for function: '" << F->getName() << "'";186else187OS << "Call graph node <<null function>>";188189OS << "<<" << this << ">> #uses=" << getNumReferences() << '\n';190191for (const auto &I : *this) {192OS << " CS<" << I.first << "> calls ";193if (Function *FI = I.second->getFunction())194OS << "function '" << FI->getName() <<"'\n";195else196OS << "external node\n";197}198OS << '\n';199}200201#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)202LLVM_DUMP_METHOD void CallGraphNode::dump() const { print(dbgs()); }203#endif204205/// removeCallEdgeFor - This method removes the edge in the node for the206/// specified call site. Note that this method takes linear time, so it207/// should be used sparingly.208void CallGraphNode::removeCallEdgeFor(CallBase &Call) {209for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {210assert(I != CalledFunctions.end() && "Cannot find callsite to remove!");211if (I->first && *I->first == &Call) {212I->second->DropRef();213*I = CalledFunctions.back();214CalledFunctions.pop_back();215216// Remove all references to callback functions if there are any.217forEachCallbackFunction(Call, [=](Function *CB) {218removeOneAbstractEdgeTo(CG->getOrInsertFunction(CB));219});220return;221}222}223}224225// removeAnyCallEdgeTo - This method removes any call edges from this node to226// the specified callee function. This takes more time to execute than227// removeCallEdgeTo, so it should not be used unless necessary.228void CallGraphNode::removeAnyCallEdgeTo(CallGraphNode *Callee) {229for (unsigned i = 0, e = CalledFunctions.size(); i != e; ++i)230if (CalledFunctions[i].second == Callee) {231Callee->DropRef();232CalledFunctions[i] = CalledFunctions.back();233CalledFunctions.pop_back();234--i; --e;235}236}237238/// removeOneAbstractEdgeTo - Remove one edge associated with a null callsite239/// from this node to the specified callee function.240void CallGraphNode::removeOneAbstractEdgeTo(CallGraphNode *Callee) {241for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {242assert(I != CalledFunctions.end() && "Cannot find callee to remove!");243CallRecord &CR = *I;244if (CR.second == Callee && !CR.first) {245Callee->DropRef();246*I = CalledFunctions.back();247CalledFunctions.pop_back();248return;249}250}251}252253/// replaceCallEdge - This method replaces the edge in the node for the254/// specified call site with a new one. Note that this method takes linear255/// time, so it should be used sparingly.256void CallGraphNode::replaceCallEdge(CallBase &Call, CallBase &NewCall,257CallGraphNode *NewNode) {258for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {259assert(I != CalledFunctions.end() && "Cannot find callsite to remove!");260if (I->first && *I->first == &Call) {261I->second->DropRef();262I->first = &NewCall;263I->second = NewNode;264NewNode->AddRef();265266// Refresh callback references. Do not resize CalledFunctions if the267// number of callbacks is the same for new and old call sites.268SmallVector<CallGraphNode *, 4u> OldCBs;269SmallVector<CallGraphNode *, 4u> NewCBs;270forEachCallbackFunction(Call, [this, &OldCBs](Function *CB) {271OldCBs.push_back(CG->getOrInsertFunction(CB));272});273forEachCallbackFunction(NewCall, [this, &NewCBs](Function *CB) {274NewCBs.push_back(CG->getOrInsertFunction(CB));275});276if (OldCBs.size() == NewCBs.size()) {277for (unsigned N = 0; N < OldCBs.size(); ++N) {278CallGraphNode *OldNode = OldCBs[N];279CallGraphNode *NewNode = NewCBs[N];280for (auto J = CalledFunctions.begin();; ++J) {281assert(J != CalledFunctions.end() &&282"Cannot find callsite to update!");283if (!J->first && J->second == OldNode) {284J->second = NewNode;285OldNode->DropRef();286NewNode->AddRef();287break;288}289}290}291} else {292for (auto *CGN : OldCBs)293removeOneAbstractEdgeTo(CGN);294for (auto *CGN : NewCBs)295addCalledFunction(nullptr, CGN);296}297return;298}299}300}301302// Provide an explicit template instantiation for the static ID.303AnalysisKey CallGraphAnalysis::Key;304305PreservedAnalyses CallGraphPrinterPass::run(Module &M,306ModuleAnalysisManager &AM) {307AM.getResult<CallGraphAnalysis>(M).print(OS);308return PreservedAnalyses::all();309}310311PreservedAnalyses CallGraphSCCsPrinterPass::run(Module &M,312ModuleAnalysisManager &AM) {313auto &CG = AM.getResult<CallGraphAnalysis>(M);314unsigned sccNum = 0;315OS << "SCCs for the program in PostOrder:";316for (scc_iterator<CallGraph *> SCCI = scc_begin(&CG); !SCCI.isAtEnd();317++SCCI) {318const std::vector<CallGraphNode *> &nextSCC = *SCCI;319OS << "\nSCC #" << ++sccNum << ": ";320bool First = true;321for (CallGraphNode *CGN : nextSCC) {322if (First)323First = false;324else325OS << ", ";326OS << (CGN->getFunction() ? CGN->getFunction()->getName()327: "external node");328}329330if (nextSCC.size() == 1 && SCCI.hasCycle())331OS << " (Has self-loop).";332}333OS << "\n";334return PreservedAnalyses::all();335}336337//===----------------------------------------------------------------------===//338// Out-of-line definitions of CallGraphAnalysis class members.339//340341//===----------------------------------------------------------------------===//342// Implementations of the CallGraphWrapperPass class methods.343//344345CallGraphWrapperPass::CallGraphWrapperPass() : ModulePass(ID) {346initializeCallGraphWrapperPassPass(*PassRegistry::getPassRegistry());347}348349CallGraphWrapperPass::~CallGraphWrapperPass() = default;350351void CallGraphWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {352AU.setPreservesAll();353}354355bool CallGraphWrapperPass::runOnModule(Module &M) {356// All the real work is done in the constructor for the CallGraph.357G.reset(new CallGraph(M));358return false;359}360361INITIALIZE_PASS(CallGraphWrapperPass, "basiccg", "CallGraph Construction",362false, true)363364char CallGraphWrapperPass::ID = 0;365366void CallGraphWrapperPass::releaseMemory() { G.reset(); }367368void CallGraphWrapperPass::print(raw_ostream &OS, const Module *) const {369if (!G) {370OS << "No call graph has been built!\n";371return;372}373374// Just delegate.375G->print(OS);376}377378#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)379LLVM_DUMP_METHOD380void CallGraphWrapperPass::dump() const { print(dbgs(), nullptr); }381#endif382383384