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