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/CharUnits.h"
     18 #include "clang/AST/DeclBase.h"
     19 #include "llvm/ADT/DenseMap.h"
     20 
     21 namespace clang {
     22 
     23 class ASTConsumer;
     24 class CXXBaseSpecifier;
     25 class DeclarationName;
     26 class ExternalSemaSource; // layering violation required for downcasting
     27 class FieldDecl;
     28 class Module;
     29 class NamedDecl;
     30 class RecordDecl;
     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 Update an out-of-date identifier.
    122   virtual void updateOutOfDateIdentifier(IdentifierInfo &II) { }
    123 
    124   /// \brief Find all declarations with the given name in the given context,
    125   /// and add them to the context by calling SetExternalVisibleDeclsForName
    126   /// or SetNoExternalVisibleDeclsForName.
    127   /// \return \c true if any declarations might have been found, \c false if
    128   /// we definitely have no declarations with tbis name.
    129   ///
    130   /// The default implementation of this method is a no-op returning \c false.
    131   virtual bool
    132   FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
    133 
    134   /// \brief Ensures that the table of all visible declarations inside this
    135   /// context is up to date.
    136   ///
    137   /// The default implementation of this function is a no-op.
    138   virtual void completeVisibleDeclsMap(const DeclContext *DC);
    139 
    140   /// \brief Retrieve the module that corresponds to the given module ID.
    141   virtual Module *getModule(unsigned ID) { return 0; }
    142 
    143   /// \brief Finds all declarations lexically contained within the given
    144   /// DeclContext, after applying an optional filter predicate.
    145   ///
    146   /// \param isKindWeWant a predicate function that returns true if the passed
    147   /// declaration kind is one we are looking for. If NULL, all declarations
    148   /// are returned.
    149   ///
    150   /// \return an indication of whether the load succeeded or failed.
    151   ///
    152   /// The default implementation of this method is a no-op.
    153   virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
    154                                         bool (*isKindWeWant)(Decl::Kind),
    155                                         SmallVectorImpl<Decl*> &Result);
    156 
    157   /// \brief Finds all declarations lexically contained within the given
    158   /// DeclContext.
    159   ///
    160   /// \return true if an error occurred
    161   ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
    162                                 SmallVectorImpl<Decl*> &Result) {
    163     return FindExternalLexicalDecls(DC, 0, Result);
    164   }
    165 
    166   template <typename DeclTy>
    167   ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC,
    168                                   SmallVectorImpl<Decl*> &Result) {
    169     return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result);
    170   }
    171 
    172   /// \brief Get the decls that are contained in a file in the Offset/Length
    173   /// range. \p Length can be 0 to indicate a point at \p Offset instead of
    174   /// a range.
    175   virtual void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length,
    176                                    SmallVectorImpl<Decl *> &Decls) {}
    177 
    178   /// \brief Gives the external AST source an opportunity to complete
    179   /// an incomplete type.
    180   virtual void CompleteType(TagDecl *Tag) {}
    181 
    182   /// \brief Gives the external AST source an opportunity to complete an
    183   /// incomplete Objective-C class.
    184   ///
    185   /// This routine will only be invoked if the "externally completed" bit is
    186   /// set on the ObjCInterfaceDecl via the function
    187   /// \c ObjCInterfaceDecl::setExternallyCompleted().
    188   virtual void CompleteType(ObjCInterfaceDecl *Class) { }
    189 
    190   /// \brief Loads comment ranges.
    191   virtual void ReadComments() { }
    192 
    193   /// \brief Notify ExternalASTSource that we started deserialization of
    194   /// a decl or type so until FinishedDeserializing is called there may be
    195   /// decls that are initializing. Must be paired with FinishedDeserializing.
    196   ///
    197   /// The default implementation of this method is a no-op.
    198   virtual void StartedDeserializing() { }
    199 
    200   /// \brief Notify ExternalASTSource that we finished the deserialization of
    201   /// a decl or type. Must be paired with StartedDeserializing.
    202   ///
    203   /// The default implementation of this method is a no-op.
    204   virtual void FinishedDeserializing() { }
    205 
    206   /// \brief Function that will be invoked when we begin parsing a new
    207   /// translation unit involving this external AST source.
    208   ///
    209   /// The default implementation of this method is a no-op.
    210   virtual void StartTranslationUnit(ASTConsumer *Consumer) { }
    211 
    212   /// \brief Print any statistics that have been gathered regarding
    213   /// the external AST source.
    214   ///
    215   /// The default implementation of this method is a no-op.
    216   virtual void PrintStats();
    217 
    218 
    219   /// \brief Perform layout on the given record.
    220   ///
    221   /// This routine allows the external AST source to provide an specific
    222   /// layout for a record, overriding the layout that would normally be
    223   /// constructed. It is intended for clients who receive specific layout
    224   /// details rather than source code (such as LLDB). The client is expected
    225   /// to fill in the field offsets, base offsets, virtual base offsets, and
    226   /// complete object size.
    227   ///
    228   /// \param Record The record whose layout is being requested.
    229   ///
    230   /// \param Size The final size of the record, in bits.
    231   ///
    232   /// \param Alignment The final alignment of the record, in bits.
    233   ///
    234   /// \param FieldOffsets The offset of each of the fields within the record,
    235   /// expressed in bits. All of the fields must be provided with offsets.
    236   ///
    237   /// \param BaseOffsets The offset of each of the direct, non-virtual base
    238   /// classes. If any bases are not given offsets, the bases will be laid
    239   /// out according to the ABI.
    240   ///
    241   /// \param VirtualBaseOffsets The offset of each of the virtual base classes
    242   /// (either direct or not). If any bases are not given offsets, the bases will be laid
    243   /// out according to the ABI.
    244   ///
    245   /// \returns true if the record layout was provided, false otherwise.
    246   virtual bool
    247   layoutRecordType(const RecordDecl *Record,
    248                    uint64_t &Size, uint64_t &Alignment,
    249                    llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
    250                  llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
    251           llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets)
    252   {
    253     return false;
    254   }
    255 
    256   //===--------------------------------------------------------------------===//
    257   // Queries for performance analysis.
    258   //===--------------------------------------------------------------------===//
    259 
    260   struct MemoryBufferSizes {
    261     size_t malloc_bytes;
    262     size_t mmap_bytes;
    263 
    264     MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes)
    265     : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
    266   };
    267 
    268   /// Return the amount of memory used by memory buffers, breaking down
    269   /// by heap-backed versus mmap'ed memory.
    270   MemoryBufferSizes getMemoryBufferSizes() const {
    271     MemoryBufferSizes sizes(0, 0);
    272     getMemoryBufferSizes(sizes);
    273     return sizes;
    274   }
    275 
    276   virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const;
    277 
    278 protected:
    279   static DeclContextLookupResult
    280   SetExternalVisibleDeclsForName(const DeclContext *DC,
    281                                  DeclarationName Name,
    282                                  ArrayRef<NamedDecl*> Decls);
    283 
    284   static DeclContextLookupResult
    285   SetNoExternalVisibleDeclsForName(const DeclContext *DC,
    286                                    DeclarationName Name);
    287 };
    288 
    289 /// \brief A lazy pointer to an AST node (of base type T) that resides
    290 /// within an external AST source.
    291 ///
    292 /// The AST node is identified within the external AST source by a
    293 /// 63-bit offset, and can be retrieved via an operation on the
    294 /// external AST source itself.
    295 template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)>
    296 struct LazyOffsetPtr {
    297   /// \brief Either a pointer to an AST node or the offset within the
    298   /// external AST source where the AST node can be found.
    299   ///
    300   /// If the low bit is clear, a pointer to the AST node. If the low
    301   /// bit is set, the upper 63 bits are the offset.
    302   mutable uint64_t Ptr;
    303 
    304 public:
    305   LazyOffsetPtr() : Ptr(0) { }
    306 
    307   explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { }
    308   explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) {
    309     assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
    310     if (Offset == 0)
    311       Ptr = 0;
    312   }
    313 
    314   LazyOffsetPtr &operator=(T *Ptr) {
    315     this->Ptr = reinterpret_cast<uint64_t>(Ptr);
    316     return *this;
    317   }
    318 
    319   LazyOffsetPtr &operator=(uint64_t Offset) {
    320     assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
    321     if (Offset == 0)
    322       Ptr = 0;
    323     else
    324       Ptr = (Offset << 1) | 0x01;
    325 
    326     return *this;
    327   }
    328 
    329   /// \brief Whether this pointer is non-NULL.
    330   ///
    331   /// This operation does not require the AST node to be deserialized.
    332   operator bool() const { return Ptr != 0; }
    333 
    334   /// \brief Whether this pointer is currently stored as an offset.
    335   bool isOffset() const { return Ptr & 0x01; }
    336 
    337   /// \brief Retrieve the pointer to the AST node that this lazy pointer
    338   ///
    339   /// \param Source the external AST source.
    340   ///
    341   /// \returns a pointer to the AST node.
    342   T* get(ExternalASTSource *Source) const {
    343     if (isOffset()) {
    344       assert(Source &&
    345              "Cannot deserialize a lazy pointer without an AST source");
    346       Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1));
    347     }
    348     return reinterpret_cast<T*>(Ptr);
    349   }
    350 };
    351 
    352 /// \brief Represents a lazily-loaded vector of data.
    353 ///
    354 /// The lazily-loaded vector of data contains data that is partially loaded
    355 /// from an external source and partially added by local translation. The
    356 /// items loaded from the external source are loaded lazily, when needed for
    357 /// iteration over the complete vector.
    358 template<typename T, typename Source,
    359          void (Source::*Loader)(SmallVectorImpl<T>&),
    360          unsigned LoadedStorage = 2, unsigned LocalStorage = 4>
    361 class LazyVector {
    362   SmallVector<T, LoadedStorage> Loaded;
    363   SmallVector<T, LocalStorage> Local;
    364 
    365 public:
    366   // Iteration over the elements in the vector.
    367   class iterator {
    368     LazyVector *Self;
    369 
    370     /// \brief Position within the vector..
    371     ///
    372     /// In a complete iteration, the Position field walks the range [-M, N),
    373     /// where negative values are used to indicate elements
    374     /// loaded from the external source while non-negative values are used to
    375     /// indicate elements added via \c push_back().
    376     /// However, to provide iteration in source order (for, e.g., chained
    377     /// precompiled headers), dereferencing the iterator flips the negative
    378     /// values (corresponding to loaded entities), so that position -M
    379     /// corresponds to element 0 in the loaded entities vector, position -M+1
    380     /// corresponds to element 1 in the loaded entities vector, etc. This
    381     /// gives us a reasonably efficient, source-order walk.
    382     int Position;
    383 
    384     friend class LazyVector;
    385 
    386   public:
    387     typedef T                   value_type;
    388     typedef value_type&         reference;
    389     typedef value_type*         pointer;
    390     typedef std::random_access_iterator_tag iterator_category;
    391     typedef int                 difference_type;
    392 
    393     iterator() : Self(0), Position(0) { }
    394 
    395     iterator(LazyVector *Self, int Position)
    396       : Self(Self), Position(Position) { }
    397 
    398     reference operator*() const {
    399       if (Position < 0)
    400         return Self->Loaded.end()[Position];
    401       return Self->Local[Position];
    402     }
    403 
    404     pointer operator->() const {
    405       if (Position < 0)
    406         return &Self->Loaded.end()[Position];
    407 
    408       return &Self->Local[Position];
    409     }
    410 
    411     reference operator[](difference_type D) {
    412       return *(*this + D);
    413     }
    414 
    415     iterator &operator++() {
    416       ++Position;
    417       return *this;
    418     }
    419 
    420     iterator operator++(int) {
    421       iterator Prev(*this);
    422       ++Position;
    423       return Prev;
    424     }
    425 
    426     iterator &operator--() {
    427       --Position;
    428       return *this;
    429     }
    430 
    431     iterator operator--(int) {
    432       iterator Prev(*this);
    433       --Position;
    434       return Prev;
    435     }
    436 
    437     friend bool operator==(const iterator &X, const iterator &Y) {
    438       return X.Position == Y.Position;
    439     }
    440 
    441     friend bool operator!=(const iterator &X, const iterator &Y) {
    442       return X.Position != Y.Position;
    443     }
    444 
    445     friend bool operator<(const iterator &X, const iterator &Y) {
    446       return X.Position < Y.Position;
    447     }
    448 
    449     friend bool operator>(const iterator &X, const iterator &Y) {
    450       return X.Position > Y.Position;
    451     }
    452 
    453     friend bool operator<=(const iterator &X, const iterator &Y) {
    454       return X.Position < Y.Position;
    455     }
    456 
    457     friend bool operator>=(const iterator &X, const iterator &Y) {
    458       return X.Position > Y.Position;
    459     }
    460 
    461     friend iterator& operator+=(iterator &X, difference_type D) {
    462       X.Position += D;
    463       return X;
    464     }
    465 
    466     friend iterator& operator-=(iterator &X, difference_type D) {
    467       X.Position -= D;
    468       return X;
    469     }
    470 
    471     friend iterator operator+(iterator X, difference_type D) {
    472       X.Position += D;
    473       return X;
    474     }
    475 
    476     friend iterator operator+(difference_type D, iterator X) {
    477       X.Position += D;
    478       return X;
    479     }
    480 
    481     friend difference_type operator-(const iterator &X, const iterator &Y) {
    482       return X.Position - Y.Position;
    483     }
    484 
    485     friend iterator operator-(iterator X, difference_type D) {
    486       X.Position -= D;
    487       return X;
    488     }
    489   };
    490   friend class iterator;
    491 
    492   iterator begin(Source *source, bool LocalOnly = false) {
    493     if (LocalOnly)
    494       return iterator(this, 0);
    495 
    496     if (source)
    497       (source->*Loader)(Loaded);
    498     return iterator(this, -(int)Loaded.size());
    499   }
    500 
    501   iterator end() {
    502     return iterator(this, Local.size());
    503   }
    504 
    505   void push_back(const T& LocalValue) {
    506     Local.push_back(LocalValue);
    507   }
    508 
    509   void erase(iterator From, iterator To) {
    510     if (From.Position < 0 && To.Position < 0) {
    511       Loaded.erase(Loaded.end() + From.Position, Loaded.end() + To.Position);
    512       return;
    513     }
    514 
    515     if (From.Position < 0) {
    516       Loaded.erase(Loaded.end() + From.Position, Loaded.end());
    517       From = begin(0, true);
    518     }
    519 
    520     Local.erase(Local.begin() + From.Position, Local.begin() + To.Position);
    521   }
    522 };
    523 
    524 /// \brief A lazy pointer to a statement.
    525 typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
    526   LazyDeclStmtPtr;
    527 
    528 /// \brief A lazy pointer to a declaration.
    529 typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
    530   LazyDeclPtr;
    531 
    532 /// \brief A lazy pointer to a set of CXXBaseSpecifiers.
    533 typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
    534                       &ExternalASTSource::GetExternalCXXBaseSpecifiers>
    535   LazyCXXBaseSpecifiersPtr;
    536 
    537 } // end namespace clang
    538 
    539 #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
    540