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