diff options
Diffstat (limited to 'lib/CodeGen/CGException.h')
-rw-r--r-- | lib/CodeGen/CGException.h | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/lib/CodeGen/CGException.h b/lib/CodeGen/CGException.h index 01536e35fb..f40e3e32c2 100644 --- a/lib/CodeGen/CGException.h +++ b/lib/CodeGen/CGException.h @@ -160,6 +160,12 @@ class EHCleanupScope : public EHScope { /// Whether this cleanup needs to be run along exception edges. bool IsEHCleanup : 1; + /// Whether this cleanup was activated before all normal uses. + bool ActivatedBeforeNormalUse : 1; + + /// Whether this cleanup was activated before all EH uses. + bool ActivatedBeforeEHUse : 1; + /// The amount of extra storage needed by the Cleanup. /// Always a multiple of the scope-stack alignment. unsigned CleanupSize : 12; @@ -167,7 +173,7 @@ class EHCleanupScope : public EHScope { /// The number of fixups required by enclosing scopes (not including /// this one). If this is the top cleanup scope, all the fixups /// from this index onwards belong to this scope. - unsigned FixupDepth : BitsRemaining - 14; + unsigned FixupDepth : BitsRemaining - 16; /// The nearest normal cleanup scope enclosing this one. EHScopeStack::stable_iterator EnclosingNormal; @@ -183,6 +189,14 @@ class EHCleanupScope : public EHScope { /// created if needed before the cleanup is popped. llvm::BasicBlock *EHBlock; + /// An optional i1 variable indicating whether this cleanup has been + /// activated yet. This has one of three states: + /// - it is null if the cleanup is inactive + /// - it is activeSentinel() if the cleanup is active and was not + /// required before activation + /// - it points to a valid variable + llvm::AllocaInst *ActiveVar; + /// Extra information required for cleanups that have resolved /// branches through them. This has to be allocated on the side /// because everything on the cleanup stack has be trivially @@ -227,15 +241,19 @@ public: return sizeof(EHCleanupScope) + CleanupSize; } - EHCleanupScope(bool IsNormal, bool IsEH, unsigned CleanupSize, - unsigned FixupDepth, + EHCleanupScope(bool IsNormal, bool IsEH, bool IsActive, + unsigned CleanupSize, unsigned FixupDepth, EHScopeStack::stable_iterator EnclosingNormal, EHScopeStack::stable_iterator EnclosingEH) : EHScope(EHScope::Cleanup), IsNormalCleanup(IsNormal), IsEHCleanup(IsEH), + ActivatedBeforeNormalUse(IsActive), + ActivatedBeforeEHUse(IsActive), CleanupSize(CleanupSize), FixupDepth(FixupDepth), EnclosingNormal(EnclosingNormal), EnclosingEH(EnclosingEH), - NormalBlock(0), EHBlock(0), ExtInfo(0) + NormalBlock(0), EHBlock(0), + ActiveVar(IsActive ? activeSentinel() : 0), + ExtInfo(0) { assert(this->CleanupSize == CleanupSize && "cleanup size overflow"); } @@ -252,6 +270,20 @@ public: llvm::BasicBlock *getEHBlock() const { return EHBlock; } void setEHBlock(llvm::BasicBlock *BB) { EHBlock = BB; } + static llvm::AllocaInst *activeSentinel() { + return reinterpret_cast<llvm::AllocaInst*>(1); + } + + bool isActive() const { return ActiveVar != 0; } + llvm::AllocaInst *getActiveVar() const { return ActiveVar; } + void setActiveVar(llvm::AllocaInst *Var) { ActiveVar = Var; } + + bool wasActivatedBeforeNormalUse() const { return ActivatedBeforeNormalUse; } + void setActivatedBeforeNormalUse(bool B) { ActivatedBeforeNormalUse = B; } + + bool wasActivatedBeforeEHUse() const { return ActivatedBeforeEHUse; } + void setActivatedBeforeEHUse(bool B) { ActivatedBeforeEHUse = B; } + unsigned getFixupDepth() const { return FixupDepth; } EHScopeStack::stable_iterator getEnclosingNormalCleanup() const { return EnclosingNormal; |