blob: 9c81a4e7a84de9743739406b9761e991380023e1 [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;
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;
51
John McCallb2593832010-09-16 06:16:50 +000052 llvm::StringRef getPersonalityFnName() const { return PersonalityFn; }
53 llvm::StringRef getCatchallRethrowFnName() const { return CatchallRethrowFn; }
John McCall8262b6a2010-07-17 00:43:08 +000054};
55
John McCallf1549f62010-07-06 01:34:17 +000056/// A protected scope for zero-cost EH handling.
57class EHScope {
58 llvm::BasicBlock *CachedLandingPad;
59
John McCall7495f222010-07-21 07:11:21 +000060 unsigned K : 2;
John McCallf1549f62010-07-06 01:34:17 +000061
62protected:
John McCall7495f222010-07-21 07:11:21 +000063 enum { BitsRemaining = 30 };
John McCallf1549f62010-07-06 01:34:17 +000064
65public:
John McCall1f0fca52010-07-21 07:22:38 +000066 enum Kind { Cleanup, Catch, Terminate, Filter };
John McCallf1549f62010-07-06 01:34:17 +000067
68 EHScope(Kind K) : CachedLandingPad(0), K(K) {}
69
70 Kind getKind() const { return static_cast<Kind>(K); }
71
72 llvm::BasicBlock *getCachedLandingPad() const {
73 return CachedLandingPad;
74 }
75
76 void setCachedLandingPad(llvm::BasicBlock *Block) {
77 CachedLandingPad = Block;
78 }
79};
80
81/// A scope which attempts to handle some, possibly all, types of
82/// exceptions.
83///
84/// Objective C @finally blocks are represented using a cleanup scope
85/// after the catch scope.
86class EHCatchScope : public EHScope {
87 unsigned NumHandlers : BitsRemaining;
88
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.
93
94public:
95 struct Handler {
96 /// A type info value, or null (C++ null, not an LLVM null pointer)
97 /// for a catch-all.
98 llvm::Value *Type;
99
100 /// The catch handler for this type.
101 llvm::BasicBlock *Block;
102
John McCallff8e1152010-07-23 21:56:41 +0000103 /// The unwind destination index for this handler.
104 unsigned Index;
John McCallf1549f62010-07-06 01:34:17 +0000105 };
106
107private:
John McCallff8e1152010-07-23 21:56:41 +0000108 friend class EHScopeStack;
109
John McCallf1549f62010-07-06 01:34:17 +0000110 Handler *getHandlers() {
111 return reinterpret_cast<Handler*>(this+1);
112 }
113
114 const Handler *getHandlers() const {
115 return reinterpret_cast<const Handler*>(this+1);
116 }
117
118public:
119 static size_t getSizeForNumHandlers(unsigned N) {
120 return sizeof(EHCatchScope) + N * sizeof(Handler);
121 }
122
123 EHCatchScope(unsigned NumHandlers)
124 : EHScope(Catch), NumHandlers(NumHandlers) {
125 }
126
127 unsigned getNumHandlers() const {
128 return NumHandlers;
129 }
130
131 void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block) {
132 setHandler(I, /*catchall*/ 0, Block);
133 }
134
135 void setHandler(unsigned I, llvm::Value *Type, llvm::BasicBlock *Block) {
136 assert(I < getNumHandlers());
John McCallff8e1152010-07-23 21:56:41 +0000137 getHandlers()[I].Type = Type;
138 getHandlers()[I].Block = Block;
John McCallf1549f62010-07-06 01:34:17 +0000139 }
140
141 const Handler &getHandler(unsigned I) const {
142 assert(I < getNumHandlers());
143 return getHandlers()[I];
144 }
145
146 typedef const Handler *iterator;
147 iterator begin() const { return getHandlers(); }
148 iterator end() const { return getHandlers() + getNumHandlers(); }
149
150 static bool classof(const EHScope *Scope) {
151 return Scope->getKind() == Catch;
152 }
153};
154
John McCallda65ea82010-07-13 20:32:21 +0000155/// A cleanup scope which generates the cleanup blocks lazily.
John McCall1f0fca52010-07-21 07:22:38 +0000156class EHCleanupScope : public EHScope {
John McCallda65ea82010-07-13 20:32:21 +0000157 /// Whether this cleanup needs to be run along normal edges.
158 bool IsNormalCleanup : 1;
159
160 /// Whether this cleanup needs to be run along exception edges.
161 bool IsEHCleanup : 1;
162
John McCall7d8647f2010-09-14 07:57:04 +0000163 /// Whether this cleanup is currently active.
164 bool IsActive : 1;
John McCallcd2d2b72010-08-13 21:20:51 +0000165
John McCall7d8647f2010-09-14 07:57:04 +0000166 /// Whether the normal cleanup should test the activation flag.
167 bool TestFlagInNormalCleanup : 1;
168
169 /// Whether the EH cleanup should test the activation flag.
170 bool TestFlagInEHCleanup : 1;
John McCallcd2d2b72010-08-13 21:20:51 +0000171
John McCall1f0fca52010-07-21 07:22:38 +0000172 /// The amount of extra storage needed by the Cleanup.
John McCallda65ea82010-07-13 20:32:21 +0000173 /// Always a multiple of the scope-stack alignment.
174 unsigned CleanupSize : 12;
175
176 /// The number of fixups required by enclosing scopes (not including
177 /// this one). If this is the top cleanup scope, all the fixups
178 /// from this index onwards belong to this scope.
John McCall7d8647f2010-09-14 07:57:04 +0000179 unsigned FixupDepth : BitsRemaining - 17; // currently 13
John McCallda65ea82010-07-13 20:32:21 +0000180
181 /// The nearest normal cleanup scope enclosing this one.
182 EHScopeStack::stable_iterator EnclosingNormal;
183
184 /// The nearest EH cleanup scope enclosing this one.
185 EHScopeStack::stable_iterator EnclosingEH;
186
187 /// The dual entry/exit block along the normal edge. This is lazily
188 /// created if needed before the cleanup is popped.
189 llvm::BasicBlock *NormalBlock;
190
191 /// The dual entry/exit block along the EH edge. This is lazily
192 /// created if needed before the cleanup is popped.
193 llvm::BasicBlock *EHBlock;
194
John McCallcd2d2b72010-08-13 21:20:51 +0000195 /// An optional i1 variable indicating whether this cleanup has been
John McCall7d8647f2010-09-14 07:57:04 +0000196 /// activated yet.
197 llvm::AllocaInst *ActiveFlag;
John McCallcd2d2b72010-08-13 21:20:51 +0000198
John McCallff8e1152010-07-23 21:56:41 +0000199 /// Extra information required for cleanups that have resolved
200 /// branches through them. This has to be allocated on the side
201 /// because everything on the cleanup stack has be trivially
202 /// movable.
203 struct ExtInfo {
204 /// The destinations of normal branch-afters and branch-throughs.
205 llvm::SmallPtrSet<llvm::BasicBlock*, 4> Branches;
206
207 /// Normal branch-afters.
208 llvm::SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4>
209 BranchAfters;
210
211 /// The destinations of EH branch-afters and branch-throughs.
212 /// TODO: optimize for the extremely common case of a single
213 /// branch-through.
214 llvm::SmallPtrSet<llvm::BasicBlock*, 4> EHBranches;
215
216 /// EH branch-afters.
217 llvm::SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4>
218 EHBranchAfters;
219 };
220 mutable struct ExtInfo *ExtInfo;
221
222 struct ExtInfo &getExtInfo() {
223 if (!ExtInfo) ExtInfo = new struct ExtInfo();
224 return *ExtInfo;
225 }
226
227 const struct ExtInfo &getExtInfo() const {
228 if (!ExtInfo) ExtInfo = new struct ExtInfo();
229 return *ExtInfo;
230 }
231
John McCallda65ea82010-07-13 20:32:21 +0000232public:
233 /// Gets the size required for a lazy cleanup scope with the given
234 /// cleanup-data requirements.
235 static size_t getSizeForCleanupSize(size_t Size) {
John McCall1f0fca52010-07-21 07:22:38 +0000236 return sizeof(EHCleanupScope) + Size;
John McCallda65ea82010-07-13 20:32:21 +0000237 }
238
239 size_t getAllocatedSize() const {
John McCall1f0fca52010-07-21 07:22:38 +0000240 return sizeof(EHCleanupScope) + CleanupSize;
John McCallda65ea82010-07-13 20:32:21 +0000241 }
242
John McCallcd2d2b72010-08-13 21:20:51 +0000243 EHCleanupScope(bool IsNormal, bool IsEH, bool IsActive,
244 unsigned CleanupSize, unsigned FixupDepth,
John McCall1f0fca52010-07-21 07:22:38 +0000245 EHScopeStack::stable_iterator EnclosingNormal,
246 EHScopeStack::stable_iterator EnclosingEH)
247 : EHScope(EHScope::Cleanup),
John McCall7d8647f2010-09-14 07:57:04 +0000248 IsNormalCleanup(IsNormal), IsEHCleanup(IsEH), IsActive(IsActive),
249 TestFlagInNormalCleanup(false), TestFlagInEHCleanup(false),
John McCallda65ea82010-07-13 20:32:21 +0000250 CleanupSize(CleanupSize), FixupDepth(FixupDepth),
251 EnclosingNormal(EnclosingNormal), EnclosingEH(EnclosingEH),
John McCall7d8647f2010-09-14 07:57:04 +0000252 NormalBlock(0), EHBlock(0), ActiveFlag(0), ExtInfo(0)
John McCallff8e1152010-07-23 21:56:41 +0000253 {
254 assert(this->CleanupSize == CleanupSize && "cleanup size overflow");
255 }
256
257 ~EHCleanupScope() {
258 delete ExtInfo;
259 }
John McCallda65ea82010-07-13 20:32:21 +0000260
261 bool isNormalCleanup() const { return IsNormalCleanup; }
262 llvm::BasicBlock *getNormalBlock() const { return NormalBlock; }
263 void setNormalBlock(llvm::BasicBlock *BB) { NormalBlock = BB; }
264
265 bool isEHCleanup() const { return IsEHCleanup; }
266 llvm::BasicBlock *getEHBlock() const { return EHBlock; }
267 void setEHBlock(llvm::BasicBlock *BB) { EHBlock = BB; }
268
John McCall7d8647f2010-09-14 07:57:04 +0000269 bool isActive() const { return IsActive; }
270 void setActive(bool A) { IsActive = A; }
John McCallcd2d2b72010-08-13 21:20:51 +0000271
John McCall7d8647f2010-09-14 07:57:04 +0000272 llvm::AllocaInst *getActiveFlag() const { return ActiveFlag; }
273 void setActiveFlag(llvm::AllocaInst *Var) { ActiveFlag = Var; }
John McCallcd2d2b72010-08-13 21:20:51 +0000274
John McCall7d8647f2010-09-14 07:57:04 +0000275 void setTestFlagInNormalCleanup() { TestFlagInNormalCleanup = true; }
276 bool shouldTestFlagInNormalCleanup() const { return TestFlagInNormalCleanup; }
John McCallcd2d2b72010-08-13 21:20:51 +0000277
John McCall7d8647f2010-09-14 07:57:04 +0000278 void setTestFlagInEHCleanup() { TestFlagInEHCleanup = true; }
279 bool shouldTestFlagInEHCleanup() const { return TestFlagInEHCleanup; }
John McCallcd2d2b72010-08-13 21:20:51 +0000280
John McCallda65ea82010-07-13 20:32:21 +0000281 unsigned getFixupDepth() const { return FixupDepth; }
282 EHScopeStack::stable_iterator getEnclosingNormalCleanup() const {
283 return EnclosingNormal;
284 }
285 EHScopeStack::stable_iterator getEnclosingEHCleanup() const {
286 return EnclosingEH;
287 }
288
289 size_t getCleanupSize() const { return CleanupSize; }
290 void *getCleanupBuffer() { return this + 1; }
291
John McCall1f0fca52010-07-21 07:22:38 +0000292 EHScopeStack::Cleanup *getCleanup() {
293 return reinterpret_cast<EHScopeStack::Cleanup*>(getCleanupBuffer());
John McCallda65ea82010-07-13 20:32:21 +0000294 }
295
John McCallff8e1152010-07-23 21:56:41 +0000296 /// True if this cleanup scope has any branch-afters or branch-throughs.
297 bool hasBranches() const { return ExtInfo && !ExtInfo->Branches.empty(); }
298
299 /// Add a branch-after to this cleanup scope. A branch-after is a
300 /// branch from a point protected by this (normal) cleanup to a
301 /// point in the normal cleanup scope immediately containing it.
302 /// For example,
303 /// for (;;) { A a; break; }
304 /// contains a branch-after.
305 ///
306 /// Branch-afters each have their own destination out of the
307 /// cleanup, guaranteed distinct from anything else threaded through
308 /// it. Therefore branch-afters usually force a switch after the
309 /// cleanup.
310 void addBranchAfter(llvm::ConstantInt *Index,
311 llvm::BasicBlock *Block) {
312 struct ExtInfo &ExtInfo = getExtInfo();
313 if (ExtInfo.Branches.insert(Block))
314 ExtInfo.BranchAfters.push_back(std::make_pair(Block, Index));
315 }
316
317 /// Return the number of unique branch-afters on this scope.
318 unsigned getNumBranchAfters() const {
319 return ExtInfo ? ExtInfo->BranchAfters.size() : 0;
320 }
321
322 llvm::BasicBlock *getBranchAfterBlock(unsigned I) const {
323 assert(I < getNumBranchAfters());
324 return ExtInfo->BranchAfters[I].first;
325 }
326
327 llvm::ConstantInt *getBranchAfterIndex(unsigned I) const {
328 assert(I < getNumBranchAfters());
329 return ExtInfo->BranchAfters[I].second;
330 }
331
332 /// Add a branch-through to this cleanup scope. A branch-through is
333 /// a branch from a scope protected by this (normal) cleanup to an
334 /// enclosing scope other than the immediately-enclosing normal
335 /// cleanup scope.
336 ///
337 /// In the following example, the branch through B's scope is a
338 /// branch-through, while the branch through A's scope is a
339 /// branch-after:
340 /// for (;;) { A a; B b; break; }
341 ///
342 /// All branch-throughs have a common destination out of the
343 /// cleanup, one possibly shared with the fall-through. Therefore
344 /// branch-throughs usually don't force a switch after the cleanup.
345 ///
346 /// \return true if the branch-through was new to this scope
347 bool addBranchThrough(llvm::BasicBlock *Block) {
348 return getExtInfo().Branches.insert(Block);
349 }
350
351 /// Determines if this cleanup scope has any branch throughs.
352 bool hasBranchThroughs() const {
353 if (!ExtInfo) return false;
354 return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size());
355 }
356
357 // Same stuff, only for EH branches instead of normal branches.
358 // It's quite possible that we could find a better representation
359 // for this.
360
361 bool hasEHBranches() const { return ExtInfo && !ExtInfo->EHBranches.empty(); }
362 void addEHBranchAfter(llvm::ConstantInt *Index,
363 llvm::BasicBlock *Block) {
364 struct ExtInfo &ExtInfo = getExtInfo();
365 if (ExtInfo.EHBranches.insert(Block))
366 ExtInfo.EHBranchAfters.push_back(std::make_pair(Block, Index));
367 }
368
369 unsigned getNumEHBranchAfters() const {
370 return ExtInfo ? ExtInfo->EHBranchAfters.size() : 0;
371 }
372
373 llvm::BasicBlock *getEHBranchAfterBlock(unsigned I) const {
374 assert(I < getNumEHBranchAfters());
375 return ExtInfo->EHBranchAfters[I].first;
376 }
377
378 llvm::ConstantInt *getEHBranchAfterIndex(unsigned I) const {
379 assert(I < getNumEHBranchAfters());
380 return ExtInfo->EHBranchAfters[I].second;
381 }
382
383 bool addEHBranchThrough(llvm::BasicBlock *Block) {
384 return getExtInfo().EHBranches.insert(Block);
385 }
386
387 bool hasEHBranchThroughs() const {
388 if (!ExtInfo) return false;
389 return (ExtInfo->EHBranchAfters.size() != ExtInfo->EHBranches.size());
390 }
391
John McCallda65ea82010-07-13 20:32:21 +0000392 static bool classof(const EHScope *Scope) {
John McCall1f0fca52010-07-21 07:22:38 +0000393 return (Scope->getKind() == Cleanup);
John McCallda65ea82010-07-13 20:32:21 +0000394 }
395};
396
John McCallf1549f62010-07-06 01:34:17 +0000397/// An exceptions scope which filters exceptions thrown through it.
398/// Only exceptions matching the filter types will be permitted to be
399/// thrown.
400///
401/// This is used to implement C++ exception specifications.
402class EHFilterScope : public EHScope {
403 unsigned NumFilters : BitsRemaining;
404
405 // Essentially ends in a flexible array member:
406 // llvm::Value *FilterTypes[0];
407
408 llvm::Value **getFilters() {
409 return reinterpret_cast<llvm::Value**>(this+1);
410 }
411
412 llvm::Value * const *getFilters() const {
413 return reinterpret_cast<llvm::Value* const *>(this+1);
414 }
415
416public:
417 EHFilterScope(unsigned NumFilters) :
418 EHScope(Filter), NumFilters(NumFilters) {}
419
420 static size_t getSizeForNumFilters(unsigned NumFilters) {
421 return sizeof(EHFilterScope) + NumFilters * sizeof(llvm::Value*);
422 }
423
424 unsigned getNumFilters() const { return NumFilters; }
425
426 void setFilter(unsigned I, llvm::Value *FilterValue) {
427 assert(I < getNumFilters());
428 getFilters()[I] = FilterValue;
429 }
430
431 llvm::Value *getFilter(unsigned I) const {
432 assert(I < getNumFilters());
433 return getFilters()[I];
434 }
435
436 static bool classof(const EHScope *Scope) {
437 return Scope->getKind() == Filter;
438 }
439};
440
441/// An exceptions scope which calls std::terminate if any exception
442/// reaches it.
443class EHTerminateScope : public EHScope {
John McCallff8e1152010-07-23 21:56:41 +0000444 unsigned DestIndex : BitsRemaining;
John McCallf1549f62010-07-06 01:34:17 +0000445public:
John McCallff8e1152010-07-23 21:56:41 +0000446 EHTerminateScope(unsigned Index) : EHScope(Terminate), DestIndex(Index) {}
John McCallf1549f62010-07-06 01:34:17 +0000447 static size_t getSize() { return sizeof(EHTerminateScope); }
448
John McCallff8e1152010-07-23 21:56:41 +0000449 unsigned getDestIndex() const { return DestIndex; }
450
John McCallf1549f62010-07-06 01:34:17 +0000451 static bool classof(const EHScope *Scope) {
452 return Scope->getKind() == Terminate;
453 }
454};
455
456/// A non-stable pointer into the scope stack.
457class EHScopeStack::iterator {
458 char *Ptr;
459
460 friend class EHScopeStack;
461 explicit iterator(char *Ptr) : Ptr(Ptr) {}
462
463public:
464 iterator() : Ptr(0) {}
465
466 EHScope *get() const {
467 return reinterpret_cast<EHScope*>(Ptr);
468 }
469
470 EHScope *operator->() const { return get(); }
471 EHScope &operator*() const { return *get(); }
472
473 iterator &operator++() {
474 switch (get()->getKind()) {
475 case EHScope::Catch:
476 Ptr += EHCatchScope::getSizeForNumHandlers(
477 static_cast<const EHCatchScope*>(get())->getNumHandlers());
478 break;
479
480 case EHScope::Filter:
481 Ptr += EHFilterScope::getSizeForNumFilters(
482 static_cast<const EHFilterScope*>(get())->getNumFilters());
483 break;
484
John McCall1f0fca52010-07-21 07:22:38 +0000485 case EHScope::Cleanup:
486 Ptr += static_cast<const EHCleanupScope*>(get())
John McCallda65ea82010-07-13 20:32:21 +0000487 ->getAllocatedSize();
488 break;
489
John McCallf1549f62010-07-06 01:34:17 +0000490 case EHScope::Terminate:
491 Ptr += EHTerminateScope::getSize();
492 break;
493 }
494
495 return *this;
496 }
497
498 iterator next() {
499 iterator copy = *this;
500 ++copy;
501 return copy;
502 }
503
504 iterator operator++(int) {
505 iterator copy = *this;
506 operator++();
507 return copy;
508 }
509
John McCallff8e1152010-07-23 21:56:41 +0000510 bool encloses(iterator other) const { return Ptr >= other.Ptr; }
511 bool strictlyEncloses(iterator other) const { return Ptr > other.Ptr; }
512
John McCallf1549f62010-07-06 01:34:17 +0000513 bool operator==(iterator other) const { return Ptr == other.Ptr; }
514 bool operator!=(iterator other) const { return Ptr != other.Ptr; }
515};
516
517inline EHScopeStack::iterator EHScopeStack::begin() const {
518 return iterator(StartOfData);
519}
520
521inline EHScopeStack::iterator EHScopeStack::end() const {
522 return iterator(EndOfBuffer);
523}
524
525inline void EHScopeStack::popCatch() {
526 assert(!empty() && "popping exception stack when not empty");
527
528 assert(isa<EHCatchScope>(*begin()));
529 StartOfData += EHCatchScope::getSizeForNumHandlers(
530 cast<EHCatchScope>(*begin()).getNumHandlers());
531
John McCallff8e1152010-07-23 21:56:41 +0000532 if (empty()) NextEHDestIndex = FirstEHDestIndex;
533
John McCallf1549f62010-07-06 01:34:17 +0000534 assert(CatchDepth > 0 && "mismatched catch/terminate push/pop");
535 CatchDepth--;
536}
537
538inline void EHScopeStack::popTerminate() {
539 assert(!empty() && "popping exception stack when not empty");
540
541 assert(isa<EHTerminateScope>(*begin()));
542 StartOfData += EHTerminateScope::getSize();
543
John McCallff8e1152010-07-23 21:56:41 +0000544 if (empty()) NextEHDestIndex = FirstEHDestIndex;
545
John McCallf1549f62010-07-06 01:34:17 +0000546 assert(CatchDepth > 0 && "mismatched catch/terminate push/pop");
547 CatchDepth--;
548}
549
550inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const {
551 assert(sp.isValid() && "finding invalid savepoint");
552 assert(sp.Size <= stable_begin().Size && "finding savepoint after pop");
553 return iterator(EndOfBuffer - sp.Size);
554}
555
556inline EHScopeStack::stable_iterator
557EHScopeStack::stabilize(iterator ir) const {
558 assert(StartOfData <= ir.Ptr && ir.Ptr <= EndOfBuffer);
559 return stable_iterator(EndOfBuffer - ir.Ptr);
560}
561
John McCall838d7962010-08-14 07:46:19 +0000562inline EHScopeStack::stable_iterator
563EHScopeStack::getInnermostActiveNormalCleanup() const {
564 for (EHScopeStack::stable_iterator
565 I = getInnermostNormalCleanup(), E = stable_end(); I != E; ) {
566 EHCleanupScope &S = cast<EHCleanupScope>(*find(I));
567 if (S.isActive()) return I;
568 I = S.getEnclosingNormalCleanup();
569 }
570 return stable_end();
571}
572
573inline EHScopeStack::stable_iterator
574EHScopeStack::getInnermostActiveEHCleanup() const {
575 for (EHScopeStack::stable_iterator
576 I = getInnermostEHCleanup(), E = stable_end(); I != E; ) {
577 EHCleanupScope &S = cast<EHCleanupScope>(*find(I));
578 if (S.isActive()) return I;
579 I = S.getEnclosingEHCleanup();
580 }
581 return stable_end();
582}
583
John McCallf1549f62010-07-06 01:34:17 +0000584}
585}
586
587#endif