From 295a2a617ac335f590e430ab7fcd98f8ce109251 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sat, 30 Oct 2010 00:23:06 +0000 Subject: [PATCH] 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 --- include/clang/Basic/IdentifierTable.h | 2 +- .../clang/Lex/ExternalPreprocessorSource.h | 3 ++ include/clang/Lex/Preprocessor.h | 7 ++- include/clang/Serialization/ASTReader.h | 18 +++++++ lib/Lex/PPMacroExpansion.cpp | 15 ++++++ 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 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 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::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 #include using namespace clang; +MacroInfo *Preprocessor::getInfoForMacro(IdentifierInfo *II) const { + assert(II->hasMacroDefinition() && "Identifier is not a macro!"); + + llvm::DenseMap::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::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::iterator Pos + = UnreadMacroRecordOffsets.find(II); + LoadMacroDefinition(Pos); } MacroDefinition *ASTReader::getMacroDefinition(MacroID ID) { -- 2.40.0