static bool canDevirtualizeWitnessMethod(ApplySite AI) { SILFunction *F; SILWitnessTable *WT; auto *WMI = cast<WitnessMethodInst>(AI.getCallee()); std::tie(F, WT) = AI.getModule().lookUpFunctionInWitnessTable(WMI->getConformance(), WMI->getMember()); if (!F) return false; if (AI.getFunction()->isSerialized()) { // function_ref inside fragile function cannot reference a private or // hidden symbol. if (!F->hasValidLinkageForFragileRef()) return false; } return true; }
/// In the cases where we can statically determine the function that /// we'll call to, replace an apply of a witness_method with an apply /// of a function_ref, returning the new apply. DevirtualizationResult swift::tryDevirtualizeWitnessMethod(ApplySite AI) { SILFunction *F; SILWitnessTable *WT; auto *WMI = cast<WitnessMethodInst>(AI.getCallee()); std::tie(F, WT) = AI.getModule().lookUpFunctionInWitnessTable(WMI->getConformance(), WMI->getMember()); if (!F) return std::make_pair(nullptr, FullApplySite()); if (AI.getFunction()->isFragile()) { // function_ref inside fragile function cannot reference a private or // hidden symbol. if (!F->hasValidLinkageForFragileRef()) return std::make_pair(nullptr, FullApplySite()); } auto Result = devirtualizeWitnessMethod(AI, F, WMI->getConformance()); return std::make_pair(Result.getInstruction(), Result); }