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 LLVM_EXPLICIT operator bool() const { return Ptr != 0; } 333 334 /// \brief Whether this pointer is non-NULL. 335 /// 336 /// This operation does not require the AST node to be deserialized. isValidLazyOffsetPtr337 bool isValid() const { return Ptr != 0; } 338 339 /// \brief Whether this pointer is currently stored as an offset. isOffsetLazyOffsetPtr340 bool isOffset() const { return Ptr & 0x01; } 341 342 /// \brief Retrieve the pointer to the AST node that this lazy pointer 343 /// 344 /// \param Source the external AST source. 345 /// 346 /// \returns a pointer to the AST node. getLazyOffsetPtr347 T* get(ExternalASTSource *Source) const { 348 if (isOffset()) { 349 assert(Source && 350 "Cannot deserialize a lazy pointer without an AST source"); 351 Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1)); 352 } 353 return reinterpret_cast<T*>(Ptr); 354 } 355 }; 356 357 /// \brief Represents a lazily-loaded vector of data. 358 /// 359 /// The lazily-loaded vector of data contains data that is partially loaded 360 /// from an external source and partially added by local translation. The 361 /// items loaded from the external source are loaded lazily, when needed for 362 /// iteration over the complete vector. 363 template<typename T, typename Source, 364 void (Source::*Loader)(SmallVectorImpl<T>&), 365 unsigned LoadedStorage = 2, unsigned LocalStorage = 4> 366 class LazyVector { 367 SmallVector<T, LoadedStorage> Loaded; 368 SmallVector<T, LocalStorage> Local; 369 370 public: 371 // Iteration over the elements in the vector. 372 class iterator { 373 LazyVector *Self; 374 375 /// \brief Position within the vector.. 376 /// 377 /// In a complete iteration, the Position field walks the range [-M, N), 378 /// where negative values are used to indicate elements 379 /// loaded from the external source while non-negative values are used to 380 /// indicate elements added via \c push_back(). 381 /// However, to provide iteration in source order (for, e.g., chained 382 /// precompiled headers), dereferencing the iterator flips the negative 383 /// values (corresponding to loaded entities), so that position -M 384 /// corresponds to element 0 in the loaded entities vector, position -M+1 385 /// corresponds to element 1 in the loaded entities vector, etc. This 386 /// gives us a reasonably efficient, source-order walk. 387 int Position; 388 389 friend class LazyVector; 390 391 public: 392 typedef T value_type; 393 typedef value_type& reference; 394 typedef value_type* pointer; 395 typedef std::random_access_iterator_tag iterator_category; 396 typedef int difference_type; 397 iterator()398 iterator() : Self(0), Position(0) { } 399 iterator(LazyVector * Self,int Position)400 iterator(LazyVector *Self, int Position) 401 : Self(Self), Position(Position) { } 402 403 reference operator*() const { 404 if (Position < 0) 405 return Self->Loaded.end()[Position]; 406 return Self->Local[Position]; 407 } 408 409 pointer operator->() const { 410 if (Position < 0) 411 return &Self->Loaded.end()[Position]; 412 413 return &Self->Local[Position]; 414 } 415 416 reference operator[](difference_type D) { 417 return *(*this + D); 418 } 419 420 iterator &operator++() { 421 ++Position; 422 return *this; 423 } 424 425 iterator operator++(int) { 426 iterator Prev(*this); 427 ++Position; 428 return Prev; 429 } 430 431 iterator &operator--() { 432 --Position; 433 return *this; 434 } 435 436 iterator operator--(int) { 437 iterator Prev(*this); 438 --Position; 439 return Prev; 440 } 441 442 friend bool operator==(const iterator &X, const iterator &Y) { 443 return X.Position == Y.Position; 444 } 445 446 friend bool operator!=(const iterator &X, const iterator &Y) { 447 return X.Position != Y.Position; 448 } 449 450 friend bool operator<(const iterator &X, const iterator &Y) { 451 return X.Position < Y.Position; 452 } 453 454 friend bool operator>(const iterator &X, const iterator &Y) { 455 return X.Position > Y.Position; 456 } 457 458 friend bool operator<=(const iterator &X, const iterator &Y) { 459 return X.Position < Y.Position; 460 } 461 462 friend bool operator>=(const iterator &X, const iterator &Y) { 463 return X.Position > Y.Position; 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+(iterator X, difference_type D) { 477 X.Position += D; 478 return X; 479 } 480 481 friend iterator operator+(difference_type D, iterator X) { 482 X.Position += D; 483 return X; 484 } 485 486 friend difference_type operator-(const iterator &X, const iterator &Y) { 487 return X.Position - Y.Position; 488 } 489 490 friend iterator operator-(iterator X, difference_type D) { 491 X.Position -= D; 492 return X; 493 } 494 }; 495 friend class iterator; 496 497 iterator begin(Source *source, bool LocalOnly = false) { 498 if (LocalOnly) 499 return iterator(this, 0); 500 501 if (source) 502 (source->*Loader)(Loaded); 503 return iterator(this, -(int)Loaded.size()); 504 } 505 end()506 iterator end() { 507 return iterator(this, Local.size()); 508 } 509 push_back(const T & LocalValue)510 void push_back(const T& LocalValue) { 511 Local.push_back(LocalValue); 512 } 513 erase(iterator From,iterator To)514 void erase(iterator From, iterator To) { 515 if (From.Position < 0 && To.Position < 0) { 516 Loaded.erase(Loaded.end() + From.Position, Loaded.end() + To.Position); 517 return; 518 } 519 520 if (From.Position < 0) { 521 Loaded.erase(Loaded.end() + From.Position, Loaded.end()); 522 From = begin(0, true); 523 } 524 525 Local.erase(Local.begin() + From.Position, Local.begin() + To.Position); 526 } 527 }; 528 529 /// \brief A lazy pointer to a statement. 530 typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt> 531 LazyDeclStmtPtr; 532 533 /// \brief A lazy pointer to a declaration. 534 typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl> 535 LazyDeclPtr; 536 537 /// \brief A lazy pointer to a set of CXXBaseSpecifiers. 538 typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, 539 &ExternalASTSource::GetExternalCXXBaseSpecifiers> 540 LazyCXXBaseSpecifiersPtr; 541 542 } // end namespace clang 543 544 #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H 545