]> granicus.if.org Git - clang/commitdiff
Introduce a global bit-offset continuous range map into the ASTReader,
authorDouglas Gregor <dgregor@apple.com>
Fri, 22 Jul 2011 06:10:01 +0000 (06:10 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 22 Jul 2011 06:10:01 +0000 (06:10 +0000)
so that we have one, simple way to map from global bit offsets to
local bit offsets. Eliminates a number of loops over the chain, and
generalizes for more interesting bit remappings.

Also, as an amusing oddity, we were computing global bit offsets
*backwards* for preprocessed entities (e.g., the directly included PCH
file in the chain would start at offset zero, rather than the original
PCH that occurs first in translation unit). Even more amusingly, it
made precompiled preambles work, because we were forgetting to adjust
the local bit offset to a global bit offset when storing preprocessed
entity offsets in the ASTUnit. Two wrongs made a right, and now
they're both right.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@135750 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Serialization/ASTReader.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriter.cpp

index c677ae284c4bf77c0ef88bfdb1d4d4e3e1e896f8..6591d1295a572ea623c2626478c9932c82c8ee73 100644 (file)
@@ -450,6 +450,10 @@ private:
   /// That is, the entry I was created with -include-pch I+1.
   SmallVector<PerFileData*, 2> Chain;
 
+  /// \brief A map of global bit offsets to the module that stores entities
+  /// at those bit offsets.
+  ContinuousRangeMap<uint64_t, PerFileData*, 4> GlobalBitOffsetsMap;
+
   /// \brief SLocEntries that we're going to preload.
   SmallVector<int, 64> PreloadSLocEntries;
 
@@ -919,7 +923,8 @@ private:
   void LoadedDecl(unsigned Index, Decl *D);
   Decl *ReadDeclRecord(unsigned Index, serialization::DeclID ID);
   RecordLocation DeclCursorForIndex(unsigned Index, serialization::DeclID ID);
-
+  RecordLocation getLocalBitOffset(uint64_t GlobalOffset);
+  
   void PassInterestingDeclsToConsumer();
 
   /// \brief Produce an error diagnostic and return true.
index 0ef94aae3b9cd2acb7559967e1d8befaadfb059f..e6d16fed3c0166177a741ee4213ea484b75dd546 100644 (file)
@@ -1735,15 +1735,8 @@ void ASTReader::SetIdentifierIsMacro(IdentifierInfo *II, PerFileData &F,
   // 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;
+  // Adjust the offset to a global offset.
+  UnreadMacroRecordOffsets[II] = F.GlobalBitOffset + Offset;
 }
 
 void ASTReader::ReadDefinedMacros() {
@@ -1807,24 +1800,11 @@ void ASTReader::ReadDefinedMacros() {
 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);
+  RecordLocation Loc = getLocalBitOffset(Offset);
+  ReadMacroRecord(*Loc.F, Loc.Offset);
 }
 
 void ASTReader::LoadMacroDefinition(IdentifierInfo *II) {
@@ -2027,7 +2007,7 @@ ASTReader::ReadASTBlock(PerFileData &F) {
         // If we have to ignore the dependency, we'll have to ignore this too.
       case IgnorePCH: return IgnorePCH;
       case Success: break;
-      }
+      }     
       break;
     }
 
@@ -2420,10 +2400,6 @@ ASTReader::ReadASTBlock(PerFileData &F) {
                                             -getTotalNumCXXBaseSpecifiers())));
 
       NumCXXBaseSpecifiersLoaded += F.LocalNumCXXBaseSpecifiers;
-
-      F.GlobalBitOffset = TotalModulesSizeInBits;
-      TotalModulesSizeInBits += F.SizeInBits;
-
       break;
     }
 
