Index: clang/include/clang/Basic/SourceManager.h =================================================================== --- clang/include/clang/Basic/SourceManager.h +++ clang/include/clang/Basic/SourceManager.h @@ -69,6 +69,33 @@ /// SourceManager implementation. namespace SrcMgr { + /// Optional index for loadable SLoc entries. Semantics of Optional + /// but without storage overhead. + class LoadedSLocEntryIndex { + public: + explicit operator bool() const { return Data; } + unsigned operator*() const { + assert(*this && "Dereferencing None?"); + return Data - 1; + } + + LoadedSLocEntryIndex &operator=(llvm::NoneType) { + return *this = LoadedSLocEntryIndex(None); + } + LoadedSLocEntryIndex &operator=(unsigned I) { + return *this = LoadedSLocEntryIndex(I); + } + LoadedSLocEntryIndex(llvm::NoneType = None) : Data(0) {} + LoadedSLocEntryIndex(unsigned I) : Data(I + 1) { + assert(*this && "Index too big"); + } + + private: + /// Index stored off-by-one with 0 as a sentinel to enable + /// zero-initialization. + unsigned Data; + }; + /// Indicates whether a file or directory holds normal user code, /// system code, or system code which is implicitly 'extern "C"' in C++ mode. /// @@ -677,8 +704,8 @@ /// The table of SLocEntries that are loaded from other modules. /// - /// Negative FileIDs are indexes into this table. To get from ID to an index, - /// use (-ID - 2). + /// Negative FileIDs are indexes into LoadedSLocEntryIndices, which contains the + /// index into this table. SmallVector LoadedSLocEntryTable; /// The starting offset of the next local SLocEntry. @@ -688,19 +715,20 @@ /// The starting offset of the latest batch of loaded SLocEntries. /// - /// This is LoadedSLocEntryTable.back().Offset, except that that entry might - /// not have been loaded, so that value would be unknown. + /// This is LoadedSLocEntryTable[SLocEntryIndices.back()].Offset, except that + /// that entry might not have been loaded, so that value would be unknown. unsigned CurrentLoadedOffset; /// The highest possible offset is 2^31-1, so CurrentLoadedOffset /// starts at 2^31. static const unsigned MaxLoadedOffset = 1U << 31U; - /// A bitmap that indicates whether the entries of LoadedSLocEntryTable - /// have already been loaded from the external source. + /// An optional index into LoadedSLocEntryTable, where None indicates that an + /// SLocEntry has not yet been allocated. /// - /// Same indexing as LoadedSLocEntryTable. - llvm::BitVector SLocEntryLoaded; + /// Negative FileIDs are indexes into this table. To get from ID to an index, + /// use (-ID - 2). + SmallVector SLocEntryIndices; /// An external source for source location entries. ExternalSLocEntrySource *ExternalSLocEntries = nullptr; @@ -1659,14 +1687,14 @@ } /// Get the number of loaded SLocEntries we have. - unsigned loaded_sloc_entry_size() const { return LoadedSLocEntryTable.size();} + unsigned loaded_sloc_entry_size() const { return SLocEntryIndices.size(); } /// Get a loaded SLocEntry. This is exposed for indexing. const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index, bool *Invalid = nullptr) const { - assert(Index < LoadedSLocEntryTable.size() && "Invalid index"); - if (SLocEntryLoaded[Index]) - return LoadedSLocEntryTable[Index]; + assert(Index < SLocEntryIndices.size() && "Invalid index"); + if (auto I = SLocEntryIndices[Index]) + return LoadedSLocEntryTable[*I]; return loadSLocEntry(Index, Invalid); } @@ -1682,8 +1710,7 @@ unsigned getNextLocalOffset() const { return NextLocalOffset; } void setExternalSLocEntrySource(ExternalSLocEntrySource *Source) { - assert(LoadedSLocEntryTable.empty() && - "Invalidating existing loaded entries"); + assert(SLocEntryIndices.empty() && "Invalidating existing loaded entries"); ExternalSLocEntries = Source; } Index: clang/lib/Basic/SourceManager.cpp =================================================================== --- clang/lib/Basic/SourceManager.cpp +++ clang/lib/Basic/SourceManager.cpp @@ -331,7 +331,7 @@ MainFileID = FileID(); LocalSLocEntryTable.clear(); LoadedSLocEntryTable.clear(); - SLocEntryLoaded.clear(); + SLocEntryIndices.clear(); LastLineNoFileIDQuery = FileID(); LastLineNoContentCache = nullptr; LastFileIDLookup = FileID(); @@ -367,8 +367,8 @@ }; // Ensure all SLocEntries are loaded from the external source. - for (unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I) - if (!Old.SLocEntryLoaded[I]) + for (unsigned I = 0, N = Old.SLocEntryIndices.size(); I != N; ++I) + if (!Old.SLocEntryIndices[I]) Old.loadSLocEntry(I, nullptr); // Inherit any content cache data from the old source manager. @@ -429,12 +429,12 @@ const SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index, bool *Invalid) const { - assert(!SLocEntryLoaded[Index]); + assert(!SLocEntryIndices[Index]); if (ExternalSLocEntries->ReadSLocEntry(-(static_cast(Index) + 2))) { if (Invalid) *Invalid = true; // If the file of the SLocEntry changed we could still have loaded it. - if (!SLocEntryLoaded[Index]) { + if (!SLocEntryIndices[Index]) { // Try to recover; create a SLocEntry so the rest of clang can handle it. if (!FakeSLocEntryForRecovery) FakeSLocEntryForRecovery = std::make_unique( @@ -445,7 +445,8 @@ } } - return LoadedSLocEntryTable[Index]; + assert(SLocEntryIndices[Index] && "Failed to load but returned success"); + return LoadedSLocEntryTable[*SLocEntryIndices[Index]]; } std::pair @@ -455,10 +456,9 @@ // Make sure we're not about to run out of source locations. if (CurrentLoadedOffset - TotalSize < NextLocalOffset) return std::make_pair(0, 0); - LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries); - SLocEntryLoaded.resize(LoadedSLocEntryTable.size()); + SLocEntryIndices.resize(SLocEntryIndices.size() + NumSLocEntries); CurrentLoadedOffset -= TotalSize; - int ID = LoadedSLocEntryTable.size(); + int ID = SLocEntryIndices.size(); return std::make_pair(-ID - 1, CurrentLoadedOffset); } @@ -497,7 +497,7 @@ if (ID > 0) { if (ID-1 == 0) return FileID(); - } else if (unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) { + } else if (unsigned(-(ID - 1) - 2) >= SLocEntryIndices.size()) { return FileID(); } @@ -598,11 +598,12 @@ if (LoadedID < 0) { assert(LoadedID != -1 && "Loading sentinel FileID"); unsigned Index = unsigned(-LoadedID) - 2; - assert(Index < LoadedSLocEntryTable.size() && "FileID out of range"); - assert(!SLocEntryLoaded[Index] && "FileID already loaded"); - LoadedSLocEntryTable[Index] = SLocEntry::get( - LoadedOffset, FileInfo::get(IncludePos, File, FileCharacter, Filename)); - SLocEntryLoaded[Index] = true; + assert(Index < SLocEntryIndices.size() && "FileID out of range"); + assert(!SLocEntryIndices[Index] && "FileID already loaded"); + SLocEntryIndices[Index] = LoadedSLocEntryTable.size(); + LoadedSLocEntryTable.push_back( + SLocEntry::get(LoadedOffset, FileInfo::get(IncludePos, File, + FileCharacter, Filename))); return FileID::get(LoadedID); } unsigned FileSize = File.getSize(); @@ -664,10 +665,10 @@ if (LoadedID < 0) { assert(LoadedID != -1 && "Loading sentinel FileID"); unsigned Index = unsigned(-LoadedID) - 2; - assert(Index < LoadedSLocEntryTable.size() && "FileID out of range"); - assert(!SLocEntryLoaded[Index] && "FileID already loaded"); - LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info); - SLocEntryLoaded[Index] = true; + assert(Index < SLocEntryIndices.size() && "FileID out of range"); + assert(!SLocEntryIndices[Index] && "FileID already loaded"); + SLocEntryIndices[Index] = LoadedSLocEntryTable.size(); + LoadedSLocEntryTable.push_back(SLocEntry::get(LoadedOffset, Info)); return SourceLocation::getMacroLoc(LoadedOffset); } LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info)); @@ -899,7 +900,7 @@ // table: GreaterIndex is the one where the offset is greater, which is // actually a lower index! unsigned GreaterIndex = I; - unsigned LessIndex = LoadedSLocEntryTable.size(); + unsigned LessIndex = SLocEntryIndices.size(); NumProbes = 0; while (true) { ++NumProbes; @@ -2090,8 +2091,8 @@ << llvm::capacity_in_bytes(LocalSLocEntryTable) << " bytes of capacity), " << NextLocalOffset << "B of Sloc address space used.\n"; - llvm::errs() << LoadedSLocEntryTable.size() - << " loaded SLocEntries allocated, " + llvm::errs() << SLocEntryIndices.size() << " loaded SLocEntries (" + << LoadedSLocEntryTable.size() << " allocated), " << MaxLoadedOffset - CurrentLoadedOffset << "B of Sloc address space used.\n"; @@ -2155,11 +2156,11 @@ } // Dump loaded SLocEntries. llvm::Optional NextStart; - for (unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) { + for (unsigned Index = 0; Index != SLocEntryIndices.size(); ++Index) { int ID = -(int)Index - 2; - if (SLocEntryLoaded[Index]) { - DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart); - NextStart = LoadedSLocEntryTable[Index].getOffset(); + if (auto I = SLocEntryIndices[Index]) { + DumpSLocEntry(ID, LoadedSLocEntryTable[*I], NextStart); + NextStart = LoadedSLocEntryTable[*I].getOffset(); } else { NextStart = None; } @@ -2192,7 +2193,7 @@ size_t size = llvm::capacity_in_bytes(MemBufferInfos) + llvm::capacity_in_bytes(LocalSLocEntryTable) + llvm::capacity_in_bytes(LoadedSLocEntryTable) - + llvm::capacity_in_bytes(SLocEntryLoaded) + + llvm::capacity_in_bytes(SLocEntryIndices) + llvm::capacity_in_bytes(FileInfos); if (OverriddenFilesInfo)