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