clang API Documentation

CGCleanup.h
Go to the documentation of this file.
00001 //===-- CGCleanup.h - Classes for cleanups 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 support the generation of LLVM IR for cleanups.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H
00015 #define LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H
00016 
00017 #include "EHScopeStack.h"
00018 #include "llvm/ADT/SmallPtrSet.h"
00019 #include "llvm/ADT/SmallVector.h"
00020 
00021 namespace llvm {
00022 class BasicBlock;
00023 class Value;
00024 class ConstantInt;
00025 class AllocaInst;
00026 }
00027 
00028 namespace clang {
00029 namespace CodeGen {
00030 
00031 /// A protected scope for zero-cost EH handling.
00032 class EHScope {
00033   llvm::BasicBlock *CachedLandingPad;
00034   llvm::BasicBlock *CachedEHDispatchBlock;
00035 
00036   EHScopeStack::stable_iterator EnclosingEHScope;
00037 
00038   class CommonBitFields {
00039     friend class EHScope;
00040     unsigned Kind : 2;
00041   };
00042   enum { NumCommonBits = 2 };
00043 
00044 protected:
00045   class CatchBitFields {
00046     friend class EHCatchScope;
00047     unsigned : NumCommonBits;
00048 
00049     unsigned NumHandlers : 32 - NumCommonBits;
00050   };
00051 
00052   class CleanupBitFields {
00053     friend class EHCleanupScope;
00054     unsigned : NumCommonBits;
00055 
00056     /// Whether this cleanup needs to be run along normal edges.
00057     unsigned IsNormalCleanup : 1;
00058 
00059     /// Whether this cleanup needs to be run along exception edges.
00060     unsigned IsEHCleanup : 1;
00061 
00062     /// Whether this cleanup is currently active.
00063     unsigned IsActive : 1;
00064 
00065     /// Whether the normal cleanup should test the activation flag.
00066     unsigned TestFlagInNormalCleanup : 1;
00067 
00068     /// Whether the EH cleanup should test the activation flag.
00069     unsigned TestFlagInEHCleanup : 1;
00070 
00071     /// The amount of extra storage needed by the Cleanup.
00072     /// Always a multiple of the scope-stack alignment.
00073     unsigned CleanupSize : 12;
00074 
00075     /// The number of fixups required by enclosing scopes (not including
00076     /// this one).  If this is the top cleanup scope, all the fixups
00077     /// from this index onwards belong to this scope.
00078     unsigned FixupDepth : 32 - 17 - NumCommonBits; // currently 13    
00079   };
00080 
00081   class FilterBitFields {
00082     friend class EHFilterScope;
00083     unsigned : NumCommonBits;
00084 
00085     unsigned NumFilters : 32 - NumCommonBits;
00086   };
00087 
00088   union {
00089     CommonBitFields CommonBits;
00090     CatchBitFields CatchBits;
00091     CleanupBitFields CleanupBits;
00092     FilterBitFields FilterBits;
00093   };
00094 
00095 public:
00096   enum Kind { Cleanup, Catch, Terminate, Filter };
00097 
00098   EHScope(Kind kind, EHScopeStack::stable_iterator enclosingEHScope)
00099     : CachedLandingPad(nullptr), CachedEHDispatchBlock(nullptr),
00100       EnclosingEHScope(enclosingEHScope) {
00101     CommonBits.Kind = kind;
00102   }
00103 
00104   Kind getKind() const { return static_cast<Kind>(CommonBits.Kind); }
00105 
00106   llvm::BasicBlock *getCachedLandingPad() const {
00107     return CachedLandingPad;
00108   }
00109 
00110   void setCachedLandingPad(llvm::BasicBlock *block) {
00111     CachedLandingPad = block;
00112   }
00113 
00114   llvm::BasicBlock *getCachedEHDispatchBlock() const {
00115     return CachedEHDispatchBlock;
00116   }
00117 
00118   void setCachedEHDispatchBlock(llvm::BasicBlock *block) {
00119     CachedEHDispatchBlock = block;
00120   }
00121 
00122   bool hasEHBranches() const {
00123     if (llvm::BasicBlock *block = getCachedEHDispatchBlock())
00124       return !block->use_empty();
00125     return false;
00126   }
00127 
00128   EHScopeStack::stable_iterator getEnclosingEHScope() const {
00129     return EnclosingEHScope;
00130   }
00131 };
00132 
00133 /// A scope which attempts to handle some, possibly all, types of
00134 /// exceptions.
00135 ///
00136 /// Objective C \@finally blocks are represented using a cleanup scope
00137 /// after the catch scope.
00138 class EHCatchScope : public EHScope {
00139   // In effect, we have a flexible array member
00140   //   Handler Handlers[0];
00141   // But that's only standard in C99, not C++, so we have to do
00142   // annoying pointer arithmetic instead.
00143 
00144 public:
00145   struct Handler {
00146     /// A type info value, or null (C++ null, not an LLVM null pointer)
00147     /// for a catch-all.
00148     llvm::Constant *Type;
00149 
00150     /// The catch handler for this type.
00151     llvm::BasicBlock *Block;
00152 
00153     bool isCatchAll() const { return Type == nullptr; }
00154   };
00155 
00156 private:
00157   friend class EHScopeStack;
00158 
00159   Handler *getHandlers() {
00160     return reinterpret_cast<Handler*>(this+1);
00161   }
00162 
00163   const Handler *getHandlers() const {
00164     return reinterpret_cast<const Handler*>(this+1);
00165   }
00166 
00167 public:
00168   static size_t getSizeForNumHandlers(unsigned N) {
00169     return sizeof(EHCatchScope) + N * sizeof(Handler);
00170   }
00171 
00172   EHCatchScope(unsigned numHandlers,
00173                EHScopeStack::stable_iterator enclosingEHScope)
00174     : EHScope(Catch, enclosingEHScope) {
00175     CatchBits.NumHandlers = numHandlers;
00176   }
00177 
00178   unsigned getNumHandlers() const {
00179     return CatchBits.NumHandlers;
00180   }
00181 
00182   void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block) {
00183     setHandler(I, /*catchall*/ nullptr, Block);
00184   }
00185 
00186   void setHandler(unsigned I, llvm::Constant *Type, llvm::BasicBlock *Block) {
00187     assert(I < getNumHandlers());
00188     getHandlers()[I].Type = Type;
00189     getHandlers()[I].Block = Block;
00190   }
00191 
00192   const Handler &getHandler(unsigned I) const {
00193     assert(I < getNumHandlers());
00194     return getHandlers()[I];
00195   }
00196 
00197   // Clear all handler blocks.
00198   // FIXME: it's better to always call clearHandlerBlocks in DTOR and have a
00199   // 'takeHandler' or some such function which removes ownership from the
00200   // EHCatchScope object if the handlers should live longer than EHCatchScope.
00201   void clearHandlerBlocks() {
00202     for (unsigned I = 0, N = getNumHandlers(); I != N; ++I)
00203       delete getHandler(I).Block;
00204   }
00205 
00206   typedef const Handler *iterator;
00207   iterator begin() const { return getHandlers(); }
00208   iterator end() const { return getHandlers() + getNumHandlers(); }
00209 
00210   static bool classof(const EHScope *Scope) {
00211     return Scope->getKind() == Catch;
00212   }
00213 };
00214 
00215 /// A cleanup scope which generates the cleanup blocks lazily.
00216 class EHCleanupScope : public EHScope {
00217   /// The nearest normal cleanup scope enclosing this one.
00218   EHScopeStack::stable_iterator EnclosingNormal;
00219 
00220   /// The nearest EH scope enclosing this one.
00221   EHScopeStack::stable_iterator EnclosingEH;
00222 
00223   /// The dual entry/exit block along the normal edge.  This is lazily
00224   /// created if needed before the cleanup is popped.
00225   llvm::BasicBlock *NormalBlock;
00226 
00227   /// An optional i1 variable indicating whether this cleanup has been
00228   /// activated yet.
00229   llvm::AllocaInst *ActiveFlag;
00230 
00231   /// Extra information required for cleanups that have resolved
00232   /// branches through them.  This has to be allocated on the side
00233   /// because everything on the cleanup stack has be trivially
00234   /// movable.
00235   struct ExtInfo {
00236     /// The destinations of normal branch-afters and branch-throughs.
00237     llvm::SmallPtrSet<llvm::BasicBlock*, 4> Branches;
00238 
00239     /// Normal branch-afters.
00240     SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4>
00241       BranchAfters;
00242   };
00243   mutable struct ExtInfo *ExtInfo;
00244 
00245   struct ExtInfo &getExtInfo() {
00246     if (!ExtInfo) ExtInfo = new struct ExtInfo();
00247     return *ExtInfo;
00248   }
00249 
00250   const struct ExtInfo &getExtInfo() const {
00251     if (!ExtInfo) ExtInfo = new struct ExtInfo();
00252     return *ExtInfo;
00253   }
00254 
00255 public:
00256   /// Gets the size required for a lazy cleanup scope with the given
00257   /// cleanup-data requirements.
00258   static size_t getSizeForCleanupSize(size_t Size) {
00259     return sizeof(EHCleanupScope) + Size;
00260   }
00261 
00262   size_t getAllocatedSize() const {
00263     return sizeof(EHCleanupScope) + CleanupBits.CleanupSize;
00264   }
00265 
00266   EHCleanupScope(bool isNormal, bool isEH, bool isActive,
00267                  unsigned cleanupSize, unsigned fixupDepth,
00268                  EHScopeStack::stable_iterator enclosingNormal,
00269                  EHScopeStack::stable_iterator enclosingEH)
00270     : EHScope(EHScope::Cleanup, enclosingEH), EnclosingNormal(enclosingNormal),
00271       NormalBlock(nullptr), ActiveFlag(nullptr), ExtInfo(nullptr) {
00272     CleanupBits.IsNormalCleanup = isNormal;
00273     CleanupBits.IsEHCleanup = isEH;
00274     CleanupBits.IsActive = isActive;
00275     CleanupBits.TestFlagInNormalCleanup = false;
00276     CleanupBits.TestFlagInEHCleanup = false;
00277     CleanupBits.CleanupSize = cleanupSize;
00278     CleanupBits.FixupDepth = fixupDepth;
00279 
00280     assert(CleanupBits.CleanupSize == cleanupSize && "cleanup size overflow");
00281   }
00282 
00283   void Destroy() {
00284     delete ExtInfo;
00285   }
00286   // Objects of EHCleanupScope are not destructed. Use Destroy().
00287   ~EHCleanupScope() LLVM_DELETED_FUNCTION;
00288 
00289   bool isNormalCleanup() const { return CleanupBits.IsNormalCleanup; }
00290   llvm::BasicBlock *getNormalBlock() const { return NormalBlock; }
00291   void setNormalBlock(llvm::BasicBlock *BB) { NormalBlock = BB; }
00292 
00293   bool isEHCleanup() const { return CleanupBits.IsEHCleanup; }
00294   llvm::BasicBlock *getEHBlock() const { return getCachedEHDispatchBlock(); }
00295   void setEHBlock(llvm::BasicBlock *BB) { setCachedEHDispatchBlock(BB); }
00296 
00297   bool isActive() const { return CleanupBits.IsActive; }
00298   void setActive(bool A) { CleanupBits.IsActive = A; }
00299 
00300   llvm::AllocaInst *getActiveFlag() const { return ActiveFlag; }
00301   void setActiveFlag(llvm::AllocaInst *Var) { ActiveFlag = Var; }
00302 
00303   void setTestFlagInNormalCleanup() {
00304     CleanupBits.TestFlagInNormalCleanup = true;
00305   }
00306   bool shouldTestFlagInNormalCleanup() const {
00307     return CleanupBits.TestFlagInNormalCleanup;
00308   }
00309 
00310   void setTestFlagInEHCleanup() {
00311     CleanupBits.TestFlagInEHCleanup = true;
00312   }
00313   bool shouldTestFlagInEHCleanup() const {
00314     return CleanupBits.TestFlagInEHCleanup;
00315   }
00316 
00317   unsigned getFixupDepth() const { return CleanupBits.FixupDepth; }
00318   EHScopeStack::stable_iterator getEnclosingNormalCleanup() const {
00319     return EnclosingNormal;
00320   }
00321 
00322   size_t getCleanupSize() const { return CleanupBits.CleanupSize; }
00323   void *getCleanupBuffer() { return this + 1; }
00324 
00325   EHScopeStack::Cleanup *getCleanup() {
00326     return reinterpret_cast<EHScopeStack::Cleanup*>(getCleanupBuffer());
00327   }
00328 
00329   /// True if this cleanup scope has any branch-afters or branch-throughs.
00330   bool hasBranches() const { return ExtInfo && !ExtInfo->Branches.empty(); }
00331 
00332   /// Add a branch-after to this cleanup scope.  A branch-after is a
00333   /// branch from a point protected by this (normal) cleanup to a
00334   /// point in the normal cleanup scope immediately containing it.
00335   /// For example,
00336   ///   for (;;) { A a; break; }
00337   /// contains a branch-after.
00338   ///
00339   /// Branch-afters each have their own destination out of the
00340   /// cleanup, guaranteed distinct from anything else threaded through
00341   /// it.  Therefore branch-afters usually force a switch after the
00342   /// cleanup.
00343   void addBranchAfter(llvm::ConstantInt *Index,
00344                       llvm::BasicBlock *Block) {
00345     struct ExtInfo &ExtInfo = getExtInfo();
00346     if (ExtInfo.Branches.insert(Block))
00347       ExtInfo.BranchAfters.push_back(std::make_pair(Block, Index));
00348   }
00349 
00350   /// Return the number of unique branch-afters on this scope.
00351   unsigned getNumBranchAfters() const {
00352     return ExtInfo ? ExtInfo->BranchAfters.size() : 0;
00353   }
00354 
00355   llvm::BasicBlock *getBranchAfterBlock(unsigned I) const {
00356     assert(I < getNumBranchAfters());
00357     return ExtInfo->BranchAfters[I].first;
00358   }
00359 
00360   llvm::ConstantInt *getBranchAfterIndex(unsigned I) const {
00361     assert(I < getNumBranchAfters());
00362     return ExtInfo->BranchAfters[I].second;
00363   }
00364 
00365   /// Add a branch-through to this cleanup scope.  A branch-through is
00366   /// a branch from a scope protected by this (normal) cleanup to an
00367   /// enclosing scope other than the immediately-enclosing normal
00368   /// cleanup scope.
00369   ///
00370   /// In the following example, the branch through B's scope is a
00371   /// branch-through, while the branch through A's scope is a
00372   /// branch-after:
00373   ///   for (;;) { A a; B b; break; }
00374   ///
00375   /// All branch-throughs have a common destination out of the
00376   /// cleanup, one possibly shared with the fall-through.  Therefore
00377   /// branch-throughs usually don't force a switch after the cleanup.
00378   ///
00379   /// \return true if the branch-through was new to this scope
00380   bool addBranchThrough(llvm::BasicBlock *Block) {
00381     return getExtInfo().Branches.insert(Block);
00382   }
00383 
00384   /// Determines if this cleanup scope has any branch throughs.
00385   bool hasBranchThroughs() const {
00386     if (!ExtInfo) return false;
00387     return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size());
00388   }
00389 
00390   static bool classof(const EHScope *Scope) {
00391     return (Scope->getKind() == Cleanup);
00392   }
00393 };
00394 
00395 /// An exceptions scope which filters exceptions thrown through it.
00396 /// Only exceptions matching the filter types will be permitted to be
00397 /// thrown.
00398 ///
00399 /// This is used to implement C++ exception specifications.
00400 class EHFilterScope : public EHScope {
00401   // Essentially ends in a flexible array member:
00402   // llvm::Value *FilterTypes[0];
00403 
00404   llvm::Value **getFilters() {
00405     return reinterpret_cast<llvm::Value**>(this+1);
00406   }
00407 
00408   llvm::Value * const *getFilters() const {
00409     return reinterpret_cast<llvm::Value* const *>(this+1);
00410   }
00411 
00412 public:
00413   EHFilterScope(unsigned numFilters)
00414     : EHScope(Filter, EHScopeStack::stable_end()) {
00415     FilterBits.NumFilters = numFilters;
00416   }
00417 
00418   static size_t getSizeForNumFilters(unsigned numFilters) {
00419     return sizeof(EHFilterScope) + numFilters * sizeof(llvm::Value*);
00420   }
00421 
00422   unsigned getNumFilters() const { return FilterBits.NumFilters; }
00423 
00424   void setFilter(unsigned i, llvm::Value *filterValue) {
00425     assert(i < getNumFilters());
00426     getFilters()[i] = filterValue;
00427   }
00428 
00429   llvm::Value *getFilter(unsigned i) const {
00430     assert(i < getNumFilters());
00431     return getFilters()[i];
00432   }
00433 
00434   static bool classof(const EHScope *scope) {
00435     return scope->getKind() == Filter;
00436   }
00437 };
00438 
00439 /// An exceptions scope which calls std::terminate if any exception
00440 /// reaches it.
00441 class EHTerminateScope : public EHScope {
00442 public:
00443   EHTerminateScope(EHScopeStack::stable_iterator enclosingEHScope)
00444     : EHScope(Terminate, enclosingEHScope) {}
00445   static size_t getSize() { return sizeof(EHTerminateScope); }
00446 
00447   static bool classof(const EHScope *scope) {
00448     return scope->getKind() == Terminate;
00449   }
00450 };
00451 
00452 /// A non-stable pointer into the scope stack.
00453 class EHScopeStack::iterator {
00454   char *Ptr;
00455 
00456   friend class EHScopeStack;
00457   explicit iterator(char *Ptr) : Ptr(Ptr) {}
00458 
00459 public:
00460   iterator() : Ptr(nullptr) {}
00461 
00462   EHScope *get() const { 
00463     return reinterpret_cast<EHScope*>(Ptr);
00464   }
00465 
00466   EHScope *operator->() const { return get(); }
00467   EHScope &operator*() const { return *get(); }
00468 
00469   iterator &operator++() {
00470     switch (get()->getKind()) {
00471     case EHScope::Catch:
00472       Ptr += EHCatchScope::getSizeForNumHandlers(
00473           static_cast<const EHCatchScope*>(get())->getNumHandlers());
00474       break;
00475 
00476     case EHScope::Filter:
00477       Ptr += EHFilterScope::getSizeForNumFilters(
00478           static_cast<const EHFilterScope*>(get())->getNumFilters());
00479       break;
00480 
00481     case EHScope::Cleanup:
00482       Ptr += static_cast<const EHCleanupScope*>(get())
00483         ->getAllocatedSize();
00484       break;
00485 
00486     case EHScope::Terminate:
00487       Ptr += EHTerminateScope::getSize();
00488       break;
00489     }
00490 
00491     return *this;
00492   }
00493 
00494   iterator next() {
00495     iterator copy = *this;
00496     ++copy;
00497     return copy;
00498   }
00499 
00500   iterator operator++(int) {
00501     iterator copy = *this;
00502     operator++();
00503     return copy;
00504   }
00505 
00506   bool encloses(iterator other) const { return Ptr >= other.Ptr; }
00507   bool strictlyEncloses(iterator other) const { return Ptr > other.Ptr; }
00508 
00509   bool operator==(iterator other) const { return Ptr == other.Ptr; }
00510   bool operator!=(iterator other) const { return Ptr != other.Ptr; }
00511 };
00512 
00513 inline EHScopeStack::iterator EHScopeStack::begin() const {
00514   return iterator(StartOfData);
00515 }
00516 
00517 inline EHScopeStack::iterator EHScopeStack::end() const {
00518   return iterator(EndOfBuffer);
00519 }
00520 
00521 inline void EHScopeStack::popCatch() {
00522   assert(!empty() && "popping exception stack when not empty");
00523 
00524   EHCatchScope &scope = cast<EHCatchScope>(*begin());
00525   InnermostEHScope = scope.getEnclosingEHScope();
00526   StartOfData += EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers());
00527 }
00528 
00529 inline void EHScopeStack::popTerminate() {
00530   assert(!empty() && "popping exception stack when not empty");
00531 
00532   EHTerminateScope &scope = cast<EHTerminateScope>(*begin());
00533   InnermostEHScope = scope.getEnclosingEHScope();
00534   StartOfData += EHTerminateScope::getSize();
00535 }
00536 
00537 inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const {
00538   assert(sp.isValid() && "finding invalid savepoint");
00539   assert(sp.Size <= stable_begin().Size && "finding savepoint after pop");
00540   return iterator(EndOfBuffer - sp.Size);
00541 }
00542 
00543 inline EHScopeStack::stable_iterator
00544 EHScopeStack::stabilize(iterator ir) const {
00545   assert(StartOfData <= ir.Ptr && ir.Ptr <= EndOfBuffer);
00546   return stable_iterator(EndOfBuffer - ir.Ptr);
00547 }
00548 
00549 }
00550 }
00551 
00552 #endif