blob: 4586649d17f086d652eaccec76231f3114cfc3df [file] [log] [blame]
Eugene Zelenko38409752017-09-22 23:46:57 +00001//===- DwarfEHPrepare - Prepare exception handling for code generation ----===//
Duncan Sandsb0f1e172009-05-22 20:36:31 +00002//
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 Wendling2ad4aca2010-03-26 23:41:30 +000011// generation. Required if using dwarf exception handling.
Duncan Sandsb0f1e172009-05-22 20:36:31 +000012//
13//===----------------------------------------------------------------------===//
14
Reid Kleckner4c27f8d2015-03-09 22:45:16 +000015#include "llvm/ADT/BitVector.h"
Eugene Zelenko38409752017-09-22 23:46:57 +000016#include "llvm/ADT/SmallVector.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000017#include "llvm/ADT/Statistic.h"
Reid Kleckner4c27f8d2015-03-09 22:45:16 +000018#include "llvm/Analysis/CFG.h"
David Majnemer1114aa22015-12-02 23:06:39 +000019#include "llvm/Analysis/EHPersonalities.h"
Reid Kleckner4c27f8d2015-03-09 22:45:16 +000020#include "llvm/Analysis/TargetTransformInfo.h"
David Blaikie8325fb22018-06-04 21:23:21 +000021#include "llvm/Transforms/Utils/Local.h"
Eugene Zelenko38409752017-09-22 23:46:57 +000022#include "llvm/CodeGen/RuntimeLibcalls.h"
David Blaikiee3a9b4c2017-11-17 01:07:10 +000023#include "llvm/CodeGen/TargetLowering.h"
Chandler Carruthe3e43d92017-06-06 11:49:48 +000024#include "llvm/CodeGen/TargetPassConfig.h"
David Blaikiee3a9b4c2017-11-17 01:07:10 +000025#include "llvm/CodeGen/TargetSubtargetInfo.h"
Eugene Zelenko38409752017-09-22 23:46:57 +000026#include "llvm/IR/BasicBlock.h"
27#include "llvm/IR/Constants.h"
28#include "llvm/IR/DerivedTypes.h"
Reid Kleckner4c27f8d2015-03-09 22:45:16 +000029#include "llvm/IR/Dominators.h"
Chandler Carruth0b8c9a82013-01-02 11:36:10 +000030#include "llvm/IR/Function.h"
31#include "llvm/IR/Instructions.h"
Chandler Carruth0b8c9a82013-01-02 11:36:10 +000032#include "llvm/IR/Module.h"
Eugene Zelenko38409752017-09-22 23:46:57 +000033#include "llvm/IR/Type.h"
Duncan Sandsb0f1e172009-05-22 20:36:31 +000034#include "llvm/Pass.h"
Eugene Zelenko38409752017-09-22 23:46:57 +000035#include "llvm/Support/Casting.h"
Eugene Zelenko38409752017-09-22 23:46:57 +000036#include "llvm/Target/TargetMachine.h"
Eugene Zelenko38409752017-09-22 23:46:57 +000037#include <cstddef>
38
Duncan Sandsb0f1e172009-05-22 20:36:31 +000039using namespace llvm;
40
Chandler Carruth8677f2f2014-04-22 02:02:50 +000041#define DEBUG_TYPE "dwarfehprepare"
42
Bill Wendlinge13eba22011-11-07 23:36:48 +000043STATISTIC(NumResumesLowered, "Number of resume calls lowered");
Duncan Sandsb0f1e172009-05-22 20:36:31 +000044
45namespace {
Eugene Zelenko38409752017-09-22 23:46:57 +000046
Nick Lewycky6726b6d2009-10-25 06:33:48 +000047 class DwarfEHPrepare : public FunctionPass {
Bill Wendlinge13eba22011-11-07 23:36:48 +000048 // RewindFunction - _Unwind_Resume or the target equivalent.
Eugene Zelenko38409752017-09-22 23:46:57 +000049 Constant *RewindFunction = nullptr;
Duncan Sandsb0f1e172009-05-22 20:36:31 +000050
Eugene Zelenko38409752017-09-22 23:46:57 +000051 DominatorTree *DT = nullptr;
52 const TargetLowering *TLI = nullptr;
Reid Kleckner4c27f8d2015-03-09 22:45:16 +000053
Bill Wendlinge13eba22011-11-07 23:36:48 +000054 bool InsertUnwindResumeCalls(Function &Fn);
Bill Wendling29424e82012-05-17 17:59:51 +000055 Value *GetExceptionObject(ResumeInst *RI);
Reid Kleckner4c27f8d2015-03-09 22:45:16 +000056 size_t
57 pruneUnreachableResumes(Function &Fn,
58 SmallVectorImpl<ResumeInst *> &Resumes,
59 SmallVectorImpl<LandingPadInst *> &CleanupLPads);
Duncan Sandsb0f1e172009-05-22 20:36:31 +000060
Duncan Sandsb0f1e172009-05-22 20:36:31 +000061 public:
62 static char ID; // Pass identification, replacement for typeid.
Reid Klecknerf89d9b12015-02-18 23:17:41 +000063
Eugene Zelenko38409752017-09-22 23:46:57 +000064 DwarfEHPrepare() : FunctionPass(ID) {}
Duncan Sandsb0f1e172009-05-22 20:36:31 +000065
Craig Topper9f998de2014-03-07 09:26:03 +000066 bool runOnFunction(Function &Fn) override;
Duncan Sandsb0f1e172009-05-22 20:36:31 +000067
Yaron Kerene1c77ca2014-09-14 20:36:28 +000068 bool doFinalization(Module &M) override {
69 RewindFunction = nullptr;
70 return false;
71 }
72
Reid Kleckner4c27f8d2015-03-09 22:45:16 +000073 void getAnalysisUsage(AnalysisUsage &AU) const override;
74
Mehdi Amini67f335d2016-10-01 02:56:57 +000075 StringRef getPassName() const override {
Duncan Sandsb0f1e172009-05-22 20:36:31 +000076 return "Exception handling preparation";
77 }
Duncan Sandsb0f1e172009-05-22 20:36:31 +000078 };
Eugene Zelenko38409752017-09-22 23:46:57 +000079
Duncan Sandsb0f1e172009-05-22 20:36:31 +000080} // end anonymous namespace
81
82char DwarfEHPrepare::ID = 0;
Eugene Zelenko38409752017-09-22 23:46:57 +000083
Matthias Braun94c49042017-05-25 21:26:32 +000084INITIALIZE_PASS_BEGIN(DwarfEHPrepare, DEBUG_TYPE,
Francis Visoiu Mistrihae1c8532017-05-18 17:21:13 +000085 "Prepare DWARF exceptions", false, false)
Reid Kleckner4c27f8d2015-03-09 22:45:16 +000086INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
Francis Visoiu Mistrihae1c8532017-05-18 17:21:13 +000087INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
Reid Kleckner4c27f8d2015-03-09 22:45:16 +000088INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
Matthias Braun94c49042017-05-25 21:26:32 +000089INITIALIZE_PASS_END(DwarfEHPrepare, DEBUG_TYPE,
Francis Visoiu Mistrihae1c8532017-05-18 17:21:13 +000090 "Prepare DWARF exceptions", false, false)
Duncan Sandsb0f1e172009-05-22 20:36:31 +000091
Francis Visoiu Mistrihae1c8532017-05-18 17:21:13 +000092FunctionPass *llvm::createDwarfEHPass() { return new DwarfEHPrepare(); }
Duncan Sandsb0f1e172009-05-22 20:36:31 +000093
Reid Kleckner4c27f8d2015-03-09 22:45:16 +000094void DwarfEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
Francis Visoiu Mistrihae1c8532017-05-18 17:21:13 +000095 AU.addRequired<TargetPassConfig>();
Reid Kleckner4c27f8d2015-03-09 22:45:16 +000096 AU.addRequired<TargetTransformInfoWrapperPass>();
97 AU.addRequired<DominatorTreeWrapperPass>();
98}
99
Bill Wendling0ae06de2012-01-28 01:17:56 +0000100/// GetExceptionObject - Return the exception object from the value passed into
101/// the 'resume' instruction (typically an aggregate). Clean up any dead
102/// instructions, including the 'resume' instruction.
Bill Wendling29424e82012-05-17 17:59:51 +0000103Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) {
Bill Wendling0ae06de2012-01-28 01:17:56 +0000104 Value *V = RI->getOperand(0);
Craig Topper4ba84432014-04-14 00:51:57 +0000105 Value *ExnObj = nullptr;
Bill Wendling0ae06de2012-01-28 01:17:56 +0000106 InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V);
Craig Topper4ba84432014-04-14 00:51:57 +0000107 LoadInst *SelLoad = nullptr;
108 InsertValueInst *ExcIVI = nullptr;
Bill Wendling0ae06de2012-01-28 01:17:56 +0000109 bool EraseIVIs = false;
110
111 if (SelIVI) {
112 if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) {
113 ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0));
114 if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) &&
115 ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) {
Bill Wendling29424e82012-05-17 17:59:51 +0000116 ExnObj = ExcIVI->getOperand(1);
Bill Wendling0ae06de2012-01-28 01:17:56 +0000117 SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1));
118 EraseIVIs = true;
119 }
120 }
121 }
122
123 if (!ExnObj)
124 ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI);
125
126 RI->eraseFromParent();
127
128 if (EraseIVIs) {
Benjamin Kramer85ffc542015-01-29 13:26:50 +0000129 if (SelIVI->use_empty())
Bill Wendling0ae06de2012-01-28 01:17:56 +0000130 SelIVI->eraseFromParent();
Benjamin Kramer85ffc542015-01-29 13:26:50 +0000131 if (ExcIVI->use_empty())
Bill Wendling0ae06de2012-01-28 01:17:56 +0000132 ExcIVI->eraseFromParent();
Benjamin Kramer85ffc542015-01-29 13:26:50 +0000133 if (SelLoad && SelLoad->use_empty())
Bill Wendling0ae06de2012-01-28 01:17:56 +0000134 SelLoad->eraseFromParent();
135 }
136
137 return ExnObj;
138}
139
Reid Kleckner4c27f8d2015-03-09 22:45:16 +0000140/// Replace resumes that are not reachable from a cleanup landing pad with
141/// unreachable and then simplify those blocks.
142size_t DwarfEHPrepare::pruneUnreachableResumes(
143 Function &Fn, SmallVectorImpl<ResumeInst *> &Resumes,
144 SmallVectorImpl<LandingPadInst *> &CleanupLPads) {
145 BitVector ResumeReachable(Resumes.size());
146 size_t ResumeIndex = 0;
147 for (auto *RI : Resumes) {
148 for (auto *LP : CleanupLPads) {
149 if (isPotentiallyReachable(LP, RI, DT)) {
150 ResumeReachable.set(ResumeIndex);
151 break;
152 }
153 }
154 ++ResumeIndex;
155 }
156
157 // If everything is reachable, there is no change.
158 if (ResumeReachable.all())
159 return Resumes.size();
160
161 const TargetTransformInfo &TTI =
162 getAnalysis<TargetTransformInfoWrapperPass>().getTTI(Fn);
163 LLVMContext &Ctx = Fn.getContext();
164
165 // Otherwise, insert unreachable instructions and call simplifycfg.
166 size_t ResumesLeft = 0;
167 for (size_t I = 0, E = Resumes.size(); I < E; ++I) {
168 ResumeInst *RI = Resumes[I];
169 if (ResumeReachable[I]) {
170 Resumes[ResumesLeft++] = RI;
171 } else {
172 BasicBlock *BB = RI->getParent();
173 new UnreachableInst(Ctx, RI);
174 RI->eraseFromParent();
Sanjay Pateldfc9ea22017-10-04 20:26:25 +0000175 simplifyCFG(BB, TTI);
Reid Kleckner4c27f8d2015-03-09 22:45:16 +0000176 }
177 }
178 Resumes.resize(ResumesLeft);
179 return ResumesLeft;
180}
181
Bill Wendling35adbb32011-08-17 19:48:49 +0000182/// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present
183/// into calls to the appropriate _Unwind_Resume function.
Bill Wendlinge13eba22011-11-07 23:36:48 +0000184bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
Bill Wendling35adbb32011-08-17 19:48:49 +0000185 SmallVector<ResumeInst*, 16> Resumes;
Reid Kleckner4c27f8d2015-03-09 22:45:16 +0000186 SmallVector<LandingPadInst*, 16> CleanupLPads;
Benjamin Kramer85ffc542015-01-29 13:26:50 +0000187 for (BasicBlock &BB : Fn) {
188 if (auto *RI = dyn_cast<ResumeInst>(BB.getTerminator()))
Bill Wendling09908c42011-08-25 23:48:11 +0000189 Resumes.push_back(RI);
David Majnemercc714e22015-06-17 20:52:32 +0000190 if (auto *LP = BB.getLandingPadInst())
Reid Kleckner4c27f8d2015-03-09 22:45:16 +0000191 if (LP->isCleanup())
192 CleanupLPads.push_back(LP);
Bill Wendling09908c42011-08-25 23:48:11 +0000193 }
Bill Wendling35adbb32011-08-17 19:48:49 +0000194
195 if (Resumes.empty())
Kai Nacke52aaf6a2013-05-31 16:30:36 +0000196 return false;
Bill Wendling35adbb32011-08-17 19:48:49 +0000197
Heejin Ahn5b752cf2018-05-17 20:52:03 +0000198 // Check the personality, don't do anything if it's scope-based.
David Majnemercc714e22015-06-17 20:52:32 +0000199 EHPersonality Pers = classifyEHPersonality(Fn.getPersonalityFn());
Heejin Ahn5b752cf2018-05-17 20:52:03 +0000200 if (isScopedEHPersonality(Pers))
David Majnemercc714e22015-06-17 20:52:32 +0000201 return false;
202
Chandler Carruth90b8e792015-02-20 02:15:36 +0000203 LLVMContext &Ctx = Fn.getContext();
Reid Kleckner4c27f8d2015-03-09 22:45:16 +0000204
205 size_t ResumesLeft = pruneUnreachableResumes(Fn, Resumes, CleanupLPads);
206 if (ResumesLeft == 0)
207 return true; // We pruned them all.
208
209 // Find the rewind function if we didn't already.
Bill Wendling35adbb32011-08-17 19:48:49 +0000210 if (!RewindFunction) {
Bill Wendling35adbb32011-08-17 19:48:49 +0000211 FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
212 Type::getInt8PtrTy(Ctx), false);
213 const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME);
Bill Wendlinge13eba22011-11-07 23:36:48 +0000214 RewindFunction = Fn.getParent()->getOrInsertFunction(RewindName, FTy);
Bill Wendling35adbb32011-08-17 19:48:49 +0000215 }
216
217 // Create the basic block where the _Unwind_Resume call will live.
Reid Kleckner4c27f8d2015-03-09 22:45:16 +0000218 if (ResumesLeft == 1) {
Bill Wendling0ae06de2012-01-28 01:17:56 +0000219 // Instead of creating a new BB and PHI node, just append the call to
220 // _Unwind_Resume to the end of the single resume block.
221 ResumeInst *RI = Resumes.front();
222 BasicBlock *UnwindBB = RI->getParent();
Bill Wendling29424e82012-05-17 17:59:51 +0000223 Value *ExnObj = GetExceptionObject(RI);
Bill Wendling0ae06de2012-01-28 01:17:56 +0000224
225 // Call the _Unwind_Resume function.
226 CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB);
227 CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
228
229 // We never expect _Unwind_Resume to return.
230 new UnreachableInst(Ctx, UnwindBB);
231 return true;
232 }
233
Bill Wendlinge13eba22011-11-07 23:36:48 +0000234 BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &Fn);
Reid Kleckner4c27f8d2015-03-09 22:45:16 +0000235 PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft,
Bill Wendling35adbb32011-08-17 19:48:49 +0000236 "exn.obj", UnwindBB);
237
238 // Extract the exception object from the ResumeInst and add it to the PHI node
239 // that feeds the _Unwind_Resume call.
Benjamin Kramer85ffc542015-01-29 13:26:50 +0000240 for (ResumeInst *RI : Resumes) {
Bill Wendling0ae06de2012-01-28 01:17:56 +0000241 BasicBlock *Parent = RI->getParent();
242 BranchInst::Create(UnwindBB, Parent);
Bill Wendlingb618ea52012-01-20 00:53:28 +0000243
Bill Wendling29424e82012-05-17 17:59:51 +0000244 Value *ExnObj = GetExceptionObject(RI);
Bill Wendling0ae06de2012-01-28 01:17:56 +0000245 PN->addIncoming(ExnObj, Parent);
Bill Wendlingb618ea52012-01-20 00:53:28 +0000246
Bill Wendlinge13eba22011-11-07 23:36:48 +0000247 ++NumResumesLowered;
Bill Wendling35adbb32011-08-17 19:48:49 +0000248 }
249
250 // Call the function.
251 CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB);
252 CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
253
254 // We never expect _Unwind_Resume to return.
255 new UnreachableInst(Ctx, UnwindBB);
256 return true;
257}
258
Duncan Sandsb0f1e172009-05-22 20:36:31 +0000259bool DwarfEHPrepare::runOnFunction(Function &Fn) {
Francis Visoiu Mistrihae1c8532017-05-18 17:21:13 +0000260 const TargetMachine &TM =
261 getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
Reid Kleckner4c27f8d2015-03-09 22:45:16 +0000262 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
Francis Visoiu Mistrihae1c8532017-05-18 17:21:13 +0000263 TLI = TM.getSubtargetImpl(Fn)->getTargetLowering();
Bill Wendlinge13eba22011-11-07 23:36:48 +0000264 bool Changed = InsertUnwindResumeCalls(Fn);
Reid Kleckner4c27f8d2015-03-09 22:45:16 +0000265 DT = nullptr;
266 TLI = nullptr;
Duncan Sandsb0f1e172009-05-22 20:36:31 +0000267 return Changed;
268}