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 Notify ExternalASTSource that we started deserialization of 183 /// a decl or type so until FinishedDeserializing is called there may be 184 /// decls that are initializing. Must be paired with FinishedDeserializing. 185 /// 186 /// The default implementation of this method is a no-op. StartedDeserializing()187 virtual void StartedDeserializing() { } 188 189 /// \brief Notify ExternalASTSource that we finished the deserialization of 190 /// a decl or type. Must be paired with StartedDeserializing. 191 /// 192 /// The default implementation of this method is a no-op. FinishedDeserializing()193 virtual void FinishedDeserializing() { } 194 195 /// \brief Function that will be invoked when we begin parsing a new 196 /// translation unit involving this external AST source. 197 /// 198 /// The default implementation of this method is a no-op. StartTranslationUnit(ASTConsumer * Consumer)199 virtual void StartTranslationUnit(ASTConsumer *Consumer) { } 200 201 /// \brief Print any statistics that have been gathered regarding 202 /// the external AST source. 203 /// 204 /// The default implementation of this method is a no-op. 205 virtual void PrintStats(); 206 207 208 /// \brief Perform layout on the given record. 209 /// 210 /// This routine allows the external AST source to provide an specific 211 /// layout for a record, overriding the layout that would normally be 212 /// constructed. It is intended for clients who receive specific layout 213 /// details rather than source code (such as LLDB). The client is expected 214 /// to fill in the field offsets, base offsets, virtual base offsets, and 215 /// complete object size. 216 /// 217 /// \param Record The record whose layout is being requested. 218 /// 219 /// \param Size The final size of the record, in bits. 220 /// 221 /// \param Alignment The final alignment of the record, in bits. 222 /// 223 /// \param FieldOffsets The offset of each of the fields within the record, 224 /// expressed in bits. All of the fields must be provided with offsets. 225 /// 226 /// \param BaseOffsets The offset of each of the direct, non-virtual base 227 /// classes. If any bases are not given offsets, the bases will be laid 228 /// out according to the ABI. 229 /// 230 /// \param VirtualBaseOffsets The offset of each of the virtual base classes 231 /// (either direct or not). If any bases are not given offsets, the bases will be laid 232 /// out according to the ABI. 233 /// 234 /// \returns true if the record layout was provided, false otherwise. 235 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)236 layoutRecordType(const RecordDecl *Record, 237 uint64_t &Size, uint64_t &Alignment, 238 llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets, 239 llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets, 240 llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets) 241 { 242 return false; 243 } 244 245 //===--------------------------------------------------------------------===// 246 // Queries for performance analysis. 247 //===--------------------------------------------------------------------===// 248 249 struct MemoryBufferSizes { 250 size_t malloc_bytes; 251 size_t mmap_bytes; 252 MemoryBufferSizesMemoryBufferSizes253 MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes) 254 : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} 255 }; 256 257 /// Return the amount of memory used by memory buffers, breaking down 258 /// by heap-backed versus mmap'ed memory. getMemoryBufferSizes()259 MemoryBufferSizes getMemoryBufferSizes() const { 260 MemoryBufferSizes sizes(0, 0); 261 getMemoryBufferSizes(sizes); 262 return sizes; 263 } 264 265 virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; 266 267 protected: 268 static DeclContextLookupResult 269 SetExternalVisibleDeclsForName(const DeclContext *DC, 270 DeclarationName Name, 271 ArrayRef<NamedDecl*> Decls); 272 273 static DeclContextLookupResult 274 SetNoExternalVisibleDeclsForName(const DeclContext *DC, 275 DeclarationName Name); 276 }; 277 278 /// \brief A lazy pointer to an AST node (of base type T) that resides 279 /// within an external AST source. 280 /// 281 /// The AST node is identified within the external AST source by a 282 /// 63-bit offset, and can be retrieved via an operation on the 283 /// external AST source itself. 284 template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)> 285 struct LazyOffsetPtr { 286 /// \brief Either a pointer to an AST node or the offset within the 287 /// external AST source where the AST node can be found. 288 /// 289 /// If the low bit is clear, a pointer to the AST node. If the low 290 /// bit is set, the upper 63 bits are the offset. 291 mutable uint64_t Ptr; 292 293 public: LazyOffsetPtrLazyOffsetPtr294 LazyOffsetPtr() : Ptr(0) { } 295 LazyOffsetPtrLazyOffsetPtr296 explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { } LazyOffsetPtrLazyOffsetPtr297 explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) { 298 assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); 299 if (Offset == 0) 300 Ptr = 0; 301 } 302 303 LazyOffsetPtr &operator=(T *Ptr) { 304 this->Ptr = reinterpret_cast<uint64_t>(Ptr); 305 return *this; 306 } 307 308 LazyOffsetPtr &operator=(uint64_t Offset) { 309 assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); 310 if (Offset == 0) 311 Ptr = 0; 312 else 313 Ptr = (Offset << 1) | 0x01; 314 315 return *this; 316 } 317 318 /// \brief Whether this pointer is non-NULL. 319 /// 320 /// This operation does not require the AST node to be deserialized. 321 operator bool() const { return Ptr != 0; } 322 323 /// \brief Whether this pointer is currently stored as an offset. isOffsetLazyOffsetPtr324 bool isOffset() const { return Ptr & 0x01; } 325 326 /// \brief Retrieve the pointer to the AST node that this lazy pointer 327 /// 328 /// \param Source the external AST source. 329 /// 330 /// \returns a pointer to the AST node. getLazyOffsetPtr331 T* get(ExternalASTSource *Source) const { 332 if (isOffset()) { 333 assert(Source && 334 "Cannot deserialize a lazy pointer without an AST source"); 335 Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1)); 336 } 337 return reinterpret_cast<T*>(Ptr); 338 } 339 }; 340 341 /// \brief Represents a lazily-loaded vector of data. 342 /// 343 /// The lazily-loaded vector of data contains data that is partially loaded 344 /// from an external source and partially added by local translation. The 345 /// items loaded from the external source are loaded lazily, when needed for 346 /// iteration over the complete vector. 347 template<typename T, typename Source, 348 void (Source::*Loader)(SmallVectorImpl<T>&), 349 unsigned LoadedStorage = 2, unsigned LocalStorage = 4> 350 class LazyVector { 351 SmallVector<T, LoadedStorage> Loaded; 352 SmallVector<T, LocalStorage> Local; 353 354 public: 355 // Iteration over the elements in the vector. 356 class iterator { 357 LazyVector *Self; 358 359 /// \brief Position within the vector.. 360 /// 361 /// In a complete iteration, the Position field walks the range [-M, N), 362 /// where negative values are used to indicate elements 363 /// loaded from the external source while non-negative values are used to 364 /// indicate elements added via \c push_back(). 365 /// However, to provide iteration in source order (for, e.g., chained 366 /// precompiled headers), dereferencing the iterator flips the negative 367 /// values (corresponding to loaded entities), so that position -M 368 /// corresponds to element 0 in the loaded entities vector, position -M+1 369 /// corresponds to element 1 in the loaded entities vector, etc. This 370 /// gives us a reasonably efficient, source-order walk. 371 int Position; 372 373 friend class LazyVector; 374 375 public: 376 typedef T value_type; 377 typedef value_type& reference; 378 typedef value_type* pointer; 379 typedef std::random_access_iterator_tag iterator_category; 380 typedef int difference_type; 381 iterator()382 iterator() : Self(0), Position(0) { } 383 iterator(LazyVector * Self,int Position)384 iterator(LazyVector *Self, int Position) 385 : Self(Self), Position(Position) { } 386 387 reference operator*() const { 388 if (Position < 0) 389 return Self->Loaded.end()[Position]; 390 return Self->Local[Position]; 391 } 392 393 pointer operator->() const { 394 if (Position < 0) 395 return &Self->Loaded.end()[Position]; 396 397 return &Self->Local[Position]; 398 } 399 400 reference operator[](difference_type D) { 401 return *(*this + D); 402 } 403 404 iterator &operator++() { 405 ++Position; 406 return *this; 407 } 408 409 iterator operator++(int) { 410 iterator Prev(*this); 411 ++Position; 412 return Prev; 413 } 414 415 iterator &operator--() { 416 --Position; 417 return *this; 418 } 419 420 iterator operator--(int) { 421 iterator Prev(*this); 422 --Position; 423 return Prev; 424 } 425 426 friend bool operator==(const iterator &X, const iterator &Y) { 427 return X.Position == Y.Position; 428 } 429 430 friend bool operator!=(const iterator &X, const iterator &Y) { 431 return X.Position != Y.Position; 432 } 433 434 friend bool operator<(const iterator &X, const iterator &Y) { 435 return X.Position < Y.Position; 436 } 437 438 friend bool operator>(const iterator &X, const iterator &Y) { 439 return X.Position > Y.Position; 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 iterator& operator+=(iterator &X, difference_type D) { 451 X.Position += D; 452 return X; 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+(difference_type D, iterator X) { 466 X.Position += D; 467 return X; 468 } 469 470 friend difference_type operator-(const iterator &X, const iterator &Y) { 471 return X.Position - Y.Position; 472 } 473 474 friend iterator operator-(iterator X, difference_type D) { 475 X.Position -= D; 476 return X; 477 } 478 }; 479 friend class iterator; 480 481 iterator begin(Source *source, bool LocalOnly = false) { 482 if (LocalOnly) 483 return iterator(this, 0); 484 485 if (source) 486 (source->*Loader)(Loaded); 487 return iterator(this, -(int)Loaded.size()); 488 } 489 end()490 iterator end() { 491 return iterator(this, Local.size()); 492 } 493 push_back(const T & LocalValue)494 void push_back(const T& LocalValue) { 495 Local.push_back(LocalValue); 496 } 497 erase(iterator From,iterator To)498 void erase(iterator From, iterator To) { 499 if (From.Position < 0 && To.Position < 0) { 500 Loaded.erase(Loaded.end() + From.Position, Loaded.end() + To.Position); 501 return; 502 } 503 504 if (From.Position < 0) { 505 Loaded.erase(Loaded.end() + From.Position, Loaded.end()); 506 From = begin(0, true); 507 } 508 509 Local.erase(Local.begin() + From.Position, Local.begin() + To.Position); 510 } 511 }; 512 513 /// \brief A lazy pointer to a statement. 514 typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt> 515 LazyDeclStmtPtr; 516 517 /// \brief A lazy pointer to a declaration. 518 typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl> 519 LazyDeclPtr; 520 521 /// \brief A lazy pointer to a set of CXXBaseSpecifiers. 522 typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, 523 &ExternalASTSource::GetExternalCXXBaseSpecifiers> 524 LazyCXXBaseSpecifiersPtr; 525 526 } // end namespace clang 527 528 #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H 529