44#define DEBUG_TYPE "dwarf-eh-prepare"
46STATISTIC(NumResumesLowered,
"Number of resume calls lowered");
48 "Number of cleanup landing pads found unreachable");
50 "Number of cleanup landing pads remaining");
51STATISTIC(NumNoUnwind,
"Number of functions with nounwind");
52STATISTIC(NumUnwind,
"Number of functions with unwind");
63 const Triple &TargetTriple;
78 bool InsertUnwindResumeCalls();
84 : OptLevel(OptLevel_),
F(F_), Libcalls(Libcalls_), DTU(DTU_),
TTI(TTI_),
85 TargetTriple(TargetTriple_) {}
94 Value *ExnObj =
nullptr;
96 LoadInst *SelLoad =
nullptr;
97 InsertValueInst *ExcIVI =
nullptr;
98 bool EraseIVIs =
false;
130size_t DwarfEHPrepare::pruneUnreachableResumes(
131 SmallVectorImpl<ResumeInst *> &Resumes,
132 SmallVectorImpl<LandingPadInst *> &CleanupLPads) {
133 assert(DTU &&
"Should have DomTreeUpdater here.");
135 BitVector ResumeReachable(Resumes.
size());
136 size_t ResumeIndex = 0;
137 for (
auto *RI : Resumes) {
138 for (
auto *LP : CleanupLPads) {
140 ResumeReachable.set(ResumeIndex);
148 if (ResumeReachable.all())
149 return Resumes.size();
151 LLVMContext &Ctx =
F.getContext();
154 size_t ResumesLeft = 0;
155 for (
size_t I = 0,
E = Resumes.size();
I <
E; ++
I) {
156 ResumeInst *RI = Resumes[
I];
157 if (ResumeReachable[
I]) {
158 Resumes[ResumesLeft++] = RI;
166 Resumes.resize(ResumesLeft);
170bool DwarfEHPrepare::InsertUnwindResumeCalls() {
173 if (
F.doesNotThrow())
177 for (BasicBlock &BB :
F) {
185 NumCleanupLandingPadsRemaining += CleanupLPads.
size();
195 LLVMContext &Ctx =
F.getContext();
197 size_t ResumesLeft = Resumes.
size();
198 if (OptLevel != CodeGenOptLevel::None) {
199 ResumesLeft = pruneUnreachableResumes(Resumes, CleanupLPads);
201 unsigned NumRemainingLPs = 0;
202 for (BasicBlock &BB :
F) {
207 NumCleanupLandingPadsUnreachable += CleanupLPads.
size() - NumRemainingLPs;
208 NumCleanupLandingPadsRemaining -= CleanupLPads.
size() - NumRemainingLPs;
212 if (ResumesLeft == 0)
216 FunctionCallee RewindFunction;
217 CallingConv::ID RewindFunctionCallingConv;
219 StringRef RewindName;
220 bool DoesRewindFunctionNeedExceptionObject;
222 if ((Pers == EHPersonality::GNU_CXX || Pers == EHPersonality::GNU_CXX_SjLj) &&
225 FTy = FunctionType::get(Type::getVoidTy(Ctx),
false);
226 RewindFunctionCallingConv =
228 DoesRewindFunctionNeedExceptionObject =
false;
231 FTy = FunctionType::get(Type::getVoidTy(Ctx), PointerType::getUnqual(Ctx),
233 RewindFunctionCallingConv =
235 DoesRewindFunctionNeedExceptionObject =
true;
237 RewindFunction =
F.getParent()->getOrInsertFunction(RewindName, FTy);
240 if (ResumesLeft == 1) {
243 ResumeInst *RI = Resumes.
front();
245 Value *ExnObj = GetExceptionObject(RI);
247 if (DoesRewindFunctionNeedExceptionObject)
258 if (DISubprogram *SP =
F.getSubprogram())
259 CI->
setDebugLoc(DILocation::get(
SP->getContext(), 0, 0, SP));
264 new UnreachableInst(Ctx, UnwindBB);
268 std::vector<DominatorTree::UpdateType> Updates;
269 Updates.reserve(Resumes.
size());
274 PHINode *PN =
PHINode::Create(PointerType::getUnqual(Ctx), ResumesLeft,
275 "exn.obj", UnwindBB);
279 for (ResumeInst *RI : Resumes) {
282 Updates.push_back({DominatorTree::Insert, Parent, UnwindBB});
284 Value *ExnObj = GetExceptionObject(RI);
290 if (DoesRewindFunctionNeedExceptionObject)
301 if (DISubprogram *SP =
F.getSubprogram())
302 CI->
setDebugLoc(DILocation::get(
SP->getContext(), 0, 0, SP));
307 new UnreachableInst(Ctx, UnwindBB);
315bool DwarfEHPrepare::run() {
316 bool Changed = InsertUnwindResumeCalls();
324 const Triple &TargetTriple) {
327 return DwarfEHPrepare(OptLevel,
F, Libcalls, DT ? &DTU :
nullptr,
TTI,
334class DwarfEHPrepareLegacyPass :
public FunctionPass {
341 DwarfEHPrepareLegacyPass(
CodeGenOptLevel OptLevel = CodeGenOptLevel::Default)
342 : FunctionPass(
ID), OptLevel(OptLevel) {}
345 const TargetMachine &TM =
346 getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
349 const LibcallLoweringInfo &Libcalls =
350 getAnalysis<LibcallLoweringInfoWrapper>().getLibcallLowering(
351 *
F.getParent(), *Subtarget);
353 DominatorTree *DT =
nullptr;
354 const TargetTransformInfo *
TTI =
nullptr;
355 if (
auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
356 DT = &DTWP->getDomTree();
357 if (OptLevel != CodeGenOptLevel::None) {
359 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
360 TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
365 void getAnalysisUsage(AnalysisUsage &AU)
const override {
369 if (OptLevel != CodeGenOptLevel::None) {
376 StringRef getPassName()
const override {
377 return "Exception handling preparation";
387 auto OptLevel = TM->getOptLevel();
394 if (!LibcallLowering) {
396 "' analysis required");
408 LibcallLowering->getLibcallLowering(*Subtarget);
420char DwarfEHPrepareLegacyPass::ID = 0;
423 "Prepare DWARF exceptions",
false,
false)
432 return new DwarfEHPrepareLegacyPass(OptLevel);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements the BitVector class.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool prepareDwarfEH(CodeGenOptLevel OptLevel, Function &F, const LibcallLoweringInfo &Libcalls, DominatorTree *DT, const TargetTransformInfo *TTI, const Triple &TargetTriple)
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI const LandingPadInst * getLandingPadInst() const
Return the landingpad instruction associated with the landing pad.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
void setCallingConv(CallingConv::ID CC)
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
FunctionPass class - This class is used to implement most global optimizations.
DISubprogram * getSubprogram() const
Get the attached subprogram.
DomTreeT & getDomTree()
Flush DomTree updates and return DomTree.
void applyUpdates(ArrayRef< UpdateT > Updates)
Submit updates to all available trees.
unsigned getNumIndices() const
idx_iterator idx_begin() const
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
Tracks which library functions to use for a particular subtarget.
LLVM_ABI const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
LLVM_ABI CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const
Record a mapping from subtarget to LibcallLoweringInfo.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Resume the propagation of an exception.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
Analysis pass providing the TargetTransformInfo.
const Triple & getTargetTriple() const
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
Target-Independent Code Generator Pass Configuration Options.
TargetSubtargetInfo - Generic base class for all target subtargets.
Triple - Helper class for working with autoconf configuration names.
bool isTargetEHABICompatible() const
Tests whether the target supports the EHABI exception handling standard.
Value * getOperand(unsigned i) const
LLVM Value Representation.
const ParentTy * getParent() const
self_iterator getIterator()
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ BasicBlock
Various leaf nodes.
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
bool isScopedEHPersonality(EHPersonality Pers)
Returns true if this personality uses scope-style EH IR instructions: catchswitch,...
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
LLVM_ABI FunctionPass * createDwarfEHPass(CodeGenOptLevel OptLevel)
createDwarfEHPass - This pass mulches exception handling code into a form adapted to code generation.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI bool simplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, DomTreeUpdater *DTU=nullptr, const SimplifyCFGOptions &Options={}, ArrayRef< WeakVH > LoopHeaders={})
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...