]> granicus.if.org Git - clang/commitdiff
Make the deserialization of macro definitions lazy, so that we can
authorDouglas Gregor <dgregor@apple.com>
Sat, 30 Oct 2010 00:23:06 +0000 (00:23 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 30 Oct 2010 00:23:06 +0000 (00:23 +0000)
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
include/clang/Lex/ExternalPreprocessorSource.h
include/clang/Lex/Preprocessor.h
include/clang/Serialization/ASTReader.h
lib/Lex/PPMacroExpansion.cpp
lib/Serialization/ASTReader.cpp

index 66c5deea547072db7b2c8535ae14b02ac28f8fbd..0013bd937c44633a7f29ad988f163cbdff60a8c8 100644 (file)
@@ -71,7 +71,7 @@ class IdentifierInfo {
   void operator=(const IdentifierInfo&);  // NONASSIGNABLE.
 
   friend class IdentifierTable;
-
+  
 public:
   IdentifierInfo();
 
index 791d3fe304ecb137a6a67e24d9660e51ada9fb55..dbf7389033718df9b5bc240d40f35ed0d3bfd2ba 100644 (file)
@@ -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;
 };
   
 }
index 87b62d0a9a7673b4d27b2f9ddcae1ef58cd0bc3f..7b138884e0bb5758fb7a56c32f0df7f91fa9ef12 100644 (file)
@@ -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.
index e855cc79488c7277fadf93c30822688a53b56d49..9ac7c3185290c0f95f95e5833ee157c1161fb355 100644 (file)
@@ -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);
 
index 68fc56f7b7893dff2c28aa8ad8be86ea9e2ac0b2..a9f4cacf6ce6abd037c4f32756200ce8a4d07638 100644 (file)
 #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) {
index aa76765dc9dac46df2fe9b556945858b2565089c..22d3cbc68f71f32faf40977e358914cd3c408c3c 100644 (file)
@@ -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) {