diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 09a5c31bad08..2851028dc9b3 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -361,6 +361,9 @@ public: /// \brief Base declaration ID for declarations local to this module. serialization::DeclID BaseDeclID; + /// \brief Remapping table for declaration IDs in this module. + ContinuousRangeMap DeclRemap; + /// \brief The number of C++ base specifier sets in this AST file. unsigned LocalNumCXXBaseSpecifiers; @@ -628,7 +631,7 @@ private: // 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 DeclContextVisibleUpdates; + typedef SmallVector, 1> DeclContextVisibleUpdates; typedef llvm::DenseMap DeclContextVisibleUpdatesPending; @@ -1023,8 +1026,8 @@ private: 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(); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 4205cdb087e8..95bc60260c52 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2068,21 +2068,31 @@ ASTReader::ReadASTBlock(Module &F) { 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, @@ -2096,28 +2106,28 @@ ASTReader::ReadASTBlock(Module &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; @@ -2282,6 +2292,7 @@ ASTReader::ReadASTBlock(Module &F) { // Continuous range maps we may be updating in our module. ContinuousRangeMap::Builder SLocRemap(F.SLocRemap); + ContinuousRangeMap::Builder DeclRemap(F.DeclRemap); ContinuousRangeMap::Builder TypeRemap(F.TypeRemap); while(Data < DataEnd) { @@ -2312,7 +2323,9 @@ ASTReader::ReadASTBlock(Module &F) { (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, @@ -2474,8 +2487,8 @@ ASTReader::ReadASTBlock(Module &F) { return Failure; } for (unsigned I = 0, N = Record.size(); I != N; I += 2) - DeclUpdateOffsets[static_cast(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; } @@ -2485,8 +2498,8 @@ ASTReader::ReadASTBlock(Module &F) { return Failure; } for (unsigned I = 0, N = Record.size(); I != N; I += 2) - ReplacedDecls[static_cast(Record[I])] = - std::make_pair(&F, Record[I+1]); + ReplacedDecls[getGlobalDeclID(F, Record[I])] + = std::make_pair(&F, Record[I+1]); break; } @@ -4090,19 +4103,30 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { } 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(DeclsLoaded[0]); + return cast(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::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) { @@ -4116,7 +4140,7 @@ Decl *ASTReader::GetDecl(DeclID ID) { unsigned Index = ID - 1; if (!DeclsLoaded[Index]) { - ReadDeclRecord(Index, ID); + ReadDeclRecord(ID); if (DeserializationListener) DeserializationListener->DeclRead(ID, DeclsLoaded[Index]); } @@ -5465,7 +5489,7 @@ ASTReader::~ASTReader() { for (DeclContextVisibleUpdates::iterator J = I->second.begin(), F = I->second.end(); J != F; ++J) - delete static_cast(*J); + delete static_cast(J->first); } } @@ -5526,9 +5550,12 @@ void Module::dump() { 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) { diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 546ca4dbe471..f9a99fc67107 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1398,7 +1398,7 @@ static bool isConsumerInterestedIn(Decl *D) { /// \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()) @@ -1407,7 +1407,7 @@ ASTReader::DeclCursorForIndex(unsigned Index, DeclID ID) { 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) { @@ -1438,8 +1438,9 @@ void ASTReader::loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID) { } /// \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. @@ -1463,7 +1464,8 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { 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: @@ -1707,12 +1709,12 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { 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); @@ -1759,23 +1761,25 @@ void ASTDeclReader::UpdateDecl(Decl *D, Module &Module, switch ((DeclUpdateKind)Record[Idx++]) { case UPD_CXX_SET_DEFINITIONDATA: { CXXRecordDecl *RD = cast(D); - CXXRecordDecl *DefinitionDecl = ReadDeclAs(Record, Idx); + CXXRecordDecl *DefinitionDecl + = Reader.ReadDeclAs(Module, Record, Idx); assert(!RD->DefinitionData && "DefinitionData is already set!"); InitializeCXXDefinitionData(RD, DefinitionDecl, Record, Idx); break; } case UPD_CXX_ADDED_IMPLICIT_MEMBER: - cast(D)->addedMember(ReadDecl(Record, Idx)); + cast(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(Record, Idx); + NamespaceDecl *Anon + = Reader.ReadDeclAs(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. diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 66c7d5f669ad..c3bbecdb0e7f 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -2033,11 +2033,13 @@ void ASTWriter::WriteTypeDeclOffsets() { Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(DECL_OFFSET)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // base decl ID Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(Abbrev); Record.clear(); Record.push_back(DECL_OFFSET); Record.push_back(DeclOffsets.size()); + Record.push_back(FirstDeclID - 1); Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, data(DeclOffsets)); }