13 #ifndef LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H 14 #define LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H 19 #include "llvm/ADT/SmallPtrSet.h" 20 #include "llvm/ADT/SmallVector.h" 33 class CodeGenFunction;
44 llvm::BasicBlock *CachedLandingPad;
45 llvm::BasicBlock *CachedEHDispatchBlock;
49 class CommonBitFields {
53 enum { NumCommonBits = 3 };
58 unsigned : NumCommonBits;
60 unsigned NumHandlers : 32 - NumCommonBits;
65 unsigned : NumCommonBits;
68 unsigned IsNormalCleanup : 1;
71 unsigned IsEHCleanup : 1;
74 unsigned IsActive : 1;
77 unsigned IsLifetimeMarker : 1;
80 unsigned TestFlagInNormalCleanup : 1;
83 unsigned TestFlagInEHCleanup : 1;
87 unsigned CleanupSize : 12;
92 unsigned : NumCommonBits;
94 unsigned NumFilters : 32 - NumCommonBits;
108 : CachedLandingPad(nullptr), CachedEHDispatchBlock(nullptr),
109 EnclosingEHScope(enclosingEHScope) {
110 CommonBits.Kind =
kind;
116 return CachedLandingPad;
120 CachedLandingPad = block;
124 return CachedEHDispatchBlock;
128 CachedEHDispatchBlock = block;
132 if (llvm::BasicBlock *block = getCachedEHDispatchBlock())
133 return !block->use_empty();
138 return EnclosingEHScope;
169 return reinterpret_cast<Handler*
>(
this+1);
172 const Handler *getHandlers()
const {
173 return reinterpret_cast<const Handler*
>(
this+1);
183 :
EHScope(Catch, enclosingEHScope) {
184 CatchBits.NumHandlers = numHandlers;
185 assert(CatchBits.NumHandlers == numHandlers &&
"NumHandlers overflow?");
189 return CatchBits.NumHandlers;
197 assert(I < getNumHandlers());
199 getHandlers()[I].Block = Block;
203 assert(I < getNumHandlers());
204 getHandlers()[I].Type =
Type;
205 getHandlers()[I].Block = Block;
209 assert(I < getNumHandlers());
210 return getHandlers()[I];
218 for (
unsigned I = 0, N = getNumHandlers(); I != N; ++I)
219 delete getHandler(I).Block;
223 iterator
begin()
const {
return getHandlers(); }
224 iterator
end()
const {
return getHandlers() + getNumHandlers(); }
227 return Scope->
getKind() == Catch;
241 llvm::BasicBlock *NormalBlock;
245 llvm::AllocaInst *ActiveFlag;
253 llvm::SmallPtrSet<llvm::BasicBlock*, 4> Branches;
259 mutable struct ExtInfo *ExtInfo;
266 struct ExtInfo &getExtInfo() {
267 if (!ExtInfo) ExtInfo =
new struct ExtInfo();
271 const struct ExtInfo &getExtInfo()
const {
272 if (!ExtInfo) ExtInfo =
new struct ExtInfo();
288 unsigned cleanupSize,
unsigned fixupDepth,
292 EnclosingNormal(enclosingNormal), NormalBlock(nullptr),
293 ActiveFlag(nullptr), ExtInfo(nullptr), FixupDepth(fixupDepth) {
294 CleanupBits.IsNormalCleanup = isNormal;
295 CleanupBits.IsEHCleanup = isEH;
296 CleanupBits.IsActive = isActive;
297 CleanupBits.IsLifetimeMarker =
false;
298 CleanupBits.TestFlagInNormalCleanup =
false;
299 CleanupBits.TestFlagInEHCleanup =
false;
300 CleanupBits.CleanupSize = cleanupSize;
302 assert(CleanupBits.CleanupSize == cleanupSize &&
"cleanup size overflow");
317 bool isActive()
const {
return CleanupBits.IsActive; }
325 return Address(ActiveFlag, CharUnits::One());
329 ActiveFlag = cast<llvm::AllocaInst>(Var.
getPointer());
333 CleanupBits.TestFlagInNormalCleanup =
true;
336 return CleanupBits.TestFlagInNormalCleanup;
340 CleanupBits.TestFlagInEHCleanup =
true;
343 return CleanupBits.TestFlagInEHCleanup;
348 return EnclosingNormal;
359 bool hasBranches()
const {
return ExtInfo && !ExtInfo->Branches.empty(); }
373 llvm::BasicBlock *Block) {
374 struct ExtInfo &ExtInfo = getExtInfo();
375 if (ExtInfo.Branches.insert(Block).second)
376 ExtInfo.BranchAfters.push_back(std::make_pair(Block, Index));
381 return ExtInfo ? ExtInfo->BranchAfters.size() : 0;
385 assert(I < getNumBranchAfters());
386 return ExtInfo->BranchAfters[I].first;
390 assert(I < getNumBranchAfters());
391 return ExtInfo->BranchAfters[I].second;
410 return getExtInfo().Branches.insert(Block).second;
415 if (!ExtInfo)
return false;
416 return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size());
420 return (Scope->
getKind() == Cleanup);
429 static_assert(
alignof(
EHCleanupScope) == EHScopeStack::ScopeStackAlignment,
430 "EHCleanupScope expected alignment");
446 return reinterpret_cast<llvm::Value*
const *
>(
this+1);
452 FilterBits.NumFilters = numFilters;
453 assert(FilterBits.NumFilters == numFilters &&
"NumFilters overflow");
463 assert(i < getNumFilters());
464 getFilters()[i] = filterValue;
468 assert(i < getNumFilters());
469 return getFilters()[i];
482 :
EHScope(Terminate, enclosingEHScope) {}
486 return scope->
getKind() == Terminate;
493 :
EHScope(PadEnd, enclosingEHScope) {}
497 return scope->
getKind() == PadEnd;
506 explicit iterator(
char *Ptr) : Ptr(Ptr) {}
512 return reinterpret_cast<EHScope*
>(Ptr);
522 Size = EHCatchScope::getSizeForNumHandlers(
523 static_cast<const EHCatchScope *>(
get())->getNumHandlers());
527 Size = EHFilterScope::getSizeForNumFilters(
528 static_cast<const EHFilterScope *>(
get())->getNumFilters());
531 case EHScope::Cleanup:
535 case EHScope::Terminate:
536 Size = EHTerminateScope::getSize();
539 case EHScope::PadEnd:
540 Size = EHPadEndScope::getSize();
543 Ptr += llvm::alignTo(Size, ScopeStackAlignment);
574 inline void EHScopeStack::popCatch() {
575 assert(!empty() &&
"popping exception stack when not empty");
579 deallocate(EHCatchScope::getSizeForNumHandlers(scope.
getNumHandlers()));
582 inline void EHScopeStack::popTerminate() {
583 assert(!empty() &&
"popping exception stack when not empty");
587 deallocate(EHTerminateScope::getSize());
591 assert(sp.
isValid() &&
"finding invalid savepoint");
592 assert(sp.Size <= stable_begin().Size &&
"finding savepoint after pop");
593 return iterator(EndOfBuffer - sp.Size);
598 assert(StartOfData <= ir.Ptr && ir.Ptr <= EndOfBuffer);
634 return isMSVCPersonality() || isWasmPersonality();
638 return this == &MSVC_except_handler ||
this == &MSVC_C_specific_handler ||
639 this == &MSVC_CxxFrameHandler3;
Represents 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
bool isWasmPersonality() 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.
Optional< types::ID > Type
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.
static const EHPersonality GNU_Wasm_CPlusPlus
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)