Store unique IDs for identifiers in the PCH file. Use some bitmangling
so that we only need to perform the lookup and identifier resolution
once per identifier in the PCH file.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68846 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 345e673..b21beed 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -477,7 +477,7 @@
return IgnorePCH;
break;
- case pch::TARGET_TRIPLE:
+ case pch::TARGET_TRIPLE: {
std::string TargetTriple(BlobStart, BlobLen);
if (TargetTriple != Context.Target.getTargetTriple()) {
Diag(diag::warn_pch_target_triple)
@@ -487,6 +487,27 @@
}
break;
}
+
+ case pch::IDENTIFIER_TABLE:
+ IdentifierTable = BlobStart;
+ break;
+
+ case pch::IDENTIFIER_OFFSET:
+ if (!IdentifierData.empty()) {
+ Error("Duplicate IDENTIFIER_OFFSET record in PCH file");
+ return Failure;
+ }
+ IdentifierData.swap(Record);
+#ifndef NDEBUG
+ for (unsigned I = 0, N = IdentifierData.size(); I != N; ++I) {
+ if ((IdentifierData[I] & 0x01) == 0) {
+ Error("Malformed identifier table in the precompiled header");
+ return Failure;
+ }
+ }
+#endif
+ break;
+ }
}
Error("Premature end of bitstream");
@@ -927,13 +948,22 @@
const IdentifierInfo *PCHReader::GetIdentifierInfo(const RecordData &Record,
unsigned &Idx) {
- // FIXME: we need unique IDs for identifiers.
- std::string Str;
- unsigned Length = Record[Idx++];
- Str.resize(Length);
- for (unsigned I = 0; I != Length; ++I)
- Str[I] = Record[Idx++];
- return &Context.Idents.get(Str);
+ pch::IdentID ID = Record[Idx++];
+ if (ID == 0)
+ return 0;
+
+ if (!IdentifierTable || IdentifierData.empty()) {
+ Error("No identifier table in PCH file");
+ return 0;
+ }
+
+ if (IdentifierData[ID - 1] & 0x01) {
+ uint64_t Offset = IdentifierData[ID - 1];
+ IdentifierData[ID - 1] = reinterpret_cast<uint64_t>(
+ &Context.Idents.get(IdentifierTable + Offset));
+ }
+
+ return reinterpret_cast<const IdentifierInfo *>(IdentifierData[ID - 1]);
}
DeclarationName
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 4963ea1..3c795bf 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -818,6 +818,55 @@
S.ExitBlock();
}
+/// \brief Write the identifier table into the PCH file.
+///
+/// The identifier table consists of a blob containing string data
+/// (the actual identifiers themselves) and a separate "offsets" index
+/// that maps identifier IDs to locations within the blob.
+void PCHWriter::WriteIdentifierTable() {
+ using namespace llvm;
+
+ // Create and write out the blob that contains the identifier
+ // strings.
+ RecordData IdentOffsets;
+ IdentOffsets.resize(IdentifierIDs.size());
+ {
+ // Create the identifier string data.
+ std::vector<char> Data;
+ Data.push_back(0); // Data must not be empty.
+ for (llvm::DenseMap<const IdentifierInfo *, pch::IdentID>::iterator
+ ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end();
+ ID != IDEnd; ++ID) {
+ assert(ID->first && "NULL identifier in identifier table");
+
+ // Make sure we're starting on an odd byte. The PCH reader
+ // expects the low bit to be set on all of the offsets.
+ if ((Data.size() & 0x01) == 0)
+ Data.push_back((char)0);
+
+ IdentOffsets[ID->second - 1] = Data.size();
+ Data.insert(Data.end(),
+ ID->first->getName(),
+ ID->first->getName() + ID->first->getLength());
+ Data.push_back((char)0);
+ }
+
+ // Create a blob abbreviation
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(pch::IDENTIFIER_TABLE));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Triple name
+ unsigned IDTableAbbrev = S.EmitAbbrev(Abbrev);
+
+ // Write the identifier table
+ RecordData Record;
+ Record.push_back(pch::IDENTIFIER_TABLE);
+ S.EmitRecordWithBlob(IDTableAbbrev, Record, &Data.front(), Data.size());
+ }
+
+ // Write the offsets table for identifier IDs.
+ S.EmitRecord(pch::IDENTIFIER_OFFSET, IdentOffsets);
+}
+
PCHWriter::PCHWriter(llvm::BitstreamWriter &S)
: S(S), NextTypeID(pch::NUM_PREDEF_TYPE_IDS) { }
@@ -842,6 +891,7 @@
WriteDeclsBlock(Context);
S.EmitRecord(pch::TYPE_OFFSET, TypeOffsets);
S.EmitRecord(pch::DECL_OFFSET, DeclOffsets);
+ WriteIdentifierTable();
S.ExitBlock();
}
@@ -858,11 +908,16 @@
}
void PCHWriter::AddIdentifierRef(const IdentifierInfo *II, RecordData &Record) {
- // FIXME: Emit an identifier ID, not the actual string!
- const char *Name = II->getName();
- unsigned Len = strlen(Name);
- Record.push_back(Len);
- Record.insert(Record.end(), Name, Name + Len);
+ if (II == 0) {
+ Record.push_back(0);
+ return;
+ }
+
+ pch::IdentID &ID = IdentifierIDs[II];
+ if (ID == 0)
+ ID = IdentifierIDs.size();
+
+ Record.push_back(ID);
}
void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {