Home | History | Annotate | Download | only in AST
      1 //===--- ExternalASTSource.h - Abstract External AST Interface --*- 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 //  This file defines the ExternalASTSource interface, which enables
     11 //  construction of AST nodes from some external source.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 #ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
     15 #define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
     16 
     17 #include "clang/AST/DeclBase.h"
     18 #include <cassert>
     19 
     20 namespace llvm {
     21 template <class T> class SmallVectorImpl;
     22 }
     23 
     24 namespace clang {
     25 
     26 class ASTConsumer;
     27 class CXXBaseSpecifier;
     28 class DeclarationName;
     29 class ExternalSemaSource; // layering violation required for downcasting
     30 class NamedDecl;
     31 class Selector;
     32 class Stmt;
     33 class TagDecl;
     34 
     35 /// \brief Enumeration describing the result of loading information from
     36 /// an external source.
     37 enum ExternalLoadResult {
     38   /// \brief Loading the external information has succeeded.
     39   ELR_Success,
     40 
     41   /// \brief Loading the external information has failed.
     42   ELR_Failure,
     43 
     44   /// \brief The external information has already been loaded, and therefore
     45   /// no additional processing is required.
     46   ELR_AlreadyLoaded
     47 };
     48 
     49 /// \brief Abstract interface for external sources of AST nodes.
     50 ///
     51 /// External AST sources provide AST nodes constructed from some
     52 /// external source, such as a precompiled header. External AST
     53 /// sources can resolve types and declarations from abstract IDs into
     54 /// actual type and declaration nodes, and read parts of declaration
     55 /// contexts.
     56 class ExternalASTSource {
     57   /// \brief Whether this AST source also provides information for
     58   /// semantic analysis.
     59   bool SemaSource;
     60 
     61   friend class ExternalSemaSource;
     62 
     63 public:
     64   ExternalASTSource() : SemaSource(false) { }
     65 
     66   virtual ~ExternalASTSource();
     67 
     68   /// \brief RAII class for safely pairing a StartedDeserializing call
     69   /// with FinishedDeserializing.
     70   class Deserializing {
     71     ExternalASTSource *Source;
     72   public:
     73     explicit Deserializing(ExternalASTSource *source) : Source(source) {
     74       assert(Source);
     75       Source->StartedDeserializing();
     76     }
     77     ~Deserializing() {
     78       Source->FinishedDeserializing();
     79     }
     80   };
     81 
     82   /// \brief Resolve a declaration ID into a declaration, potentially
     83   /// building a new declaration.
     84   ///
     85   /// This method only needs to be implemented if the AST source ever
     86   /// passes back decl sets as VisibleDeclaration objects.
     87   ///
     88   /// The default implementation of this method is a no-op.
     89   virtual Decl *GetExternalDecl(uint32_t ID);
     90 
     91   /// \brief Resolve a selector ID into a selector.
     92   ///
     93   /// This operation only needs to be implemented if the AST source
     94   /// returns non-zero for GetNumKnownSelectors().
     95   ///
     96   /// The default implementation of this method is a no-op.
     97   virtual Selector GetExternalSelector(uint32_t ID);
     98 
     99   /// \brief Returns the number of selectors known to the external AST
    100   /// source.
    101   ///
    102   /// The default implementation of this method is a no-op.
    103   virtual uint32_t GetNumExternalSelectors();
    104 
    105   /// \brief Resolve the offset of a statement in the decl stream into
    106   /// a statement.
    107   ///
    108   /// This operation is meant to be used via a LazyOffsetPtr.  It only
    109   /// needs to be implemented if the AST source uses methods like
    110   /// FunctionDecl::setLazyBody when building decls.
    111   ///
    112   /// The default implementation of this method is a no-op.
    113   virtual Stmt *GetExternalDeclStmt(uint64_t Offset);
    114 
    115   /// \brief Resolve the offset of a set of C++ base specifiers in the decl
    116   /// stream into an array of specifiers.
    117   ///
    118   /// The default implementation of this method is a no-op.
    119   virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
    120 
    121   /// \brief Finds all declarations with the given name in the
    122   /// given context.
    123   ///
    124   /// Generally the final step of this method is either to call
    125   /// SetExternalVisibleDeclsForName or to recursively call lookup on
    126   /// the DeclContext after calling SetExternalVisibleDecls.
    127   ///
    128   /// The default implementation of this method is a no-op.
    129   virtual DeclContextLookupResult
    130   FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
    131 
    132   /// \brief Deserialize all the visible declarations from external storage.
    133   ///
    134   /// Name lookup deserializes visible declarations lazily, thus a DeclContext
    135   /// may not have a complete name lookup table. This function deserializes
    136   /// the rest of visible declarations from the external storage and completes
    137   /// the name lookup table of the DeclContext.
    138   ///
    139   /// The default implementation of this method is a no-op.
    140   virtual void MaterializeVisibleDecls(const DeclContext *DC);
    141 
    142   /// \brief Finds all declarations lexically contained within the given
    143   /// DeclContext, after applying an optional filter predicate.
    144   ///
    145   /// \param isKindWeWant a predicate function that returns true if the passed
    146   /// declaration kind is one we are looking for. If NULL, all declarations
    147   /// are returned.
    148   ///
    149   /// \return an indication of whether the load succeeded or failed.
    150   ///
    151   /// The default implementation of this method is a no-op.
    152   virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
    153                                         bool (*isKindWeWant)(Decl::Kind),
    154                                         llvm::SmallVectorImpl<Decl*> &Result);
    155 
    156   /// \brief Finds all declarations lexically contained within the given
    157   /// DeclContext.
    158   ///
    159   /// \return true if an error occurred
    160   ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
    161                                 llvm::SmallVectorImpl<Decl*> &Result) {
    162     return FindExternalLexicalDecls(DC, 0, Result);
    163   }
    164 
    165   template <typename DeclTy>
    166   ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC,
    167                                   llvm::SmallVectorImpl<Decl*> &Result) {
    168     return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result);
    169   }
    170 
    171   /// \brief Gives the external AST source an opportunity to complete
    172   /// an incomplete type.
    173   virtual void CompleteType(TagDecl *Tag) {}
    174 
    175   /// \brief Gives the external AST source an opportunity to complete an
    176   /// incomplete Objective-C class.
    177   ///
    178   /// This routine will only be invoked if the "externally completed" bit is
    179   /// set on the ObjCInterfaceDecl via the function
    180   /// \c ObjCInterfaceDecl::setExternallyCompleted().
    181   virtual void CompleteType(ObjCInterfaceDecl *Class) { }
    182 
    183   /// \brief Notify ExternalASTSource that we started deserialization of
    184   /// a decl or type so until FinishedDeserializing is called there may be
    185   /// decls that are initializing. Must be paired with FinishedDeserializing.
    186   ///
    187   /// The default implementation of this method is a no-op.
    188   virtual void StartedDeserializing() { }
    189 
    190   /// \brief Notify ExternalASTSource that we finished the deserialization of
    191   /// a decl or type. Must be paired with StartedDeserializing.
    192   ///
    193   /// The default implementation of this method is a no-op.
    194   virtual void FinishedDeserializing() { }
    195 
    196   /// \brief Function that will be invoked when we begin parsing a new
    197   /// translation unit involving this external AST source.
    198   ///
    199   /// The default implementation of this method is a no-op.
    200   virtual void StartTranslationUnit(ASTConsumer *Consumer) { }
    201 
    202   /// \brief Print any statistics that have been gathered regarding
    203   /// the external AST source.
    204   ///
    205   /// The default implementation of this method is a no-op.
    206   virtual void PrintStats();
    207 
    208   //===--------------------------------------------------------------------===//
    209   // Queries for performance analysis.
    210   //===--------------------------------------------------------------------===//
    211 
    212   struct MemoryBufferSizes {
    213     size_t malloc_bytes;
    214     size_t mmap_bytes;
    215 
    216     MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes)
    217     : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
    218   };
    219 
    220   /// Return the amount of memory used by memory buffers, breaking down
    221   /// by heap-backed versus mmap'ed memory.
    222   MemoryBufferSizes getMemoryBufferSizes() const {
    223     MemoryBufferSizes sizes(0, 0);
    224     getMemoryBufferSizes(sizes);
    225     return sizes;
    226   }
    227 
    228   virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const;
    229 
    230 protected:
    231   static DeclContextLookupResult
    232   SetExternalVisibleDeclsForName(const DeclContext *DC,
    233                                  DeclarationName Name,
    234                                  llvm::SmallVectorImpl<NamedDecl*> &Decls);
    235 
    236   static DeclContextLookupResult
    237   SetNoExternalVisibleDeclsForName(const DeclContext *DC,
    238                                    DeclarationName Name);
    239 
    240   void MaterializeVisibleDeclsForName(const DeclContext *DC,
    241                                       DeclarationName Name,
    242                                  llvm::SmallVectorImpl<NamedDecl*> &Decls);
    243 };
    244 
    245 /// \brief A lazy pointer to an AST node (of base type T) that resides
    246 /// within an external AST source.
    247 ///
    248 /// The AST node is identified within the external AST source by a
    249 /// 63-bit offset, and can be retrieved via an operation on the
    250 /// external AST source itself.
    251 template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)>
    252 struct LazyOffsetPtr {
    253   /// \brief Either a pointer to an AST node or the offset within the
    254   /// external AST source where the AST node can be found.
    255   ///
    256   /// If the low bit is clear, a pointer to the AST node. If the low
    257   /// bit is set, the upper 63 bits are the offset.
    258   mutable uint64_t Ptr;
    259 
    260 public:
    261   LazyOffsetPtr() : Ptr(0) { }
    262 
    263   explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { }
    264   explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) {
    265     assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
    266     if (Offset == 0)
    267       Ptr = 0;
    268   }
    269 
    270   LazyOffsetPtr &operator=(T *Ptr) {
    271     this->Ptr = reinterpret_cast<uint64_t>(Ptr);
    272     return *this;
    273   }
    274 
    275   LazyOffsetPtr &operator=(uint64_t Offset) {
    276     assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
    277     if (Offset == 0)
    278       Ptr = 0;
    279     else
    280       Ptr = (Offset << 1) | 0x01;
    281 
    282     return *this;
    283   }
    284 
    285   /// \brief Whether this pointer is non-NULL.
    286   ///
    287   /// This operation does not require the AST node to be deserialized.
    288   operator bool() const { return Ptr != 0; }
    289 
    290   /// \brief Whether this pointer is currently stored as an offset.
    291   bool isOffset() const { return Ptr & 0x01; }
    292 
    293   /// \brief Retrieve the pointer to the AST node that this lazy pointer
    294   ///
    295   /// \param Source the external AST source.
    296   ///
    297   /// \returns a pointer to the AST node.
    298   T* get(ExternalASTSource *Source) const {
    299     if (isOffset()) {
    300       assert(Source &&
    301              "Cannot deserialize a lazy pointer without an AST source");
    302       Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1));
    303     }
    304     return reinterpret_cast<T*>(Ptr);
    305   }
    306 };
    307 
    308 /// \brief A lazy pointer to a statement.
    309 typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
    310   LazyDeclStmtPtr;
    311 
    312 /// \brief A lazy pointer to a declaration.
    313 typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
    314   LazyDeclPtr;
    315 
    316 /// \brief A lazy pointer to a set of CXXBaseSpecifiers.
    317 typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
    318                       &ExternalASTSource::GetExternalCXXBaseSpecifiers>
    319   LazyCXXBaseSpecifiersPtr;
    320 
    321 } // end namespace clang
    322 
    323 #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
    324