clang API Documentation
00001 //===-- EHScopeStack.h - Stack for cleanup IR generation --------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // These classes should be the minimum interface required for other parts of 00011 // CodeGen to emit cleanups. The implementation is in CGCleanup.cpp and other 00012 // implemenentation details that are not widely needed are in CGCleanup.h. 00013 // 00014 //===----------------------------------------------------------------------===// 00015 00016 #ifndef LLVM_CLANG_LIB_CODEGEN_EHSCOPESTACK_H 00017 #define LLVM_CLANG_LIB_CODEGEN_EHSCOPESTACK_H 00018 00019 #include "clang/Basic/LLVM.h" 00020 #include "llvm/ADT/SmallVector.h" 00021 #include "llvm/IR/BasicBlock.h" 00022 #include "llvm/IR/Instructions.h" 00023 #include "llvm/IR/Value.h" 00024 00025 namespace clang { 00026 namespace CodeGen { 00027 00028 class CodeGenFunction; 00029 00030 /// A branch fixup. These are required when emitting a goto to a 00031 /// label which hasn't been emitted yet. The goto is optimistically 00032 /// emitted as a branch to the basic block for the label, and (if it 00033 /// occurs in a scope with non-trivial cleanups) a fixup is added to 00034 /// the innermost cleanup. When a (normal) cleanup is popped, any 00035 /// unresolved fixups in that scope are threaded through the cleanup. 00036 struct BranchFixup { 00037 /// The block containing the terminator which needs to be modified 00038 /// into a switch if this fixup is resolved into the current scope. 00039 /// If null, LatestBranch points directly to the destination. 00040 llvm::BasicBlock *OptimisticBranchBlock; 00041 00042 /// The ultimate destination of the branch. 00043 /// 00044 /// This can be set to null to indicate that this fixup was 00045 /// successfully resolved. 00046 llvm::BasicBlock *Destination; 00047 00048 /// The destination index value. 00049 unsigned DestinationIndex; 00050 00051 /// The initial branch of the fixup. 00052 llvm::BranchInst *InitialBranch; 00053 }; 00054 00055 template <class T> struct InvariantValue { 00056 typedef T type; 00057 typedef T saved_type; 00058 static bool needsSaving(type value) { return false; } 00059 static saved_type save(CodeGenFunction &CGF, type value) { return value; } 00060 static type restore(CodeGenFunction &CGF, saved_type value) { return value; } 00061 }; 00062 00063 /// A metaprogramming class for ensuring that a value will dominate an 00064 /// arbitrary position in a function. 00065 template <class T> struct DominatingValue : InvariantValue<T> {}; 00066 00067 template <class T, bool mightBeInstruction = 00068 std::is_base_of<llvm::Value, T>::value && 00069 !std::is_base_of<llvm::Constant, T>::value && 00070 !std::is_base_of<llvm::BasicBlock, T>::value> 00071 struct DominatingPointer; 00072 template <class T> struct DominatingPointer<T,false> : InvariantValue<T*> {}; 00073 // template <class T> struct DominatingPointer<T,true> at end of file 00074 00075 template <class T> struct DominatingValue<T*> : DominatingPointer<T> {}; 00076 00077 enum CleanupKind : unsigned { 00078 EHCleanup = 0x1, 00079 NormalCleanup = 0x2, 00080 NormalAndEHCleanup = EHCleanup | NormalCleanup, 00081 00082 InactiveCleanup = 0x4, 00083 InactiveEHCleanup = EHCleanup | InactiveCleanup, 00084 InactiveNormalCleanup = NormalCleanup | InactiveCleanup, 00085 InactiveNormalAndEHCleanup = NormalAndEHCleanup | InactiveCleanup 00086 }; 00087 00088 /// A stack of scopes which respond to exceptions, including cleanups 00089 /// and catch blocks. 00090 class EHScopeStack { 00091 public: 00092 /// A saved depth on the scope stack. This is necessary because 00093 /// pushing scopes onto the stack invalidates iterators. 00094 class stable_iterator { 00095 friend class EHScopeStack; 00096 00097 /// Offset from StartOfData to EndOfBuffer. 00098 ptrdiff_t Size; 00099 00100 stable_iterator(ptrdiff_t Size) : Size(Size) {} 00101 00102 public: 00103 static stable_iterator invalid() { return stable_iterator(-1); } 00104 stable_iterator() : Size(-1) {} 00105 00106 bool isValid() const { return Size >= 0; } 00107 00108 /// Returns true if this scope encloses I. 00109 /// Returns false if I is invalid. 00110 /// This scope must be valid. 00111 bool encloses(stable_iterator I) const { return Size <= I.Size; } 00112 00113 /// Returns true if this scope strictly encloses I: that is, 00114 /// if it encloses I and is not I. 00115 /// Returns false is I is invalid. 00116 /// This scope must be valid. 00117 bool strictlyEncloses(stable_iterator I) const { return Size < I.Size; } 00118 00119 friend bool operator==(stable_iterator A, stable_iterator B) { 00120 return A.Size == B.Size; 00121 } 00122 friend bool operator!=(stable_iterator A, stable_iterator B) { 00123 return A.Size != B.Size; 00124 } 00125 }; 00126 00127 /// Information for lazily generating a cleanup. Subclasses must be 00128 /// POD-like: cleanups will not be destructed, and they will be 00129 /// allocated on the cleanup stack and freely copied and moved 00130 /// around. 00131 /// 00132 /// Cleanup implementations should generally be declared in an 00133 /// anonymous namespace. 00134 class Cleanup { 00135 // Anchor the construction vtable. 00136 virtual void anchor(); 00137 public: 00138 /// Generation flags. 00139 class Flags { 00140 enum { 00141 F_IsForEH = 0x1, 00142 F_IsNormalCleanupKind = 0x2, 00143 F_IsEHCleanupKind = 0x4 00144 }; 00145 unsigned flags; 00146 00147 public: 00148 Flags() : flags(0) {} 00149 00150 /// isForEH - true if the current emission is for an EH cleanup. 00151 bool isForEHCleanup() const { return flags & F_IsForEH; } 00152 bool isForNormalCleanup() const { return !isForEHCleanup(); } 00153 void setIsForEHCleanup() { flags |= F_IsForEH; } 00154 00155 bool isNormalCleanupKind() const { return flags & F_IsNormalCleanupKind; } 00156 void setIsNormalCleanupKind() { flags |= F_IsNormalCleanupKind; } 00157 00158 /// isEHCleanupKind - true if the cleanup was pushed as an EH 00159 /// cleanup. 00160 bool isEHCleanupKind() const { return flags & F_IsEHCleanupKind; } 00161 void setIsEHCleanupKind() { flags |= F_IsEHCleanupKind; } 00162 }; 00163 00164 // Provide a virtual destructor to suppress a very common warning 00165 // that unfortunately cannot be suppressed without this. Cleanups 00166 // should not rely on this destructor ever being called. 00167 virtual ~Cleanup() {} 00168 00169 /// Emit the cleanup. For normal cleanups, this is run in the 00170 /// same EH context as when the cleanup was pushed, i.e. the 00171 /// immediately-enclosing context of the cleanup scope. For 00172 /// EH cleanups, this is run in a terminate context. 00173 /// 00174 // \param flags cleanup kind. 00175 virtual void Emit(CodeGenFunction &CGF, Flags flags) = 0; 00176 }; 00177 00178 /// ConditionalCleanupN stores the saved form of its N parameters, 00179 /// then restores them and performs the cleanup. 00180 template <class T, class A0> 00181 class ConditionalCleanup1 : public Cleanup { 00182 typedef typename DominatingValue<A0>::saved_type A0_saved; 00183 A0_saved a0_saved; 00184 00185 void Emit(CodeGenFunction &CGF, Flags flags) override { 00186 A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved); 00187 T(a0).Emit(CGF, flags); 00188 } 00189 00190 public: 00191 ConditionalCleanup1(A0_saved a0) 00192 : a0_saved(a0) {} 00193 }; 00194 00195 template <class T, class A0, class A1> 00196 class ConditionalCleanup2 : public Cleanup { 00197 typedef typename DominatingValue<A0>::saved_type A0_saved; 00198 typedef typename DominatingValue<A1>::saved_type A1_saved; 00199 A0_saved a0_saved; 00200 A1_saved a1_saved; 00201 00202 void Emit(CodeGenFunction &CGF, Flags flags) override { 00203 A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved); 00204 A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved); 00205 T(a0, a1).Emit(CGF, flags); 00206 } 00207 00208 public: 00209 ConditionalCleanup2(A0_saved a0, A1_saved a1) 00210 : a0_saved(a0), a1_saved(a1) {} 00211 }; 00212 00213 template <class T, class A0, class A1, class A2> 00214 class ConditionalCleanup3 : public Cleanup { 00215 typedef typename DominatingValue<A0>::saved_type A0_saved; 00216 typedef typename DominatingValue<A1>::saved_type A1_saved; 00217 typedef typename DominatingValue<A2>::saved_type A2_saved; 00218 A0_saved a0_saved; 00219 A1_saved a1_saved; 00220 A2_saved a2_saved; 00221 00222 void Emit(CodeGenFunction &CGF, Flags flags) override { 00223 A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved); 00224 A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved); 00225 A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved); 00226 T(a0, a1, a2).Emit(CGF, flags); 00227 } 00228 00229 public: 00230 ConditionalCleanup3(A0_saved a0, A1_saved a1, A2_saved a2) 00231 : a0_saved(a0), a1_saved(a1), a2_saved(a2) {} 00232 }; 00233 00234 template <class T, class A0, class A1, class A2, class A3> 00235 class ConditionalCleanup4 : public Cleanup { 00236 typedef typename DominatingValue<A0>::saved_type A0_saved; 00237 typedef typename DominatingValue<A1>::saved_type A1_saved; 00238 typedef typename DominatingValue<A2>::saved_type A2_saved; 00239 typedef typename DominatingValue<A3>::saved_type A3_saved; 00240 A0_saved a0_saved; 00241 A1_saved a1_saved; 00242 A2_saved a2_saved; 00243 A3_saved a3_saved; 00244 00245 void Emit(CodeGenFunction &CGF, Flags flags) override { 00246 A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved); 00247 A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved); 00248 A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved); 00249 A3 a3 = DominatingValue<A3>::restore(CGF, a3_saved); 00250 T(a0, a1, a2, a3).Emit(CGF, flags); 00251 } 00252 00253 public: 00254 ConditionalCleanup4(A0_saved a0, A1_saved a1, A2_saved a2, A3_saved a3) 00255 : a0_saved(a0), a1_saved(a1), a2_saved(a2), a3_saved(a3) {} 00256 }; 00257 00258 private: 00259 // The implementation for this class is in CGException.h and 00260 // CGException.cpp; the definition is here because it's used as a 00261 // member of CodeGenFunction. 00262 00263 /// The start of the scope-stack buffer, i.e. the allocated pointer 00264 /// for the buffer. All of these pointers are either simultaneously 00265 /// null or simultaneously valid. 00266 char *StartOfBuffer; 00267 00268 /// The end of the buffer. 00269 char *EndOfBuffer; 00270 00271 /// The first valid entry in the buffer. 00272 char *StartOfData; 00273 00274 /// The innermost normal cleanup on the stack. 00275 stable_iterator InnermostNormalCleanup; 00276 00277 /// The innermost EH scope on the stack. 00278 stable_iterator InnermostEHScope; 00279 00280 /// The current set of branch fixups. A branch fixup is a jump to 00281 /// an as-yet unemitted label, i.e. a label for which we don't yet 00282 /// know the EH stack depth. Whenever we pop a cleanup, we have 00283 /// to thread all the current branch fixups through it. 00284 /// 00285 /// Fixups are recorded as the Use of the respective branch or 00286 /// switch statement. The use points to the final destination. 00287 /// When popping out of a cleanup, these uses are threaded through 00288 /// the cleanup and adjusted to point to the new cleanup. 00289 /// 00290 /// Note that branches are allowed to jump into protected scopes 00291 /// in certain situations; e.g. the following code is legal: 00292 /// struct A { ~A(); }; // trivial ctor, non-trivial dtor 00293 /// goto foo; 00294 /// A a; 00295 /// foo: 00296 /// bar(); 00297 SmallVector<BranchFixup, 8> BranchFixups; 00298 00299 char *allocate(size_t Size); 00300 00301 void *pushCleanup(CleanupKind K, size_t DataSize); 00302 00303 public: 00304 EHScopeStack() : StartOfBuffer(nullptr), EndOfBuffer(nullptr), 00305 StartOfData(nullptr), InnermostNormalCleanup(stable_end()), 00306 InnermostEHScope(stable_end()) {} 00307 ~EHScopeStack() { delete[] StartOfBuffer; } 00308 00309 // Variadic templates would make this not terrible. 00310 00311 /// Push a lazily-created cleanup on the stack. 00312 template <class T> 00313 void pushCleanup(CleanupKind Kind) { 00314 void *Buffer = pushCleanup(Kind, sizeof(T)); 00315 Cleanup *Obj = new(Buffer) T(); 00316 (void) Obj; 00317 } 00318 00319 /// Push a lazily-created cleanup on the stack. 00320 template <class T, class A0> 00321 void pushCleanup(CleanupKind Kind, A0 a0) { 00322 void *Buffer = pushCleanup(Kind, sizeof(T)); 00323 Cleanup *Obj = new(Buffer) T(a0); 00324 (void) Obj; 00325 } 00326 00327 /// Push a lazily-created cleanup on the stack. 00328 template <class T, class A0, class A1> 00329 void pushCleanup(CleanupKind Kind, A0 a0, A1 a1) { 00330 void *Buffer = pushCleanup(Kind, sizeof(T)); 00331 Cleanup *Obj = new(Buffer) T(a0, a1); 00332 (void) Obj; 00333 } 00334 00335 /// Push a lazily-created cleanup on the stack. 00336 template <class T, class A0, class A1, class A2> 00337 void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2) { 00338 void *Buffer = pushCleanup(Kind, sizeof(T)); 00339 Cleanup *Obj = new(Buffer) T(a0, a1, a2); 00340 (void) Obj; 00341 } 00342 00343 /// Push a lazily-created cleanup on the stack. 00344 template <class T, class A0, class A1, class A2, class A3> 00345 void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3) { 00346 void *Buffer = pushCleanup(Kind, sizeof(T)); 00347 Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3); 00348 (void) Obj; 00349 } 00350 00351 /// Push a lazily-created cleanup on the stack. 00352 template <class T, class A0, class A1, class A2, class A3, class A4> 00353 void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { 00354 void *Buffer = pushCleanup(Kind, sizeof(T)); 00355 Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3, a4); 00356 (void) Obj; 00357 } 00358 00359 // Feel free to add more variants of the following: 00360 00361 /// Push a cleanup with non-constant storage requirements on the 00362 /// stack. The cleanup type must provide an additional static method: 00363 /// static size_t getExtraSize(size_t); 00364 /// The argument to this method will be the value N, which will also 00365 /// be passed as the first argument to the constructor. 00366 /// 00367 /// The data stored in the extra storage must obey the same 00368 /// restrictions as normal cleanup member data. 00369 /// 00370 /// The pointer returned from this method is valid until the cleanup 00371 /// stack is modified. 00372 template <class T, class A0, class A1, class A2> 00373 T *pushCleanupWithExtra(CleanupKind Kind, size_t N, A0 a0, A1 a1, A2 a2) { 00374 void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N)); 00375 return new (Buffer) T(N, a0, a1, a2); 00376 } 00377 00378 void pushCopyOfCleanup(CleanupKind Kind, const void *Cleanup, size_t Size) { 00379 void *Buffer = pushCleanup(Kind, Size); 00380 std::memcpy(Buffer, Cleanup, Size); 00381 } 00382 00383 /// Pops a cleanup scope off the stack. This is private to CGCleanup.cpp. 00384 void popCleanup(); 00385 00386 /// Push a set of catch handlers on the stack. The catch is 00387 /// uninitialized and will need to have the given number of handlers 00388 /// set on it. 00389 class EHCatchScope *pushCatch(unsigned NumHandlers); 00390 00391 /// Pops a catch scope off the stack. This is private to CGException.cpp. 00392 void popCatch(); 00393 00394 /// Push an exceptions filter on the stack. 00395 class EHFilterScope *pushFilter(unsigned NumFilters); 00396 00397 /// Pops an exceptions filter off the stack. 00398 void popFilter(); 00399 00400 /// Push a terminate handler on the stack. 00401 void pushTerminate(); 00402 00403 /// Pops a terminate handler off the stack. 00404 void popTerminate(); 00405 00406 /// Determines whether the exception-scopes stack is empty. 00407 bool empty() const { return StartOfData == EndOfBuffer; } 00408 00409 bool requiresLandingPad() const { 00410 return InnermostEHScope != stable_end(); 00411 } 00412 00413 /// Determines whether there are any normal cleanups on the stack. 00414 bool hasNormalCleanups() const { 00415 return InnermostNormalCleanup != stable_end(); 00416 } 00417 00418 /// Returns the innermost normal cleanup on the stack, or 00419 /// stable_end() if there are no normal cleanups. 00420 stable_iterator getInnermostNormalCleanup() const { 00421 return InnermostNormalCleanup; 00422 } 00423 stable_iterator getInnermostActiveNormalCleanup() const; 00424 00425 stable_iterator getInnermostEHScope() const { 00426 return InnermostEHScope; 00427 } 00428 00429 stable_iterator getInnermostActiveEHScope() const; 00430 00431 /// An unstable reference to a scope-stack depth. Invalidated by 00432 /// pushes but not pops. 00433 class iterator; 00434 00435 /// Returns an iterator pointing to the innermost EH scope. 00436 iterator begin() const; 00437 00438 /// Returns an iterator pointing to the outermost EH scope. 00439 iterator end() const; 00440 00441 /// Create a stable reference to the top of the EH stack. The 00442 /// returned reference is valid until that scope is popped off the 00443 /// stack. 00444 stable_iterator stable_begin() const { 00445 return stable_iterator(EndOfBuffer - StartOfData); 00446 } 00447 00448 /// Create a stable reference to the bottom of the EH stack. 00449 static stable_iterator stable_end() { 00450 return stable_iterator(0); 00451 } 00452 00453 /// Translates an iterator into a stable_iterator. 00454 stable_iterator stabilize(iterator it) const; 00455 00456 /// Turn a stable reference to a scope depth into a unstable pointer 00457 /// to the EH stack. 00458 iterator find(stable_iterator save) const; 00459 00460 /// Removes the cleanup pointed to by the given stable_iterator. 00461 void removeCleanup(stable_iterator save); 00462 00463 /// Add a branch fixup to the current cleanup scope. 00464 BranchFixup &addBranchFixup() { 00465 assert(hasNormalCleanups() && "adding fixup in scope without cleanups"); 00466 BranchFixups.push_back(BranchFixup()); 00467 return BranchFixups.back(); 00468 } 00469 00470 unsigned getNumBranchFixups() const { return BranchFixups.size(); } 00471 BranchFixup &getBranchFixup(unsigned I) { 00472 assert(I < getNumBranchFixups()); 00473 return BranchFixups[I]; 00474 } 00475 00476 /// Pops lazily-removed fixups from the end of the list. This 00477 /// should only be called by procedures which have just popped a 00478 /// cleanup or resolved one or more fixups. 00479 void popNullFixups(); 00480 00481 /// Clears the branch-fixups list. This should only be called by 00482 /// ResolveAllBranchFixups. 00483 void clearFixups() { BranchFixups.clear(); } 00484 }; 00485 00486 } // namespace CodeGen 00487 } // namespace clang 00488 00489 #endif