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