@@ -30,12 +30,16 @@ struct CatchTypeInfo {
3030
3131// / A protected scope for zero-cost EH handling.
3232class EHScope {
33+ EHScopeStack::stable_iterator enclosingEHScope;
34+
3335 class CommonBitFields {
3436 friend class EHScope ;
3537 unsigned kind : 3 ;
3638 };
3739 enum { NumCommonBits = 3 };
3840
41+ bool isScopeMayThrow;
42+
3943protected:
4044 class CatchBitFields {
4145 friend class EHCatchScope ;
@@ -79,16 +83,24 @@ class EHScope {
7983public:
8084 enum Kind { Cleanup, Catch, Terminate, Filter };
8185
82- EHScope (Kind kind) { commonBits.kind = kind; }
86+ EHScope (Kind kind, EHScopeStack::stable_iterator enclosingEHScope)
87+ : enclosingEHScope(enclosingEHScope) {
88+ commonBits.kind = kind;
89+ }
8390
8491 Kind getKind () const { return static_cast <Kind>(commonBits.kind ); }
8592
8693 bool mayThrow () const {
8794 // Traditional LLVM codegen also checks for `!block->use_empty()`, but
8895 // in CIRGen the block content is not important, just used as a way to
8996 // signal `hasEHBranches`.
90- assert (!cir::MissingFeatures::ehstackBranches ());
91- return false ;
97+ return isScopeMayThrow;
98+ }
99+
100+ void setMayThrow (bool mayThrow) { isScopeMayThrow = mayThrow; }
101+
102+ EHScopeStack::stable_iterator getEnclosingEHScope () const {
103+ return enclosingEHScope;
92104 }
93105};
94106
@@ -111,19 +123,27 @@ class EHCatchScope : public EHScope {
111123
112124 // / The catch handler for this type.
113125 mlir::Region *region;
126+
127+ bool isCatchAll () const { return type.rtti == nullptr ; }
114128 };
115129
116130private:
117131 friend class EHScopeStack ;
118132
119133 Handler *getHandlers () { return reinterpret_cast <Handler *>(this + 1 ); }
120134
135+ const Handler *getHandlers () const {
136+ return reinterpret_cast <const Handler *>(this + 1 );
137+ }
138+
121139public:
122140 static size_t getSizeForNumHandlers (unsigned n) {
123141 return sizeof (EHCatchScope) + n * sizeof (Handler);
124142 }
125143
126- EHCatchScope (unsigned numHandlers) : EHScope(Catch) {
144+ EHCatchScope (unsigned numHandlers,
145+ EHScopeStack::stable_iterator enclosingEHScope)
146+ : EHScope(Catch, enclosingEHScope) {
127147 catchBits.numHandlers = numHandlers;
128148 assert (catchBits.numHandlers == numHandlers && " NumHandlers overflow?" );
129149 }
@@ -136,6 +156,11 @@ class EHCatchScope : public EHScope {
136156 getHandlers ()[i].region = region;
137157 }
138158
159+ const Handler &getHandler (unsigned i) const {
160+ assert (i < getNumHandlers ());
161+ return getHandlers ()[i];
162+ }
163+
139164 // Clear all handler blocks.
140165 // FIXME: it's better to always call clearHandlerBlocks in DTOR and have a
141166 // 'takeHandler' or some such function which removes ownership from the
@@ -144,6 +169,10 @@ class EHCatchScope : public EHScope {
144169 // The blocks are owned by TryOp, nothing to delete.
145170 }
146171
172+ using iterator = const Handler *;
173+ iterator begin () const { return getHandlers (); }
174+ iterator end () const { return getHandlers () + getNumHandlers (); }
175+
147176 static bool classof (const EHScope *scope) {
148177 return scope->getKind () == Catch;
149178 }
@@ -176,9 +205,10 @@ class alignas(EHScopeStack::ScopeStackAlignment) EHCleanupScope
176205 }
177206
178207 EHCleanupScope (unsigned cleanupSize, unsigned fixupDepth,
179- EHScopeStack::stable_iterator enclosingNormal)
180- : EHScope (EHScope::Cleanup), enclosingNormal (enclosingNormal),
181- fixupDepth (fixupDepth) {
208+ EHScopeStack::stable_iterator enclosingNormal,
209+ EHScopeStack::stable_iterator enclosingEH)
210+ : EHScope (EHScope::Cleanup, enclosingEH),
211+ enclosingNormal (enclosingNormal), fixupDepth (fixupDepth) {
182212 // TODO(cir): When exception handling is upstreamed, isNormalCleanup and
183213 // isEHCleanup will be arguments to the constructor.
184214 cleanupBits.isNormalCleanup = true ;
@@ -235,13 +265,45 @@ class EHScopeStack::iterator {
235265
236266 EHScope *get () const { return reinterpret_cast <EHScope *>(ptr); }
237267
268+ EHScope *operator ->() const { return get (); }
238269 EHScope &operator *() const { return *get (); }
270+
271+ iterator &operator ++() {
272+ size_t size;
273+ switch (get ()->getKind ()) {
274+ case EHScope::Catch:
275+ size = EHCatchScope::getSizeForNumHandlers (
276+ static_cast <const EHCatchScope *>(get ())->getNumHandlers ());
277+ break ;
278+
279+ case EHScope::Filter:
280+ llvm_unreachable (" EHScopeStack::iterator Filter" );
281+ break ;
282+
283+ case EHScope::Cleanup:
284+ llvm_unreachable (" EHScopeStack::iterator Cleanup" );
285+ break ;
286+
287+ case EHScope::Terminate:
288+ llvm_unreachable (" EHScopeStack::iterator Terminate" );
289+ break ;
290+ }
291+ ptr += llvm::alignTo (size, ScopeStackAlignment);
292+ return *this ;
293+ }
294+
295+ bool operator ==(iterator other) const { return ptr == other.ptr ; }
296+ bool operator !=(iterator other) const { return ptr != other.ptr ; }
239297};
240298
241299inline EHScopeStack::iterator EHScopeStack::begin () const {
242300 return iterator (startOfData);
243301}
244302
303+ inline EHScopeStack::iterator EHScopeStack::end () const {
304+ return iterator (endOfBuffer);
305+ }
306+
245307inline EHScopeStack::iterator
246308EHScopeStack::find (stable_iterator savePoint) const {
247309 assert (savePoint.isValid () && " finding invalid savepoint" );
@@ -254,7 +316,7 @@ inline void EHScopeStack::popCatch() {
254316 assert (!empty () && " popping exception stack when not empty" );
255317
256318 EHCatchScope &scope = llvm::cast<EHCatchScope>(*begin ());
257- assert (! cir::MissingFeatures:: innermostEHScope() );
319+ innermostEHScope = scope. getEnclosingEHScope ( );
258320 deallocate (EHCatchScope::getSizeForNumHandlers (scope.getNumHandlers ()));
259321}
260322
0 commit comments