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/DeclBase.h" 18 #include "clang/AST/CharUnits.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 NamedDecl; 28 class Selector; 29 class Stmt; 30 class TagDecl; 31 32 /// \brief Enumeration describing the result of loading information from 33 /// an external source. 34 enum ExternalLoadResult { 35 /// \brief Loading the external information has succeeded. 36 ELR_Success, 37 38 /// \brief Loading the external information has failed. 39 ELR_Failure, 40 41 /// \brief The external information has already been loaded, and therefore 42 /// no additional processing is required. 43 ELR_AlreadyLoaded 44 }; 45 46 /// \brief Abstract interface for external sources of AST nodes. 47 /// 48 /// External AST sources provide AST nodes constructed from some 49 /// external source, such as a precompiled header. External AST 50 /// sources can resolve types and declarations from abstract IDs into 51 /// actual type and declaration nodes, and read parts of declaration 52 /// contexts. 53 class ExternalASTSource { 54 /// \brief Whether this AST source also provides information for 55 /// semantic analysis. 56 bool SemaSource; 57 58 friend class ExternalSemaSource; 59 60 public: ExternalASTSource()61 ExternalASTSource() : SemaSource(false) { } 62 63 virtual ~ExternalASTSource(); 64 65 /// \brief RAII class for safely pairing a StartedDeserializing call 66 /// with FinishedDeserializing. 67 class Deserializing { 68 ExternalASTSource *Source; 69 public: Deserializing(ExternalASTSource * source)70 explicit Deserializing(ExternalASTSource *source) : Source(source) { 71 assert(Source); 72 Source->StartedDeserializing(); 73 } ~Deserializing()74 ~Deserializing() { 75 Source->FinishedDeserializing(); 76 } 77 }; 78 79 /// \brief Resolve a declaration ID into a declaration, potentially 80 /// building a new declaration. 81 /// 82 /// This method only needs to be implemented if the AST source ever 83 /// passes back decl sets as VisibleDeclaration objects. 84 /// 85 /// The default implementation of this method is a no-op. 86 virtual Decl *GetExternalDecl(uint32_t ID); 87 88 /// \brief Resolve a selector ID into a selector. 89 /// 90 /// This operation only needs to be implemented if the AST source 91 /// returns non-zero for GetNumKnownSelectors(). 92 /// 93 /// The default implementation of this method is a no-op. 94 virtual Selector GetExternalSelector(uint32_t ID); 95 96 /// \brief Returns the number of selectors known to the external AST 97 /// source. 98 /// 99 /// The default implementation of this method is a no-op. 100 virtual uint32_t GetNumExternalSelectors(); 101 102 /// \brief Resolve the offset of a statement in the decl stream into 103 /// a statement. 104 /// 105 /// This operation is meant to be used via a LazyOffsetPtr. It only 106 /// needs to be implemented if the AST source uses methods like 107 /// FunctionDecl::setLazyBody when building decls. 108 /// 109 /// The default implementation of this method is a no-op. 110 virtual Stmt *GetExternalDeclStmt(uint64_t Offset); 111 112 /// \brief Resolve the offset of a set of C++ base specifiers in the decl 113 /// stream into an array of specifiers. 114 /// 115 /// The default implementation of this method is a no-op. 116 virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); 117 118 /// \brief Finds all declarations with the given name in the 119 /// given context. 120 /// 121 /// Generally the final step of this method is either to call 122 /// SetExternalVisibleDeclsForName or to recursively call lookup on 123 /// the DeclContext after calling SetExternalVisibleDecls. 124 /// 125 /// The default implementation of this method is a no-op. 126 virtual DeclContextLookupResult 127 FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); 128 129 /// \brief Ensures that the table of all visible declarations inside this 130 /// context is up to date. 131 /// 132 /// The default implementation of this functino is a no-op. 133 virtual void completeVisibleDeclsMap(const DeclContext *DC); 134 135 /// \brief Finds all declarations lexically contained within the given 136 /// DeclContext, after applying an optional filter predicate. 137 /// 138 /// \param isKindWeWant a predicate function that returns true if the passed 139 /// declaration kind is one we are looking for. If NULL, all declarations 140 /// are returned. 141 /// 142 /// \return an indication of whether the load succeeded or failed. 143 /// 144 /// The default implementation of this method is a no-op. 145 virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, 146 bool (*isKindWeWant)(Decl::Kind), 147 SmallVectorImpl<Decl*> &Result); 148 149 /// \brief Finds all declarations lexically contained within the given 150 /// DeclContext. 151 /// 152 /// \return true if an error occurred FindExternalLexicalDecls(const DeclContext * DC,SmallVectorImpl<Decl * > & Result)153 ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, 154 SmallVectorImpl<Decl*> &Result) { 155 return FindExternalLexicalDecls(DC, 0, Result); 156 } 157 158 template <typename DeclTy> FindExternalLexicalDeclsBy(const DeclContext * DC,SmallVectorImpl<Decl * > & Result)159 ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC, 160 SmallVectorImpl<Decl*> &Result) { 161 return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result); 162 } 163 164 /// \brief Get the decls that are contained in a file in the Offset/Length 165 /// range. \arg Length can be 0 to indicate a point at \arg Offset instead of 166 /// a range. FindFileRegionDecls(FileID File,unsigned Offset,unsigned Length,SmallVectorImpl<Decl * > & Decls)167 virtual void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length, 168 SmallVectorImpl<Decl *> &Decls) {} 169 170 /// \brief Gives the external AST source an opportunity to complete 171 /// an incomplete type. CompleteType(TagDecl * Tag)172 virtual void CompleteType(TagDecl *Tag) {} 173 174 /// \brief Gives the external AST source an opportunity to complete an 175 /// incomplete Objective-C class. 176 /// 177 /// This routine will only be invoked if the "externally completed" bit is 178 /// set on the ObjCInterfaceDecl via the function 179 /// \c ObjCInterfaceDecl::setExternallyCompleted(). CompleteType(ObjCInterfaceDecl * Class)180 virtual void CompleteType(ObjCInterfaceDecl *Class) { } 181 182 /// \brief Loads comment ranges. ReadComments()183 virtual void ReadComments() { } 184 185 /// \brief Notify ExternalASTSource that we started deserialization of 186 /// a decl or type so until FinishedDeserializing is called there may be 187 /// decls that are initializing. Must be paired with FinishedDeserializing. 188 /// 189 /// The default implementation of this method is a no-op. StartedDeserializing()190 virtual void StartedDeserializing() { } 191 192 /// \brief Notify ExternalASTSource that we finished the deserialization of 193 /// a decl or type. Must be paired with StartedDeserializing. 194 /// 195 /// The default implementation of this method is a no-op. FinishedDeserializing()196 virtual void FinishedDeserializing() { } 197 198 /// \brief Function that will be invoked when we begin parsing a new 199 /// translation unit involving this external AST source. 200 /// 201 /// The default implementation of this method is a no-op. StartTranslationUnit(ASTConsumer * Consumer)202 virtual void StartTranslationUnit(ASTConsumer *Consumer) { } 203 204 /// \brief Print any statistics that have been gathered regarding 205 /// the external AST source. 206 /// 207 /// The default implementation of this method is a no-op. 208 virtual void PrintStats(); 209 210 211 /// \brief Perform layout on the given record. 212 /// 213 /// This routine allows the external AST source to provide an specific 214 /// layout for a record, overriding the layout that would normally be 215 /// constructed. It is intended for clients who receive specific layout 216 /// details rather than source code (such as LLDB). The client is expected 217 /// to fill in the field offsets, base offsets, virtual base offsets, and 218 /// complete object size. 219 /// 220 /// \param Record The record whose layout is being requested. 221 /// 222 /// \param Size The final size of the record, in bits. 223 /// 224 /// \param Alignment The final alignment of the record, in bits. 225 /// 226 /// \param FieldOffsets The offset of each of the fields within the record, 227 /// expressed in bits. All of the fields must be provided with offsets. 228 /// 229 /// \param BaseOffsets The offset of each of the direct, non-virtual base 230 /// classes. If any bases are not given offsets, the bases will be laid 231 /// out according to the ABI. 232 /// 233 /// \param VirtualBaseOffsets The offset of each of the virtual base classes 234 /// (either direct or not). If any bases are not given offsets, the bases will be laid 235 /// out according to the ABI. 236 /// 237 /// \returns true if the record layout was provided, false otherwise. 238 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)239 layoutRecordType(const RecordDecl *Record, 240 uint64_t &Size, uint64_t &Alignment, 241 llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets, 242 llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets, 243 llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets) 244 { 245 return false; 246 } 247 248 //===--------------------------------------------------------------------===// 249 // Queries for performance analysis. 250 //===--------------------------------------------------------------------===// 251 252 struct MemoryBufferSizes { 253 size_t malloc_bytes; 254 size_t mmap_bytes; 255 MemoryBufferSizesMemoryBufferSizes256 MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes) 257 : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} 258 }; 259 260 /// Return the amount of memory used by memory buffers, breaking down 261 /// by heap-backed versus mmap'ed memory. getMemoryBufferSizes()262 MemoryBufferSizes getMemoryBufferSizes() const { 263 MemoryBufferSizes sizes(0, 0); 264 getMemoryBufferSizes(sizes); 265 return sizes; 266 } 267 268 virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; 269 270 protected: 271 static DeclContextLookupResult 272 SetExternalVisibleDeclsForName(const DeclContext *DC, 273 DeclarationName Name, 274 ArrayRef<NamedDecl*> Decls); 275 276 static DeclContextLookupResult 277 SetNoExternalVisibleDeclsForName(const DeclContext *DC, 278 DeclarationName Name); 279 }; 280 281 /// \brief A lazy pointer to an AST node (of base type T) that resides 282 /// within an external AST source. 283 /// 284 /// The AST node is identified within the external AST source by a 285 /// 63-bit offset, and can be retrieved via an operation on the 286 /// external AST source itself. 287 template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)> 288 struct LazyOffsetPtr { 289 /// \brief Either a pointer to an AST node or the offset within the 290 /// external AST source where the AST node can be found. 291 /// 292 /// If the low bit is clear, a pointer to the AST node. If the low 293 /// bit is set, the upper 63 bits are the offset. 294 mutable uint64_t Ptr; 295 296 public: LazyOffsetPtrLazyOffsetPtr297 LazyOffsetPtr() : Ptr(0) { } 298 LazyOffsetPtrLazyOffsetPtr299 explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { } LazyOffsetPtrLazyOffsetPtr300 explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) { 301 assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); 302 if (Offset == 0) 303 Ptr = 0; 304 } 305 306 LazyOffsetPtr &operator=(T *Ptr) { 307 this->Ptr = reinterpret_cast<uint64_t>(Ptr); 308 return *this; 309 } 310 311 LazyOffsetPtr &operator=(uint64_t Offset) { 312 assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); 313 if (Offset == 0) 314 Ptr = 0; 315 else 316 Ptr = (Offset << 1) | 0x01; 317 318 return *this; 319 } 320 321 /// \brief Whether this pointer is non-NULL. 322 /// 323 /// This operation does not require the AST node to be deserialized. 324 operator bool() const { return Ptr != 0; } 325 326 /// \brief Whether this pointer is currently stored as an offset. isOffsetLazyOffsetPtr327 bool isOffset() const { return Ptr & 0x01; } 328 329 /// \brief Retrieve the pointer to the AST node that this lazy pointer 330 /// 331 /// \param Source the external AST source. 332 /// 333 /// \returns a pointer to the AST node. getLazyOffsetPtr334 T* get(ExternalASTSource *Source) const { 335 if (isOffset()) { 336 assert(Source && 337 "Cannot deserialize a lazy pointer without an AST source"); 338 Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1)); 339 } 340 return reinterpret_cast<T*>(Ptr); 341 } 342 }; 343 344 /// \brief Represents a lazily-loaded vector of data. 345 /// 346 /// The lazily-loaded vector of data contains data that is partially loaded 347 /// from an external source and partially added by local translation. The 348 /// items loaded from the external source are loaded lazily, when needed for 349 /// iteration over the complete vector. 350 template<typename T, typename Source, 351 void (Source::*Loader)(SmallVectorImpl<T>&), 352 unsigned LoadedStorage = 2, unsigned LocalStorage = 4> 353 class LazyVector { 354 SmallVector<T, LoadedStorage> Loaded; 355 SmallVector<T, LocalStorage> Local; 356 357 public: 358 // Iteration over the elements in the vector. 359 class iterator { 360 LazyVector *Self; 361 362 /// \brief Position within the vector.. 363 /// 364 /// In a complete iteration, the Position field walks the range [-M, N), 365 /// where negative values are used to indicate elements 366 /// loaded from the external source while non-negative values are used to 367 /// indicate elements added via \c push_back(). 368 /// However, to provide iteration in source order (for, e.g., chained 369 /// precompiled headers), dereferencing the iterator flips the negative 370 /// values (corresponding to loaded entities), so that position -M 371 /// corresponds to element 0 in the loaded entities vector, position -M+1 372 /// corresponds to element 1 in the loaded entities vector, etc. This 373 /// gives us a reasonably efficient, source-order walk. 374 int Position; 375 376 friend class LazyVector; 377 378 public: 379 typedef T value_type; 380 typedef value_type& reference; 381 typedef value_type* pointer; 382 typedef std::random_access_iterator_tag iterator_category; 383 typedef int difference_type; 384 iterator()385 iterator() : Self(0), Position(0) { } 386 iterator(LazyVector * Self,int Position)387 iterator(LazyVector *Self, int Position) 388 : Self(Self), Position(Position) { } 389 390 reference operator*() const { 391 if (Position < 0) 392 return Self->Loaded.end()[Position]; 393 return Self->Local[Position]; 394 } 395 396 pointer operator->() const { 397 if (Position < 0) 398 return &Self->Loaded.end()[Position]; 399 400 return &Self->Local[Position]; 401 } 402 403 reference operator[](difference_type D) { 404 return *(*this + D); 405 } 406 407 iterator &operator++() { 408 ++Position; 409 return *this; 410 } 411 412 iterator operator++(int) { 413 iterator Prev(*this); 414 ++Position; 415 return Prev; 416 } 417 418 iterator &operator--() { 419 --Position; 420 return *this; 421 } 422 423 iterator operator--(int) { 424 iterator Prev(*this); 425 --Position; 426 return Prev; 427 } 428 429 friend bool operator==(const iterator &X, const iterator &Y) { 430 return X.Position == Y.Position; 431 } 432 433 friend bool operator!=(const iterator &X, const iterator &Y) { 434 return X.Position != Y.Position; 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 iterator& operator+=(iterator &X, difference_type D) { 454 X.Position += D; 455 return X; 456 } 457 458 friend iterator& operator-=(iterator &X, difference_type D) { 459 X.Position -= D; 460 return X; 461 } 462 463 friend iterator operator+(iterator X, difference_type D) { 464 X.Position += D; 465 return X; 466 } 467 468 friend iterator operator+(difference_type D, iterator X) { 469 X.Position += D; 470 return X; 471 } 472 473 friend difference_type operator-(const iterator &X, const iterator &Y) { 474 return X.Position - Y.Position; 475 } 476 477 friend iterator operator-(iterator X, difference_type D) { 478 X.Position -= D; 479 return X; 480 } 481 }; 482 friend class iterator; 483 484 iterator begin(Source *source, bool LocalOnly = false) { 485 if (LocalOnly) 486 return iterator(this, 0); 487 488 if (source) 489 (source->*Loader)(Loaded); 490 return iterator(this, -(int)Loaded.size()); 491 } 492 end()493 iterator end() { 494 return iterator(this, Local.size()); 495 } 496 push_back(const T & LocalValue)497 void push_back(const T& LocalValue) { 498 Local.push_back(LocalValue); 499 } 500 erase(iterator From,iterator To)501 void erase(iterator From, iterator To) { 502 if (From.Position < 0 && To.Position < 0) { 503 Loaded.erase(Loaded.end() + From.Position, Loaded.end() + To.Position); 504 return; 505 } 506 507 if (From.Position < 0) { 508 Loaded.erase(Loaded.end() + From.Position, Loaded.end()); 509 From = begin(0, true); 510 } 511 512 Local.erase(Local.begin() + From.Position, Local.begin() + To.Position); 513 } 514 }; 515 516 /// \brief A lazy pointer to a statement. 517 typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt> 518 LazyDeclStmtPtr; 519 520 /// \brief A lazy pointer to a declaration. 521 typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl> 522 LazyDeclPtr; 523 524 /// \brief A lazy pointer to a set of CXXBaseSpecifiers. 525 typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, 526 &ExternalASTSource::GetExternalCXXBaseSpecifiers> 527 LazyCXXBaseSpecifiersPtr; 528 529 } // end namespace clang 530 531 #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H 532