DwarfEHPrepare.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. //===-- DwarfEHPrepare - Prepare exception handling for code generation ---===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This pass mulches exception handling code into a form adapted to code
  11. // generation. Required if using dwarf exception handling.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm/CodeGen/Passes.h"
  15. #include "llvm/ADT/BitVector.h"
  16. #include "llvm/ADT/Statistic.h"
  17. #include "llvm/Analysis/CFG.h"
  18. #include "llvm/Analysis/LibCallSemantics.h"
  19. #include "llvm/Analysis/TargetTransformInfo.h"
  20. #include "llvm/IR/Dominators.h"
  21. #include "llvm/IR/Function.h"
  22. #include "llvm/IR/Instructions.h"
  23. #include "llvm/IR/Module.h"
  24. #include "llvm/Pass.h"
  25. #include "llvm/Target/TargetLowering.h"
  26. #include "llvm/Target/TargetSubtargetInfo.h"
  27. #include "llvm/Transforms/Utils/Local.h"
  28. using namespace llvm;
  29. #define DEBUG_TYPE "dwarfehprepare"
  30. STATISTIC(NumResumesLowered, "Number of resume calls lowered");
  31. namespace {
  32. class DwarfEHPrepare : public FunctionPass {
  33. const TargetMachine *TM;
  34. // RewindFunction - _Unwind_Resume or the target equivalent.
  35. Constant *RewindFunction;
  36. DominatorTree *DT;
  37. const TargetLowering *TLI;
  38. bool InsertUnwindResumeCalls(Function &Fn);
  39. Value *GetExceptionObject(ResumeInst *RI);
  40. size_t
  41. pruneUnreachableResumes(Function &Fn,
  42. SmallVectorImpl<ResumeInst *> &Resumes,
  43. SmallVectorImpl<LandingPadInst *> &CleanupLPads);
  44. public:
  45. static char ID; // Pass identification, replacement for typeid.
  46. // INITIALIZE_TM_PASS requires a default constructor, but it isn't used in
  47. // practice.
  48. DwarfEHPrepare()
  49. : FunctionPass(ID), TM(nullptr), RewindFunction(nullptr), DT(nullptr),
  50. TLI(nullptr) {}
  51. DwarfEHPrepare(const TargetMachine *TM)
  52. : FunctionPass(ID), TM(TM), RewindFunction(nullptr), DT(nullptr),
  53. TLI(nullptr) {}
  54. bool runOnFunction(Function &Fn) override;
  55. bool doFinalization(Module &M) override {
  56. RewindFunction = nullptr;
  57. return false;
  58. }
  59. void getAnalysisUsage(AnalysisUsage &AU) const override;
  60. const char *getPassName() const override {
  61. return "Exception handling preparation";
  62. }
  63. };
  64. } // end anonymous namespace
  65. char DwarfEHPrepare::ID = 0;
  66. INITIALIZE_TM_PASS_BEGIN(DwarfEHPrepare, "dwarfehprepare",
  67. "Prepare DWARF exceptions", false, false)
  68. INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
  69. INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
  70. INITIALIZE_TM_PASS_END(DwarfEHPrepare, "dwarfehprepare",
  71. "Prepare DWARF exceptions", false, false)
  72. FunctionPass *llvm::createDwarfEHPass(const TargetMachine *TM) {
  73. return new DwarfEHPrepare(TM);
  74. }
  75. void DwarfEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
  76. AU.addRequired<TargetTransformInfoWrapperPass>();
  77. AU.addRequired<DominatorTreeWrapperPass>();
  78. }
  79. /// GetExceptionObject - Return the exception object from the value passed into
  80. /// the 'resume' instruction (typically an aggregate). Clean up any dead
  81. /// instructions, including the 'resume' instruction.
  82. Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) {
  83. Value *V = RI->getOperand(0);
  84. Value *ExnObj = nullptr;
  85. InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V);
  86. LoadInst *SelLoad = nullptr;
  87. InsertValueInst *ExcIVI = nullptr;
  88. bool EraseIVIs = false;
  89. if (SelIVI) {
  90. if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) {
  91. ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0));
  92. if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) &&
  93. ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) {
  94. ExnObj = ExcIVI->getOperand(1);
  95. SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1));
  96. EraseIVIs = true;
  97. }
  98. }
  99. }
  100. if (!ExnObj)
  101. ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI);
  102. RI->eraseFromParent();
  103. if (EraseIVIs) {
  104. if (SelIVI->use_empty())
  105. SelIVI->eraseFromParent();
  106. if (ExcIVI->use_empty())
  107. ExcIVI->eraseFromParent();
  108. if (SelLoad && SelLoad->use_empty())
  109. SelLoad->eraseFromParent();
  110. }
  111. return ExnObj;
  112. }
  113. /// Replace resumes that are not reachable from a cleanup landing pad with
  114. /// unreachable and then simplify those blocks.
  115. size_t DwarfEHPrepare::pruneUnreachableResumes(
  116. Function &Fn, SmallVectorImpl<ResumeInst *> &Resumes,
  117. SmallVectorImpl<LandingPadInst *> &CleanupLPads) {
  118. BitVector ResumeReachable(Resumes.size());
  119. size_t ResumeIndex = 0;
  120. for (auto *RI : Resumes) {
  121. for (auto *LP : CleanupLPads) {
  122. if (isPotentiallyReachable(LP, RI, DT)) {
  123. ResumeReachable.set(ResumeIndex);
  124. break;
  125. }
  126. }
  127. ++ResumeIndex;
  128. }
  129. // If everything is reachable, there is no change.
  130. if (ResumeReachable.all())
  131. return Resumes.size();
  132. const TargetTransformInfo &TTI =
  133. getAnalysis<TargetTransformInfoWrapperPass>().getTTI(Fn);
  134. LLVMContext &Ctx = Fn.getContext();
  135. // Otherwise, insert unreachable instructions and call simplifycfg.
  136. size_t ResumesLeft = 0;
  137. for (size_t I = 0, E = Resumes.size(); I < E; ++I) {
  138. ResumeInst *RI = Resumes[I];
  139. if (ResumeReachable[I]) {
  140. Resumes[ResumesLeft++] = RI;
  141. } else {
  142. BasicBlock *BB = RI->getParent();
  143. new UnreachableInst(Ctx, RI);
  144. RI->eraseFromParent();
  145. SimplifyCFG(BB, TTI, 1);
  146. }
  147. }
  148. Resumes.resize(ResumesLeft);
  149. return ResumesLeft;
  150. }
  151. /// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present
  152. /// into calls to the appropriate _Unwind_Resume function.
  153. bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
  154. SmallVector<ResumeInst*, 16> Resumes;
  155. SmallVector<LandingPadInst*, 16> CleanupLPads;
  156. for (BasicBlock &BB : Fn) {
  157. if (auto *RI = dyn_cast<ResumeInst>(BB.getTerminator()))
  158. Resumes.push_back(RI);
  159. if (auto *LP = BB.getLandingPadInst())
  160. if (LP->isCleanup())
  161. CleanupLPads.push_back(LP);
  162. }
  163. if (Resumes.empty())
  164. return false;
  165. // Check the personality, don't do anything if it's for MSVC.
  166. EHPersonality Pers = classifyEHPersonality(Fn.getPersonalityFn());
  167. if (isMSVCEHPersonality(Pers))
  168. return false;
  169. LLVMContext &Ctx = Fn.getContext();
  170. size_t ResumesLeft = pruneUnreachableResumes(Fn, Resumes, CleanupLPads);
  171. if (ResumesLeft == 0)
  172. return true; // We pruned them all.
  173. // Find the rewind function if we didn't already.
  174. if (!RewindFunction) {
  175. FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
  176. Type::getInt8PtrTy(Ctx), false);
  177. const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME);
  178. RewindFunction = Fn.getParent()->getOrInsertFunction(RewindName, FTy);
  179. }
  180. // Create the basic block where the _Unwind_Resume call will live.
  181. if (ResumesLeft == 1) {
  182. // Instead of creating a new BB and PHI node, just append the call to
  183. // _Unwind_Resume to the end of the single resume block.
  184. ResumeInst *RI = Resumes.front();
  185. BasicBlock *UnwindBB = RI->getParent();
  186. Value *ExnObj = GetExceptionObject(RI);
  187. // Call the _Unwind_Resume function.
  188. CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB);
  189. CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
  190. // We never expect _Unwind_Resume to return.
  191. new UnreachableInst(Ctx, UnwindBB);
  192. return true;
  193. }
  194. BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &Fn);
  195. PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft,
  196. "exn.obj", UnwindBB);
  197. // Extract the exception object from the ResumeInst and add it to the PHI node
  198. // that feeds the _Unwind_Resume call.
  199. for (ResumeInst *RI : Resumes) {
  200. BasicBlock *Parent = RI->getParent();
  201. BranchInst::Create(UnwindBB, Parent);
  202. Value *ExnObj = GetExceptionObject(RI);
  203. PN->addIncoming(ExnObj, Parent);
  204. ++NumResumesLowered;
  205. }
  206. // Call the function.
  207. CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB);
  208. CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
  209. // We never expect _Unwind_Resume to return.
  210. new UnreachableInst(Ctx, UnwindBB);
  211. return true;
  212. }
  213. bool DwarfEHPrepare::runOnFunction(Function &Fn) {
  214. assert(TM && "DWARF EH preparation requires a target machine");
  215. DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
  216. TLI = TM->getSubtargetImpl(Fn)->getTargetLowering();
  217. bool Changed = InsertUnwindResumeCalls(Fn);
  218. DT = nullptr;
  219. TLI = nullptr;
  220. return Changed;
  221. }