14 #ifndef LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H 15 #define LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H 20 #include "llvm/ADT/SmallPtrSet.h" 21 #include "llvm/ADT/SmallVector.h" 34 class CodeGenFunction;
45 llvm::BasicBlock *CachedLandingPad;
46 llvm::BasicBlock *CachedEHDispatchBlock;
50 class CommonBitFields {
54 enum { NumCommonBits = 3 };
59 unsigned : NumCommonBits;
61 unsigned NumHandlers : 32 - NumCommonBits;
66 unsigned : NumCommonBits;
69 unsigned IsNormalCleanup : 1;
72 unsigned IsEHCleanup : 1;
75 unsigned IsActive : 1;
78 unsigned IsLifetimeMarker : 1;
81 unsigned TestFlagInNormalCleanup : 1;
84 unsigned TestFlagInEHCleanup : 1;
88 unsigned CleanupSize : 12;
93 unsigned : NumCommonBits;
95 unsigned NumFilters : 32 - NumCommonBits;
109 : CachedLandingPad(nullptr), CachedEHDispatchBlock(nullptr),
110 EnclosingEHScope(enclosingEHScope) {
111 CommonBits.Kind =
kind;
117 return CachedLandingPad;
121 CachedLandingPad = block;
125 return CachedEHDispatchBlock;
129 CachedEHDispatchBlock = block;
133 if (llvm::BasicBlock *block = getCachedEHDispatchBlock())
134 return !block->use_empty();
139 return EnclosingEHScope;
170 return reinterpret_cast<Handler*
>(
this+1);
173 const Handler *getHandlers()
const {
174 return reinterpret_cast<const Handler*
>(
this+1);
184 :
EHScope(Catch, enclosingEHScope) {
185 CatchBits.NumHandlers = numHandlers;
186 assert(CatchBits.NumHandlers == numHandlers &&
"NumHandlers overflow?");
190 return CatchBits.NumHandlers;
198 assert(I < getNumHandlers());
200 getHandlers()[I].Block = Block;
204 assert(I < getNumHandlers());
205 getHandlers()[I].Type = Type;
206 getHandlers()[I].Block = Block;
210 assert(I < getNumHandlers());
211 return getHandlers()[I];
219 for (
unsigned I = 0, N = getNumHandlers(); I != N; ++I)
220 delete getHandler(I).Block;
224 iterator
begin()
const {
return getHandlers(); }
225 iterator
end()
const {
return getHandlers() + getNumHandlers(); }
228 return Scope->
getKind() == Catch;
242 llvm::BasicBlock *NormalBlock;
246 llvm::AllocaInst *ActiveFlag;
254 llvm::SmallPtrSet<llvm::BasicBlock*, 4> Branches;
260 mutable struct ExtInfo *ExtInfo;
267 struct ExtInfo &getExtInfo() {
268 if (!ExtInfo) ExtInfo =
new struct ExtInfo();
272 const struct ExtInfo &getExtInfo()
const {
273 if (!ExtInfo) ExtInfo =
new struct ExtInfo();
289 unsigned cleanupSize,
unsigned fixupDepth,
293 EnclosingNormal(enclosingNormal), NormalBlock(nullptr),
294 ActiveFlag(nullptr), ExtInfo(nullptr), FixupDepth(fixupDepth) {
295 CleanupBits.IsNormalCleanup = isNormal;
296 CleanupBits.IsEHCleanup = isEH;
297 CleanupBits.IsActive = isActive;
298 CleanupBits.IsLifetimeMarker =
false;
299 CleanupBits.TestFlagInNormalCleanup =
false;
300 CleanupBits.TestFlagInEHCleanup =
false;
301 CleanupBits.CleanupSize = cleanupSize;
303 assert(CleanupBits.CleanupSize == cleanupSize &&
"cleanup size overflow");
318 bool isActive()
const {
return CleanupBits.IsActive; }
326 return Address(ActiveFlag, CharUnits::One());
330 ActiveFlag = cast<llvm::AllocaInst>(Var.
getPointer());
334 CleanupBits.TestFlagInNormalCleanup =
true;
337 return CleanupBits.TestFlagInNormalCleanup;
341 CleanupBits.TestFlagInEHCleanup =
true;
344 return CleanupBits.TestFlagInEHCleanup;
349 return EnclosingNormal;
360 bool hasBranches()
const {
return ExtInfo && !ExtInfo->Branches.empty(); }
374 llvm::BasicBlock *Block) {
375 struct ExtInfo &ExtInfo = getExtInfo();
376 if (ExtInfo.Branches.insert(Block).second)
377 ExtInfo.BranchAfters.push_back(std::make_pair(Block, Index));
382 return ExtInfo ? ExtInfo->BranchAfters.size() : 0;
386 assert(I < getNumBranchAfters());
387 return ExtInfo->BranchAfters[I].first;
391 assert(I < getNumBranchAfters());
392 return ExtInfo->BranchAfters[I].second;
411 return getExtInfo().Branches.insert(Block).second;
416 if (!ExtInfo)
return false;
417 return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size());
421 return (Scope->
getKind() == Cleanup);
430 static_assert(
alignof(
EHCleanupScope) == EHScopeStack::ScopeStackAlignment,
431 "EHCleanupScope expected alignment");
447 return reinterpret_cast<llvm::Value*
const *
>(
this+1);
453 FilterBits.NumFilters = numFilters;
454 assert(FilterBits.NumFilters == numFilters &&
"NumFilters overflow");
464 assert(i < getNumFilters());
465 getFilters()[i] = filterValue;
469 assert(i < getNumFilters());
470 return getFilters()[i];
474 return scope->
getKind() == Filter;
483 :
EHScope(Terminate, enclosingEHScope) {}
487 return scope->
getKind() == Terminate;
494 :
EHScope(PadEnd, enclosingEHScope) {}
498 return scope->
getKind() == PadEnd;
507 explicit iterator(
char *Ptr) : Ptr(Ptr) {}
513 return reinterpret_cast<EHScope*
>(Ptr);
523 Size = EHCatchScope::getSizeForNumHandlers(
524 static_cast<const EHCatchScope *>(
get())->getNumHandlers());
527 case EHScope::Filter:
528 Size = EHFilterScope::getSizeForNumFilters(
529 static_cast<const EHFilterScope *>(
get())->getNumFilters());
532 case EHScope::Cleanup:
536 case EHScope::Terminate:
537 Size = EHTerminateScope::getSize();
540 case EHScope::PadEnd:
541 Size = EHPadEndScope::getSize();
544 Ptr += llvm::alignTo(Size, ScopeStackAlignment);
575 inline void EHScopeStack::popCatch() {
576 assert(!empty() &&
"popping exception stack when not empty");
580 deallocate(EHCatchScope::getSizeForNumHandlers(scope.
getNumHandlers()));
583 inline void EHScopeStack::popTerminate() {
584 assert(!empty() &&
"popping exception stack when not empty");
588 deallocate(EHTerminateScope::getSize());
592 assert(sp.
isValid() &&
"finding invalid savepoint");
593 assert(sp.Size <= stable_begin().Size &&
"finding savepoint after pop");
594 return iterator(EndOfBuffer - sp.Size);
599 assert(StartOfData <= ir.Ptr && ir.Ptr <= EndOfBuffer);
636 return this == &MSVC_except_handler ||
this == &MSVC_C_specific_handler ||
637 this == &MSVC_CxxFrameHandler3;
An instance of this class is created to represent a function declaration or definition.
EHScopeStack::stable_iterator getEnclosingEHScope() const
void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block)
bool usesFuncletPads() const
Does this personality use landingpads or the family of pad instructions designed to form funclets...
bool strictlyEncloses(iterator other) const
llvm::BasicBlock * getCachedEHDispatchBlock() const
static const EHPersonality GNU_C_SJLJ
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
static const EHPersonality MSVC_C_specific_handler
static const EHPersonality MSVC_CxxFrameHandler3
bool hasEHBranches() const
void clearHandlerBlocks()
static const EHPersonality GNU_C
EHCatchScope(unsigned numHandlers, EHScopeStack::stable_iterator enclosingEHScope)
The base class of the type hierarchy.
llvm::BasicBlock * getNormalBlock() const
unsigned getNumFilters() const
bool operator==(iterator other) const
bool hasActiveFlag() const
unsigned getNumHandlers() const
llvm::Value * getPointer() const
A protected scope for zero-cost EH handling.
A scope which attempts to handle some, possibly all, types of exceptions.
bool addBranchThrough(llvm::BasicBlock *Block)
Add a branch-through to this cleanup scope.
bool operator!=(iterator other) const
static size_t getSizeForCleanupSize(size_t Size)
Gets the size required for a lazy cleanup scope with the given cleanup-data requirements.
An exceptions scope which calls std::terminate if any exception reaches it.
bool isMSVCPersonality() const
const char * CatchallRethrowFn
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
static const EHPersonality GNU_CPlusPlus_SJLJ
bool shouldTestFlagInNormalCleanup() const
void setFilter(unsigned i, llvm::Value *filterValue)
void setCachedLandingPad(llvm::BasicBlock *block)
void setNormalBlock(llvm::BasicBlock *BB)
bool isOne() const
isOne - Test whether the quantity equals one.
CharUnits getAlignment() const
Return the alignment of this pointer.
static bool classof(const EHScope *scope)
const Handler & getHandler(unsigned I) const
static const EHPersonality GNUstep_ObjC
Scope - A scope is a transient data structure that is used while parsing the program.
A stack of scopes which respond to exceptions, including cleanups and catch blocks.
EHScope(Kind kind, EHScopeStack::stable_iterator enclosingEHScope)
static size_t getSizeForNumHandlers(unsigned N)
EHFilterScope(unsigned numFilters)
static bool classof(const EHScope *Scope)
unsigned getFixupDepth() const
unsigned getNumBranchAfters() const
Return the number of unique branch-afters on this scope.
static const EHPersonality MSVC_except_handler
EHScope & operator*() const
EHScopeStack::Cleanup * getCleanup()
CatchTypeInfo Type
A type info value, or null (C++ null, not an LLVM null pointer) for a catch-all.
size_t getCleanupSize() const
void * getCleanupBuffer()
static bool classof(const EHScope *Scope)
llvm::BasicBlock * Block
The catch handler for this type.
llvm::ConstantInt * getBranchAfterIndex(unsigned I) const
static const EHPersonality GNU_ObjCXX
static const EHPersonality GNU_ObjC_SEH
void setActiveFlag(Address Var)
CommonBitFields CommonBits
void setTestFlagInNormalCleanup()
size_t getAllocatedSize() const
llvm::BasicBlock * getCachedLandingPad() const
CleanupBitFields CleanupBits
A saved depth on the scope stack.
const char * PersonalityFn
EHScopeStack::stable_iterator getEnclosingNormalCleanup() const
EHPadEndScope(EHScopeStack::stable_iterator enclosingEHScope)
EHScope * operator->() const
void setCachedEHDispatchBlock(llvm::BasicBlock *block)
llvm::Value * getFilter(unsigned i) const
The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the type of a catch handler...
static size_t getSizeForNumFilters(unsigned numFilters)
static const EHPersonality NeXT_ObjC
This class organizes the cross-function state that is used while generating LLVM code.
Dataflow Directional Tag Classes.
EHTerminateScope(EHScopeStack::stable_iterator enclosingEHScope)
static const EHPersonality GNU_CPlusPlus_SEH
bool isLifetimeMarker() const
bool shouldTestFlagInEHCleanup() const
void addBranchAfter(llvm::ConstantInt *Index, llvm::BasicBlock *Block)
Add a branch-after to this cleanup scope.
static const EHPersonality GNU_ObjC
static bool classof(const EHScope *scope)
bool isMSVCXXPersonality() const
static const EHPersonality GNU_CPlusPlus
static const EHPersonality GNU_ObjC_SJLJ
bool hasBranches() const
True if this cleanup scope has any branch-afters or branch-throughs.
bool isNormalCleanup() const
Address getActiveFlag() const
bool encloses(iterator other) const
static const EHPersonality GNU_C_SEH
The exceptions personality for a function.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
llvm::BasicBlock * getBranchAfterBlock(unsigned I) const
A cleanup scope which generates the cleanup blocks lazily.
bool hasBranchThroughs() const
Determines if this cleanup scope has any branch throughs.
EHCleanupScope(bool isNormal, bool isEH, bool isActive, unsigned cleanupSize, unsigned fixupDepth, EHScopeStack::stable_iterator enclosingNormal, EHScopeStack::stable_iterator enclosingEH)
static Decl::Kind getKind(const Decl *D)
An exceptions scope which filters exceptions thrown through it.
Information for lazily generating a cleanup.
A non-stable pointer into the scope stack.
void setHandler(unsigned I, CatchTypeInfo Type, llvm::BasicBlock *Block)
void setTestFlagInEHCleanup()
void setHandler(unsigned I, llvm::Constant *Type, llvm::BasicBlock *Block)
FilterBitFields FilterBits
static bool classof(const EHScope *scope)