| 171 | } // anonymous namespace |
| 172 | |
| 173 | llvm::PreservedAnalyses IntrospectStructPass::run(llvm::Module& M, llvm::ModuleAnalysisManager& AM) { |
| 174 | llvm::SmallVector<llvm::Function*, 8> BuiltinInstantiations; |
| 175 | for(auto& F: M) { |
| 176 | if(F.getName().contains(builtin_name)) { |
| 177 | BuiltinInstantiations.push_back(&F); |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | llvm::SmallDenseMap<llvm::Function *, TypeInformation> StructTypeInfoForBuiltin; |
| 182 | llvm::SmallVector<llvm::CallInst *, 16> Calls; |
| 183 | for (auto *F : BuiltinInstantiations) { |
| 184 | for (auto *U : F->users()) { |
| 185 | if (llvm::CallInst *CI = llvm::dyn_cast<llvm::CallInst>(U)) { |
| 186 | Calls.push_back(CI); |
| 187 | |
| 188 | if (auto *AI = recurseOperandUntilAlloca(CI)) { |
| 189 | llvm::Type *T = AI->getAllocatedType(); |
| 190 | StructTypeInfoForBuiltin[F] = getTypeInformation(T, M); |
| 191 | } else { |
| 192 | HIPSYCL_DEBUG_WARNING |
| 193 | << "IntrospectStructPass: " << F->getName().str() |
| 194 | << " instantiation could not be connected to type information, ignoring.\n"; |
| 195 | } |
| 196 | } |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | if (StructTypeInfoForBuiltin.size() > 0) |
| 201 | for(auto* CI : Calls) { |
| 202 | llvm::Function* F = CI->getCalledFunction(); |
| 203 | if(F) { |
| 204 | auto It = StructTypeInfoForBuiltin.find(F); |
| 205 | |
| 206 | auto GVs = storeTypeInformationAsGlobals(F, M, It->getSecond()); |
| 207 | |
| 208 | if(It != StructTypeInfoForBuiltin.end()) { |
| 209 | if(F->getFunctionType()->getNumParams() != 5) { |
| 210 | HIPSYCL_DEBUG_WARNING << "IntrospectStructPass: Call to " << F->getName().str() |
| 211 | << " has the wrong number of parameters, ignoring call\n"; |
| 212 | } else { |
| 213 | auto createStoreOp = [&](int ArgIndex, llvm::GlobalVariable* GV) { |
| 214 | if(!CI->getArgOperand(ArgIndex)->getType()->isPointerTy()) { |
| 215 | HIPSYCL_DEBUG_WARNING |
| 216 | << "IntrospectStructPass: Call to " << F->getName().str() |
| 217 | << " is invalid; argument is not a pointer type. Ingoring call.\n"; |
| 218 | return; |
| 219 | } |
| 220 | // In case of non-opaque pointers, we need a bitcast since the stored |
| 221 | // vaue may be pointer-to-array, while the argument may be pointer-to-pointer. |
| 222 | auto* StoreTarget = CI->getArgOperand(ArgIndex); |
| 223 | auto *BCInst = |
| 224 | new llvm::BitCastInst(StoreTarget, getPointerType(GV->getType(), 0), "", CI); |
| 225 | [[maybe_unused]] llvm::StoreInst *S = |
| 226 | new llvm::StoreInst(GV, BCInst, CI); |
| 227 | }; |
| 228 | |
| 229 | createStoreOp(1, GVs.FlattenedNumMembers); |
| 230 | createStoreOp(2, GVs.MemberOffsets); |
nothing calls this directly
no test coverage detected