| 10 | : Handler(std::move(Handler)) {} |
| 11 | |
| 12 | std::set<const llvm::Function *> |
| 13 | GlobalInitializerSolver::solve(const llvm::CallBase &CB) const { |
| 14 | const auto *CO = CB.getCalledOperand(); |
| 15 | if (!CO) |
| 16 | return {}; |
| 17 | |
| 18 | const auto *LI = dyn_cast_or_null<LoadInst>(CO->stripPointerCasts()); |
| 19 | if (!LI) |
| 20 | return {}; |
| 21 | |
| 22 | const auto *Ptr = LI->getPointerOperand(); |
| 23 | assert(Ptr && "Unexpected LLVM API Behavior"); |
| 24 | |
| 25 | Ptr = Ptr->stripPointerCasts(); |
| 26 | assert(Ptr && "Unexpected LLVM API Behavior"); |
| 27 | |
| 28 | if (const auto *CE = dyn_cast<ConstantExpr>(Ptr)) { |
| 29 | Ptr = CE->getAsInstruction(); |
| 30 | } |
| 31 | |
| 32 | if (!isa<Instruction>(Ptr)) |
| 33 | return {}; |
| 34 | |
| 35 | const auto *GEPI = dyn_cast_or_null<GetElementPtrInst>(Ptr); |
| 36 | if (!GEPI) { |
| 37 | const auto *Ty = Ptr->getType(); |
| 38 | return Handler.get(Ty, 0); |
| 39 | } |
| 40 | |
| 41 | Ptr = GEPI->getOperand(0); |
| 42 | if (!Ptr) |
| 43 | return {}; |
| 44 | |
| 45 | const ConstantInt *CI = nullptr; |
| 46 | unsigned NumIndices = GEPI->getNumIndices(); |
| 47 | if (NumIndices == 1) |
| 48 | CI = dyn_cast_or_null<ConstantInt>(GEPI->getOperand(1)); |
| 49 | else if (NumIndices > 1) |
| 50 | CI = dyn_cast_or_null<ConstantInt>(GEPI->getOperand(2)); |
| 51 | if (!CI) |
| 52 | return {}; |
| 53 | |
| 54 | return Handler.get(Ptr->getType(), CI->getSExtValue()); |
| 55 | } |