diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-10-30 00:23:06 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-10-30 00:23:06 +0000 |
commit | 295a2a617ac335f590e430ab7fcd98f8ce109251 (patch) | |
tree | f99afd1bb537d0c93b87cd955cefe6e810cc36e0 | |
parent | 20e047abc5f19dc948436c0fb891450d9cd40667 (diff) |
Make the deserialization of macro definitions lazy, so that we can
load identifiers without loading their corresponding macro
definitions. This is likely to improve PCH performance slightly, and
reduces deserialization stack depth considerably when using
preprocessor metaprogramming.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117750 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/IdentifierTable.h | 2 | ||||
-rw-r--r-- | include/clang/Lex/ExternalPreprocessorSource.h | 3 | ||||
-rw-r--r-- | include/clang/Lex/Preprocessor.h | 7 | ||||
-rw-r--r-- | include/clang/Serialization/ASTReader.h | 18 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 15 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 51 |
6 files changed, 93 insertions, 3 deletions
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index 66c5deea54..0013bd937c 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -71,7 +71,7 @@ class IdentifierInfo { void operator=(const IdentifierInfo&); // NONASSIGNABLE. friend class IdentifierTable; - + public: IdentifierInfo(); diff --git a/include/clang/Lex/ExternalPreprocessorSource.h b/include/clang/Lex/ExternalPreprocessorSource.h index 791d3fe304..dbf7389033 100644 --- a/include/clang/Lex/ExternalPreprocessorSource.h +++ b/include/clang/Lex/ExternalPreprocessorSource.h @@ -27,6 +27,9 @@ public: /// \brief Read the set of macros defined by this external macro source. virtual void ReadDefinedMacros() = 0; + + /// \brief Read the definition for the given macro. + virtual void LoadMacroDefinition(IdentifierInfo *II) = 0; }; } diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 87b62d0a9a..7b138884e0 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -262,6 +262,8 @@ private: // Cached tokens state. /// allocation. MacroInfoChain *MICache; + MacroInfo *getInfoForMacro(IdentifierInfo *II) const; + public: Preprocessor(Diagnostic &diags, const LangOptions &opts, const TargetInfo &target, @@ -335,7 +337,10 @@ public: /// getMacroInfo - Given an identifier, return the MacroInfo it is #defined to /// or null if it isn't #define'd. MacroInfo *getMacroInfo(IdentifierInfo *II) const { - return II->hasMacroDefinition() ? Macros.find(II)->second : 0; + if (!II->hasMacroDefinition()) + return 0; + + return getInfoForMacro(II); } /// setMacroInfo - Specify a macro for this identifier. diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index e855cc7948..9ac7c31852 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -488,6 +488,11 @@ private: /// \brief The macro definitions we have already loaded. llvm::SmallVector<MacroDefinition *, 16> MacroDefinitionsLoaded; + /// \brief Mapping from identifiers that represent macros whose definitions + /// have not yet been deserialized to the global offset where the macro + /// record resides. + llvm::DenseMap<IdentifierInfo *, uint64_t> UnreadMacroRecordOffsets; + /// \name CodeGen-relevant special data /// \brief Fields containing data that is relevant to CodeGen. //@{ @@ -1145,9 +1150,22 @@ public: /// \brief Reads the macro record located at the given offset. void ReadMacroRecord(PerFileData &F, uint64_t Offset); + /// \brief Note that the identifier is a macro whose record will be loaded + /// from the given AST file at the given (file-local) offset. + void SetIdentifierIsMacro(IdentifierInfo *II, PerFileData &F, + uint64_t Offset); + /// \brief Read the set of macros defined by this external macro source. virtual void ReadDefinedMacros(); + /// \brief Read the macro definition for this identifier. + virtual void LoadMacroDefinition(IdentifierInfo *II); + + /// \brief Read the macro definition corresponding to this iterator + /// into the unread macro record offsets table. + void LoadMacroDefinition( + llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos); + /// \brief Retrieve the macro definition with the given ID. MacroDefinition *getMacroDefinition(serialization::MacroID ID); diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 68fc56f7b7..a9f4cacf6c 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -20,12 +20,27 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/CodeCompletionHandler.h" +#include "clang/Lex/ExternalPreprocessorSource.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/raw_ostream.h" #include <cstdio> #include <ctime> using namespace clang; +MacroInfo *Preprocessor::getInfoForMacro(IdentifierInfo *II) const { + assert(II->hasMacroDefinition() && "Identifier is not a macro!"); + + llvm::DenseMap<IdentifierInfo*, MacroInfo*>::const_iterator Pos + = Macros.find(II); + if (Pos == Macros.end()) { + // Load this macro from the external source. + getExternalSource()->LoadMacroDefinition(II); + Pos = Macros.find(II); + } + assert(Pos != Macros.end() && "Identifier macro info is missing!"); + return Pos->second; +} + /// setMacroInfo - Specify a macro for this identifier. /// void Preprocessor::setMacroInfo(IdentifierInfo *II, MacroInfo *MI) { diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index aa76765dc9..22d3cbc68f 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -682,7 +682,7 @@ public: // definition. if (hasMacroDefinition) { uint32_t Offset = ReadUnalignedLE32(d); - Reader.ReadMacroRecord(F, Offset); + Reader.SetIdentifierIsMacro(II, F, Offset); DataLen -= 4; } @@ -1568,6 +1568,22 @@ void ASTReader::ReadMacroRecord(PerFileData &F, uint64_t Offset) { } } +void ASTReader::SetIdentifierIsMacro(IdentifierInfo *II, PerFileData &F, + uint64_t Offset) { + // Note that this identifier has a macro definition. + II->setHasMacroDefinition(true); + + // Adjust the offset based on our position in the chain. + for (unsigned I = 0, N = Chain.size(); I != N; ++I) { + if (Chain[I] == &F) + break; + + Offset += Chain[I]->SizeInBits; + } + + UnreadMacroRecordOffsets[II] = Offset; +} + void ASTReader::ReadDefinedMacros() { for (unsigned I = 0, N = Chain.size(); I != N; ++I) { PerFileData &F = *Chain[N - I - 1]; @@ -1629,6 +1645,39 @@ void ASTReader::ReadDefinedMacros() { } } } + + // Drain the unread macro-record offsets map. + while (!UnreadMacroRecordOffsets.empty()) + LoadMacroDefinition(UnreadMacroRecordOffsets.begin()); +} + +void ASTReader::LoadMacroDefinition( + llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos) { + assert(Pos != UnreadMacroRecordOffsets.end() && "Unknown macro definition"); + PerFileData *F = 0; + uint64_t Offset = Pos->second; + UnreadMacroRecordOffsets.erase(Pos); + + for (unsigned I = 0, N = Chain.size(); I != N; ++I) { + if (Offset < Chain[I]->SizeInBits) { + F = Chain[I]; + break; + } + + Offset -= Chain[I]->SizeInBits; + } + if (!F) { + Error("Malformed macro record offset"); + return; + } + + ReadMacroRecord(*F, Offset); +} + +void ASTReader::LoadMacroDefinition(IdentifierInfo *II) { + llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos + = UnreadMacroRecordOffsets.find(II); + LoadMacroDefinition(Pos); } MacroDefinition *ASTReader::getMacroDefinition(MacroID ID) { |