/// \brief Base declaration ID for declarations local to this module.
serialization::DeclID BaseDeclID;
+ /// \brief Remapping table for declaration IDs in this module.
+ ContinuousRangeMap<uint32_t, int, 2> DeclRemap;
+
/// \brief The number of C++ base specifier sets in this AST file.
unsigned LocalNumCXXBaseSpecifiers;
// TU, and when we read those update records, the actual context will not
// be available yet (unless it's the TU), so have this pending map using the
// ID as a key. It will be realized when the context is actually loaded.
- typedef SmallVector<void *, 1> DeclContextVisibleUpdates;
+ typedef SmallVector<std::pair<void *, Module*>, 1> DeclContextVisibleUpdates;
typedef llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates>
DeclContextVisibleUpdatesPending;
QualType readTypeRecord(unsigned Index);
RecordLocation TypeCursorForIndex(unsigned Index);
void LoadedDecl(unsigned Index, Decl *D);
- Decl *ReadDeclRecord(unsigned Index, serialization::DeclID ID);
- RecordLocation DeclCursorForIndex(unsigned Index, serialization::DeclID ID);
+ Decl *ReadDeclRecord(serialization::DeclID ID);
+ RecordLocation DeclCursorForID(serialization::DeclID ID);
RecordLocation getLocalBitOffset(uint64_t GlobalOffset);
void PassInterestingDeclsToConsumer();
break;
}
- case DECL_OFFSET:
+ case DECL_OFFSET: {
if (F.LocalNumDecls != 0) {
Error("duplicate DECL_OFFSET record in AST file");
return Failure;
}
F.DeclOffsets = (const uint32_t *)BlobStart;
F.LocalNumDecls = Record[0];
+ unsigned LocalBaseDeclID = Record[1];
F.BaseDeclID = getTotalNumDecls();
- // Introduce the global -> local mapping for declarations within this
- // AST file.
- GlobalDeclMap.insert(std::make_pair(getTotalNumDecls() + 1, &F));
- DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls);
+ if (F.LocalNumDecls > 0) {
+ // Introduce the global -> local mapping for declarations within this
+ // module.
+ GlobalDeclMap.insert(std::make_pair(getTotalNumDecls() + 1, &F));
+
+ // Introduce the local -> global mapping for declarations within this
+ // module.
+ F.DeclRemap.insert(std::make_pair(LocalBaseDeclID,
+ F.BaseDeclID - LocalBaseDeclID));
+
+ DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls);
+ }
break;
-
+ }
+
case TU_UPDATE_LEXICAL: {
DeclContextInfo Info = {
&F,
}
case UPDATE_VISIBLE: {
- serialization::DeclID ID = Record[0];
+ unsigned Idx = 0;
+ serialization::DeclID ID = ReadDeclID(F, Record, Idx);
void *Table = ASTDeclContextNameLookupTable::Create(
- (const unsigned char *)BlobStart + Record[1],
+ (const unsigned char *)BlobStart + Record[Idx++],
(const unsigned char *)BlobStart,
ASTDeclContextNameLookupTrait(*this, F));
- if (ID == 1 && Context) { // Is it the TU?
+ // FIXME: Complete hack to check for the TU
+ if (ID == (*(ModuleMgr.end() - 1))->BaseDeclID + 1 && Context) { // Is it the TU?
DeclContextInfo Info = {
- &F, Table, /* No lexical inforamtion */ 0, 0
+ &F, Table, /* No lexical information */ 0, 0
};
DeclContextOffsets[Context->getTranslationUnitDecl()].push_back(Info);
} else
- PendingVisibleUpdates[ID].push_back(Table);
+ PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F));
break;
}
case REDECLS_UPDATE_LATEST: {
assert(Record.size() % 2 == 0 && "Expected pairs of DeclIDs");
- for (unsigned i = 0, e = Record.size(); i < e; i += 2) {
- DeclID First = Record[i], Latest = Record[i+1];
- assert((FirstLatestDeclIDs.find(First) == FirstLatestDeclIDs.end() ||
- Latest > FirstLatestDeclIDs[First]) &&
- "The new latest is supposed to come after the previous latest");
+ for (unsigned i = 0, e = Record.size(); i < e; /* in loop */) {
+ DeclID First = ReadDeclID(F, Record, i);
+ DeclID Latest = ReadDeclID(F, Record, i);
FirstLatestDeclIDs[First] = Latest;
}
break;
// Continuous range maps we may be updating in our module.
ContinuousRangeMap<uint32_t, int, 2>::Builder SLocRemap(F.SLocRemap);
+ ContinuousRangeMap<uint32_t, int, 2>::Builder DeclRemap(F.DeclRemap);
ContinuousRangeMap<uint32_t, int, 2>::Builder TypeRemap(F.TypeRemap);
while(Data < DataEnd) {
(void)PreprocessedEntityIDOffset;
(void)MacroDefinitionIDOffset;
(void)SelectorIDOffset;
- (void)DeclIDOffset;
+ DeclRemap.insert(std::make_pair(DeclIDOffset,
+ OM->BaseDeclID - DeclIDOffset));
+
(void)CXXBaseSpecifiersIDOffset;
TypeRemap.insert(std::make_pair(TypeIndexOffset,
return Failure;
}
for (unsigned I = 0, N = Record.size(); I != N; I += 2)
- DeclUpdateOffsets[static_cast<DeclID>(Record[I])]
- .push_back(std::make_pair(&F, Record[I+1]));
+ DeclUpdateOffsets[getGlobalDeclID(F, Record[I])]
+ .push_back(std::make_pair(&F, Record[I+1]));
break;
}
return Failure;
}
for (unsigned I = 0, N = Record.size(); I != N; I += 2)
- ReplacedDecls[static_cast<DeclID>(Record[I])] =
- std::make_pair(&F, Record[I+1]);
+ ReplacedDecls[getGlobalDeclID(F, Record[I])]
+ = std::make_pair(&F, Record[I+1]);
break;
}
}
TranslationUnitDecl *ASTReader::GetTranslationUnitDecl() {
- if (!DeclsLoaded[0]) {
- ReadDeclRecord(0, 1);
+ // FIXME: This routine might not even make sense when we're loading multiple
+ // unrelated AST files, since we'll have to merge the translation units
+ // somehow.
+ unsigned TranslationUnitID = (*(ModuleMgr.end() - 1))->BaseDeclID + 1;
+ if (!DeclsLoaded[TranslationUnitID - 1]) {
+ ReadDeclRecord(TranslationUnitID);
if (DeserializationListener)
- DeserializationListener->DeclRead(1, DeclsLoaded[0]);
+ DeserializationListener->DeclRead(TranslationUnitID,
+ DeclsLoaded[TranslationUnitID - 1]);
}
- return cast<TranslationUnitDecl>(DeclsLoaded[0]);
+ return cast<TranslationUnitDecl>(DeclsLoaded[TranslationUnitID - 1]);
}
serialization::DeclID
ASTReader::getGlobalDeclID(Module &F, unsigned LocalID) const {
- // FIXME: Perform local -> global remapping for declarations.
- return LocalID;
+ if (LocalID == 0)
+ return LocalID;
+
+ ContinuousRangeMap<uint32_t, int, 2>::iterator I
+ = F.DeclRemap.find(LocalID - 1);
+ assert(I != F.DeclRemap.end() && "Invalid index into decl index remap");
+
+ return LocalID + I->second;
}
Decl *ASTReader::GetDecl(DeclID ID) {
unsigned Index = ID - 1;
if (!DeclsLoaded[Index]) {
- ReadDeclRecord(Index, ID);
+ ReadDeclRecord(ID);
if (DeserializationListener)
DeserializationListener->DeclRead(ID, DeclsLoaded[Index]);
}
for (DeclContextVisibleUpdates::iterator J = I->second.begin(),
F = I->second.end();
J != F; ++J)
- delete static_cast<ASTDeclContextNameLookupTable*>(*J);
+ delete static_cast<ASTDeclContextNameLookupTable*>(J->first);
}
}
llvm::errs() << " Base source location offset: " << SLocEntryBaseOffset
<< '\n';
dumpLocalRemap("Source location offset map", SLocRemap);
- llvm::errs() << " Base type ID: " << BaseTypeIndex << '\n'
+ llvm::errs() << " Base type index: " << BaseTypeIndex << '\n'
<< " Number of types: " << LocalNumTypes << '\n';
- dumpLocalRemap("Type ID map", TypeRemap);
+ dumpLocalRemap("Type index map", TypeRemap);
+ llvm::errs() << " Base decl ID: " << BaseDeclID << '\n'
+ << " Number of decls: " << LocalNumDecls << '\n';
+ dumpLocalRemap("Decl ID map", DeclRemap);
}
Module *ModuleManager::lookup(StringRef Name) {
/// \brief Get the correct cursor and offset for loading a declaration.
ASTReader::RecordLocation
-ASTReader::DeclCursorForIndex(unsigned Index, DeclID ID) {
+ASTReader::DeclCursorForID(DeclID ID) {
// See if there's an override.
DeclReplacementMap::iterator It = ReplacedDecls.find(ID);
if (It != ReplacedDecls.end())
GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID);
assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
Module *M = I->second;
- return RecordLocation(M, M->DeclOffsets[Index - M->BaseDeclID]);
+ return RecordLocation(M, M->DeclOffsets[ID - M->BaseDeclID - 1]);
}
ASTReader::RecordLocation ASTReader::getLocalBitOffset(uint64_t GlobalOffset) {
}
/// \brief Read the declaration at the given offset from the AST file.
-Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) {
- RecordLocation Loc = DeclCursorForIndex(Index, ID);
+Decl *ASTReader::ReadDeclRecord(DeclID ID) {
+ unsigned Index = ID - 1;
+ RecordLocation Loc = DeclCursorForID(ID);
llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor;
// Keep track of where we are in the stream, then jump back there
// after reading this declaration.
assert(false && "Record cannot be de-serialized with ReadDeclRecord");
break;
case DECL_TRANSLATION_UNIT:
- assert(Index == 0 && "Translation unit must be at index 0");
+ assert(Index == Loc.F->BaseDeclID &&
+ "Translation unit must be at first index in file");
D = Context->getTranslationUnitDecl();
break;
case DECL_TYPEDEF:
DeclContextVisibleUpdates &U = I->second;
DeclContextInfos &Infos = DeclContextOffsets[DC];
DeclContextInfo Info;
- Info.F = Loc.F;
Info.LexicalDecls = 0;
Info.NumLexicalDecls = 0;
for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end();
UI != UE; ++UI) {
- Info.NameLookupTableData = *UI;
+ Info.NameLookupTableData = UI->first;
+ Info.F = UI->second;
Infos.push_back(Info);
}
PendingVisibleUpdates.erase(I);
switch ((DeclUpdateKind)Record[Idx++]) {
case UPD_CXX_SET_DEFINITIONDATA: {
CXXRecordDecl *RD = cast<CXXRecordDecl>(D);
- CXXRecordDecl *DefinitionDecl = ReadDeclAs<CXXRecordDecl>(Record, Idx);
+ CXXRecordDecl *DefinitionDecl
+ = Reader.ReadDeclAs<CXXRecordDecl>(Module, Record, Idx);
assert(!RD->DefinitionData && "DefinitionData is already set!");
InitializeCXXDefinitionData(RD, DefinitionDecl, Record, Idx);
break;
}
case UPD_CXX_ADDED_IMPLICIT_MEMBER:
- cast<CXXRecordDecl>(D)->addedMember(ReadDecl(Record, Idx));
+ cast<CXXRecordDecl>(D)->addedMember(Reader.ReadDecl(Module, Record, Idx));
break;
case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
// It will be added to the template's specializations set when loaded.
- (void)ReadDecl(Record, Idx);
+ (void)Reader.ReadDecl(Module, Record, Idx);
break;
case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: {
- NamespaceDecl *Anon = ReadDeclAs<NamespaceDecl>(Record, Idx);
+ NamespaceDecl *Anon
+ = Reader.ReadDeclAs<NamespaceDecl>(Module, Record, Idx);
// Guard against these being loaded out of original order. Don't use
// getNextNamespace(), since it tries to access the context and can't in
// the middle of deserialization.