blob: 2f833260bca209f7f2b219ef6be7207729df2db7 [file] [log] [blame]
Duncan Sandsd6fb6502009-05-22 20:36:31 +00001//===-- 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
Bill Wendlingd1aa77c2010-03-26 23:41:30 +000011// generation. Required if using dwarf exception handling.
Duncan Sandsd6fb6502009-05-22 20:36:31 +000012//
13//===----------------------------------------------------------------------===//
14
Reid Klecknerbe0a0502015-03-09 22:45:16 +000015#include "llvm/ADT/BitVector.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000016#include "llvm/ADT/Statistic.h"
Reid Klecknerbe0a0502015-03-09 22:45:16 +000017#include "llvm/Analysis/CFG.h"
David Majnemer70497c62015-12-02 23:06:39 +000018#include "llvm/Analysis/EHPersonalities.h"
Reid Klecknerbe0a0502015-03-09 22:45:16 +000019#include "llvm/Analysis/TargetTransformInfo.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "llvm/CodeGen/Passes.h"
21#include "llvm/CodeGen/TargetPassConfig.h"
Reid Klecknerbe0a0502015-03-09 22:45:16 +000022#include "llvm/IR/Dominators.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000023#include "llvm/IR/Function.h"
24#include "llvm/IR/Instructions.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000025#include "llvm/IR/Module.h"
Duncan Sandsd6fb6502009-05-22 20:36:31 +000026#include "llvm/Pass.h"
Duncan Sandsd6fb6502009-05-22 20:36:31 +000027#include "llvm/Target/TargetLowering.h"
Eric Christopherd9134482014-08-04 21:25:23 +000028#include "llvm/Target/TargetSubtargetInfo.h"
Reid Klecknerbe0a0502015-03-09 22:45:16 +000029#include "llvm/Transforms/Utils/Local.h"
Duncan Sandsd6fb6502009-05-22 20:36:31 +000030using namespace llvm;
31
Chandler Carruth1b9dde02014-04-22 02:02:50 +000032#define DEBUG_TYPE "dwarfehprepare"
33
Bill Wendling478f58c2011-11-07 23:36:48 +000034STATISTIC(NumResumesLowered, "Number of resume calls lowered");
Duncan Sandsd6fb6502009-05-22 20:36:31 +000035
36namespace {
Nick Lewycky02d5f772009-10-25 06:33:48 +000037 class DwarfEHPrepare : public FunctionPass {
Bill Wendling478f58c2011-11-07 23:36:48 +000038 // RewindFunction - _Unwind_Resume or the target equivalent.
Duncan Sandsd6fb6502009-05-22 20:36:31 +000039 Constant *RewindFunction;
40
Reid Klecknerbe0a0502015-03-09 22:45:16 +000041 DominatorTree *DT;
42 const TargetLowering *TLI;
43
Bill Wendling478f58c2011-11-07 23:36:48 +000044 bool InsertUnwindResumeCalls(Function &Fn);
Bill Wendling27489fe2012-05-17 17:59:51 +000045 Value *GetExceptionObject(ResumeInst *RI);
Reid Klecknerbe0a0502015-03-09 22:45:16 +000046 size_t
47 pruneUnreachableResumes(Function &Fn,
48 SmallVectorImpl<ResumeInst *> &Resumes,
49 SmallVectorImpl<LandingPadInst *> &CleanupLPads);
Duncan Sandsd6fb6502009-05-22 20:36:31 +000050
Duncan Sandsd6fb6502009-05-22 20:36:31 +000051 public:
52 static char ID; // Pass identification, replacement for typeid.
Reid Kleckner7bb07382015-02-18 23:17:41 +000053
Reid Klecknerbe0a0502015-03-09 22:45:16 +000054 DwarfEHPrepare()
Francis Visoiu Mistrih8b617642017-05-18 17:21:13 +000055 : FunctionPass(ID), RewindFunction(nullptr), DT(nullptr), TLI(nullptr) {
56 }
Duncan Sandsd6fb6502009-05-22 20:36:31 +000057
Craig Topper4584cd52014-03-07 09:26:03 +000058 bool runOnFunction(Function &Fn) override;
Duncan Sandsd6fb6502009-05-22 20:36:31 +000059
Yaron Keren66b0ceb2014-09-14 20:36:28 +000060 bool doFinalization(Module &M) override {
61 RewindFunction = nullptr;
62 return false;
63 }
64
Reid Klecknerbe0a0502015-03-09 22:45:16 +000065 void getAnalysisUsage(AnalysisUsage &AU) const override;
66
Mehdi Amini117296c2016-10-01 02:56:57 +000067 StringRef getPassName() const override {
Duncan Sandsd6fb6502009-05-22 20:36:31 +000068 return "Exception handling preparation";
69 }
Duncan Sandsd6fb6502009-05-22 20:36:31 +000070 };
71} // end anonymous namespace
72
73char DwarfEHPrepare::ID = 0;
Matthias Braun1527baa2017-05-25 21:26:32 +000074INITIALIZE_PASS_BEGIN(DwarfEHPrepare, DEBUG_TYPE,
Francis Visoiu Mistrih8b617642017-05-18 17:21:13 +000075 "Prepare DWARF exceptions", false, false)
Reid Klecknerbe0a0502015-03-09 22:45:16 +000076INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
Francis Visoiu Mistrih8b617642017-05-18 17:21:13 +000077INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
Reid Klecknerbe0a0502015-03-09 22:45:16 +000078INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
Matthias Braun1527baa2017-05-25 21:26:32 +000079INITIALIZE_PASS_END(DwarfEHPrepare, DEBUG_TYPE,
Francis Visoiu Mistrih8b617642017-05-18 17:21:13 +000080 "Prepare DWARF exceptions", false, false)
Duncan Sandsd6fb6502009-05-22 20:36:31 +000081
Francis Visoiu Mistrih8b617642017-05-18 17:21:13 +000082FunctionPass *llvm::createDwarfEHPass() { return new DwarfEHPrepare(); }
Duncan Sandsd6fb6502009-05-22 20:36:31 +000083
Reid Klecknerbe0a0502015-03-09 22:45:16 +000084void DwarfEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
Francis Visoiu Mistrih8b617642017-05-18 17:21:13 +000085 AU.addRequired<TargetPassConfig>();
Reid Klecknerbe0a0502015-03-09 22:45:16 +000086 AU.addRequired<TargetTransformInfoWrapperPass>();
87 AU.addRequired<DominatorTreeWrapperPass>();
88}
89
Bill Wendling8c090402012-01-28 01:17:56 +000090/// GetExceptionObject - Return the exception object from the value passed into
91/// the 'resume' instruction (typically an aggregate). Clean up any dead
92/// instructions, including the 'resume' instruction.
Bill Wendling27489fe2012-05-17 17:59:51 +000093Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) {
Bill Wendling8c090402012-01-28 01:17:56 +000094 Value *V = RI->getOperand(0);
Craig Topperc0196b12014-04-14 00:51:57 +000095 Value *ExnObj = nullptr;
Bill Wendling8c090402012-01-28 01:17:56 +000096 InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V);
Craig Topperc0196b12014-04-14 00:51:57 +000097 LoadInst *SelLoad = nullptr;
98 InsertValueInst *ExcIVI = nullptr;
Bill Wendling8c090402012-01-28 01:17:56 +000099 bool EraseIVIs = false;
100
101 if (SelIVI) {
102 if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) {
103 ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0));
104 if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) &&
105 ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) {
Bill Wendling27489fe2012-05-17 17:59:51 +0000106 ExnObj = ExcIVI->getOperand(1);
Bill Wendling8c090402012-01-28 01:17:56 +0000107 SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1));
108 EraseIVIs = true;
109 }
110 }
111 }
112
113 if (!ExnObj)
114 ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI);
115
116 RI->eraseFromParent();
117
118 if (EraseIVIs) {
Benjamin Kramereb63e4d2015-01-29 13:26:50 +0000119 if (SelIVI->use_empty())
Bill Wendling8c090402012-01-28 01:17:56 +0000120 SelIVI->eraseFromParent();
Benjamin Kramereb63e4d2015-01-29 13:26:50 +0000121 if (ExcIVI->use_empty())
Bill Wendling8c090402012-01-28 01:17:56 +0000122 ExcIVI->eraseFromParent();
Benjamin Kramereb63e4d2015-01-29 13:26:50 +0000123 if (SelLoad && SelLoad->use_empty())
Bill Wendling8c090402012-01-28 01:17:56 +0000124 SelLoad->eraseFromParent();
125 }
126
127 return ExnObj;
128}
129
Reid Klecknerbe0a0502015-03-09 22:45:16 +0000130/// Replace resumes that are not reachable from a cleanup landing pad with
131/// unreachable and then simplify those blocks.
132size_t DwarfEHPrepare::pruneUnreachableResumes(
133 Function &Fn, SmallVectorImpl<ResumeInst *> &Resumes,
134 SmallVectorImpl<LandingPadInst *> &CleanupLPads) {
135 BitVector ResumeReachable(Resumes.size());
136 size_t ResumeIndex = 0;
137 for (auto *RI : Resumes) {
138 for (auto *LP : CleanupLPads) {
139 if (isPotentiallyReachable(LP, RI, DT)) {
140 ResumeReachable.set(ResumeIndex);
141 break;
142 }
143 }
144 ++ResumeIndex;
145 }
146
147 // If everything is reachable, there is no change.
148 if (ResumeReachable.all())
149 return Resumes.size();
150
151 const TargetTransformInfo &TTI =
152 getAnalysis<TargetTransformInfoWrapperPass>().getTTI(Fn);
153 LLVMContext &Ctx = Fn.getContext();
154
155 // Otherwise, insert unreachable instructions and call simplifycfg.
156 size_t ResumesLeft = 0;
157 for (size_t I = 0, E = Resumes.size(); I < E; ++I) {
158 ResumeInst *RI = Resumes[I];
159 if (ResumeReachable[I]) {
160 Resumes[ResumesLeft++] = RI;
161 } else {
162 BasicBlock *BB = RI->getParent();
163 new UnreachableInst(Ctx, RI);
164 RI->eraseFromParent();
Mehdi Aminia28d91d2015-03-10 02:37:25 +0000165 SimplifyCFG(BB, TTI, 1);
Reid Klecknerbe0a0502015-03-09 22:45:16 +0000166 }
167 }
168 Resumes.resize(ResumesLeft);
169 return ResumesLeft;
170}
171
Bill Wendling1cdd7fd2011-08-17 19:48:49 +0000172/// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present
173/// into calls to the appropriate _Unwind_Resume function.
Bill Wendling478f58c2011-11-07 23:36:48 +0000174bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
Bill Wendling1cdd7fd2011-08-17 19:48:49 +0000175 SmallVector<ResumeInst*, 16> Resumes;
Reid Klecknerbe0a0502015-03-09 22:45:16 +0000176 SmallVector<LandingPadInst*, 16> CleanupLPads;
Benjamin Kramereb63e4d2015-01-29 13:26:50 +0000177 for (BasicBlock &BB : Fn) {
178 if (auto *RI = dyn_cast<ResumeInst>(BB.getTerminator()))
Bill Wendling8ac20412011-08-25 23:48:11 +0000179 Resumes.push_back(RI);
David Majnemer7fddecc2015-06-17 20:52:32 +0000180 if (auto *LP = BB.getLandingPadInst())
Reid Klecknerbe0a0502015-03-09 22:45:16 +0000181 if (LP->isCleanup())
182 CleanupLPads.push_back(LP);
Bill Wendling8ac20412011-08-25 23:48:11 +0000183 }
Bill Wendling1cdd7fd2011-08-17 19:48:49 +0000184
185 if (Resumes.empty())
Kai Nackee1823b62013-05-31 16:30:36 +0000186 return false;
Bill Wendling1cdd7fd2011-08-17 19:48:49 +0000187
Joseph Tremoulet2afea542015-10-06 20:28:16 +0000188 // Check the personality, don't do anything if it's funclet-based.
David Majnemer7fddecc2015-06-17 20:52:32 +0000189 EHPersonality Pers = classifyEHPersonality(Fn.getPersonalityFn());
Joseph Tremoulet2afea542015-10-06 20:28:16 +0000190 if (isFuncletEHPersonality(Pers))
David Majnemer7fddecc2015-06-17 20:52:32 +0000191 return false;
192
Chandler Carruth301ed0c2015-02-20 02:15:36 +0000193 LLVMContext &Ctx = Fn.getContext();
Reid Klecknerbe0a0502015-03-09 22:45:16 +0000194
195 size_t ResumesLeft = pruneUnreachableResumes(Fn, Resumes, CleanupLPads);
196 if (ResumesLeft == 0)
197 return true; // We pruned them all.
198
199 // Find the rewind function if we didn't already.
Bill Wendling1cdd7fd2011-08-17 19:48:49 +0000200 if (!RewindFunction) {
Bill Wendling1cdd7fd2011-08-17 19:48:49 +0000201 FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
202 Type::getInt8PtrTy(Ctx), false);
203 const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME);
Bill Wendling478f58c2011-11-07 23:36:48 +0000204 RewindFunction = Fn.getParent()->getOrInsertFunction(RewindName, FTy);
Bill Wendling1cdd7fd2011-08-17 19:48:49 +0000205 }
206
207 // Create the basic block where the _Unwind_Resume call will live.
Reid Klecknerbe0a0502015-03-09 22:45:16 +0000208 if (ResumesLeft == 1) {
Bill Wendling8c090402012-01-28 01:17:56 +0000209 // Instead of creating a new BB and PHI node, just append the call to
210 // _Unwind_Resume to the end of the single resume block.
211 ResumeInst *RI = Resumes.front();
212 BasicBlock *UnwindBB = RI->getParent();
Bill Wendling27489fe2012-05-17 17:59:51 +0000213 Value *ExnObj = GetExceptionObject(RI);
Bill Wendling8c090402012-01-28 01:17:56 +0000214
215 // Call the _Unwind_Resume function.
216 CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB);
217 CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
218
219 // We never expect _Unwind_Resume to return.
220 new UnreachableInst(Ctx, UnwindBB);
221 return true;
222 }
223
Bill Wendling478f58c2011-11-07 23:36:48 +0000224 BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &Fn);
Reid Klecknerbe0a0502015-03-09 22:45:16 +0000225 PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft,
Bill Wendling1cdd7fd2011-08-17 19:48:49 +0000226 "exn.obj", UnwindBB);
227
228 // Extract the exception object from the ResumeInst and add it to the PHI node
229 // that feeds the _Unwind_Resume call.
Benjamin Kramereb63e4d2015-01-29 13:26:50 +0000230 for (ResumeInst *RI : Resumes) {
Bill Wendling8c090402012-01-28 01:17:56 +0000231 BasicBlock *Parent = RI->getParent();
232 BranchInst::Create(UnwindBB, Parent);
Bill Wendling92492612012-01-20 00:53:28 +0000233
Bill Wendling27489fe2012-05-17 17:59:51 +0000234 Value *ExnObj = GetExceptionObject(RI);
Bill Wendling8c090402012-01-28 01:17:56 +0000235 PN->addIncoming(ExnObj, Parent);
Bill Wendling92492612012-01-20 00:53:28 +0000236
Bill Wendling478f58c2011-11-07 23:36:48 +0000237 ++NumResumesLowered;
Bill Wendling1cdd7fd2011-08-17 19:48:49 +0000238 }
239
240 // Call the function.
241 CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB);
242 CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
243
244 // We never expect _Unwind_Resume to return.
245 new UnreachableInst(Ctx, UnwindBB);
246 return true;
247}
248
Duncan Sandsd6fb6502009-05-22 20:36:31 +0000249bool DwarfEHPrepare::runOnFunction(Function &Fn) {
Francis Visoiu Mistrih8b617642017-05-18 17:21:13 +0000250 const TargetMachine &TM =
251 getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
Reid Klecknerbe0a0502015-03-09 22:45:16 +0000252 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
Francis Visoiu Mistrih8b617642017-05-18 17:21:13 +0000253 TLI = TM.getSubtargetImpl(Fn)->getTargetLowering();
Bill Wendling478f58c2011-11-07 23:36:48 +0000254 bool Changed = InsertUnwindResumeCalls(Fn);
Reid Klecknerbe0a0502015-03-09 22:45:16 +0000255 DT = nullptr;
256 TLI = nullptr;
Duncan Sandsd6fb6502009-05-22 20:36:31 +0000257 return Changed;
258}