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: ExternalASTSource()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: Deserializing(ExternalASTSource * source)73 explicit Deserializing(ExternalASTSource *source) : Source(source) { 74 assert(Source); 75 Source->StartedDeserializing(); 76 } ~Deserializing()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. updateOutOfDateIdentifier(IdentifierInfo & II)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. getModule(unsigned 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 FindExternalLexicalDecls(const DeclContext * DC,SmallVectorImpl<Decl * > & Result)161 ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, 162 SmallVectorImpl<Decl*> &Result) { 163 return FindExternalLexicalDecls(DC, 0, Result); 164 } 165 166 template <typename DeclTy> FindExternalLexicalDeclsBy(const DeclContext * DC,SmallVectorImpl<Decl * > & Result)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. FindFileRegionDecls(FileID File,unsigned Offset,unsigned Length,SmallVectorImpl<Decl * > & Decls)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. CompleteType(TagDecl * Tag)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(). CompleteType(ObjCInterfaceDecl * Class)188 virtual void CompleteType(ObjCInterfaceDecl *Class) { } 189 190 /// \brief Loads comment ranges. ReadComments()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. StartedDeserializing()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. FinishedDeserializing()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. StartTranslationUnit(ASTConsumer * Consumer)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 layoutRecordType(const RecordDecl * Record,uint64_t & Size,uint64_t & Alignment,llvm::DenseMap<const FieldDecl *,uint64_t> & FieldOffsets,llvm::DenseMap<const CXXRecordDecl *,CharUnits> & BaseOffsets,llvm::DenseMap<const CXXRecordDecl *,CharUnits> & VirtualBaseOffsets)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 MemoryBufferSizesMemoryBufferSizes264 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. getMemoryBufferSizes()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: LazyOffsetPtrLazyOffsetPtr305 LazyOffsetPtr() : Ptr(0) { } 306 LazyOffsetPtrLazyOffsetPtr307 explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { } LazyOffsetPtrLazyOffsetPtr308 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. isOffsetLazyOffsetPtr335 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. getLazyOffsetPtr342 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 iterator()393 iterator() : Self(0), Position(0) { } 394 iterator(LazyVector * Self,int Position)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 end()501 iterator end() { 502 return iterator(this, Local.size()); 503 } 504 push_back(const T & LocalValue)505 void push_back(const T& LocalValue) { 506 Local.push_back(LocalValue); 507 } 508 erase(iterator From,iterator To)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