blob: 5e6f1511aec6adc8712a4e9e6dc719d08a9ca93b [file] [log] [blame]
John McCallf1549f62010-07-06 01:34:17 +00001//===-- CGException.h - Classes for exceptions IR generation ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// These classes support the generation of LLVM IR for exceptions in
11// C++ and Objective C.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef CLANG_CODEGEN_CGEXCEPTION_H
16#define CLANG_CODEGEN_CGEXCEPTION_H
17
18/// EHScopeStack is defined in CodeGenFunction.h, but its
19/// implementation is in this file and in CGException.cpp.
20#include "CodeGenFunction.h"
21
22namespace llvm {
23 class Value;
24 class BasicBlock;
25}
26
27namespace clang {
28namespace CodeGen {
29
John McCall8262b6a2010-07-17 00:43:08 +000030/// The exceptions personality for a function. When
31class EHPersonality {
John McCallb2593832010-09-16 06:16:50 +000032 llvm::StringRef PersonalityFn;
John McCall8262b6a2010-07-17 00:43:08 +000033
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*).
John McCallb2593832010-09-16 06:16:50 +000037 llvm::StringRef CatchallRethrowFn;
John McCall8262b6a2010-07-17 00:43:08 +000038
John McCallb2593832010-09-16 06:16:50 +000039 EHPersonality(llvm::StringRef PersonalityFn,
40 llvm::StringRef CatchallRethrowFn = llvm::StringRef())
John McCall8262b6a2010-07-17 00:43:08 +000041 : PersonalityFn(PersonalityFn),
42 CatchallRethrowFn(CatchallRethrowFn) {}
43
44public:
45 static const EHPersonality &get(const LangOptions &Lang);
46 static const EHPersonality GNU_C;
John McCall44680782010-11-07 02:35:25 +000047 static const EHPersonality GNU_C_SJLJ;
John McCall8262b6a2010-07-17 00:43:08 +000048 static const EHPersonality GNU_ObjC;
49 static const EHPersonality NeXT_ObjC;
50 static const EHPersonality GNU_CPlusPlus;
51 static const EHPersonality GNU_CPlusPlus_SJLJ;
52
John McCallb2593832010-09-16 06:16:50 +000053 llvm::StringRef getPersonalityFnName() const { return PersonalityFn; }
54 llvm::StringRef getCatchallRethrowFnName() const { return CatchallRethrowFn; }
John McCall8262b6a2010-07-17 00:43:08 +000055};
56
John McCallf1549f62010-07-06 01:34:17 +000057/// A protected scope for zero-cost EH handling.
58class EHScope {
59 llvm::BasicBlock *CachedLandingPad;
60
John McCall7495f222010-07-21 07:11:21 +000061 unsigned K : 2;
John McCallf1549f62010-07-06 01:34:17 +000062
63protected:
John McCall7495f222010-07-21 07:11:21 +000064 enum { BitsRemaining = 30 };
John McCallf1549f62010-07-06 01:34:17 +000065
66public:
John McCall1f0fca52010-07-21 07:22:38 +000067 enum Kind { Cleanup, Catch, Terminate, Filter };
John McCallf1549f62010-07-06 01:34:17 +000068
69 EHScope(Kind K) : CachedLandingPad(0), K(K) {}
70
71 Kind getKind() const { return static_cast<Kind>(K); }
72
73 llvm::BasicBlock *getCachedLandingPad() const {
74 return CachedLandingPad;
75 }
76
77 void setCachedLandingPad(llvm::BasicBlock *Block) {
78 CachedLandingPad = Block;
79 }
80};
81
82/// A scope which attempts to handle some, possibly all, types of
83/// exceptions.
84///
85/// Objective C @finally blocks are represented using a cleanup scope
86/// after the catch scope.
87class EHCatchScope : public EHScope {
88 unsigned NumHandlers : BitsRemaining;
89
90 // In effect, we have a flexible array member
91 // Handler Handlers[0];
92 // But that's only standard in C99, not C++, so we have to do
93 // annoying pointer arithmetic instead.
94
95public:
96 struct Handler {
97 /// A type info value, or null (C++ null, not an LLVM null pointer)
98 /// for a catch-all.
99 llvm::Value *Type;
100
101 /// The catch handler for this type.
102 llvm::BasicBlock *Block;
103
John McCallff8e1152010-07-23 21:56:41 +0000104 /// The unwind destination index for this handler.
105 unsigned Index;
John McCallf1549f62010-07-06 01:34:17 +0000106 };
107
108private:
John McCallff8e1152010-07-23 21:56:41 +0000109 friend class EHScopeStack;
110
John McCallf1549f62010-07-06 01:34:17 +0000111 Handler *getHandlers() {
112 return reinterpret_cast<Handler*>(this+1);
113 }
114
115 const Handler *getHandlers() const {
116 return reinterpret_cast<const Handler*>(this+1);
117 }
118
119public:
120 static size_t getSizeForNumHandlers(unsigned N) {
121 return sizeof(EHCatchScope) + N * sizeof(Handler);
122 }
123
124 EHCatchScope(unsigned NumHandlers)
125 : EHScope(Catch), NumHandlers(NumHandlers) {
126 }
127
128 unsigned getNumHandlers() const {
129 return NumHandlers;
130 }
131
132 void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block) {
133 setHandler(I, /*catchall*/ 0, Block);
134 }
135
136 void setHandler(unsigned I, llvm::Value *Type, llvm::BasicBlock *Block) {
137 assert(I < getNumHandlers());
John McCallff8e1152010-07-23 21:56:41 +0000138 getHandlers()[I].Type = Type;
139 getHandlers()[I].Block = Block;
John McCallf1549f62010-07-06 01:34:17 +0000140 }
141
142 const Handler &getHandler(unsigned I) const {
143 assert(I < getNumHandlers());
144 return getHandlers()[I];
145 }
146
147 typedef const Handler *iterator;
148 iterator begin() const { return getHandlers(); }
149 iterator end() const { return getHandlers() + getNumHandlers(); }
150
151 static bool classof(const EHScope *Scope) {
152 return Scope->getKind() == Catch;
153 }
154};
155
John McCallda65ea82010-07-13 20:32:21 +0000156/// A cleanup scope which generates the cleanup blocks lazily.
John McCall1f0fca52010-07-21 07:22:38 +0000157class EHCleanupScope : public EHScope {
John McCallda65ea82010-07-13 20:32:21 +0000158 /// Whether this cleanup needs to be run along normal edges.
159 bool IsNormalCleanup : 1;
160
161 /// Whether this cleanup needs to be run along exception edges.
162 bool IsEHCleanup : 1;
163
John McCall7d8647f2010-09-14 07:57:04 +0000164 /// Whether this cleanup is currently active.
165 bool IsActive : 1;
John McCallcd2d2b72010-08-13 21:20:51 +0000166
John McCall7d8647f2010-09-14 07:57:04 +0000167 /// Whether the normal cleanup should test the activation flag.
168 bool TestFlagInNormalCleanup : 1;
169
170 /// Whether the EH cleanup should test the activation flag.
171 bool TestFlagInEHCleanup : 1;
John McCallcd2d2b72010-08-13 21:20:51 +0000172
John McCall1f0fca52010-07-21 07:22:38 +0000173 /// The amount of extra storage needed by the Cleanup.
John McCallda65ea82010-07-13 20:32:21 +0000174 /// Always a multiple of the scope-stack alignment.
175 unsigned CleanupSize : 12;
176
177 /// The number of fixups required by enclosing scopes (not including
178 /// this one). If this is the top cleanup scope, all the fixups
179 /// from this index onwards belong to this scope.
John McCall7d8647f2010-09-14 07:57:04 +0000180 unsigned FixupDepth : BitsRemaining - 17; // currently 13
John McCallda65ea82010-07-13 20:32:21 +0000181
182 /// The nearest normal cleanup scope enclosing this one.
183 EHScopeStack::stable_iterator EnclosingNormal;
184
185 /// The nearest EH cleanup scope enclosing this one.
186 EHScopeStack::stable_iterator EnclosingEH;
187
188 /// The dual entry/exit block along the normal edge. This is lazily
189 /// created if needed before the cleanup is popped.
190 llvm::BasicBlock *NormalBlock;
191
192 /// The dual entry/exit block along the EH edge. This is lazily
193 /// created if needed before the cleanup is popped.
194 llvm::BasicBlock *EHBlock;
195
John McCallcd2d2b72010-08-13 21:20:51 +0000196 /// An optional i1 variable indicating whether this cleanup has been
John McCall7d8647f2010-09-14 07:57:04 +0000197 /// activated yet.
198 llvm::AllocaInst *ActiveFlag;
John McCallcd2d2b72010-08-13 21:20:51 +0000199
John McCallff8e1152010-07-23 21:56:41 +0000200 /// 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
203 /// movable.
204 struct ExtInfo {
205 /// The destinations of normal branch-afters and branch-throughs.
206 llvm::SmallPtrSet<llvm::BasicBlock*, 4> Branches;
207
208 /// Normal branch-afters.
209 llvm::SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4>
210 BranchAfters;
211
212 /// The destinations of EH branch-afters and branch-throughs.
213 /// TODO: optimize for the extremely common case of a single
214 /// branch-through.
215 llvm::SmallPtrSet<llvm::BasicBlock*, 4> EHBranches;
216
217 /// EH branch-afters.
218 llvm::SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4>
219 EHBranchAfters;
220 };
221 mutable struct ExtInfo *ExtInfo;
222
223 struct ExtInfo &getExtInfo() {
224 if (!ExtInfo) ExtInfo = new struct ExtInfo();
225 return *ExtInfo;
226 }
227
228 const struct ExtInfo &getExtInfo() const {
229 if (!ExtInfo) ExtInfo = new struct ExtInfo();
230 return *ExtInfo;
231 }
232
John McCallda65ea82010-07-13 20:32:21 +0000233public:
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) {
John McCall1f0fca52010-07-21 07:22:38 +0000237 return sizeof(EHCleanupScope) + Size;
John McCallda65ea82010-07-13 20:32:21 +0000238 }
239
240 size_t getAllocatedSize() const {
John McCall1f0fca52010-07-21 07:22:38 +0000241 return sizeof(EHCleanupScope) + CleanupSize;
John McCallda65ea82010-07-13 20:32:21 +0000242 }
243
John McCallcd2d2b72010-08-13 21:20:51 +0000244 EHCleanupScope(bool IsNormal, bool IsEH, bool IsActive,
245 unsigned CleanupSize, unsigned FixupDepth,
John McCall1f0fca52010-07-21 07:22:38 +0000246 EHScopeStack::stable_iterator EnclosingNormal,
247 EHScopeStack::stable_iterator EnclosingEH)
248 : EHScope(EHScope::Cleanup),
John McCall7d8647f2010-09-14 07:57:04 +0000249 IsNormalCleanup(IsNormal), IsEHCleanup(IsEH), IsActive(IsActive),
250 TestFlagInNormalCleanup(false), TestFlagInEHCleanup(false),
John McCallda65ea82010-07-13 20:32:21 +0000251 CleanupSize(CleanupSize), FixupDepth(FixupDepth),
252 EnclosingNormal(EnclosingNormal), EnclosingEH(EnclosingEH),
John McCall7d8647f2010-09-14 07:57:04 +0000253 NormalBlock(0), EHBlock(0), ActiveFlag(0), ExtInfo(0)
John McCallff8e1152010-07-23 21:56:41 +0000254 {
255 assert(this->CleanupSize == CleanupSize && "cleanup size overflow");
256 }
257
258 ~EHCleanupScope() {
259 delete ExtInfo;
260 }
John McCallda65ea82010-07-13 20:32:21 +0000261
262 bool isNormalCleanup() const { return IsNormalCleanup; }
263 llvm::BasicBlock *getNormalBlock() const { return NormalBlock; }
264 void setNormalBlock(llvm::BasicBlock *BB) { NormalBlock = BB; }
265
266 bool isEHCleanup() const { return IsEHCleanup; }
267 llvm::BasicBlock *getEHBlock() const { return EHBlock; }
268 void setEHBlock(llvm::BasicBlock *BB) { EHBlock = BB; }
269
John McCall7d8647f2010-09-14 07:57:04 +0000270 bool isActive() const { return IsActive; }
271 void setActive(bool A) { IsActive = A; }
John McCallcd2d2b72010-08-13 21:20:51 +0000272
John McCall7d8647f2010-09-14 07:57:04 +0000273 llvm::AllocaInst *getActiveFlag() const { return ActiveFlag; }
274 void setActiveFlag(llvm::AllocaInst *Var) { ActiveFlag = Var; }
John McCallcd2d2b72010-08-13 21:20:51 +0000275
John McCall7d8647f2010-09-14 07:57:04 +0000276 void setTestFlagInNormalCleanup() { TestFlagInNormalCleanup = true; }
277 bool shouldTestFlagInNormalCleanup() const { return TestFlagInNormalCleanup; }
John McCallcd2d2b72010-08-13 21:20:51 +0000278
John McCall7d8647f2010-09-14 07:57:04 +0000279 void setTestFlagInEHCleanup() { TestFlagInEHCleanup = true; }
280 bool shouldTestFlagInEHCleanup() const { return TestFlagInEHCleanup; }
John McCallcd2d2b72010-08-13 21:20:51 +0000281
John McCallda65ea82010-07-13 20:32:21 +0000282 unsigned getFixupDepth() const { return FixupDepth; }
283 EHScopeStack::stable_iterator getEnclosingNormalCleanup() const {
284 return EnclosingNormal;
285 }
286 EHScopeStack::stable_iterator getEnclosingEHCleanup() const {
287 return EnclosingEH;
288 }
289
290 size_t getCleanupSize() const { return CleanupSize; }
291 void *getCleanupBuffer() { return this + 1; }
292
John McCall1f0fca52010-07-21 07:22:38 +0000293 EHScopeStack::Cleanup *getCleanup() {
294 return reinterpret_cast<EHScopeStack::Cleanup*>(getCleanupBuffer());
John McCallda65ea82010-07-13 20:32:21 +0000295 }
296
John McCallff8e1152010-07-23 21:56:41 +0000297 /// True if this cleanup scope has any branch-afters or branch-throughs.
298 bool hasBranches() const { return ExtInfo && !ExtInfo->Branches.empty(); }
299
300 /// Add a branch-after to this cleanup scope. A branch-after is a
301 /// branch from a point protected by this (normal) cleanup to a
302 /// point in the normal cleanup scope immediately containing it.
303 /// For example,
304 /// for (;;) { A a; break; }
305 /// contains a branch-after.
306 ///
307 /// Branch-afters each have their own destination out of the
308 /// cleanup, guaranteed distinct from anything else threaded through
309 /// it. Therefore branch-afters usually force a switch after the
310 /// cleanup.
311 void addBranchAfter(llvm::ConstantInt *Index,
312 llvm::BasicBlock *Block) {
313 struct ExtInfo &ExtInfo = getExtInfo();
314 if (ExtInfo.Branches.insert(Block))
315 ExtInfo.BranchAfters.push_back(std::make_pair(Block, Index));
316 }
317
318 /// Return the number of unique branch-afters on this scope.
319 unsigned getNumBranchAfters() const {
320 return ExtInfo ? ExtInfo->BranchAfters.size() : 0;
321 }
322
323 llvm::BasicBlock *getBranchAfterBlock(unsigned I) const {
324 assert(I < getNumBranchAfters());
325 return ExtInfo->BranchAfters[I].first;
326 }
327
328 llvm::ConstantInt *getBranchAfterIndex(unsigned I) const {
329 assert(I < getNumBranchAfters());
330 return ExtInfo->BranchAfters[I].second;
331 }
332
333 /// Add a branch-through to this cleanup scope. A branch-through is
334 /// a branch from a scope protected by this (normal) cleanup to an
335 /// enclosing scope other than the immediately-enclosing normal
336 /// cleanup scope.
337 ///
338 /// In the following example, the branch through B's scope is a
339 /// branch-through, while the branch through A's scope is a
340 /// branch-after:
341 /// for (;;) { A a; B b; break; }
342 ///
343 /// All branch-throughs have a common destination out of the
344 /// cleanup, one possibly shared with the fall-through. Therefore
345 /// branch-throughs usually don't force a switch after the cleanup.
346 ///
347 /// \return true if the branch-through was new to this scope
348 bool addBranchThrough(llvm::BasicBlock *Block) {
349 return getExtInfo().Branches.insert(Block);
350 }
351
352 /// Determines if this cleanup scope has any branch throughs.
353 bool hasBranchThroughs() const {
354 if (!ExtInfo) return false;
355 return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size());
356 }
357
358 // Same stuff, only for EH branches instead of normal branches.
359 // It's quite possible that we could find a better representation
360 // for this.
361
362 bool hasEHBranches() const { return ExtInfo && !ExtInfo->EHBranches.empty(); }
363 void addEHBranchAfter(llvm::ConstantInt *Index,
364 llvm::BasicBlock *Block) {
365 struct ExtInfo &ExtInfo = getExtInfo();
366 if (ExtInfo.EHBranches.insert(Block))
367 ExtInfo.EHBranchAfters.push_back(std::make_pair(Block, Index));
368 }
369
370 unsigned getNumEHBranchAfters() const {
371 return ExtInfo ? ExtInfo->EHBranchAfters.size() : 0;
372 }
373
374 llvm::BasicBlock *getEHBranchAfterBlock(unsigned I) const {
375 assert(I < getNumEHBranchAfters());
376 return ExtInfo->EHBranchAfters[I].first;
377 }
378
379 llvm::ConstantInt *getEHBranchAfterIndex(unsigned I) const {
380 assert(I < getNumEHBranchAfters());
381 return ExtInfo->EHBranchAfters[I].second;
382 }
383
384 bool addEHBranchThrough(llvm::BasicBlock *Block) {
385 return getExtInfo().EHBranches.insert(Block);
386 }
387
388 bool hasEHBranchThroughs() const {
389 if (!ExtInfo) return false;
390 return (ExtInfo->EHBranchAfters.size() != ExtInfo->EHBranches.size());
391 }
392
John McCallda65ea82010-07-13 20:32:21 +0000393 static bool classof(const EHScope *Scope) {
John McCall1f0fca52010-07-21 07:22:38 +0000394 return (Scope->getKind() == Cleanup);
John McCallda65ea82010-07-13 20:32:21 +0000395 }
396};
397
John McCallf1549f62010-07-06 01:34:17 +0000398/// An exceptions scope which filters exceptions thrown through it.
399/// Only exceptions matching the filter types will be permitted to be
400/// thrown.
401///
402/// This is used to implement C++ exception specifications.
403class EHFilterScope : public EHScope {
404 unsigned NumFilters : BitsRemaining;
405
406 // Essentially ends in a flexible array member:
407 // llvm::Value *FilterTypes[0];
408
409 llvm::Value **getFilters() {
410 return reinterpret_cast<llvm::Value**>(this+1);
411 }
412
413 llvm::Value * const *getFilters() const {
414 return reinterpret_cast<llvm::Value* const *>(this+1);
415 }
416
417public:
418 EHFilterScope(unsigned NumFilters) :
419 EHScope(Filter), NumFilters(NumFilters) {}
420
421 static size_t getSizeForNumFilters(unsigned NumFilters) {
422 return sizeof(EHFilterScope) + NumFilters * sizeof(llvm::Value*);
423 }
424
425 unsigned getNumFilters() const { return NumFilters; }
426
427 void setFilter(unsigned I, llvm::Value *FilterValue) {
428 assert(I < getNumFilters());
429 getFilters()[I] = FilterValue;
430 }
431
432 llvm::Value *getFilter(unsigned I) const {
433 assert(I < getNumFilters());
434 return getFilters()[I];
435 }
436
437 static bool classof(const EHScope *Scope) {
438 return Scope->getKind() == Filter;
439 }
440};
441
442/// An exceptions scope which calls std::terminate if any exception
443/// reaches it.
444class EHTerminateScope : public EHScope {
John McCallff8e1152010-07-23 21:56:41 +0000445 unsigned DestIndex : BitsRemaining;
John McCallf1549f62010-07-06 01:34:17 +0000446public:
John McCallff8e1152010-07-23 21:56:41 +0000447 EHTerminateScope(unsigned Index) : EHScope(Terminate), DestIndex(Index) {}
John McCallf1549f62010-07-06 01:34:17 +0000448 static size_t getSize() { return sizeof(EHTerminateScope); }
449
John McCallff8e1152010-07-23 21:56:41 +0000450 unsigned getDestIndex() const { return DestIndex; }
451
John McCallf1549f62010-07-06 01:34:17 +0000452 static bool classof(const EHScope *Scope) {
453 return Scope->getKind() == Terminate;
454 }
455};
456
457/// A non-stable pointer into the scope stack.
458class EHScopeStack::iterator {
459 char *Ptr;
460
461 friend class EHScopeStack;
462 explicit iterator(char *Ptr) : Ptr(Ptr) {}
463
464public:
465 iterator() : Ptr(0) {}
466
467 EHScope *get() const {
468 return reinterpret_cast<EHScope*>(Ptr);
469 }
470
471 EHScope *operator->() const { return get(); }
472 EHScope &operator*() const { return *get(); }
473
474 iterator &operator++() {
475 switch (get()->getKind()) {
476 case EHScope::Catch:
477 Ptr += EHCatchScope::getSizeForNumHandlers(
478 static_cast<const EHCatchScope*>(get())->getNumHandlers());
479 break;
480
481 case EHScope::Filter:
482 Ptr += EHFilterScope::getSizeForNumFilters(
483 static_cast<const EHFilterScope*>(get())->getNumFilters());
484 break;
485
John McCall1f0fca52010-07-21 07:22:38 +0000486 case EHScope::Cleanup:
487 Ptr += static_cast<const EHCleanupScope*>(get())
John McCallda65ea82010-07-13 20:32:21 +0000488 ->getAllocatedSize();
489 break;
490
John McCallf1549f62010-07-06 01:34:17 +0000491 case EHScope::Terminate:
492 Ptr += EHTerminateScope::getSize();
493 break;
494 }
495
496 return *this;
497 }
498
499 iterator next() {
500 iterator copy = *this;
501 ++copy;
502 return copy;
503 }
504
505 iterator operator++(int) {
506 iterator copy = *this;
507 operator++();
508 return copy;
509 }
510
John McCallff8e1152010-07-23 21:56:41 +0000511 bool encloses(iterator other) const { return Ptr >= other.Ptr; }
512 bool strictlyEncloses(iterator other) const { return Ptr > other.Ptr; }
513
John McCallf1549f62010-07-06 01:34:17 +0000514 bool operator==(iterator other) const { return Ptr == other.Ptr; }
515 bool operator!=(iterator other) const { return Ptr != other.Ptr; }
516};
517
518inline EHScopeStack::iterator EHScopeStack::begin() const {
519 return iterator(StartOfData);
520}
521
522inline EHScopeStack::iterator EHScopeStack::end() const {
523 return iterator(EndOfBuffer);
524}
525
526inline void EHScopeStack::popCatch() {
527 assert(!empty() && "popping exception stack when not empty");
528
529 assert(isa<EHCatchScope>(*begin()));
530 StartOfData += EHCatchScope::getSizeForNumHandlers(
531 cast<EHCatchScope>(*begin()).getNumHandlers());
532
John McCallff8e1152010-07-23 21:56:41 +0000533 if (empty()) NextEHDestIndex = FirstEHDestIndex;
534
John McCallf1549f62010-07-06 01:34:17 +0000535 assert(CatchDepth > 0 && "mismatched catch/terminate push/pop");
536 CatchDepth--;
537}
538
539inline void EHScopeStack::popTerminate() {
540 assert(!empty() && "popping exception stack when not empty");
541
542 assert(isa<EHTerminateScope>(*begin()));
543 StartOfData += EHTerminateScope::getSize();
544
John McCallff8e1152010-07-23 21:56:41 +0000545 if (empty()) NextEHDestIndex = FirstEHDestIndex;
546
John McCallf1549f62010-07-06 01:34:17 +0000547 assert(CatchDepth > 0 && "mismatched catch/terminate push/pop");
548 CatchDepth--;
549}
550
551inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const {
552 assert(sp.isValid() && "finding invalid savepoint");
553 assert(sp.Size <= stable_begin().Size && "finding savepoint after pop");
554 return iterator(EndOfBuffer - sp.Size);
555}
556
557inline EHScopeStack::stable_iterator
558EHScopeStack::stabilize(iterator ir) const {
559 assert(StartOfData <= ir.Ptr && ir.Ptr <= EndOfBuffer);
560 return stable_iterator(EndOfBuffer - ir.Ptr);
561}
562
John McCall838d7962010-08-14 07:46:19 +0000563inline EHScopeStack::stable_iterator
564EHScopeStack::getInnermostActiveNormalCleanup() const {
565 for (EHScopeStack::stable_iterator
566 I = getInnermostNormalCleanup(), E = stable_end(); I != E; ) {
567 EHCleanupScope &S = cast<EHCleanupScope>(*find(I));
568 if (S.isActive()) return I;
569 I = S.getEnclosingNormalCleanup();
570 }
571 return stable_end();
572}
573
574inline EHScopeStack::stable_iterator
575EHScopeStack::getInnermostActiveEHCleanup() const {
576 for (EHScopeStack::stable_iterator
577 I = getInnermostEHCleanup(), E = stable_end(); I != E; ) {
578 EHCleanupScope &S = cast<EHCleanupScope>(*find(I));
579 if (S.isActive()) return I;
580 I = S.getEnclosingEHCleanup();
581 }
582 return stable_end();
583}
584
John McCallf1549f62010-07-06 01:34:17 +0000585}
586}
587
588#endif