diff options
-rw-r--r-- | clang/include/clang/Lex/ExternalPreprocessorSource.h | 52 | ||||
-rw-r--r-- | clang/include/clang/Lex/HeaderSearch.h | 12 | ||||
-rw-r--r-- | clang/lib/Lex/HeaderSearch.cpp | 33 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 7 |
5 files changed, 76 insertions, 30 deletions
diff --git a/clang/include/clang/Lex/ExternalPreprocessorSource.h b/clang/include/clang/Lex/ExternalPreprocessorSource.h index 6775841..6672ada 100644 --- a/clang/include/clang/Lex/ExternalPreprocessorSource.h +++ b/clang/include/clang/Lex/ExternalPreprocessorSource.h @@ -42,6 +42,58 @@ public: virtual Module *getModule(unsigned ModuleID) = 0; }; +// Either a pointer to an IdentifierInfo of the controlling macro or the ID +// number of the controlling macro. +class LazyIdentifierInfoPtr { + // If the low bit is clear, a pointer to the IdentifierInfo. If the low + // bit is set, the upper 63 bits are the ID number. + mutable uint64_t Ptr = 0; + +public: + LazyIdentifierInfoPtr() = default; + + explicit LazyIdentifierInfoPtr(const IdentifierInfo *Ptr) + : Ptr(reinterpret_cast<uint64_t>(Ptr)) {} + + explicit LazyIdentifierInfoPtr(uint64_t ID) : Ptr((ID << 1) | 0x01) { + assert((ID << 1 >> 1) == ID && "ID must require < 63 bits"); + if (ID == 0) + Ptr = 0; + } + + LazyIdentifierInfoPtr &operator=(const IdentifierInfo *Ptr) { + this->Ptr = reinterpret_cast<uint64_t>(Ptr); + return *this; + } + + LazyIdentifierInfoPtr &operator=(uint64_t ID) { + assert((ID << 1 >> 1) == ID && "IDs must require < 63 bits"); + if (ID == 0) + Ptr = 0; + else + Ptr = (ID << 1) | 0x01; + + return *this; + } + + /// Whether this pointer is non-NULL. + /// + /// This operation does not require the AST node to be deserialized. + bool isValid() const { return Ptr != 0; } + + /// Whether this pointer is currently stored as ID. + bool isID() const { return Ptr & 0x01; } + + IdentifierInfo *getPtr() const { + assert(!isID()); + return reinterpret_cast<IdentifierInfo *>(Ptr); + } + + uint64_t getID() const { + assert(isID()); + return Ptr >> 1; + } +}; } #endif diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h index d8ca1c5..df75c19 100644 --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -16,6 +16,7 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/DirectoryLookup.h" +#include "clang/Lex/ExternalPreprocessorSource.h" #include "clang/Lex/HeaderMap.h" #include "clang/Lex/ModuleMap.h" #include "llvm/ADT/ArrayRef.h" @@ -121,13 +122,6 @@ struct HeaderFileInfo { LLVM_PREFERRED_TYPE(bool) unsigned IsValid : 1; - /// The ID number of the controlling macro. - /// - /// This ID number will be non-zero when there is a controlling - /// macro whose IdentifierInfo may not yet have been loaded from - /// external storage. - unsigned ControllingMacroID = 0; - /// If this file has a \#ifndef XXX (or equivalent) guard that /// protects the entire contents of the file, this is the identifier /// for the macro that controls whether or not it has any effect. @@ -136,7 +130,7 @@ struct HeaderFileInfo { /// the controlling macro of this header, since /// getControllingMacro() is able to load a controlling macro from /// external storage. - const IdentifierInfo *ControllingMacro = nullptr; + LazyIdentifierInfoPtr LazyControllingMacro; /// If this header came from a framework include, this is the name /// of the framework. @@ -582,7 +576,7 @@ public: /// no-op \#includes. void SetFileControllingMacro(FileEntryRef File, const IdentifierInfo *ControllingMacro) { - getFileInfo(File).ControllingMacro = ControllingMacro; + getFileInfo(File).LazyControllingMacro = ControllingMacro; } /// Determine whether this file is intended to be safe from diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 9321a36..3bd3aa4 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -60,19 +60,21 @@ ALWAYS_ENABLED_STATISTIC(NumSubFrameworkLookups, const IdentifierInfo * HeaderFileInfo::getControllingMacro(ExternalPreprocessorSource *External) { - if (ControllingMacro) { - if (ControllingMacro->isOutOfDate()) { - assert(External && "We must have an external source if we have a " - "controlling macro that is out of date."); - External->updateOutOfDateIdentifier(*ControllingMacro); - } - return ControllingMacro; - } + if (LazyControllingMacro.isID()) { + if (!External) + return nullptr; - if (!ControllingMacroID || !External) - return nullptr; + LazyControllingMacro = + External->GetIdentifier(LazyControllingMacro.getID()); + return LazyControllingMacro.getPtr(); + } - ControllingMacro = External->GetIdentifier(ControllingMacroID); + IdentifierInfo *ControllingMacro = LazyControllingMacro.getPtr(); + if (ControllingMacro && ControllingMacro->isOutOfDate()) { + assert(External && "We must have an external source if we have a " + "controlling macro that is out of date."); + External->updateOutOfDateIdentifier(*ControllingMacro); + } return ControllingMacro; } @@ -1348,10 +1350,8 @@ static void mergeHeaderFileInfo(HeaderFileInfo &HFI, mergeHeaderFileInfoModuleBits(HFI, OtherHFI.isModuleHeader, OtherHFI.isTextualModuleHeader); - if (!HFI.ControllingMacro && !HFI.ControllingMacroID) { - HFI.ControllingMacro = OtherHFI.ControllingMacro; - HFI.ControllingMacroID = OtherHFI.ControllingMacroID; - } + if (!HFI.LazyControllingMacro.isValid()) + HFI.LazyControllingMacro = OtherHFI.LazyControllingMacro; HFI.DirInfo = OtherHFI.DirInfo; HFI.External = (!HFI.IsValid || HFI.External); @@ -1426,8 +1426,7 @@ bool HeaderSearch::isFileMultipleIncludeGuarded(FileEntryRef File) const { // once. Note that we dor't check for #import, because that's not a property // of the file itself. if (auto *HFI = getExistingFileInfo(File)) - return HFI->isPragmaOnce || HFI->ControllingMacro || - HFI->ControllingMacroID; + return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid(); return false; } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 973475c..0afbc44 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2092,7 +2092,7 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, HFI.isPragmaOnce |= (Flags >> 4) & 0x01; HFI.DirInfo = (Flags >> 1) & 0x07; HFI.IndexHeaderMapHeader = Flags & 0x01; - HFI.ControllingMacroID = Reader.getGlobalIdentifierID( + HFI.LazyControllingMacro = Reader.getGlobalIdentifierID( M, endian::readNext<uint32_t, llvm::endianness::little>(d)); if (unsigned FrameworkOffset = endian::readNext<uint32_t, llvm::endianness::little>(d)) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 50fa44d..a60092a 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -2028,10 +2028,11 @@ namespace { | Data.HFI.IndexHeaderMapHeader; LE.write<uint8_t>(Flags); - if (!Data.HFI.ControllingMacro) - LE.write<uint32_t>(Data.HFI.ControllingMacroID); + if (Data.HFI.LazyControllingMacro.isID()) + LE.write<IdentifierID>(Data.HFI.LazyControllingMacro.getID()); else - LE.write<uint32_t>(Writer.getIdentifierRef(Data.HFI.ControllingMacro)); + LE.write<IdentifierID>( + Writer.getIdentifierRef(Data.HFI.LazyControllingMacro.getPtr())); unsigned Offset = 0; if (!Data.HFI.Framework.empty()) { |