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_EXTERNALASTSOURCE_H 15 #define LLVM_CLANG_AST_EXTERNALASTSOURCE_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 CXXCtorInitializer; 26 class DeclarationName; 27 class ExternalSemaSource; // layering violation required for downcasting 28 class FieldDecl; 29 class Module; 30 class NamedDecl; 31 class RecordDecl; 32 class Selector; 33 class Stmt; 34 class TagDecl; 35 36 /// \brief Enumeration describing the result of loading information from 37 /// an external source. 38 enum ExternalLoadResult { 39 /// \brief Loading the external information has succeeded. 40 ELR_Success, 41 42 /// \brief Loading the external information has failed. 43 ELR_Failure, 44 45 /// \brief The external information has already been loaded, and therefore 46 /// no additional processing is required. 47 ELR_AlreadyLoaded 48 }; 49 50 /// \brief Abstract interface for external sources of AST nodes. 51 /// 52 /// External AST sources provide AST nodes constructed from some 53 /// external source, such as a precompiled header. External AST 54 /// sources can resolve types and declarations from abstract IDs into 55 /// actual type and declaration nodes, and read parts of declaration 56 /// contexts. 57 class ExternalASTSource : public RefCountedBase<ExternalASTSource> { 58 /// Generation number for this external AST source. Must be increased 59 /// whenever we might have added new redeclarations for existing decls. 60 uint32_t CurrentGeneration; 61 62 /// \brief Whether this AST source also provides information for 63 /// semantic analysis. 64 bool SemaSource; 65 66 friend class ExternalSemaSource; 67 68 public: ExternalASTSource()69 ExternalASTSource() : CurrentGeneration(0), SemaSource(false) { } 70 71 virtual ~ExternalASTSource(); 72 73 /// \brief RAII class for safely pairing a StartedDeserializing call 74 /// with FinishedDeserializing. 75 class Deserializing { 76 ExternalASTSource *Source; 77 public: Deserializing(ExternalASTSource * source)78 explicit Deserializing(ExternalASTSource *source) : Source(source) { 79 assert(Source); 80 Source->StartedDeserializing(); 81 } ~Deserializing()82 ~Deserializing() { 83 Source->FinishedDeserializing(); 84 } 85 }; 86 87 /// \brief Get the current generation of this AST source. This number 88 /// is incremented each time the AST source lazily extends an existing 89 /// entity. getGeneration()90 uint32_t getGeneration() const { return CurrentGeneration; } 91 92 /// \brief Resolve a declaration ID into a declaration, potentially 93 /// building a new declaration. 94 /// 95 /// This method only needs to be implemented if the AST source ever 96 /// passes back decl sets as VisibleDeclaration objects. 97 /// 98 /// The default implementation of this method is a no-op. 99 virtual Decl *GetExternalDecl(uint32_t ID); 100 101 /// \brief Resolve a selector ID into a selector. 102 /// 103 /// This operation only needs to be implemented if the AST source 104 /// returns non-zero for GetNumKnownSelectors(). 105 /// 106 /// The default implementation of this method is a no-op. 107 virtual Selector GetExternalSelector(uint32_t ID); 108 109 /// \brief Returns the number of selectors known to the external AST 110 /// source. 111 /// 112 /// The default implementation of this method is a no-op. 113 virtual uint32_t GetNumExternalSelectors(); 114 115 /// \brief Resolve the offset of a statement in the decl stream into 116 /// a statement. 117 /// 118 /// This operation is meant to be used via a LazyOffsetPtr. It only 119 /// needs to be implemented if the AST source uses methods like 120 /// FunctionDecl::setLazyBody when building decls. 121 /// 122 /// The default implementation of this method is a no-op. 123 virtual Stmt *GetExternalDeclStmt(uint64_t Offset); 124 125 /// \brief Resolve the offset of a set of C++ constructor initializers in 126 /// the decl stream into an array of initializers. 127 /// 128 /// The default implementation of this method is a no-op. 129 virtual CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset); 130 131 /// \brief Resolve the offset of a set of C++ base specifiers in the decl 132 /// stream into an array of specifiers. 133 /// 134 /// The default implementation of this method is a no-op. 135 virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); 136 137 /// \brief Update an out-of-date identifier. updateOutOfDateIdentifier(IdentifierInfo & II)138 virtual void updateOutOfDateIdentifier(IdentifierInfo &II) { } 139 140 /// \brief Find all declarations with the given name in the given context, 141 /// and add them to the context by calling SetExternalVisibleDeclsForName 142 /// or SetNoExternalVisibleDeclsForName. 143 /// \return \c true if any declarations might have been found, \c false if 144 /// we definitely have no declarations with tbis name. 145 /// 146 /// The default implementation of this method is a no-op returning \c false. 147 virtual bool 148 FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); 149 150 /// \brief Ensures that the table of all visible declarations inside this 151 /// context is up to date. 152 /// 153 /// The default implementation of this function is a no-op. 154 virtual void completeVisibleDeclsMap(const DeclContext *DC); 155 156 /// \brief Retrieve the module that corresponds to the given module ID. getModule(unsigned ID)157 virtual Module *getModule(unsigned ID) { return nullptr; } 158 159 /// \brief Finds all declarations lexically contained within the given 160 /// DeclContext, after applying an optional filter predicate. 161 /// 162 /// \param isKindWeWant a predicate function that returns true if the passed 163 /// declaration kind is one we are looking for. If NULL, all declarations 164 /// are returned. 165 /// 166 /// \return an indication of whether the load succeeded or failed. 167 /// 168 /// The default implementation of this method is a no-op. 169 virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, 170 bool (*isKindWeWant)(Decl::Kind), 171 SmallVectorImpl<Decl*> &Result); 172 173 /// \brief Finds all declarations lexically contained within the given 174 /// DeclContext. 175 /// 176 /// \return true if an error occurred FindExternalLexicalDecls(const DeclContext * DC,SmallVectorImpl<Decl * > & Result)177 ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, 178 SmallVectorImpl<Decl*> &Result) { 179 return FindExternalLexicalDecls(DC, nullptr, Result); 180 } 181 182 template <typename DeclTy> FindExternalLexicalDeclsBy(const DeclContext * DC,SmallVectorImpl<Decl * > & Result)183 ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC, 184 SmallVectorImpl<Decl*> &Result) { 185 return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result); 186 } 187 188 /// \brief Get the decls that are contained in a file in the Offset/Length 189 /// range. \p Length can be 0 to indicate a point at \p Offset instead of 190 /// a range. 191 virtual void FindFileRegionDecls(FileID File, unsigned Offset, 192 unsigned Length, 193 SmallVectorImpl<Decl *> &Decls); 194 195 /// \brief Gives the external AST source an opportunity to complete 196 /// the redeclaration chain for a declaration. Called each time we 197 /// need the most recent declaration of a declaration after the 198 /// generation count is incremented. 199 virtual void CompleteRedeclChain(const Decl *D); 200 201 /// \brief Gives the external AST source an opportunity to complete 202 /// an incomplete type. 203 virtual void CompleteType(TagDecl *Tag); 204 205 /// \brief Gives the external AST source an opportunity to complete an 206 /// incomplete Objective-C class. 207 /// 208 /// This routine will only be invoked if the "externally completed" bit is 209 /// set on the ObjCInterfaceDecl via the function 210 /// \c ObjCInterfaceDecl::setExternallyCompleted(). 211 virtual void CompleteType(ObjCInterfaceDecl *Class); 212 213 /// \brief Loads comment ranges. 214 virtual void ReadComments(); 215 216 /// \brief Notify ExternalASTSource that we started deserialization of 217 /// a decl or type so until FinishedDeserializing is called there may be 218 /// decls that are initializing. Must be paired with FinishedDeserializing. 219 /// 220 /// The default implementation of this method is a no-op. 221 virtual void StartedDeserializing(); 222 223 /// \brief Notify ExternalASTSource that we finished the deserialization of 224 /// a decl or type. Must be paired with StartedDeserializing. 225 /// 226 /// The default implementation of this method is a no-op. 227 virtual void FinishedDeserializing(); 228 229 /// \brief Function that will be invoked when we begin parsing a new 230 /// translation unit involving this external AST source. 231 /// 232 /// The default implementation of this method is a no-op. 233 virtual void StartTranslationUnit(ASTConsumer *Consumer); 234 235 /// \brief Print any statistics that have been gathered regarding 236 /// the external AST source. 237 /// 238 /// The default implementation of this method is a no-op. 239 virtual void PrintStats(); 240 241 242 /// \brief Perform layout on the given record. 243 /// 244 /// This routine allows the external AST source to provide an specific 245 /// layout for a record, overriding the layout that would normally be 246 /// constructed. It is intended for clients who receive specific layout 247 /// details rather than source code (such as LLDB). The client is expected 248 /// to fill in the field offsets, base offsets, virtual base offsets, and 249 /// complete object size. 250 /// 251 /// \param Record The record whose layout is being requested. 252 /// 253 /// \param Size The final size of the record, in bits. 254 /// 255 /// \param Alignment The final alignment of the record, in bits. 256 /// 257 /// \param FieldOffsets The offset of each of the fields within the record, 258 /// expressed in bits. All of the fields must be provided with offsets. 259 /// 260 /// \param BaseOffsets The offset of each of the direct, non-virtual base 261 /// classes. If any bases are not given offsets, the bases will be laid 262 /// out according to the ABI. 263 /// 264 /// \param VirtualBaseOffsets The offset of each of the virtual base classes 265 /// (either direct or not). If any bases are not given offsets, the bases will be laid 266 /// out according to the ABI. 267 /// 268 /// \returns true if the record layout was provided, false otherwise. 269 virtual bool layoutRecordType( 270 const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, 271 llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets, 272 llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets, 273 llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets); 274 275 //===--------------------------------------------------------------------===// 276 // Queries for performance analysis. 277 //===--------------------------------------------------------------------===// 278 279 struct MemoryBufferSizes { 280 size_t malloc_bytes; 281 size_t mmap_bytes; 282 MemoryBufferSizesMemoryBufferSizes283 MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes) 284 : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} 285 }; 286 287 /// Return the amount of memory used by memory buffers, breaking down 288 /// by heap-backed versus mmap'ed memory. getMemoryBufferSizes()289 MemoryBufferSizes getMemoryBufferSizes() const { 290 MemoryBufferSizes sizes(0, 0); 291 getMemoryBufferSizes(sizes); 292 return sizes; 293 } 294 295 virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; 296 297 protected: 298 static DeclContextLookupResult 299 SetExternalVisibleDeclsForName(const DeclContext *DC, 300 DeclarationName Name, 301 ArrayRef<NamedDecl*> Decls); 302 303 static DeclContextLookupResult 304 SetNoExternalVisibleDeclsForName(const DeclContext *DC, 305 DeclarationName Name); 306 307 /// \brief Increment the current generation. 308 uint32_t incrementGeneration(ASTContext &C); 309 }; 310 311 /// \brief A lazy pointer to an AST node (of base type T) that resides 312 /// within an external AST source. 313 /// 314 /// The AST node is identified within the external AST source by a 315 /// 63-bit offset, and can be retrieved via an operation on the 316 /// external AST source itself. 317 template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)> 318 struct LazyOffsetPtr { 319 /// \brief Either a pointer to an AST node or the offset within the 320 /// external AST source where the AST node can be found. 321 /// 322 /// If the low bit is clear, a pointer to the AST node. If the low 323 /// bit is set, the upper 63 bits are the offset. 324 mutable uint64_t Ptr; 325 326 public: LazyOffsetPtrLazyOffsetPtr327 LazyOffsetPtr() : Ptr(0) { } 328 LazyOffsetPtrLazyOffsetPtr329 explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { } LazyOffsetPtrLazyOffsetPtr330 explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) { 331 assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); 332 if (Offset == 0) 333 Ptr = 0; 334 } 335 336 LazyOffsetPtr &operator=(T *Ptr) { 337 this->Ptr = reinterpret_cast<uint64_t>(Ptr); 338 return *this; 339 } 340 341 LazyOffsetPtr &operator=(uint64_t Offset) { 342 assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); 343 if (Offset == 0) 344 Ptr = 0; 345 else 346 Ptr = (Offset << 1) | 0x01; 347 348 return *this; 349 } 350 351 /// \brief Whether this pointer is non-NULL. 352 /// 353 /// This operation does not require the AST node to be deserialized. 354 explicit operator bool() const { return Ptr != 0; } 355 356 /// \brief Whether this pointer is non-NULL. 357 /// 358 /// This operation does not require the AST node to be deserialized. isValidLazyOffsetPtr359 bool isValid() const { return Ptr != 0; } 360 361 /// \brief Whether this pointer is currently stored as an offset. isOffsetLazyOffsetPtr362 bool isOffset() const { return Ptr & 0x01; } 363 364 /// \brief Retrieve the pointer to the AST node that this lazy pointer 365 /// 366 /// \param Source the external AST source. 367 /// 368 /// \returns a pointer to the AST node. getLazyOffsetPtr369 T* get(ExternalASTSource *Source) const { 370 if (isOffset()) { 371 assert(Source && 372 "Cannot deserialize a lazy pointer without an AST source"); 373 Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1)); 374 } 375 return reinterpret_cast<T*>(Ptr); 376 } 377 }; 378 379 /// \brief A lazy value (of type T) that is within an AST node of type Owner, 380 /// where the value might change in later generations of the external AST 381 /// source. 382 template<typename Owner, typename T, void (ExternalASTSource::*Update)(Owner)> 383 struct LazyGenerationalUpdatePtr { 384 /// A cache of the value of this pointer, in the most recent generation in 385 /// which we queried it. 386 struct LazyData { LazyDataLazyGenerationalUpdatePtr::LazyData387 LazyData(ExternalASTSource *Source, T Value) 388 : ExternalSource(Source), LastGeneration(0), LastValue(Value) {} 389 ExternalASTSource *ExternalSource; 390 uint32_t LastGeneration; 391 T LastValue; 392 }; 393 394 // Our value is represented as simply T if there is no external AST source. 395 typedef llvm::PointerUnion<T, LazyData*> ValueType; 396 ValueType Value; 397 LazyGenerationalUpdatePtrLazyGenerationalUpdatePtr398 LazyGenerationalUpdatePtr(ValueType V) : Value(V) {} 399 400 // Defined in ASTContext.h 401 static ValueType makeValue(const ASTContext &Ctx, T Value); 402 403 public: 404 explicit LazyGenerationalUpdatePtr(const ASTContext &Ctx, T Value = T()) ValueLazyGenerationalUpdatePtr405 : Value(makeValue(Ctx, Value)) {} 406 407 /// Create a pointer that is not potentially updated by later generations of 408 /// the external AST source. 409 enum NotUpdatedTag { NotUpdated }; 410 LazyGenerationalUpdatePtr(NotUpdatedTag, T Value = T()) ValueLazyGenerationalUpdatePtr411 : Value(Value) {} 412 413 /// Forcibly set this pointer (which must be lazy) as needing updates. markIncompleteLazyGenerationalUpdatePtr414 void markIncomplete() { 415 Value.template get<LazyData *>()->LastGeneration = 0; 416 } 417 418 /// Set the value of this pointer, in the current generation. setLazyGenerationalUpdatePtr419 void set(T NewValue) { 420 if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) { 421 LazyVal->LastValue = NewValue; 422 return; 423 } 424 Value = NewValue; 425 } 426 427 /// Set the value of this pointer, for this and all future generations. setNotUpdatedLazyGenerationalUpdatePtr428 void setNotUpdated(T NewValue) { Value = NewValue; } 429 430 /// Get the value of this pointer, updating its owner if necessary. getLazyGenerationalUpdatePtr431 T get(Owner O) { 432 if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) { 433 if (LazyVal->LastGeneration != LazyVal->ExternalSource->getGeneration()) { 434 LazyVal->LastGeneration = LazyVal->ExternalSource->getGeneration(); 435 (LazyVal->ExternalSource->*Update)(O); 436 } 437 return LazyVal->LastValue; 438 } 439 return Value.template get<T>(); 440 } 441 442 /// Get the most recently computed value of this pointer without updating it. getNotUpdatedLazyGenerationalUpdatePtr443 T getNotUpdated() const { 444 if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) 445 return LazyVal->LastValue; 446 return Value.template get<T>(); 447 } 448 getOpaqueValueLazyGenerationalUpdatePtr449 void *getOpaqueValue() { return Value.getOpaqueValue(); } getFromOpaqueValueLazyGenerationalUpdatePtr450 static LazyGenerationalUpdatePtr getFromOpaqueValue(void *Ptr) { 451 return LazyGenerationalUpdatePtr(ValueType::getFromOpaqueValue(Ptr)); 452 } 453 }; 454 } // end namespace clang 455 456 /// Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be 457 /// placed into a PointerUnion. 458 namespace llvm { 459 template<typename Owner, typename T, 460 void (clang::ExternalASTSource::*Update)(Owner)> 461 struct PointerLikeTypeTraits< 462 clang::LazyGenerationalUpdatePtr<Owner, T, Update>> { 463 typedef clang::LazyGenerationalUpdatePtr<Owner, T, Update> Ptr; 464 static void *getAsVoidPointer(Ptr P) { return P.getOpaqueValue(); } 465 static Ptr getFromVoidPointer(void *P) { return Ptr::getFromOpaqueValue(P); } 466 enum { 467 NumLowBitsAvailable = PointerLikeTypeTraits<T>::NumLowBitsAvailable - 1 468 }; 469 }; 470 } 471 472 namespace clang { 473 /// \brief Represents a lazily-loaded vector of data. 474 /// 475 /// The lazily-loaded vector of data contains data that is partially loaded 476 /// from an external source and partially added by local translation. The 477 /// items loaded from the external source are loaded lazily, when needed for 478 /// iteration over the complete vector. 479 template<typename T, typename Source, 480 void (Source::*Loader)(SmallVectorImpl<T>&), 481 unsigned LoadedStorage = 2, unsigned LocalStorage = 4> 482 class LazyVector { 483 SmallVector<T, LoadedStorage> Loaded; 484 SmallVector<T, LocalStorage> Local; 485 486 public: 487 /// Iteration over the elements in the vector. 488 /// 489 /// In a complete iteration, the iterator walks the range [-M, N), 490 /// where negative values are used to indicate elements 491 /// loaded from the external source while non-negative values are used to 492 /// indicate elements added via \c push_back(). 493 /// However, to provide iteration in source order (for, e.g., chained 494 /// precompiled headers), dereferencing the iterator flips the negative 495 /// values (corresponding to loaded entities), so that position -M 496 /// corresponds to element 0 in the loaded entities vector, position -M+1 497 /// corresponds to element 1 in the loaded entities vector, etc. This 498 /// gives us a reasonably efficient, source-order walk. 499 /// 500 /// We define this as a wrapping iterator around an int. The 501 /// iterator_adaptor_base class forwards the iterator methods to basic integer 502 /// arithmetic. 503 class iterator : public llvm::iterator_adaptor_base< 504 iterator, int, std::random_access_iterator_tag, T, int> { 505 LazyVector *Self; 506 507 iterator(LazyVector *Self, int Position) 508 : iterator::iterator_adaptor_base(Position), Self(Self) {} 509 510 bool isLoaded() const { return this->I < 0; } 511 friend class LazyVector; 512 513 public: 514 iterator() : iterator(nullptr, 0) {} 515 516 typename iterator::reference operator*() const { 517 if (isLoaded()) 518 return Self->Loaded.end()[this->I]; 519 return Self->Local.begin()[this->I]; 520 } 521 }; 522 523 iterator begin(Source *source, bool LocalOnly = false) { 524 if (LocalOnly) 525 return iterator(this, 0); 526 527 if (source) 528 (source->*Loader)(Loaded); 529 return iterator(this, -(int)Loaded.size()); 530 } 531 532 iterator end() { 533 return iterator(this, Local.size()); 534 } 535 536 void push_back(const T& LocalValue) { 537 Local.push_back(LocalValue); 538 } 539 540 void erase(iterator From, iterator To) { 541 if (From.isLoaded() && To.isLoaded()) { 542 Loaded.erase(&*From, &*To); 543 return; 544 } 545 546 if (From.isLoaded()) { 547 Loaded.erase(&*From, Loaded.end()); 548 From = begin(nullptr, true); 549 } 550 551 Local.erase(&*From, &*To); 552 } 553 }; 554 555 /// \brief A lazy pointer to a statement. 556 typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt> 557 LazyDeclStmtPtr; 558 559 /// \brief A lazy pointer to a declaration. 560 typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl> 561 LazyDeclPtr; 562 563 /// \brief A lazy pointer to a set of CXXCtorInitializers. 564 typedef LazyOffsetPtr<CXXCtorInitializer *, uint64_t, 565 &ExternalASTSource::GetExternalCXXCtorInitializers> 566 LazyCXXCtorInitializersPtr; 567 568 /// \brief A lazy pointer to a set of CXXBaseSpecifiers. 569 typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, 570 &ExternalASTSource::GetExternalCXXBaseSpecifiers> 571 LazyCXXBaseSpecifiersPtr; 572 573 } // end namespace clang 574 575 #endif 576