aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend/PCHReader.cpp
diff options
context:
space:
mode:
authorSteve Naroff <snaroff@apple.com>2009-04-23 10:39:46 +0000
committerSteve Naroff <snaroff@apple.com>2009-04-23 10:39:46 +0000
commit90cd1bb1baac2a0221f3642de0cbea3244b116e5 (patch)
tree5fc871b111c9848b029793228385bd2867596150 /lib/Frontend/PCHReader.cpp
parent325f75896d346605a00b9cc3494ed20a2a5dfb4e (diff)
Add PCH read/write support for Objective-C Selectors.
Note: This support is non-lazy. Once we get "Cocoa.h" humming, we can optimize this. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69884 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend/PCHReader.cpp')
-rw-r--r--lib/Frontend/PCHReader.cpp109
1 files changed, 104 insertions, 5 deletions
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 851eebc355..0e2d06eaf3 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -1063,7 +1063,7 @@ unsigned PCHStmtReader::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
unsigned PCHStmtReader::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
VisitExpr(E);
- // FIXME: Selectors.
+ E->setSelector(Reader.GetSelector(Record, Idx));
E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
return 0;
@@ -1586,8 +1586,69 @@ bool PCHReader::ReadPreprocessorBlock() {
}
}
+bool PCHReader::ReadSelectorBlock() {
+ if (Stream.EnterSubBlock(pch::SELECTOR_BLOCK_ID))
+ return Error("Malformed selector block record");
+
+ RecordData Record;
+ while (true) {
+ unsigned Code = Stream.ReadCode();
+ switch (Code) {
+ case llvm::bitc::END_BLOCK:
+ if (Stream.ReadBlockEnd())
+ return Error("Error at end of preprocessor block");
+ return false;
+
+ case llvm::bitc::ENTER_SUBBLOCK:
+ // No known subblocks, always skip them.
+ Stream.ReadSubBlockID();
+ if (Stream.SkipBlock())
+ return Error("Malformed block record");
+ continue;
+
+ case llvm::bitc::DEFINE_ABBREV:
+ Stream.ReadAbbrevRecord();
+ continue;
+ default: break;
+ }
+
+ // Read a record.
+ Record.clear();
+ pch::PCHRecordTypes RecType =
+ (pch::PCHRecordTypes)Stream.ReadRecord(Code, Record);
+ switch (RecType) {
+ default: // Default behavior: ignore unknown records.
+ break;
+ case pch::SELECTOR_TABLE:
+ unsigned Idx = 1; // Record[0] == pch::SELECTOR_TABLE.
+ unsigned NumSels = Record[Idx++];
+
+ llvm::SmallVector<IdentifierInfo *, 8> KeyIdents;
+ for (unsigned SelIdx = 0; SelIdx < NumSels; SelIdx++) {
+ unsigned NumArgs = Record[Idx++];
+ KeyIdents.clear();
+ if (NumArgs <= 1) {
+ IdentifierInfo *II = DecodeIdentifierInfo(Record[Idx++]);
+ assert(II && "DecodeIdentifierInfo returned 0");
+ KeyIdents.push_back(II);
+ } else {
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+ IdentifierInfo *II = DecodeIdentifierInfo(Record[Idx++]);
+ assert(II && "DecodeIdentifierInfo returned 0");
+ KeyIdents.push_back(II);
+ }
+ }
+ Selector Sel = PP.getSelectorTable().getSelector(NumArgs,&KeyIdents[0]);
+ SelectorData.push_back(Sel);
+ }
+ }
+ }
+ return false;
+}
+
PCHReader::PCHReadResult
-PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset) {
+PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset,
+ uint64_t &SelectorBlockOffset) {
if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
Error("Malformed block record");
return Failure;
@@ -1630,6 +1691,20 @@ PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset) {
return Failure;
}
break;
+
+ case pch::SELECTOR_BLOCK_ID:
+ // Skip the selector block for now, but remember where it is. We
+ // want to read it in after the identifier table.
+ if (SelectorBlockOffset) {
+ Error("Multiple selector blocks found.");
+ return Failure;
+ }
+ SelectorBlockOffset = Stream.GetCurrentBitNo();
+ if (Stream.SkipBlock()) {
+ Error("Malformed block record");
+ return Failure;
+ }
+ break;
case pch::SOURCE_MANAGER_BLOCK_ID:
switch (ReadSourceManagerBlock()) {
@@ -1740,7 +1815,6 @@ PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset) {
TotalLexicalDeclContexts = Record[2];
TotalVisibleDeclContexts = Record[3];
break;
-
case pch::TENTATIVE_DEFINITIONS:
if (!TentativeDefinitions.empty()) {
Error("Duplicate TENTATIVE_DEFINITIONS record in PCH file");
@@ -1758,7 +1832,6 @@ PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset) {
break;
}
}
-
Error("Premature end of bitstream");
return Failure;
}
@@ -1791,6 +1864,8 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
// We expect a number of well-defined blocks, though we don't necessarily
// need to understand them all.
uint64_t PreprocessorBlockOffset = 0;
+ uint64_t SelectorBlockOffset = 0;
+
while (!Stream.AtEndOfStream()) {
unsigned Code = Stream.ReadCode();
@@ -1810,7 +1885,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
}
break;
case pch::PCH_BLOCK_ID:
- switch (ReadPCHBlock(PreprocessorBlockOffset)) {
+ switch (ReadPCHBlock(PreprocessorBlockOffset, SelectorBlockOffset)) {
case Success:
break;
@@ -1882,6 +1957,14 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
return Failure;
}
}
+ if (SelectorBlockOffset) {
+ SavedStreamPosition SavedPos(Stream);
+ Stream.JumpToBit(SelectorBlockOffset);
+ if (ReadSelectorBlock()) {
+ Error("Malformed preprocessor block");
+ return Failure;
+ }
+ }
return Success;
}
@@ -2633,6 +2716,22 @@ IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
return reinterpret_cast<IdentifierInfo *>(IdentifierData[ID - 1]);
}
+Selector PCHReader::DecodeSelector(unsigned ID) {
+ if (ID == 0)
+ return Selector();
+
+ if (SelectorData.empty()) {
+ Error("No selector table in PCH file");
+ return Selector();
+ }
+
+ if (ID > SelectorData.size()) {
+ Error("Selector ID out of range");
+ return Selector();
+ }
+ return SelectorData[ID-1];
+}
+
DeclarationName
PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];