@@ -2705,7 +2681,7 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(llvm::StringRef FileName,
   llvm::BitstreamCursor &Stream = F.Stream;
   Stream.init(F.StreamFile);
   F.SizeInBits = F.Buffer->getBufferSize() * 8;
-
+  
   // Sniff for the signature.
   if (Stream.Read(8) != 'C' ||
       Stream.Read(8) != 'P' ||
@@ -2764,7 +2740,12 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(llvm::StringRef FileName,
       break;
     }
   }
-
+  
+  // Once read, set the PerFileData bit base offset and update the size in 
+  // bits of all files we've seen.
+  F.GlobalBitOffset = TotalModulesSizeInBits;
+  TotalModulesSizeInBits += F.SizeInBits;
+  GlobalBitOffsetsMap.insert(std::make_pair(F.GlobalBitOffset, &F));
   return Success;
 }
 
@@ -3090,26 +3071,13 @@ void ASTReader::ReadPreprocessedEntities() {
 }
 
 PreprocessedEntity *ASTReader::ReadPreprocessedEntityAtOffset(uint64_t Offset) {
-  PerFileData *F = 0;  
-  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 preprocessed entity offset");
-    return 0;
-  }
+  RecordLocation Loc = getLocalBitOffset(Offset);
 
   // Keep track of where we are in the stream, then jump back there
   // after reading this entity.
-  SavedStreamPosition SavedPosition(F->PreprocessorDetailCursor);  
-  F->PreprocessorDetailCursor.JumpToBit(Offset);
-  return LoadPreprocessedEntity(*F);
+  SavedStreamPosition SavedPosition(Loc.F->PreprocessorDetailCursor);  
+  Loc.F->PreprocessorDetailCursor.JumpToBit(Loc.Offset);
+  return LoadPreprocessedEntity(*Loc.F);
 }
 
 HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) {
@@ -4006,25 +3974,10 @@ ASTReader::GetCXXBaseSpecifiersOffset(serialization::CXXBaseSpecifiersID ID) {
 }
 
 CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
-  // Figure out which AST file contains this offset.
-  PerFileData *F = 0;
-  for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
-    if (Offset < Chain[N - I - 1]->SizeInBits) {
-      F = Chain[N - I - 1];
-      break;
-    }
-    
-    Offset -= Chain[N - I - 1]->SizeInBits;
-  }
-
-  if (!F) {
-    Error("Malformed AST file: C++ base specifiers at impossible offset");
-    return 0;
-  }
-  
-  llvm::BitstreamCursor &Cursor = F->DeclsCursor;
+  RecordLocation Loc = getLocalBitOffset(Offset);
+  llvm::BitstreamCursor &Cursor = Loc.F->DeclsCursor;
   SavedStreamPosition SavedPosition(Cursor);
-  Cursor.JumpToBit(Offset);
+  Cursor.JumpToBit(Loc.Offset);
   ReadingKindTracker ReadingKind(Read_Decl, *this);
   RecordData Record;
   unsigned Code = Cursor.ReadCode();
@@ -4039,7 +3992,7 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
   void *Mem = Context->Allocate(sizeof(CXXBaseSpecifier) * NumBases);
   CXXBaseSpecifier *Bases = new (Mem) CXXBaseSpecifier [NumBases];
   for (unsigned I = 0; I != NumBases; ++I)
-    Bases[I] = ReadCXXBaseSpecifier(*F, Record, Idx);
+    Bases[I] = ReadCXXBaseSpecifier(*Loc.F, Record, Idx);
   return Bases;
 }
 
