/// table, indexed by the Selector ID (-1).
std::vector<uint32_t> SelectorOffsets;
- /// \brief A vector of all Selectors (ordered by ID).
- std::vector<Selector> SelVector;
-
/// \brief Offsets of each of the macro identifiers into the
/// bitstream.
///
/// \brief Emit a CXXTemporary.
void AddCXXTemporary(const CXXTemporary *Temp, RecordData &Record);
+
+ /// \brief Get the unique number used to refer to the given selector.
+ pch::SelectorID getSelectorRef(Selector Sel);
- /// \brief Get the unique number used to refer to the given
- /// identifier.
+ /// \brief Get the unique number used to refer to the given identifier.
pch::IdentID getIdentifierRef(const IdentifierInfo *II);
/// \brief Retrieve the offset of the macro definition for the given
void IdentifierRead(pch::IdentID ID, IdentifierInfo *II);
void TypeRead(pch::TypeID ID, QualType T);
void DeclRead(pch::DeclID ID, const Decl *D);
+ void SelectorRead(pch::SelectorID iD, Selector Sel);
};
/// \brief AST and semantic-analysis consumer that generates a
PCHReader &Reader;
public:
- typedef std::pair<ObjCMethodList, ObjCMethodList> data_type;
+ struct data_type {
+ pch::SelectorID ID;
+ ObjCMethodList Instance, Factory;
+ };
typedef Selector external_key_type;
typedef external_key_type internal_key_type;
data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) {
using namespace clang::io;
- unsigned NumInstanceMethods = ReadUnalignedLE16(d);
- unsigned NumFactoryMethods = ReadUnalignedLE16(d);
data_type Result;
+ Result.ID = ReadUnalignedLE32(d);
+ unsigned NumInstanceMethods = ReadUnalignedLE16(d);
+ unsigned NumFactoryMethods = ReadUnalignedLE16(d);
+
// Load instance methods
ObjCMethodList *Prev = 0;
for (unsigned I = 0; I != NumInstanceMethods; ++I) {
ObjCMethodDecl *Method
= cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
- if (!Result.first.Method) {
+ if (!Result.Instance.Method) {
// This is the first method, which is the easy case.
- Result.first.Method = Method;
- Prev = &Result.first;
+ Result.Instance.Method = Method;
+ Prev = &Result.Instance;
continue;
}
for (unsigned I = 0; I != NumFactoryMethods; ++I) {
ObjCMethodDecl *Method
= cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
- if (!Result.second.Method) {
+ if (!Result.Factory.Method) {
// This is the first method, which is the easy case.
- Result.second.Method = Method;
- Prev = &Result.second;
+ Result.Factory.Method = Method;
+ Prev = &Result.Factory;
continue;
}
PCHMethodPoolLookupTable::iterator Pos = PoolTable->find(Sel);
if (Pos == PoolTable->end()) {
++NumMethodPoolMisses;
- return std::pair<ObjCMethodList, ObjCMethodList>();;
+ return std::pair<ObjCMethodList, ObjCMethodList>();
}
++NumMethodPoolSelectorsRead;
- return *Pos;
+ PCHMethodPoolLookupTrait::data_type Data = *Pos;
+ if (DeserializationListener)
+ DeserializationListener->SelectorRead(Data.ID, Sel);
+ return std::make_pair(Data.Instance, Data.Factory);
}
void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
typedef Selector key_type;
typedef key_type key_type_ref;
- typedef std::pair<ObjCMethodList, ObjCMethodList> data_type;
+ struct data_type {
+ pch::SelectorID ID;
+ ObjCMethodList Instance, Factory;
+ };
typedef const data_type& data_type_ref;
explicit PCHMethodPoolTrait(PCHWriter &Writer) : Writer(Writer) { }
data_type_ref Methods) {
unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4);
clang::io::Emit16(Out, KeyLen);
- unsigned DataLen = 2 + 2; // 2 bytes for each of the method counts
- for (const ObjCMethodList *Method = &Methods.first; Method;
+ unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts
+ for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->Next)
if (Method->Method)
DataLen += 4;
- for (const ObjCMethodList *Method = &Methods.second; Method;
+ for (const ObjCMethodList *Method = &Methods.Factory; Method;
Method = Method->Next)
if (Method->Method)
DataLen += 4;
void EmitData(llvm::raw_ostream& Out, key_type_ref,
data_type_ref Methods, unsigned DataLen) {
uint64_t Start = Out.tell(); (void)Start;
+ clang::io::Emit32(Out, Methods.ID);
unsigned NumInstanceMethods = 0;
- for (const ObjCMethodList *Method = &Methods.first; Method;
+ for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->Next)
if (Method->Method)
++NumInstanceMethods;
unsigned NumFactoryMethods = 0;
- for (const ObjCMethodList *Method = &Methods.second; Method;
+ for (const ObjCMethodList *Method = &Methods.Factory; Method;
Method = Method->Next)
if (Method->Method)
++NumFactoryMethods;
clang::io::Emit16(Out, NumInstanceMethods);
clang::io::Emit16(Out, NumFactoryMethods);
- for (const ObjCMethodList *Method = &Methods.first; Method;
+ for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->Next)
if (Method->Method)
clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
- for (const ObjCMethodList *Method = &Methods.second; Method;
+ for (const ObjCMethodList *Method = &Methods.Factory; Method;
Method = Method->Next)
if (Method->Method)
clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
using namespace llvm;
// Do we have to do anything at all?
- if (SemaRef.MethodPool.empty() && SelVector.empty())
+ if (SemaRef.MethodPool.empty() && SelectorIDs.empty())
return;
// Create and write out the blob that contains selectors and the method pool.
{
// Create the on-disk hash table representation. We walk through every
// selector we've seen and look it up in the method pool.
- SelectorOffsets.resize(SelVector.size());
- for (unsigned I = 0, N = SelVector.size(); I != N; ++I) {
- Selector S = SelVector[I];
+ SelectorOffsets.resize(SelectorIDs.size());
+ for (llvm::DenseMap<Selector, pch::SelectorID>::iterator
+ I = SelectorIDs.begin(), E = SelectorIDs.end();
+ I != E; ++I) {
+ Selector S = I->first;
Sema::GlobalMethodPool::iterator F = SemaRef.MethodPool.find(S);
- Generator.insert(S, F != SemaRef.MethodPool.end() ? F->second :
- std::make_pair(ObjCMethodList(), ObjCMethodList()));
-
+ PCHMethodPoolTrait::data_type Data = {
+ I->second,
+ ObjCMethodList(),
+ ObjCMethodList()
+ };
+ if (F != SemaRef.MethodPool.end()) {
+ Data.Instance = F->second.first;
+ Data.Factory = F->second.second;
+ }
+ Generator.insert(S, Data);
}
// Create the on-disk hash table in a buffer.
RecordData Record;
Record.push_back(pch::METHOD_POOL);
Record.push_back(BucketOffset);
- Record.push_back(SelVector.size());
+ Record.push_back(SelectorIDs.size());
Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool.str());
// Create a blob abbreviation for the selector table offsets.
}
void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) {
- if (SelRef.getAsOpaquePtr() == 0) {
- Record.push_back(0);
- return;
+ Record.push_back(getSelectorRef(SelRef));
+}
+
+pch::SelectorID PCHWriter::getSelectorRef(Selector Sel) {
+ if (Sel.getAsOpaquePtr() == 0) {
+ return 0;
}
- pch::SelectorID &SID = SelectorIDs[SelRef];
+ pch::SelectorID &SID = SelectorIDs[Sel];
if (SID == 0) {
SID = SelectorIDs.size();
- SelVector.push_back(SelRef);
}
- Record.push_back(SID);
+ return SID;
}
void PCHWriter::AddCXXTemporary(const CXXTemporary *Temp, RecordData &Record) {
void PCHWriter::DeclRead(pch::DeclID ID, const Decl *D) {
DeclIDs[D] = ID;
}
+
+void PCHWriter::SelectorRead(pch::SelectorID ID, Selector S) {
+ SelectorIDs[S] = ID;
+}