clang API Documentation

EHScopeStack.h
Go to the documentation of this file.
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