@@ -4099,17 +4052,9 @@ Stmt *ASTReader::GetExternalDeclStmt(uint64_t Offset) {
   ClearSwitchCaseIDs();
 
   // Offset here is a global offset across the entire chain.
-  for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
-    PerFileData &F = *Chain[N - I - 1];
-    if (Offset < F.SizeInBits) {
-      // Since we know that this statement is part of a decl, make sure to use
-      // the decl cursor to read it.
-      F.DeclsCursor.JumpToBit(Offset);
-      return ReadStmtFromStream(F);
-    }
-    Offset -= F.SizeInBits;
-  }
-  llvm_unreachable("Broken chain");
+  RecordLocation Loc = getLocalBitOffset(Offset);
+  Loc.F->DeclsCursor.JumpToBit(Loc.Offset);
+  return ReadStmtFromStream(*Loc.F);
 }
 
 ExternalLoadResult ASTReader::FindExternalLexicalDecls(const DeclContext *DC,
@@ -4342,6 +4287,7 @@ dumpModuleIDOffsetMap(llvm::StringRef Name,
                             
 void ASTReader::dump() {
   llvm::errs() << "*** AST File Remapping:\n";
+  dumpModuleIDMap("Global bit offset map", GlobalBitOffsetsMap);
   dumpModuleIDMap("Global source location entry map", GlobalSLocEntryMap);
   dumpModuleIDOffsetMap("Global type map", GlobalTypeMap);
   dumpModuleIDOffsetMap("Global declaration map", GlobalDeclMap);
index 20b72ec4e2aea4353ec66c0154db109d7ad36b0e..841c4d7d1b832ff0915a5a1bd1b8e9a6a0a0274d 100644 (file)
@@ -178,16 +178,7 @@ namespace clang {
 }
 
 uint64_t ASTDeclReader::GetCurrentCursorOffset() {
-  uint64_t Off = 0;
-  for (unsigned I = 0, N = Reader.Chain.size(); I != N; ++I) {
-    ASTReader::PerFileData &F = *Reader.Chain[N - I - 1];
-    if (&Cursor == &F.DeclsCursor) {
-      Off += F.DeclsCursor.GetCurrentBitNo();
-      break;
-    }
-    Off += F.SizeInBits;
-  }
-  return Off;
+  return F.DeclsCursor.GetCurrentBitNo() + F.GlobalBitOffset;
 }
 
 void ASTDeclReader::Visit(Decl *D) {
@@ -1419,6 +1410,14 @@ ASTReader::DeclCursorForIndex(unsigned Index, DeclID ID) {
                         I->second.first->DeclOffsets[Index + I->second.second]);
 }
 
+ASTReader::RecordLocation ASTReader::getLocalBitOffset(uint64_t GlobalOffset) {
+  ContinuousRangeMap<uint64_t, PerFileData*, 4>::iterator I
+    = GlobalBitOffsetsMap.find(GlobalOffset);
+
+  assert(I != GlobalBitOffsetsMap.end() && "Corrupted global bit offsets map");
+  return RecordLocation(I->second, GlobalOffset - I->second->GlobalBitOffset);
+}
+
 void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
   assert(D && previous);
   if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
index aaf4678ba29bf6999f14d042758ad890a3772f18..e6e88f8f872b5c7d9cbf9cfec08701117ab8d63d 100644 (file)
@@ -1803,6 +1803,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
   
   unsigned IndexBase = Chain ? PPRec.getNumLoadedPreprocessedEntities() : 0;
   RecordData Record;
+  uint64_t BitsInChain = Chain? Chain->TotalModulesSizeInBits : 0;
   for (PreprocessingRecord::iterator E = PPRec.begin(Chain),
                                   EEnd = PPRec.end(Chain);
        E != EEnd; ++E) {
@@ -1819,7 +1820,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
       // Notify the serialization listener that we're serializing this entity.
       if (SerializationListener)
         SerializationListener->SerializedPreprocessedEntity(*E, 
-                                                    Stream.GetCurrentBitNo());
+          BitsInChain + Stream.GetCurrentBitNo());
 
       unsigned Position = ID - FirstMacroID;
       if (Position != MacroDefinitionOffsets.size()) {
@@ -1843,7 +1844,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
     // Notify the serialization listener that we're serializing this entity.
     if (SerializationListener)
       SerializationListener->SerializedPreprocessedEntity(*E, 
-                                                    Stream.GetCurrentBitNo());
+        BitsInChain + Stream.GetCurrentBitNo());
 
     if (MacroExpansion *ME = dyn_cast<MacroExpansion>(*E)) {
       Record.push_back(IndexBase + NumPreprocessingRecords++);