aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend/PCHReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Frontend/PCHReader.cpp')
-rw-r--r--lib/Frontend/PCHReader.cpp192
1 files changed, 136 insertions, 56 deletions
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 86848758ad..ff8795ca64 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/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();