13#ifndef LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H
14#define LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/SetVector.h"
21#include "llvm/ADT/SmallPtrSet.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/IR/Instruction.h"
50 llvm::BasicBlock *CachedLandingPad;
51 llvm::BasicBlock *CachedEHDispatchBlock;
55 class CommonBitFields {
57 LLVM_PREFERRED_TYPE(Kind)
60 enum { NumCommonBits = 3 };
67 unsigned NumHandlers : 32 - NumCommonBits;
75 LLVM_PREFERRED_TYPE(
bool)
76 unsigned IsNormalCleanup : 1;
79 LLVM_PREFERRED_TYPE(
bool)
80 unsigned IsEHCleanup : 1;
83 LLVM_PREFERRED_TYPE(
bool)
84 unsigned IsActive : 1;
87 LLVM_PREFERRED_TYPE(
bool)
88 unsigned IsLifetimeMarker : 1;
91 LLVM_PREFERRED_TYPE(
bool)
92 unsigned IsFakeUse : 1;
95 LLVM_PREFERRED_TYPE(
bool)
96 unsigned TestFlagInNormalCleanup : 1;
99 LLVM_PREFERRED_TYPE(
bool)
100 unsigned TestFlagInEHCleanup : 1;
102 LLVM_PREFERRED_TYPE(
bool)
103 unsigned IsSEHFinallyCleanup : 1;
105 LLVM_PREFERRED_TYPE(
bool)
106 unsigned IsStackRestore : 1;
110 unsigned CleanupSize : 12;
117 unsigned NumFilters : 32 - NumCommonBits;
130 EnclosingEHScope(enclosingEHScope) {
137 return CachedLandingPad;
141 CachedLandingPad = block;
145 return CachedEHDispatchBlock;
149 CachedEHDispatchBlock = block;
154 return !block->use_empty();
159 return EnclosingEHScope;
190 return reinterpret_cast<Handler*
>(
this+1);
193 const Handler *getHandlers()
const {
194 return reinterpret_cast<const Handler*
>(
this+1);
206 assert(
CatchBits.NumHandlers == numHandlers &&
"NumHandlers overflow?");
220 getHandlers()[I].Block =
Block;
225 getHandlers()[I].Type =
Type;
226 getHandlers()[I].Block =
Block;
231 return getHandlers()[I];
262 llvm::BasicBlock *NormalBlock;
280 mutable struct ExtInfo *ExtInfo;
285 struct AuxillaryAllocas {
290 void Add(llvm::AllocaInst *Alloca) { AuxAllocas.push_back(Alloca); }
298 ~AuxillaryAllocas() {
301 llvm::SetVector<llvm::Instruction *> Uses;
302 for (
auto *Inst : llvm::reverse(AuxAllocas))
303 CollectUses(Inst, Uses);
305 for (
auto *I : llvm::reverse(Uses))
306 I->eraseFromParent();
310 void CollectUses(llvm::Instruction *I,
311 llvm::SetVector<llvm::Instruction *> &Uses) {
312 if (!I || !Uses.insert(I))
314 for (
auto *User : I->users())
318 mutable struct AuxillaryAllocas *AuxAllocas;
320 AuxillaryAllocas &getAuxillaryAllocas() {
322 AuxAllocas =
new struct AuxillaryAllocas();
332 struct ExtInfo &getExtInfo() {
333 if (!ExtInfo) ExtInfo =
new struct ExtInfo();
337 const struct ExtInfo &getExtInfo()
const {
338 if (!ExtInfo) ExtInfo =
new struct ExtInfo();
358 EnclosingNormal(enclosingNormal), NormalBlock(
nullptr),
360 FixupDepth(fixupDepth) {
372 assert(
CleanupBits.CleanupSize == cleanupSize &&
"cleanup size overflow");
381 for (
auto *Alloca : Allocas)
382 getAuxillaryAllocas().Add(Alloca);
438 return EnclosingNormal;
449 bool hasBranches()
const {
return ExtInfo && !ExtInfo->Branches.empty(); }
463 llvm::BasicBlock *
Block) {
464 struct ExtInfo &ExtInfo = getExtInfo();
465 if (ExtInfo.Branches.insert(
Block).second)
466 ExtInfo.BranchAfters.push_back(std::make_pair(
Block, Index));
471 return ExtInfo ? ExtInfo->BranchAfters.size() : 0;
476 return ExtInfo->BranchAfters[I].first;
481 return ExtInfo->BranchAfters[I].second;
500 return getExtInfo().Branches.insert(
Block).second;
505 if (!ExtInfo)
return false;
506 return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size());
520 "EHCleanupScope expected alignment");
531 llvm::Value **getFilters() {
532 return reinterpret_cast<llvm::Value**
>(
this+1);
535 llvm::Value *
const *getFilters()
const {
536 return reinterpret_cast<llvm::Value*
const *
>(
this+1);
543 assert(
FilterBits.NumFilters == numFilters &&
"NumFilters overflow");
547 return sizeof(
EHFilterScope) + numFilters *
sizeof(llvm::Value*);
554 getFilters()[i] = filterValue;
559 return getFilters()[i];
585 explicit iterator(
char *Ptr) : Ptr(Ptr) {}
591 return reinterpret_cast<EHScope*
>(Ptr);
623 iterator copy = *
this;
629 iterator copy = *
this;
634 bool encloses(iterator other)
const {
return Ptr >= other.Ptr; }
637 bool operator==(iterator other)
const {
return Ptr == other.Ptr; }
638 bool operator!=(iterator other)
const {
return Ptr != other.Ptr; }
650 assert(!
empty() &&
"popping exception stack when not empty");
658 assert(!
empty() &&
"popping exception stack when not empty");
666 assert(sp.
isValid() &&
"finding invalid savepoint");
667 assert(sp.Size <=
stable_begin().Size &&
"finding savepoint after pop");
668 return iterator(EndOfBuffer - sp.Size);
673 assert(StartOfData <= ir.Ptr && ir.Ptr <= EndOfBuffer);
static Decl::Kind getKind(const Decl *D)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
bool isOne() const
isOne - Test whether the quantity equals one.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
This class organizes the cross-function state that is used while generating LLVM code.
A scope which attempts to handle some, possibly all, types of exceptions.
EHCatchScope(unsigned numHandlers, EHScopeStack::stable_iterator enclosingEHScope)
const Handler & getHandler(unsigned I) const
void setHandler(unsigned I, llvm::Constant *Type, llvm::BasicBlock *Block)
friend class EHScopeStack
static size_t getSizeForNumHandlers(unsigned N)
void setHandler(unsigned I, CatchTypeInfo Type, llvm::BasicBlock *Block)
void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block)
void clearHandlerBlocks()
static bool classof(const EHScope *Scope)
unsigned getNumHandlers() const
A cleanup scope which generates the cleanup blocks lazily.
void setSEHFinallyCleanup()
bool shouldTestFlagInEHCleanup() const
bool isLifetimeMarker() const
Address getActiveFlag() const
EHScopeStack::stable_iterator getEnclosingNormalCleanup() const
size_t getAllocatedSize() const
bool hasActiveFlag() const
void setNormalBlock(llvm::BasicBlock *BB)
llvm::ConstantInt * getBranchAfterIndex(unsigned I) const
bool shouldTestFlagInNormalCleanup() const
bool isRedundantBeforeReturn() const
bool addBranchThrough(llvm::BasicBlock *Block)
Add a branch-through to this cleanup scope.
llvm::BasicBlock * getBranchAfterBlock(unsigned I) const
void AddAuxAllocas(llvm::SmallVector< llvm::AllocaInst * > Allocas)
void setTestFlagInNormalCleanup()
void setTestFlagInEHCleanup()
void * getCleanupBuffer()
unsigned getNumBranchAfters() const
Return the number of unique branch-afters on this scope.
bool isNormalCleanup() const
static size_t getSizeForCleanupSize(size_t Size)
Gets the size required for a lazy cleanup scope with the given cleanup-data requirements.
bool hasBranches() const
True if this cleanup scope has any branch-afters or branch-throughs.
void addBranchAfter(llvm::ConstantInt *Index, llvm::BasicBlock *Block)
Add a branch-after to this cleanup scope.
void setActiveFlag(RawAddress Var)
EHCleanupScope(bool isNormal, bool isEH, unsigned cleanupSize, unsigned fixupDepth, EHScopeStack::stable_iterator enclosingNormal, EHScopeStack::stable_iterator enclosingEH)
EHScopeStack::Cleanup * getCleanup()
unsigned getFixupDepth() const
size_t getCleanupSize() const
bool isSEHFinallyCleanup() const
static bool classof(const EHScope *Scope)
llvm::BasicBlock * getNormalBlock() const
bool hasBranchThroughs() const
Determines if this cleanup scope has any branch throughs.
bool isStackRestore() const
An exceptions scope which filters exceptions thrown through it.
void setFilter(unsigned i, llvm::Value *filterValue)
static size_t getSizeForNumFilters(unsigned numFilters)
EHFilterScope(unsigned numFilters)
llvm::Value * getFilter(unsigned i) const
unsigned getNumFilters() const
static bool classof(const EHScope *scope)
A non-stable pointer into the scope stack.
bool operator!=(iterator other) const
EHScope & operator*() const
bool encloses(iterator other) const
friend class EHScopeStack
bool strictlyEncloses(iterator other) const
EHScope * operator->() const
bool operator==(iterator other) const
A saved depth on the scope stack.
A stack of scopes which respond to exceptions, including cleanups and catch blocks.
stable_iterator stable_begin() const
Create a stable reference to the top of the EH stack.
bool empty() const
Determines whether the exception-scopes stack is empty.
iterator end() const
Returns an iterator pointing to the outermost EH scope.
iterator begin() const
Returns an iterator pointing to the innermost EH scope.
void popCatch()
Pops a catch scope off the stack. This is private to CGException.cpp.
iterator find(stable_iterator save) const
Turn a stable reference to a scope depth into a unstable pointer to the EH stack.
stable_iterator stabilize(iterator it) const
Translates an iterator into a stable_iterator.
void popTerminate()
Pops a terminate handler off the stack.
friend class EHCatchScope
friend class EHCleanupScope
friend class EHFilterScope
A protected scope for zero-cost EH handling.
llvm::BasicBlock * getCachedLandingPad() const
EHScope(Kind kind, EHScopeStack::stable_iterator enclosingEHScope)
void setCachedLandingPad(llvm::BasicBlock *block)
CleanupBitFields CleanupBits
FilterBitFields FilterBits
EHScopeStack::stable_iterator getEnclosingEHScope() const
llvm::BasicBlock * getCachedEHDispatchBlock() const
void setCachedEHDispatchBlock(llvm::BasicBlock *block)
bool hasEHBranches() const
CommonBitFields CommonBits
An exceptions scope which calls std::terminate if any exception reaches it.
EHTerminateScope(EHScopeStack::stable_iterator enclosingEHScope)
static bool classof(const EHScope *scope)
An abstract representation of an aligned address.
CharUnits getAlignment() const
Return the alignment of this pointer.
Represents a function declaration or definition.
Scope - A scope is a transient data structure that is used while parsing the program.
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
Top level wrappers for InstallAPI frontend operations.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
U cast(CodeGen::Address addr)
Diagnostic wrappers for TextAPI types for error reporting.
The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the type of a catch handler,...
CatchTypeInfo Type
A type info value, or null (C++ null, not an LLVM null pointer) for a catch-all.
llvm::BasicBlock * Block
The catch handler for this type.
The exceptions personality for a function.
bool isMSVCXXPersonality() const
static const EHPersonality & get(CodeGenModule &CGM, const FunctionDecl *FD)
static const EHPersonality XL_CPlusPlus
static const EHPersonality GNU_ObjC_SJLJ
bool isWasmPersonality() const
static const EHPersonality ZOS_CPlusPlus
static const EHPersonality GNUstep_ObjC
static const EHPersonality MSVC_CxxFrameHandler3
bool usesFuncletPads() const
Does this personality use landingpads or the family of pad instructions designed to form funclets?
static const EHPersonality MSVC_C_specific_handler
static const EHPersonality GNU_CPlusPlus_SEH
static const EHPersonality GNU_ObjC
static const EHPersonality GNU_CPlusPlus_SJLJ
static const EHPersonality GNU_C_SJLJ
static const EHPersonality GNU_C
static const EHPersonality NeXT_ObjC
const char * CatchallRethrowFn
static const EHPersonality GNU_CPlusPlus
static const EHPersonality GNU_ObjCXX
bool isMSVCPersonality() const
static const EHPersonality GNU_C_SEH
static const EHPersonality MSVC_except_handler
static const EHPersonality GNU_ObjC_SEH
const char * PersonalityFn
static const EHPersonality GNU_Wasm_CPlusPlus