// 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)); } }
// When we see the coroutine the first time, we insert an indirect call to a // devirt trigger function and mark the coroutine that it is now ready for // split. static void prepareForSplit(Function &F, CallGraph &CG) { Module &M = *F.getParent(); #ifndef NDEBUG Function *DevirtFn = M.getFunction(CORO_DEVIRT_TRIGGER_FN); assert(DevirtFn && "coro.devirt.trigger function not found"); #endif F.addFnAttr(CORO_PRESPLIT_ATTR, PREPARED_FOR_SPLIT); // Insert an indirect call sequence that will be devirtualized by CoroElide // pass: // %0 = call i8* @llvm.coro.subfn.addr(i8* null, i8 -1) // %1 = bitcast i8* %0 to void(i8*)* // call void %1(i8* null) coro::LowererBase Lowerer(M); Instruction *InsertPt = F.getEntryBlock().getTerminator(); auto *Null = ConstantPointerNull::get(Type::getInt8PtrTy(F.getContext())); auto *DevirtFnAddr = Lowerer.makeSubFnCall(Null, CoroSubFnInst::RestartTrigger, InsertPt); auto *IndirectCall = CallInst::Create(DevirtFnAddr, Null, "", InsertPt); // Update CG graph with an indirect call we just added. CG[&F]->addCalledFunction(IndirectCall, CG.getCallsExternalNode()); }