diff options
-rw-r--r-- | include/clang/Frontend/PCHBitCodes.h | 10 | ||||
-rw-r--r-- | include/clang/Frontend/PCHReader.h | 42 | ||||
-rw-r--r-- | include/clang/Frontend/PCHWriter.h | 9 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 202 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 75 |
5 files changed, 172 insertions, 166 deletions
diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index ba9d3e4c9d..26e2c1744c 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -68,10 +68,7 @@ namespace clang { /// \brief The block containing the definitions of all of the /// declarations stored in the PCH file. - DECLS_BLOCK_ID, - - /// \brief The block containing ObjC selectors stored in the PCH file. - SELECTOR_BLOCK_ID + DECLS_BLOCK_ID }; /// \brief Record types that occur within the PCH block itself. @@ -167,8 +164,9 @@ namespace clang { /// declarations. LOCALLY_SCOPED_EXTERNAL_DECLS = 11, - /// \brief Record code for the Objective-C Selector Table. - SELECTOR_TABLE = 12, + /// \brief Record code for the table of offsets into the + /// Objective-C method pool. + SELECTOR_OFFSETS = 12, /// \brief Record code for the Objective-C method pool, METHOD_POOL = 13 diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 941e92426f..c3de6093aa 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -146,9 +146,6 @@ private: /// an IdentifierInfo* that has already been resolved. llvm::SmallVector<uint64_t, 16> IdentifierData; - /// \brief SelectorData, indexed by the selector ID minus one. - llvm::SmallVector<Selector, 16> SelectorData; - /// \brief A pointer to an on-disk hash table of opaque type /// PCHMethodPoolLookupTable. /// @@ -156,6 +153,29 @@ private: /// associated with every selector known in the PCH file. void *MethodPoolLookupTable; + /// \brief A pointer to the character data that comprises the method + /// pool. + /// + /// The SelectorOffsets table refers into this memory. + const unsigned char *MethodPoolLookupTableData; + + /// \brief The number of selectors stored in the method pool itself. + unsigned TotalSelectorsInMethodPool; + + /// \brief Offsets into the method pool lookup table's data array + /// where each selector resides. + const uint32_t *SelectorOffsets; + + /// \brief The total number of selectors stored in the PCH file. + unsigned TotalNumSelectors; + + /// \brief A vector containing selectors that have already been loaded. + /// + /// This vector is indexed by the Selector ID (-1). NULL selector + /// entries indicate that the particular selector ID has not yet + /// been loaded. + llvm::SmallVector<Selector, 16> SelectorsLoaded; + /// \brief The set of external definitions stored in the the PCH /// file. llvm::SmallVector<uint64_t, 16> ExternalDefinitions; @@ -197,6 +217,13 @@ private: /// \brief The number of macros de-serialized from the PCH file. unsigned NumMacrosRead; + /// \brief The number of method pool entries that have been read. + unsigned NumMethodPoolSelectorsRead; + + /// \brief The number of times we have looked into the global method + /// pool and not found anything. + unsigned NumMethodPoolMisses; + /// \brief The total number of macros stored in the PCH file. unsigned TotalNumMacros; @@ -217,14 +244,12 @@ private: /// Objective-C protocols. llvm::SmallVector<Decl *, 16> InterestingDecls; - PCHReadResult ReadPCHBlock(uint64_t &PreprocessorBlockOffset, - uint64_t &SelectorBlockOffset); + PCHReadResult ReadPCHBlock(uint64_t &PreprocessorBlockOffset); bool CheckPredefinesBuffer(const char *PCHPredef, unsigned PCHPredefLen, FileID PCHBufferID); PCHReadResult ReadSourceManagerBlock(); bool ReadPreprocessorBlock(); - bool ReadSelectorBlock(); bool ParseLanguageOptions(const llvm::SmallVectorImpl<uint64_t> &Record); QualType ReadTypeRecord(uint64_t Offset); @@ -240,7 +265,10 @@ public: explicit PCHReader(Preprocessor &PP, ASTContext &Context) : SemaObj(0), PP(PP), Context(Context), Consumer(0), IdentifierTableData(0), IdentifierLookupTable(0), - MethodPoolLookupTable(0), NumStatementsRead(0), NumMacrosRead(0), + MethodPoolLookupTable(0), MethodPoolLookupTableData(0), + TotalSelectorsInMethodPool(0), SelectorOffsets(0), + TotalNumSelectors(0), NumStatementsRead(0), NumMacrosRead(0), + NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0), NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { } ~PCHReader() {} diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index 15c2e10bda..41f8ad4af5 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -101,6 +101,10 @@ private: /// \brief Map that provides the ID numbers of each Selector. llvm::DenseMap<Selector, pch::SelectorID> SelectorIDs; + /// \brief Offset of each selector within the method pool/selector + /// table, indexed by the Selector ID (-1). + llvm::SmallVector<uint32_t, 16> SelectorOffsets; + /// \brief A vector of all Selectors (ordered by ID). llvm::SmallVector<Selector, 16> SelVector; @@ -161,7 +165,6 @@ private: void WriteDeclsBlock(ASTContext &Context); void WriteMethodPool(Sema &SemaRef); void WriteIdentifierTable(Preprocessor &PP); - void WriteSelectorTable(); void WriteAttributeRecord(const Attr *Attr); public: @@ -224,6 +227,10 @@ public: /// within the identifier table. void SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset); + /// \brief Note that the selector Sel occurs at the given offset + /// within the method pool/selector table. + void SetSelectorOffset(Selector Sel, uint32_t Offset); + /// \brief Add the given statement or expression to the queue of /// statements to emit. /// diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index edb17c764c..3e612be629 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1141,7 +1141,7 @@ public: return std::make_pair(KeyLen, DataLen); } - internal_key_type ReadKey(const unsigned char* d, unsigned n) { + internal_key_type ReadKey(const unsigned char* d, unsigned) { using namespace clang::io; SelectorTable &SelTable = Reader.getContext().Selectors; unsigned N = ReadUnalignedLE16(d); @@ -1725,70 +1725,8 @@ 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 == 0) { - // If the number of arguments is 0, we must have an Identifier. - IdentifierInfo *II = DecodeIdentifierInfo(Record[Idx++]); - assert(II && "DecodeIdentifierInfo returned 0"); - KeyIdents.push_back(II); - } else { - // For keyword selectors, the Identifier is optional (::: is legal!). - for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { - IdentifierInfo *II = DecodeIdentifierInfo(Record[Idx++]); - 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, - uint64_t &SelectorBlockOffset) { +PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset) { if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) { Error("Malformed block record"); return Failure; @@ -1832,20 +1770,6 @@ PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset, } 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()) { case Success: @@ -1971,12 +1895,21 @@ PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset, LocallyScopedExternalDecls.swap(Record); break; + case pch::SELECTOR_OFFSETS: + SelectorOffsets = (const uint32_t *)BlobStart; + TotalNumSelectors = Record[0]; + SelectorsLoaded.resize(TotalNumSelectors); + break; + case pch::METHOD_POOL: - MethodPoolLookupTable - = PCHMethodPoolLookupTable::Create( - (const unsigned char *)BlobStart + Record[0], - (const unsigned char *)BlobStart, + MethodPoolLookupTableData = (const unsigned char *)BlobStart; + if (Record[0]) + MethodPoolLookupTable + = PCHMethodPoolLookupTable::Create( + MethodPoolLookupTableData + Record[0], + MethodPoolLookupTableData, PCHMethodPoolLookupTrait(*this)); + TotalSelectorsInMethodPool = Record[1]; break; } } @@ -2012,7 +1945,6 @@ 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(); @@ -2033,7 +1965,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { } break; case pch::PCH_BLOCK_ID: - switch (ReadPCHBlock(PreprocessorBlockOffset, SelectorBlockOffset)) { + switch (ReadPCHBlock(PreprocessorBlockOffset)) { case Success: break; @@ -2117,14 +2049,6 @@ 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; } @@ -2799,30 +2723,53 @@ void PCHReader::PrintStats() { if ((IdentifierData[I] & 0x01) == 0) ++NumIdentifiersLoaded; } - - std::fprintf(stderr, " %u/%u types read (%f%%)\n", - NumTypesLoaded, (unsigned)TypeAlreadyLoaded.size(), - ((float)NumTypesLoaded/TypeAlreadyLoaded.size() * 100)); - std::fprintf(stderr, " %u/%u declarations read (%f%%)\n", - NumDeclsLoaded, (unsigned)DeclAlreadyLoaded.size(), - ((float)NumDeclsLoaded/DeclAlreadyLoaded.size() * 100)); - std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n", - NumIdentifiersLoaded, (unsigned)IdentifierData.size(), - ((float)NumIdentifiersLoaded/IdentifierData.size() * 100)); - std::fprintf(stderr, " %u/%u statements read (%f%%)\n", - NumStatementsRead, TotalNumStatements, - ((float)NumStatementsRead/TotalNumStatements * 100)); - std::fprintf(stderr, " %u/%u macros read (%f%%)\n", - NumMacrosRead, TotalNumMacros, - ((float)NumMacrosRead/TotalNumMacros * 100)); - std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n", - NumLexicalDeclContextsRead, TotalLexicalDeclContexts, - ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts - * 100)); - std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n", - NumVisibleDeclContextsRead, TotalVisibleDeclContexts, - ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts - * 100)); + unsigned NumSelectorsLoaded = 0; + for (unsigned I = 0; I < SelectorsLoaded.size(); ++I) { + if (SelectorsLoaded[I].getAsOpaquePtr()) + ++NumSelectorsLoaded; + } + + if (!TypeAlreadyLoaded.empty()) + std::fprintf(stderr, " %u/%u types read (%f%%)\n", + NumTypesLoaded, (unsigned)TypeAlreadyLoaded.size(), + ((float)NumTypesLoaded/TypeAlreadyLoaded.size() * 100)); + if (!DeclAlreadyLoaded.empty()) + std::fprintf(stderr, " %u/%u declarations read (%f%%)\n", + NumDeclsLoaded, (unsigned)DeclAlreadyLoaded.size(), + ((float)NumDeclsLoaded/DeclAlreadyLoaded.size() * 100)); + if (!IdentifierData.empty()) + std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n", + NumIdentifiersLoaded, (unsigned)IdentifierData.size(), + ((float)NumIdentifiersLoaded/IdentifierData.size() * 100)); + if (TotalNumSelectors) + std::fprintf(stderr, " %u/%u selectors read (%f%%)\n", + NumSelectorsLoaded, TotalNumSelectors, + ((float)NumSelectorsLoaded/TotalNumSelectors * 100)); + if (TotalNumStatements) + std::fprintf(stderr, " %u/%u statements read (%f%%)\n", + NumStatementsRead, TotalNumStatements, + ((float)NumStatementsRead/TotalNumStatements * 100)); + if (TotalNumMacros) + std::fprintf(stderr, " %u/%u macros read (%f%%)\n", + NumMacrosRead, TotalNumMacros, + ((float)NumMacrosRead/TotalNumMacros * 100)); + if (TotalLexicalDeclContexts) + std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n", + NumLexicalDeclContextsRead, TotalLexicalDeclContexts, + ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts + * 100)); + if (TotalVisibleDeclContexts) + std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n", + NumVisibleDeclContextsRead, TotalVisibleDeclContexts, + ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts + * 100)); + if (TotalSelectorsInMethodPool) { + std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n", + NumMethodPoolSelectorsRead, TotalSelectorsInMethodPool, + ((float)NumMethodPoolSelectorsRead/TotalSelectorsInMethodPool + * 100)); + std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses); + } std::fprintf(stderr, "\n"); } @@ -2878,9 +2825,12 @@ PCHReader::ReadMethodPool(Selector Sel) { PCHMethodPoolLookupTable *PoolTable = (PCHMethodPoolLookupTable*)MethodPoolLookupTable; PCHMethodPoolLookupTable::iterator Pos = PoolTable->find(Sel); - if (Pos == PoolTable->end()) + if (Pos == PoolTable->end()) { + ++NumMethodPoolMisses; return std::pair<ObjCMethodList, ObjCMethodList>();; + } + ++NumMethodPoolSelectorsRead; return *Pos; } @@ -2911,16 +2861,26 @@ Selector PCHReader::DecodeSelector(unsigned ID) { if (ID == 0) return Selector(); - if (SelectorData.empty()) { + if (!MethodPoolLookupTableData) { Error("No selector table in PCH file"); return Selector(); } - - if (ID > SelectorData.size()) { + + if (ID > TotalNumSelectors) { Error("Selector ID out of range"); return Selector(); } - return SelectorData[ID-1]; + + unsigned Index = ID - 1; + if (SelectorsLoaded[Index].getAsOpaquePtr() == 0) { + // Load this selector from the selector table. + // FIXME: endianness portability issues with SelectorOffsets table + PCHMethodPoolLookupTrait Trait(*this); + SelectorsLoaded[Index] + = Trait.ReadKey(MethodPoolLookupTableData + SelectorOffsets[Index], 0); + } + + return SelectorsLoaded[Index]; } DeclarationName diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index f8c4a779fb..56c8296c94 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1832,11 +1832,10 @@ public: return std::make_pair(KeyLen, DataLen); } - void EmitKey(llvm::raw_ostream& Out, Selector Sel, unsigned KeyLen) { - // FIXME: Keep track of the location of the key data (the - // selector), so we can fold the selector table's storage into - // this hash table. - uint64_t Start = Out.tell(); (void)Start; + void EmitKey(llvm::raw_ostream& Out, Selector Sel, unsigned) { + uint64_t Start = Out.tell(); + assert((Start >> 32) == 0 && "Selector key offset too large"); + Writer.SetSelectorOffset(Sel, Start); unsigned N = Sel.getNumArgs(); clang::io::Emit16(Out, N); if (N == 0) @@ -1844,8 +1843,6 @@ public: for (unsigned I = 0; I != N; ++I) clang::io::Emit32(Out, Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I))); - - assert(Out.tell() - Start == KeyLen && "Key length is wrong"); } void EmitData(llvm::raw_ostream& Out, key_type_ref, @@ -1895,6 +1892,7 @@ void PCHWriter::WriteMethodPool(Sema &SemaRef) { // Create the on-disk hash table representation. Start by // iterating through the instance method pool. PCHMethodPoolTrait::key_type Key; + unsigned NumSelectorsInMethodPool = 0; for (llvm::DenseMap<Selector, ObjCMethodList>::iterator Instance = SemaRef.InstanceMethodPool.begin(), InstanceEnd = SemaRef.InstanceMethodPool.end(); @@ -1912,6 +1910,7 @@ void PCHWriter::WriteMethodPool(Sema &SemaRef) { Generator.insert(Instance->first, std::make_pair(Instance->second, Factory->second)); + ++NumSelectorsInMethodPool; Empty = false; } @@ -1926,41 +1925,68 @@ void PCHWriter::WriteMethodPool(Sema &SemaRef) { llvm::DenseMap<Selector, ObjCMethodList>::iterator Instance = SemaRef.InstanceMethodPool.find(Factory->first); - if (Instance == SemaRef.InstanceMethodPool.end()) + if (Instance == SemaRef.InstanceMethodPool.end()) { Generator.insert(Factory->first, std::make_pair(ObjCMethodList(), Factory->second)); + ++NumSelectorsInMethodPool; + } Empty = false; } - if (Empty) + if (Empty && SelectorOffsets.empty()) return; // Create the on-disk hash table in a buffer. llvm::SmallVector<char, 4096> MethodPool; uint32_t BucketOffset; + SelectorOffsets.resize(SelVector.size()); { PCHMethodPoolTrait Trait(*this); llvm::raw_svector_ostream Out(MethodPool); // Make sure that no bucket is at offset 0 clang::io::Emit32(Out, 0); BucketOffset = Generator.Emit(Out, Trait); + + // For every selector that we have seen but which was not + // written into the hash table, write the selector itself and + // record it's offset. + for (unsigned I = 0, N = SelVector.size(); I != N; ++I) + if (SelectorOffsets[I] == 0) + Trait.EmitKey(Out, SelVector[I], 0); } // Create a blob abbreviation BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(pch::METHOD_POOL)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned MethodPoolAbbrev = Stream.EmitAbbrev(Abbrev); - // Write the identifier table + // Write the method pool RecordData Record; Record.push_back(pch::METHOD_POOL); Record.push_back(BucketOffset); + Record.push_back(NumSelectorsInMethodPool); Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, &MethodPool.front(), MethodPool.size()); + + // Create a blob abbreviation for the selector table offsets. + Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(pch::SELECTOR_OFFSETS)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // index + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(Abbrev); + + // Write the selector offsets table. + Record.clear(); + Record.push_back(pch::SELECTOR_OFFSETS); + Record.push_back(SelectorOffsets.size()); + Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record, + (const char *)&SelectorOffsets.front(), + SelectorOffsets.size() * 4); } } @@ -2096,26 +2122,6 @@ void PCHWriter::WriteIdentifierTable(Preprocessor &PP) { Stream.EmitRecord(pch::IDENTIFIER_OFFSET, IdentifierOffsets); } -void PCHWriter::WriteSelectorTable() { - Stream.EnterSubblock(pch::SELECTOR_BLOCK_ID, 2); - RecordData Record; - Record.push_back(pch::SELECTOR_TABLE); - Record.push_back(SelectorIDs.size()); - - // Create the on-disk representation. - for (unsigned selIdx = 0; selIdx < SelVector.size(); selIdx++) { - assert(SelVector[selIdx].getAsOpaquePtr() && "NULL Selector found"); - Record.push_back(SelVector[selIdx].getNumArgs()); - if (SelVector[selIdx].getNumArgs()) - for (unsigned i = 0; i < SelVector[selIdx].getNumArgs(); i++) - AddIdentifierRef(SelVector[selIdx].getIdentifierInfoForSlot(i), Record); - else - AddIdentifierRef(SelVector[selIdx].getIdentifierInfoForSlot(0), Record); - } - Stream.EmitRecord(pch::SELECTOR_TABLE, Record); - Stream.ExitBlock(); -} - /// \brief Write a record containing the given attributes. void PCHWriter::WriteAttributeRecord(const Attr *Attr) { RecordData Record; @@ -2250,6 +2256,14 @@ void PCHWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) { IdentifierOffsets[IdentifierIDs[II] - 1] = (Offset << 1) | 0x01; } +/// \brief Note that the selector Sel occurs at the given offset +/// within the method pool/selector table. +void PCHWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { + unsigned ID = SelectorIDs[Sel]; + assert(ID && "Unknown selector"); + SelectorOffsets[ID - 1] = Offset; +} + PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream) : Stream(Stream), NextTypeID(pch::NUM_PREDEF_TYPE_IDS), NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0), @@ -2309,7 +2323,6 @@ void PCHWriter::WritePCH(Sema &SemaRef) { WriteTypesBlock(Context); WriteDeclsBlock(Context); WriteMethodPool(SemaRef); - WriteSelectorTable(); WriteIdentifierTable(PP); Stream.EmitRecord(pch::TYPE_OFFSET, TypeOffsets); Stream.EmitRecord(pch::DECL_OFFSET, DeclOffsets); |