[llvm-objcopy] [COFF] Test absolute symbols wrt --strip-unneeded and --discard-all...
[llvm-complete.git] / lib / CodeGen / DwarfEHPrepare.cpp
blob4586649d17f086d652eaccec76231f3114cfc3df
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.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/ADT/BitVector.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/Statistic.h"
18 #include "llvm/Analysis/CFG.h"
19 #include "llvm/Analysis/EHPersonalities.h"
20 #include "llvm/Analysis/TargetTransformInfo.h"
21 #include "llvm/Transforms/Utils/Local.h"
22 #include "llvm/CodeGen/RuntimeLibcalls.h"
23 #include "llvm/CodeGen/TargetLowering.h"
24 #include "llvm/CodeGen/TargetPassConfig.h"
25 #include "llvm/CodeGen/TargetSubtargetInfo.h"
26 #include "llvm/IR/BasicBlock.h"
27 #include "llvm/IR/Constants.h"
28 #include "llvm/IR/DerivedTypes.h"
29 #include "llvm/IR/Dominators.h"
30 #include "llvm/IR/Function.h"
31 #include "llvm/IR/Instructions.h"
32 #include "llvm/IR/Module.h"
33 #include "llvm/IR/Type.h"
34 #include "llvm/Pass.h"
35 #include "llvm/Support/Casting.h"
36 #include "llvm/Target/TargetMachine.h"
37 #include <cstddef>
39 using namespace llvm;
41 #define DEBUG_TYPE "dwarfehprepare"
43 STATISTIC(NumResumesLowered, "Number of resume calls lowered");
45 namespace {
47 class DwarfEHPrepare : public FunctionPass {
48 // RewindFunction - _Unwind_Resume or the target equivalent.
49 Constant *RewindFunction = nullptr;
51 DominatorTree *DT = nullptr;
52 const TargetLowering *TLI = nullptr;
54 bool InsertUnwindResumeCalls(Function &Fn);
55 Value *GetExceptionObject(ResumeInst *RI);
56 size_t
57 pruneUnreachableResumes(Function &Fn,
58 SmallVectorImpl<ResumeInst *> &Resumes,
59 SmallVectorImpl<LandingPadInst *> &CleanupLPads);
61 public:
62 static char ID; // Pass identification, replacement for typeid.
64 DwarfEHPrepare() : FunctionPass(ID) {}
66 bool runOnFunction(Function &Fn) override;
68 bool doFinalization(Module &M) override {
69 RewindFunction = nullptr;
70 return false;
73 void getAnalysisUsage(AnalysisUsage &AU) const override;
75 StringRef getPassName() const override {
76 return "Exception handling preparation";
80 } // end anonymous namespace
82 char DwarfEHPrepare::ID = 0;
84 INITIALIZE_PASS_BEGIN(DwarfEHPrepare, DEBUG_TYPE,
85 "Prepare DWARF exceptions", false, false)
86 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
87 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
88 INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
89 INITIALIZE_PASS_END(DwarfEHPrepare, DEBUG_TYPE,
90 "Prepare DWARF exceptions", false, false)
92 FunctionPass *llvm::createDwarfEHPass() { return new DwarfEHPrepare(); }
94 void DwarfEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
95 AU.addRequired<TargetPassConfig>();
96 AU.addRequired<TargetTransformInfoWrapperPass>();
97 AU.addRequired<DominatorTreeWrapperPass>();
100 /// 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.
103 Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) {
104 Value *V = RI->getOperand(0);
105 Value *ExnObj = nullptr;
106 InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V);
107 LoadInst *SelLoad = nullptr;
108 InsertValueInst *ExcIVI = nullptr;
109 bool EraseIVIs = false;
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) {
116 ExnObj = ExcIVI->getOperand(1);
117 SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1));
118 EraseIVIs = true;
123 if (!ExnObj)
124 ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI);
126 RI->eraseFromParent();
128 if (EraseIVIs) {
129 if (SelIVI->use_empty())
130 SelIVI->eraseFromParent();
131 if (ExcIVI->use_empty())
132 ExcIVI->eraseFromParent();
133 if (SelLoad && SelLoad->use_empty())
134 SelLoad->eraseFromParent();
137 return ExnObj;
140 /// Replace resumes that are not reachable from a cleanup landing pad with
141 /// unreachable and then simplify those blocks.
142 size_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;
154 ++ResumeIndex;
157 // If everything is reachable, there is no change.
158 if (ResumeReachable.all())
159 return Resumes.size();
161 const TargetTransformInfo &TTI =
162 getAnalysis<TargetTransformInfoWrapperPass>().getTTI(Fn);
163 LLVMContext &Ctx = Fn.getContext();
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();
175 simplifyCFG(BB, TTI);
178 Resumes.resize(ResumesLeft);
179 return ResumesLeft;
182 /// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present
183 /// into calls to the appropriate _Unwind_Resume function.
184 bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
185 SmallVector<ResumeInst*, 16> Resumes;
186 SmallVector<LandingPadInst*, 16> CleanupLPads;
187 for (BasicBlock &BB : Fn) {
188 if (auto *RI = dyn_cast<ResumeInst>(BB.getTerminator()))
189 Resumes.push_back(RI);
190 if (auto *LP = BB.getLandingPadInst())
191 if (LP->isCleanup())
192 CleanupLPads.push_back(LP);
195 if (Resumes.empty())
196 return false;
198 // Check the personality, don't do anything if it's scope-based.
199 EHPersonality Pers = classifyEHPersonality(Fn.getPersonalityFn());
200 if (isScopedEHPersonality(Pers))
201 return false;
203 LLVMContext &Ctx = Fn.getContext();
205 size_t ResumesLeft = pruneUnreachableResumes(Fn, Resumes, CleanupLPads);
206 if (ResumesLeft == 0)
207 return true; // We pruned them all.
209 // Find the rewind function if we didn't already.
210 if (!RewindFunction) {
211 FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
212 Type::getInt8PtrTy(Ctx), false);
213 const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME);
214 RewindFunction = Fn.getParent()->getOrInsertFunction(RewindName, FTy);
217 // Create the basic block where the _Unwind_Resume call will live.
218 if (ResumesLeft == 1) {
219 // 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();
223 Value *ExnObj = GetExceptionObject(RI);
225 // Call the _Unwind_Resume function.
226 CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB);
227 CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
229 // We never expect _Unwind_Resume to return.
230 new UnreachableInst(Ctx, UnwindBB);
231 return true;
234 BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &Fn);
235 PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft,
236 "exn.obj", UnwindBB);
238 // Extract the exception object from the ResumeInst and add it to the PHI node
239 // that feeds the _Unwind_Resume call.
240 for (ResumeInst *RI : Resumes) {
241 BasicBlock *Parent = RI->getParent();
242 BranchInst::Create(UnwindBB, Parent);
244 Value *ExnObj = GetExceptionObject(RI);
245 PN->addIncoming(ExnObj, Parent);
247 ++NumResumesLowered;
250 // Call the function.
251 CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB);
252 CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
254 // We never expect _Unwind_Resume to return.
255 new UnreachableInst(Ctx, UnwindBB);
256 return true;
259 bool DwarfEHPrepare::runOnFunction(Function &Fn) {
260 const TargetMachine &TM =
261 getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
262 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
263 TLI = TM.getSubtargetImpl(Fn)->getTargetLowering();
264 bool Changed = InsertUnwindResumeCalls(Fn);
265 DT = nullptr;
266 TLI = nullptr;
267 return Changed;