| 67 | } |
| 68 | |
| 69 | void TestTypeVirtSolverHandler::collect(const Module &M) { |
| 70 | const auto *TypeTestFunc = Intrinsic::getDeclaration( |
| 71 | const_cast<llvm::Module *>(&M), Intrinsic::type_test); |
| 72 | if (!TypeTestFunc) |
| 73 | return; |
| 74 | |
| 75 | for (const auto &U : TypeTestFunc->uses()) { |
| 76 | const auto *CB = dyn_cast_or_null<CallBase>(U.getUser()); |
| 77 | if (!CB) |
| 78 | continue; |
| 79 | |
| 80 | const auto *Op0 = CB->getArgOperand(0); |
| 81 | assert(Op0 && "Unexpected LLVM API Behavior"); |
| 82 | |
| 83 | Op0 = Op0->stripPointerCasts(); |
| 84 | assert(Op0 && "Unexpected LLVM API Behavior"); |
| 85 | |
| 86 | std::vector<DevirtCallBase> DCBases; |
| 87 | collectDevirtCallBases(DCBases, *Op0, 0, M); |
| 88 | |
| 89 | for (const auto &DCBase : DCBases) { |
| 90 | const auto *MDValue = |
| 91 | dyn_cast_or_null<MetadataAsValue>(CB->getArgOperand(1)); |
| 92 | if (!MDValue) |
| 93 | continue; |
| 94 | |
| 95 | for (const auto &TM : TypeIDMap[MDValue->getMetadata()]) { |
| 96 | const auto *Ptr = getPointerAtOffset( |
| 97 | const_cast<Constant *>(TM.GV->getInitializer()), |
| 98 | TM.GVOffset + DCBase.VTOffset, *const_cast<Module *>(&M)); |
| 99 | if (!Ptr) |
| 100 | continue; |
| 101 | |
| 102 | const auto *F = dyn_cast_or_null<Function>(Ptr->stripPointerCasts()); |
| 103 | if (!F) |
| 104 | continue; |
| 105 | |
| 106 | Map[DCBase.CO].emplace(F); |
| 107 | } |
| 108 | } |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | std::set<const Function *> |
| 113 | TestTypeVirtSolverHandler::get(const Value *V) const { |
no test coverage detected