diff options
author | Steve Naroff <snaroff@apple.com> | 2009-04-23 10:39:46 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2009-04-23 10:39:46 +0000 |
commit | 90cd1bb1baac2a0221f3642de0cbea3244b116e5 (patch) | |
tree | 5fc871b111c9848b029793228385bd2867596150 /lib/Frontend/PCHReader.cpp | |
parent | 325f75896d346605a00b9cc3494ed20a2a5dfb4e (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.cpp | 109 |
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++]; |