diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Basic/SourceManager.cpp | 56 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHReader.cpp | 192 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHWriter.cpp | 166 |
3 files changed, 286 insertions, 128 deletions
diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index 9ed21635259..50576636db3 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -308,6 +308,17 @@ SourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) { return Entry; } +void SourceManager::PreallocateSLocEntries(ExternalSLocEntrySource *Source, + unsigned NumSLocEntries, + unsigned NextOffset) { + ExternalSLocEntries = Source; + this->NextOffset = NextOffset; + SLocEntryLoaded.resize(NumSLocEntries + 1); + SLocEntryLoaded[0] = true; + SLocEntryTable.resize(SLocEntryTable.size() + NumSLocEntries); +} + + //===----------------------------------------------------------------------===// // Methods to create new FileID's and instantiations. //===----------------------------------------------------------------------===// @@ -317,7 +328,26 @@ SourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) { /// corresponds to a file or some other input source. FileID SourceManager::createFileID(const ContentCache *File, SourceLocation IncludePos, - SrcMgr::CharacteristicKind FileCharacter) { + SrcMgr::CharacteristicKind FileCharacter, + unsigned PreallocatedID, + unsigned Offset) { + SLocEntry NewEntry = SLocEntry::get(NextOffset, + FileInfo::get(IncludePos, File, + FileCharacter)); + if (PreallocatedID) { + // If we're filling in a preallocated ID, just load in the file + // entry and return. + assert(PreallocatedID < SLocEntryLoaded.size() && + "Preallocate ID out-of-range"); + assert(!SLocEntryLoaded[PreallocatedID] && + "Source location entry already loaded"); + assert(Offset && "Preallocate source location cannot have zero offset"); + SLocEntryTable[PreallocatedID] + = SLocEntry::get(Offset, FileInfo::get(IncludePos, File, FileCharacter)); + SLocEntryLoaded[PreallocatedID] = true; + return LastFileIDLookup = FileID::get(PreallocatedID); + } + SLocEntryTable.push_back(SLocEntry::get(NextOffset, FileInfo::get(IncludePos, File, FileCharacter))); @@ -336,8 +366,22 @@ FileID SourceManager::createFileID(const ContentCache *File, SourceLocation SourceManager::createInstantiationLoc(SourceLocation SpellingLoc, SourceLocation ILocStart, SourceLocation ILocEnd, - unsigned TokLength) { + unsigned TokLength, + unsigned PreallocatedID, + unsigned Offset) { InstantiationInfo II = InstantiationInfo::get(ILocStart,ILocEnd, SpellingLoc); + if (PreallocatedID) { + // If we're filling in a preallocated ID, just load in the + // instantiation entry and return. + assert(PreallocatedID < SLocEntryLoaded.size() && + "Preallocate ID out-of-range"); + assert(!SLocEntryLoaded[PreallocatedID] && + "Source location entry already loaded"); + assert(Offset && "Preallocate source location cannot have zero offset"); + SLocEntryTable[PreallocatedID] = SLocEntry::get(Offset, II); + SLocEntryLoaded[PreallocatedID] = true; + return SourceLocation::getMacroLoc(Offset); + } SLocEntryTable.push_back(SLocEntry::get(NextOffset, II)); assert(NextOffset+TokLength+1 > NextOffset && "Ran out of source locations!"); NextOffset += TokLength+1; @@ -391,6 +435,8 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { unsigned NumProbes = 0; while (1) { --I; + if (ExternalSLocEntries) + getSLocEntry(FileID::get(I - SLocEntryTable.begin())); if (I->getOffset() <= SLocOffset) { #if 0 printf("lin %d -> %d [%s] %d %d\n", SLocOffset, @@ -399,7 +445,7 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { LastFileIDLookup.ID, int(SLocEntryTable.end()-I)); #endif FileID Res = FileID::get(I-SLocEntryTable.begin()); - + // If this isn't an instantiation, remember it. We have good locality // across FileID lookups. if (!I->isInstantiation()) @@ -421,7 +467,7 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { NumProbes = 0; while (1) { unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex; - unsigned MidOffset = SLocEntryTable[MiddleIndex].getOffset(); + unsigned MidOffset = getSLocEntry(FileID::get(MiddleIndex)).getOffset(); ++NumProbes; @@ -865,3 +911,5 @@ void SourceManager::PrintStats() const { llvm::cerr << "FileID scans: " << NumLinearScans << " linear, " << NumBinaryProbes << " binary.\n"; } + +ExternalSLocEntrySource::~ExternalSLocEntrySource() { } diff --git a/clang/lib/Frontend/PCHReader.cpp b/clang/lib/Frontend/PCHReader.cpp index 86848758ad6..ff8795ca640 100644 --- a/clang/lib/Frontend/PCHReader.cpp +++ b/clang/lib/Frontend/PCHReader.cpp @@ -43,8 +43,8 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext &Context) IdentifierOffsets(0), MethodPoolLookupTable(0), MethodPoolLookupTableData(0), TotalSelectorsInMethodPool(0), SelectorOffsets(0), - TotalNumSelectors(0), NumStatementsRead(0), NumMacrosRead(0), - NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0), + TotalNumSelectors(0), NumSLocEntriesRead(0), NumStatementsRead(0), + NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0), NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { } PCHReader::~PCHReader() {} @@ -423,7 +423,21 @@ static bool ParseLineTable(SourceManager &SourceMgr, /// \brief Read the source manager block PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { using namespace SrcMgr; - if (Stream.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) { + + // Set the source-location entry cursor to the current position in + // the stream. This cursor will be used to read the contents of the + // source manager block initially, and then lazily read + // source-location entries as needed. + SLocEntryCursor = Stream; + + // The stream itself is going to skip over the source manager block. + if (Stream.SkipBlock()) { + Error("Malformed block record"); + return Failure; + } + + // Enter the source manager block. + if (SLocEntryCursor.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) { Error("Malformed source manager block record"); return Failure; } @@ -432,20 +446,19 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { RecordData Record; unsigned NumHeaderInfos = 0; while (true) { - unsigned Code = Stream.ReadCode(); + unsigned Code = SLocEntryCursor.ReadCode(); if (Code == llvm::bitc::END_BLOCK) { - if (Stream.ReadBlockEnd()) { + if (SLocEntryCursor.ReadBlockEnd()) { Error("Error at end of Source Manager block"); return Failure; } - return Success; } if (Code == llvm::bitc::ENTER_SUBBLOCK) { // No known subblocks, always skip them. - Stream.ReadSubBlockID(); - if (Stream.SkipBlock()) { + SLocEntryCursor.ReadSubBlockID(); + if (SLocEntryCursor.SkipBlock()) { Error("Malformed block record"); return Failure; } @@ -453,7 +466,7 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { } if (Code == llvm::bitc::DEFINE_ABBREV) { - Stream.ReadAbbrevRecord(); + SLocEntryCursor.ReadAbbrevRecord(); continue; } @@ -461,56 +474,10 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { const char *BlobStart; unsigned BlobLen; Record.clear(); - switch (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { + switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { default: // Default behavior: ignore. break; - case pch::SM_SLOC_FILE_ENTRY: { - // FIXME: We would really like to delay the creation of this - // FileEntry until it is actually required, e.g., when producing - // a diagnostic with a source location in this file. - const FileEntry *File - = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen); - // FIXME: Error recovery if file cannot be found. - FileID ID = SourceMgr.createFileID(File, - SourceLocation::getFromRawEncoding(Record[1]), - (CharacteristicKind)Record[2]); - if (Record[3]) - const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(ID).getFile()) - .setHasLineDirectives(); - break; - } - - case pch::SM_SLOC_BUFFER_ENTRY: { - const char *Name = BlobStart; - unsigned Code = Stream.ReadCode(); - Record.clear(); - unsigned RecCode = Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen); - assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file"); - (void)RecCode; - llvm::MemoryBuffer *Buffer - = llvm::MemoryBuffer::getMemBuffer(BlobStart, - BlobStart + BlobLen - 1, - Name); - FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer); - - if (strcmp(Name, "<built-in>") == 0 - && CheckPredefinesBuffer(BlobStart, BlobLen - 1, BufferID)) - return IgnorePCH; - break; - } - - case pch::SM_SLOC_INSTANTIATION_ENTRY: { - SourceLocation SpellingLoc - = SourceLocation::getFromRawEncoding(Record[1]); - SourceMgr.createInstantiationLoc( - SpellingLoc, - SourceLocation::getFromRawEncoding(Record[2]), - SourceLocation::getFromRawEncoding(Record[3]), - Record[4]); - break; - } - case pch::SM_LINE_TABLE: if (ParseLineTable(SourceMgr, Record)) return Failure; @@ -525,10 +492,98 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++); break; } + + case pch::SM_SLOC_FILE_ENTRY: + case pch::SM_SLOC_BUFFER_ENTRY: + case pch::SM_SLOC_INSTANTIATION_ENTRY: + // Once we hit one of the source location entries, we're done. + return Success; } } } +/// \brief Read in the source location entry with the given ID. +PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) { + if (ID == 0) + return Success; + + if (ID > TotalNumSLocEntries) { + Error("source location entry ID out-of-range for PCH file"); + return Failure; + } + + ++NumSLocEntriesRead; + SLocEntryCursor.JumpToBit(SLocOffsets[ID - 1]); + unsigned Code = SLocEntryCursor.ReadCode(); + if (Code == llvm::bitc::END_BLOCK || + Code == llvm::bitc::ENTER_SUBBLOCK || + Code == llvm::bitc::DEFINE_ABBREV) { + Error("incorrectly-formatted source location entry in PCH file"); + return Failure; + } + + SourceManager &SourceMgr = Context.getSourceManager(); + RecordData Record; + const char *BlobStart; + unsigned BlobLen; + switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { + default: + Error("incorrectly-formatted source location entry in PCH file"); + return Failure; + + case pch::SM_SLOC_FILE_ENTRY: { + const FileEntry *File + = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen); + // FIXME: Error recovery if file cannot be found. + FileID FID = SourceMgr.createFileID(File, + SourceLocation::getFromRawEncoding(Record[1]), + (SrcMgr::CharacteristicKind)Record[2], + ID, Record[0]); + if (Record[3]) + const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile()) + .setHasLineDirectives(); + + break; + } + + case pch::SM_SLOC_BUFFER_ENTRY: { + const char *Name = BlobStart; + unsigned Offset = Record[0]; + unsigned Code = SLocEntryCursor.ReadCode(); + Record.clear(); + unsigned RecCode + = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen); + assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file"); + (void)RecCode; + llvm::MemoryBuffer *Buffer + = llvm::MemoryBuffer::getMemBuffer(BlobStart, + BlobStart + BlobLen - 1, + Name); + FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset); + + if (strcmp(Name, "<built-in>") == 0 + && CheckPredefinesBuffer(BlobStart, BlobLen - 1, BufferID)) + return IgnorePCH; + + break; + } + + case pch::SM_SLOC_INSTANTIATION_ENTRY: { + SourceLocation SpellingLoc + = SourceLocation::getFromRawEncoding(Record[1]); + SourceMgr.createInstantiationLoc(SpellingLoc, + SourceLocation::getFromRawEncoding(Record[2]), + SourceLocation::getFromRawEncoding(Record[3]), + Record[4], + ID, + Record[0]); + break; + } + } + + return Success; +} + /// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the /// specified cursor. Read the abbreviations that are at the top of the block /// and then leave the cursor pointing into the block. @@ -807,6 +862,7 @@ PCHReader::ReadPCHBlock() { TotalLexicalDeclContexts = Record[2]; TotalVisibleDeclContexts = Record[3]; break; + case pch::TENTATIVE_DEFINITIONS: if (!TentativeDefinitions.empty()) { Error("Duplicate TENTATIVE_DEFINITIONS record in PCH file"); @@ -844,6 +900,22 @@ PCHReader::ReadPCHBlock() { if (!Record.empty()) PP.setCounterValue(Record[0]); break; + + case pch::SOURCE_LOCATION_OFFSETS: + SLocOffsets = (const uint64_t *)BlobStart; + TotalNumSLocEntries = Record[0]; + PP.getSourceManager().PreallocateSLocEntries(this, + TotalNumSLocEntries, + Record[1]); + break; + + case pch::SOURCE_LOCATION_PRELOADS: + for (unsigned I = 0, N = Record.size(); I != N; ++I) { + PCHReadResult Result = ReadSLocEntryRecord(Record[I]); + if (Result != Success) + return Result; + } + break; } } Error("Premature end of bitstream"); @@ -1434,6 +1506,10 @@ void PCHReader::PrintStats() { SelectorsLoaded.end(), Selector()); + if (TotalNumSLocEntries) + std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n", + NumSLocEntriesRead, TotalNumSLocEntries, + ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100)); if (!TypesLoaded.empty()) std::fprintf(stderr, " %u/%u types read (%f%%)\n", NumTypesLoaded, (unsigned)TypesLoaded.size(), @@ -1604,6 +1680,10 @@ IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) { return IdentifiersLoaded[ID - 1]; } +void PCHReader::ReadSLocEntry(unsigned ID) { + ReadSLocEntryRecord(ID); +} + Selector PCHReader::DecodeSelector(unsigned ID) { if (ID == 0) return Selector(); diff --git a/clang/lib/Frontend/PCHWriter.cpp b/clang/lib/Frontend/PCHWriter.cpp index c8b64659994..d181013a37e 100644 --- a/clang/lib/Frontend/PCHWriter.cpp +++ b/clang/lib/Frontend/PCHWriter.cpp @@ -353,7 +353,9 @@ void PCHWriter::WriteBlockInfoBlock() { RECORD(SELECTOR_OFFSETS); RECORD(METHOD_POOL); RECORD(PP_COUNTER_VALUE); - + RECORD(SOURCE_LOCATION_OFFSETS); + RECORD(SOURCE_LOCATION_PRELOADS); + // SourceManager Block. BLOCK(SOURCE_MANAGER_BLOCK); RECORD(SM_SLOC_FILE_ENTRY); @@ -578,22 +580,79 @@ static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &Stream) { /// the files in the AST. void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, const Preprocessor &PP) { + RecordData Record; + // Enter the source manager block. Stream.EnterSubblock(pch::SOURCE_MANAGER_BLOCK_ID, 3); // Abbreviations for the various kinds of source-location entries. - int SLocFileAbbrv = -1; - int SLocBufferAbbrv = -1; - int SLocBufferBlobAbbrv = -1; - int SLocInstantiationAbbrv = -1; + int SLocFileAbbrv = CreateSLocFileAbbrev(Stream); + int SLocBufferAbbrv = CreateSLocBufferAbbrev(Stream); + int SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream); + int SLocInstantiationAbbrv = CreateSLocInstantiationAbbrev(Stream); + + // Write the line table. + if (SourceMgr.hasLineTable()) { + LineTableInfo &LineTable = SourceMgr.getLineTable(); + + // Emit the file names + Record.push_back(LineTable.getNumFilenames()); + for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) { + // Emit the file name + const char *Filename = LineTable.getFilename(I); + unsigned FilenameLen = Filename? strlen(Filename) : 0; + Record.push_back(FilenameLen); + if (FilenameLen) + Record.insert(Record.end(), Filename, Filename + FilenameLen); + } + + // Emit the line entries + for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end(); + L != LEnd; ++L) { + // Emit the file ID + Record.push_back(L->first); + + // Emit the line entries + Record.push_back(L->second.size()); + for (std::vector<LineEntry>::iterator LE = L->second.begin(), + LEEnd = L->second.end(); + LE != LEEnd; ++LE) { + Record.push_back(LE->FileOffset); + Record.push_back(LE->LineNo); + Record.push_back(LE->FilenameID); + Record.push_back((unsigned)LE->FileKind); + Record.push_back(LE->IncludeOffset); + } + Stream.EmitRecord(pch::SM_LINE_TABLE, Record); + } + } + + // Write out entries for all of the header files we know about. + HeaderSearch &HS = PP.getHeaderSearchInfo(); + Record.clear(); + for (HeaderSearch::header_file_iterator I = HS.header_file_begin(), + E = HS.header_file_end(); + I != E; ++I) { + Record.push_back(I->isImport); + Record.push_back(I->DirInfo); + Record.push_back(I->NumIncludes); + AddIdentifierRef(I->ControllingMacro, Record); + Stream.EmitRecord(pch::SM_HEADER_FILE_INFO, Record); + Record.clear(); + } // Write out the source location entry table. We skip the first // entry, which is always the same dummy entry. - RecordData Record; + std::vector<uint64_t> SLocEntryOffsets; + RecordData PreloadSLocs; + SLocEntryOffsets.reserve(SourceMgr.sloc_entry_size() - 1); for (SourceManager::sloc_entry_iterator SLoc = SourceMgr.sloc_entry_begin() + 1, SLocEnd = SourceMgr.sloc_entry_end(); SLoc != SLocEnd; ++SLoc) { + // Record the offset of this source-location entry. + SLocEntryOffsets.push_back(Stream.GetCurrentBitNo()); + // Figure out which record code to use. unsigned Code; if (SLoc->isFile()) { @@ -603,6 +662,7 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, Code = pch::SM_SLOC_BUFFER_ENTRY; } else Code = pch::SM_SLOC_INSTANTIATION_ENTRY; + Record.clear(); Record.push_back(Code); Record.push_back(SLoc->getOffset()); @@ -616,18 +676,17 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, if (Content->Entry) { // The source location entry is a file. The blob associated // with this entry is the file name. - if (SLocFileAbbrv == -1) - SLocFileAbbrv = CreateSLocFileAbbrev(Stream); Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, Content->Entry->getName(), strlen(Content->Entry->getName())); + + // FIXME: For now, preload all file source locations, so that + // we get the appropriate File entries in the reader. This is + // a temporary measure. + PreloadSLocs.push_back(SLocEntryOffsets.size()); } else { // The source location entry is a buffer. The blob associated // with this entry contains the contents of the buffer. - if (SLocBufferAbbrv == -1) { - SLocBufferAbbrv = CreateSLocBufferAbbrev(Stream); - SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream); - } // We add one to the size so that we capture the trailing NULL // that is required by llvm::MemoryBuffer::getMemBuffer (on @@ -640,6 +699,9 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, Buffer->getBufferStart(), Buffer->getBufferSize() + 1); + + if (strcmp(Name, "<built-in>") == 0) + PreloadSLocs.push_back(SLocEntryOffsets.size()); } } else { // The source location entry is an instantiation. @@ -654,68 +716,36 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, if (++NextSLoc != SLocEnd) NextOffset = NextSLoc->getOffset(); Record.push_back(NextOffset - SLoc->getOffset() - 1); - - if (SLocInstantiationAbbrv == -1) - SLocInstantiationAbbrv = CreateSLocInstantiationAbbrev(Stream); Stream.EmitRecordWithAbbrev(SLocInstantiationAbbrv, Record); } - - Record.clear(); } - // Write the line table. - if (SourceMgr.hasLineTable()) { - LineTableInfo &LineTable = SourceMgr.getLineTable(); - - // Emit the file names - Record.push_back(LineTable.getNumFilenames()); - for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) { - // Emit the file name - const char *Filename = LineTable.getFilename(I); - unsigned FilenameLen = Filename? strlen(Filename) : 0; - Record.push_back(FilenameLen); - if (FilenameLen) - Record.insert(Record.end(), Filename, Filename + FilenameLen); - } - - // Emit the line entries - for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end(); - L != LEnd; ++L) { - // Emit the file ID - Record.push_back(L->first); - - // Emit the line entries - Record.push_back(L->second.size()); - for (std::vector<LineEntry>::iterator LE = L->second.begin(), - LEEnd = L->second.end(); - LE != LEEnd; ++LE) { - Record.push_back(LE->FileOffset); - Record.push_back(LE->LineNo); - Record.push_back(LE->FilenameID); - Record.push_back((unsigned)LE->FileKind); - Record.push_back(LE->IncludeOffset); - } - Stream.EmitRecord(pch::SM_LINE_TABLE, Record); - } - } + Stream.ExitBlock(); - // Loop over all the header files. - HeaderSearch &HS = PP.getHeaderSearchInfo(); - for (HeaderSearch::header_file_iterator I = HS.header_file_begin(), - E = HS.header_file_end(); - I != E; ++I) { - Record.push_back(I->isImport); - Record.push_back(I->DirInfo); - Record.push_back(I->NumIncludes); - if (I->ControllingMacro) - AddIdentifierRef(I->ControllingMacro, Record); - else - Record.push_back(0); - Stream.EmitRecord(pch::SM_HEADER_FILE_INFO, Record); - Record.clear(); - } + if (SLocEntryOffsets.empty()) + return; - Stream.ExitBlock(); + // Write the source-location offsets table into the PCH block. This + // table is used for lazily loading source-location information. + using namespace llvm; + BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(pch::SOURCE_LOCATION_OFFSETS)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // next offset + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets + unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(Abbrev); + + Record.clear(); + Record.push_back(pch::SOURCE_LOCATION_OFFSETS); + Record.push_back(SLocEntryOffsets.size()); + Record.push_back(SourceMgr.getNextOffset()); + Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, + (const char *)&SLocEntryOffsets.front(), + SLocEntryOffsets.size() * 8); + + // Write the source location entry preloads array, telling the PCH + // reader which source locations entries it should load eagerly. + Stream.EmitRecord(pch::SOURCE_LOCATION_PRELOADS, PreloadSLocs); } /// \brief Writes the block containing the serialized form of the |