// FIXME: This code is stolen from CallGraph::addToCallGraph(Function *F), which // happens to be private. It is better for this functionality exposed by the // CallGraph. static void buildCGN(CallGraph &CG, CallGraphNode *Node) { Function *F = Node->getFunction(); // Look for calls by this function. for (Instruction &I : instructions(F)) if (CallSite CS = CallSite(cast<Value>(&I))) { const Function *Callee = CS.getCalledFunction(); if (!Callee || !Intrinsic::isLeaf(Callee->getIntrinsicID())) // Indirect calls of intrinsics are not allowed so no need to check. // We can be more precise here by using TargetArg returned by // Intrinsic::isLeaf. Node->addCalledFunction(CS, CG.getCallsExternalNode()); else if (!Callee->isIntrinsic()) Node->addCalledFunction(CS, CG.getOrInsertFunction(Callee)); } }
// Rebuild CGN after we extracted parts of the code from ParentFunc into // NewFuncs. Builds CGNs for the NewFuncs and adds them to the current SCC. void coro::updateCallGraph(Function &ParentFunc, ArrayRef<Function *> NewFuncs, CallGraph &CG, CallGraphSCC &SCC) { // Rebuild CGN from scratch for the ParentFunc auto *ParentNode = CG[&ParentFunc]; ParentNode->removeAllCalledFunctions(); buildCGN(CG, ParentNode); SmallVector<CallGraphNode *, 8> Nodes(SCC.begin(), SCC.end()); for (Function *F : NewFuncs) { CallGraphNode *Callee = CG.getOrInsertFunction(F); Nodes.push_back(Callee); buildCGN(CG, Callee); } SCC.initialize(Nodes); }
// Make sure that there is a devirtualization trigger function that CoroSplit // pass uses the force restart CGSCC pipeline. If devirt trigger function is not // found, we will create one and add it to the current SCC. static void createDevirtTriggerFunc(CallGraph &CG, CallGraphSCC &SCC) { Module &M = CG.getModule(); if (M.getFunction(CORO_DEVIRT_TRIGGER_FN)) return; LLVMContext &C = M.getContext(); auto *FnTy = FunctionType::get(Type::getVoidTy(C), Type::getInt8PtrTy(C), /*IsVarArgs=*/false); Function *DevirtFn = Function::Create(FnTy, GlobalValue::LinkageTypes::PrivateLinkage, CORO_DEVIRT_TRIGGER_FN, &M); DevirtFn->addFnAttr(Attribute::AlwaysInline); auto *Entry = BasicBlock::Create(C, "entry", DevirtFn); ReturnInst::Create(C, Entry); auto *Node = CG.getOrInsertFunction(DevirtFn); SmallVector<CallGraphNode *, 8> Nodes(SCC.begin(), SCC.end()); Nodes.push_back(Node); SCC.initialize(Nodes); }