1 //===-- CGException.h - Classes for exceptions IR generation ----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // These classes support the generation of LLVM IR for exceptions in
11 // C++ and Objective C.
13 //===----------------------------------------------------------------------===//
15 #ifndef CLANG_CODEGEN_CGEXCEPTION_H
16 #define CLANG_CODEGEN_CGEXCEPTION_H
18 /// EHScopeStack is defined in CodeGenFunction.h, but its
19 /// implementation is in this file and in CGException.cpp.
20 #include "CodeGenFunction.h"
30 /// The exceptions personality for a function. When
32 const char *PersonalityFn;
34 // If this is non-null, this personality requires a non-standard
35 // function for rethrowing an exception after a catchall cleanup.
36 // This function must have prototype void(void*).
37 const char *CatchallRethrowFn;
39 EHPersonality(const char *PersonalityFn,
40 const char *CatchallRethrowFn = 0)
41 : PersonalityFn(PersonalityFn),
42 CatchallRethrowFn(CatchallRethrowFn) {}
45 static const EHPersonality &get(const LangOptions &Lang);
46 static const EHPersonality GNU_C;
47 static const EHPersonality GNU_ObjC;
48 static const EHPersonality NeXT_ObjC;
49 static const EHPersonality GNU_CPlusPlus;
50 static const EHPersonality GNU_CPlusPlus_SJLJ;
52 const char *getPersonalityFnName() const { return PersonalityFn; }
53 const char *getCatchallRethrowFnName() const { return CatchallRethrowFn; }
56 /// A protected scope for zero-cost EH handling.
58 llvm::BasicBlock *CachedLandingPad;
63 enum { BitsRemaining = 30 };
66 enum Kind { Cleanup, Catch, Terminate, Filter };
68 EHScope(Kind K) : CachedLandingPad(0), K(K) {}
70 Kind getKind() const { return static_cast<Kind>(K); }
72 llvm::BasicBlock *getCachedLandingPad() const {
73 return CachedLandingPad;
76 void setCachedLandingPad(llvm::BasicBlock *Block) {
77 CachedLandingPad = Block;
81 /// A scope which attempts to handle some, possibly all, types of
84 /// Objective C @finally blocks are represented using a cleanup scope
85 /// after the catch scope.
86 class EHCatchScope : public EHScope {
87 unsigned NumHandlers : BitsRemaining;
89 // In effect, we have a flexible array member
90 // Handler Handlers[0];
91 // But that's only standard in C99, not C++, so we have to do
92 // annoying pointer arithmetic instead.
96 /// A type info value, or null (C++ null, not an LLVM null pointer)
100 /// The catch handler for this type.
101 llvm::BasicBlock *Block;
103 /// The unwind destination index for this handler.
108 friend class EHScopeStack;
110 Handler *getHandlers() {
111 return reinterpret_cast<Handler*>(this+1);
114 const Handler *getHandlers() const {
115 return reinterpret_cast<const Handler*>(this+1);
119 static size_t getSizeForNumHandlers(unsigned N) {
120 return sizeof(EHCatchScope) + N * sizeof(Handler);
123 EHCatchScope(unsigned NumHandlers)
124 : EHScope(Catch), NumHandlers(NumHandlers) {
127 unsigned getNumHandlers() const {
131 void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block) {
132 setHandler(I, /*catchall*/ 0, Block);
135 void setHandler(unsigned I, llvm::Value *Type, llvm::BasicBlock *Block) {
136 assert(I < getNumHandlers());
137 getHandlers()[I].Type = Type;
138 getHandlers()[I].Block = Block;
141 const Handler &getHandler(unsigned I) const {
142 assert(I < getNumHandlers());
143 return getHandlers()[I];
146 typedef const Handler *iterator;
147 iterator begin() const { return getHandlers(); }
148 iterator end() const { return getHandlers() + getNumHandlers(); }
150 static bool classof(const EHScope *Scope) {
151 return Scope->getKind() == Catch;
155 /// A cleanup scope which generates the cleanup blocks lazily.
156 class EHCleanupScope : public EHScope {
157 /// Whether this cleanup needs to be run along normal edges.
158 bool IsNormalCleanup : 1;
160 /// Whether this cleanup needs to be run along exception edges.
161 bool IsEHCleanup : 1;
163 /// Whether this cleanup was activated before all normal uses.
164 bool ActivatedBeforeNormalUse : 1;
166 /// Whether this cleanup was activated before all EH uses.
167 bool ActivatedBeforeEHUse : 1;
169 /// The amount of extra storage needed by the Cleanup.
170 /// Always a multiple of the scope-stack alignment.
171 unsigned CleanupSize : 12;
173 /// The number of fixups required by enclosing scopes (not including
174 /// this one). If this is the top cleanup scope, all the fixups
175 /// from this index onwards belong to this scope.
176 unsigned FixupDepth : BitsRemaining - 16;
178 /// The nearest normal cleanup scope enclosing this one.
179 EHScopeStack::stable_iterator EnclosingNormal;
181 /// The nearest EH cleanup scope enclosing this one.
182 EHScopeStack::stable_iterator EnclosingEH;
184 /// The dual entry/exit block along the normal edge. This is lazily
185 /// created if needed before the cleanup is popped.
186 llvm::BasicBlock *NormalBlock;
188 /// The dual entry/exit block along the EH edge. This is lazily
189 /// created if needed before the cleanup is popped.
190 llvm::BasicBlock *EHBlock;
192 /// An optional i1 variable indicating whether this cleanup has been
193 /// activated yet. This has one of three states:
194 /// - it is null if the cleanup is inactive
195 /// - it is activeSentinel() if the cleanup is active and was not
196 /// required before activation
197 /// - it points to a valid variable
198 llvm::AllocaInst *ActiveVar;
200 /// Extra information required for cleanups that have resolved
201 /// branches through them. This has to be allocated on the side
202 /// because everything on the cleanup stack has be trivially
205 /// The destinations of normal branch-afters and branch-throughs.
206 llvm::SmallPtrSet<llvm::BasicBlock*, 4> Branches;
208 /// Normal branch-afters.
209 llvm::SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4>
212 /// The destinations of EH branch-afters and branch-throughs.
213 /// TODO: optimize for the extremely common case of a single
215 llvm::SmallPtrSet<llvm::BasicBlock*, 4> EHBranches;
217 /// EH branch-afters.
218 llvm::SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4>
221 mutable struct ExtInfo *ExtInfo;
223 struct ExtInfo &getExtInfo() {
224 if (!ExtInfo) ExtInfo = new struct ExtInfo();
228 const struct ExtInfo &getExtInfo() const {
229 if (!ExtInfo) ExtInfo = new struct ExtInfo();
234 /// Gets the size required for a lazy cleanup scope with the given
235 /// cleanup-data requirements.
236 static size_t getSizeForCleanupSize(size_t Size) {
237 return sizeof(EHCleanupScope) + Size;
240 size_t getAllocatedSize() const {
241 return sizeof(EHCleanupScope) + CleanupSize;
244 EHCleanupScope(bool IsNormal, bool IsEH, bool IsActive,
245 unsigned CleanupSize, unsigned FixupDepth,
246 EHScopeStack::stable_iterator EnclosingNormal,
247 EHScopeStack::stable_iterator EnclosingEH)
248 : EHScope(EHScope::Cleanup),
249 IsNormalCleanup(IsNormal), IsEHCleanup(IsEH),
250 ActivatedBeforeNormalUse(IsActive),
251 ActivatedBeforeEHUse(IsActive),
252 CleanupSize(CleanupSize), FixupDepth(FixupDepth),
253 EnclosingNormal(EnclosingNormal), EnclosingEH(EnclosingEH),
254 NormalBlock(0), EHBlock(0),
255 ActiveVar(IsActive ? activeSentinel() : 0),
258 assert(this->CleanupSize == CleanupSize && "cleanup size overflow");
265 bool isNormalCleanup() const { return IsNormalCleanup; }
266 llvm::BasicBlock *getNormalBlock() const { return NormalBlock; }
267 void setNormalBlock(llvm::BasicBlock *BB) { NormalBlock = BB; }
269 bool isEHCleanup() const { return IsEHCleanup; }
270 llvm::BasicBlock *getEHBlock() const { return EHBlock; }
271 void setEHBlock(llvm::BasicBlock *BB) { EHBlock = BB; }
273 static llvm::AllocaInst *activeSentinel() {
274 return reinterpret_cast<llvm::AllocaInst*>(1);
277 bool isActive() const { return ActiveVar != 0; }
278 llvm::AllocaInst *getActiveVar() const { return ActiveVar; }
279 void setActiveVar(llvm::AllocaInst *Var) { ActiveVar = Var; }
281 bool wasActivatedBeforeNormalUse() const { return ActivatedBeforeNormalUse; }
282 void setActivatedBeforeNormalUse(bool B) { ActivatedBeforeNormalUse = B; }
284 bool wasActivatedBeforeEHUse() const { return ActivatedBeforeEHUse; }
285 void setActivatedBeforeEHUse(bool B) { ActivatedBeforeEHUse = B; }
287 unsigned getFixupDepth() const { return FixupDepth; }
288 EHScopeStack::stable_iterator getEnclosingNormalCleanup() const {
289 return EnclosingNormal;
291 EHScopeStack::stable_iterator getEnclosingEHCleanup() const {
295 size_t getCleanupSize() const { return CleanupSize; }
296 void *getCleanupBuffer() { return this + 1; }
298 EHScopeStack::Cleanup *getCleanup() {
299 return reinterpret_cast<EHScopeStack::Cleanup*>(getCleanupBuffer());
302 /// True if this cleanup scope has any branch-afters or branch-throughs.
303 bool hasBranches() const { return ExtInfo && !ExtInfo->Branches.empty(); }
305 /// Add a branch-after to this cleanup scope. A branch-after is a
306 /// branch from a point protected by this (normal) cleanup to a
307 /// point in the normal cleanup scope immediately containing it.
309 /// for (;;) { A a; break; }
310 /// contains a branch-after.
312 /// Branch-afters each have their own destination out of the
313 /// cleanup, guaranteed distinct from anything else threaded through
314 /// it. Therefore branch-afters usually force a switch after the
316 void addBranchAfter(llvm::ConstantInt *Index,
317 llvm::BasicBlock *Block) {
318 struct ExtInfo &ExtInfo = getExtInfo();
319 if (ExtInfo.Branches.insert(Block))
320 ExtInfo.BranchAfters.push_back(std::make_pair(Block, Index));
323 /// Return the number of unique branch-afters on this scope.
324 unsigned getNumBranchAfters() const {
325 return ExtInfo ? ExtInfo->BranchAfters.size() : 0;
328 llvm::BasicBlock *getBranchAfterBlock(unsigned I) const {
329 assert(I < getNumBranchAfters());
330 return ExtInfo->BranchAfters[I].first;
333 llvm::ConstantInt *getBranchAfterIndex(unsigned I) const {
334 assert(I < getNumBranchAfters());
335 return ExtInfo->BranchAfters[I].second;
338 /// Add a branch-through to this cleanup scope. A branch-through is
339 /// a branch from a scope protected by this (normal) cleanup to an
340 /// enclosing scope other than the immediately-enclosing normal
343 /// In the following example, the branch through B's scope is a
344 /// branch-through, while the branch through A's scope is a
346 /// for (;;) { A a; B b; break; }
348 /// All branch-throughs have a common destination out of the
349 /// cleanup, one possibly shared with the fall-through. Therefore
350 /// branch-throughs usually don't force a switch after the cleanup.
352 /// \return true if the branch-through was new to this scope
353 bool addBranchThrough(llvm::BasicBlock *Block) {
354 return getExtInfo().Branches.insert(Block);
357 /// Determines if this cleanup scope has any branch throughs.
358 bool hasBranchThroughs() const {
359 if (!ExtInfo) return false;
360 return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size());
363 // Same stuff, only for EH branches instead of normal branches.
364 // It's quite possible that we could find a better representation
367 bool hasEHBranches() const { return ExtInfo && !ExtInfo->EHBranches.empty(); }
368 void addEHBranchAfter(llvm::ConstantInt *Index,
369 llvm::BasicBlock *Block) {
370 struct ExtInfo &ExtInfo = getExtInfo();
371 if (ExtInfo.EHBranches.insert(Block))
372 ExtInfo.EHBranchAfters.push_back(std::make_pair(Block, Index));
375 unsigned getNumEHBranchAfters() const {
376 return ExtInfo ? ExtInfo->EHBranchAfters.size() : 0;
379 llvm::BasicBlock *getEHBranchAfterBlock(unsigned I) const {
380 assert(I < getNumEHBranchAfters());
381 return ExtInfo->EHBranchAfters[I].first;
384 llvm::ConstantInt *getEHBranchAfterIndex(unsigned I) const {
385 assert(I < getNumEHBranchAfters());
386 return ExtInfo->EHBranchAfters[I].second;
389 bool addEHBranchThrough(llvm::BasicBlock *Block) {
390 return getExtInfo().EHBranches.insert(Block);
393 bool hasEHBranchThroughs() const {
394 if (!ExtInfo) return false;
395 return (ExtInfo->EHBranchAfters.size() != ExtInfo->EHBranches.size());
398 static bool classof(const EHScope *Scope) {
399 return (Scope->getKind() == Cleanup);
403 /// An exceptions scope which filters exceptions thrown through it.
404 /// Only exceptions matching the filter types will be permitted to be
407 /// This is used to implement C++ exception specifications.
408 class EHFilterScope : public EHScope {
409 unsigned NumFilters : BitsRemaining;
411 // Essentially ends in a flexible array member:
412 // llvm::Value *FilterTypes[0];
414 llvm::Value **getFilters() {
415 return reinterpret_cast<llvm::Value**>(this+1);
418 llvm::Value * const *getFilters() const {
419 return reinterpret_cast<llvm::Value* const *>(this+1);
423 EHFilterScope(unsigned NumFilters) :
424 EHScope(Filter), NumFilters(NumFilters) {}
426 static size_t getSizeForNumFilters(unsigned NumFilters) {
427 return sizeof(EHFilterScope) + NumFilters * sizeof(llvm::Value*);
430 unsigned getNumFilters() const { return NumFilters; }
432 void setFilter(unsigned I, llvm::Value *FilterValue) {
433 assert(I < getNumFilters());
434 getFilters()[I] = FilterValue;
437 llvm::Value *getFilter(unsigned I) const {
438 assert(I < getNumFilters());
439 return getFilters()[I];
442 static bool classof(const EHScope *Scope) {
443 return Scope->getKind() == Filter;
447 /// An exceptions scope which calls std::terminate if any exception
449 class EHTerminateScope : public EHScope {
450 unsigned DestIndex : BitsRemaining;
452 EHTerminateScope(unsigned Index) : EHScope(Terminate), DestIndex(Index) {}
453 static size_t getSize() { return sizeof(EHTerminateScope); }
455 unsigned getDestIndex() const { return DestIndex; }
457 static bool classof(const EHScope *Scope) {
458 return Scope->getKind() == Terminate;
462 /// A non-stable pointer into the scope stack.
463 class EHScopeStack::iterator {
466 friend class EHScopeStack;
467 explicit iterator(char *Ptr) : Ptr(Ptr) {}
470 iterator() : Ptr(0) {}
472 EHScope *get() const {
473 return reinterpret_cast<EHScope*>(Ptr);
476 EHScope *operator->() const { return get(); }
477 EHScope &operator*() const { return *get(); }
479 iterator &operator++() {
480 switch (get()->getKind()) {
482 Ptr += EHCatchScope::getSizeForNumHandlers(
483 static_cast<const EHCatchScope*>(get())->getNumHandlers());
486 case EHScope::Filter:
487 Ptr += EHFilterScope::getSizeForNumFilters(
488 static_cast<const EHFilterScope*>(get())->getNumFilters());
491 case EHScope::Cleanup:
492 Ptr += static_cast<const EHCleanupScope*>(get())
493 ->getAllocatedSize();
496 case EHScope::Terminate:
497 Ptr += EHTerminateScope::getSize();
505 iterator copy = *this;
510 iterator operator++(int) {
511 iterator copy = *this;
516 bool encloses(iterator other) const { return Ptr >= other.Ptr; }
517 bool strictlyEncloses(iterator other) const { return Ptr > other.Ptr; }
519 bool operator==(iterator other) const { return Ptr == other.Ptr; }
520 bool operator!=(iterator other) const { return Ptr != other.Ptr; }
523 inline EHScopeStack::iterator EHScopeStack::begin() const {
524 return iterator(StartOfData);
527 inline EHScopeStack::iterator EHScopeStack::end() const {
528 return iterator(EndOfBuffer);
531 inline void EHScopeStack::popCatch() {
532 assert(!empty() && "popping exception stack when not empty");
534 assert(isa<EHCatchScope>(*begin()));
535 StartOfData += EHCatchScope::getSizeForNumHandlers(
536 cast<EHCatchScope>(*begin()).getNumHandlers());
538 if (empty()) NextEHDestIndex = FirstEHDestIndex;
540 assert(CatchDepth > 0 && "mismatched catch/terminate push/pop");
544 inline void EHScopeStack::popTerminate() {
545 assert(!empty() && "popping exception stack when not empty");
547 assert(isa<EHTerminateScope>(*begin()));
548 StartOfData += EHTerminateScope::getSize();
550 if (empty()) NextEHDestIndex = FirstEHDestIndex;
552 assert(CatchDepth > 0 && "mismatched catch/terminate push/pop");
556 inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const {
557 assert(sp.isValid() && "finding invalid savepoint");
558 assert(sp.Size <= stable_begin().Size && "finding savepoint after pop");
559 return iterator(EndOfBuffer - sp.Size);
562 inline EHScopeStack::stable_iterator
563 EHScopeStack::stabilize(iterator ir) const {
564 assert(StartOfData <= ir.Ptr && ir.Ptr <= EndOfBuffer);
565 return stable_iterator(EndOfBuffer - ir.Ptr);
568 inline EHScopeStack::stable_iterator
569 EHScopeStack::getInnermostActiveNormalCleanup() const {
570 for (EHScopeStack::stable_iterator
571 I = getInnermostNormalCleanup(), E = stable_end(); I != E; ) {
572 EHCleanupScope &S = cast<EHCleanupScope>(*find(I));
573 if (S.isActive()) return I;
574 I = S.getEnclosingNormalCleanup();
579 inline EHScopeStack::stable_iterator
580 EHScopeStack::getInnermostActiveEHCleanup() const {
581 for (EHScopeStack::stable_iterator
582 I = getInnermostEHCleanup(), E = stable_end(); I != E; ) {
583 EHCleanupScope &S = cast<EHCleanupScope>(*find(I));
584 if (S.isActive()) return I;
585 I = S.getEnclosingEHCleanup();