diff options
Diffstat (limited to 'lib/Serialization')
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 66 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 39 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 51 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 6 |
4 files changed, 106 insertions, 56 deletions
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 1bda1ed42a..43435b6754 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2091,7 +2091,8 @@ ASTReader::ReadASTBlock(Module &F) { if (F.LocalNumDecls > 0) { // Introduce the global -> local mapping for declarations within this // module. - GlobalDeclMap.insert(std::make_pair(getTotalNumDecls() + 1, &F)); + GlobalDeclMap.insert( + std::make_pair(getTotalNumDecls() + NUM_PREDEF_DECL_IDS, &F)); // Introduce the local -> global mapping for declarations within this // module. @@ -2110,8 +2111,12 @@ ASTReader::ReadASTBlock(Module &F) { reinterpret_cast<const KindDeclIDPair *>(BlobStart), static_cast<unsigned int>(BlobLen / sizeof(KindDeclIDPair)) }; - DeclContextOffsets[Context ? Context->getTranslationUnitDecl() : 0] - .push_back(Info); + + DeclContext *TU = Context ? Context->getTranslationUnitDecl() : 0; + DeclContextOffsets[TU].push_back(Info); + if (TU) + TU->setHasExternalLexicalStorage(true); + break; } @@ -2123,11 +2128,14 @@ ASTReader::ReadASTBlock(Module &F) { (const unsigned char *)BlobStart, ASTDeclContextNameLookupTrait(*this, F)); // FIXME: Complete hack to check for the TU - if (ID == (*(ModuleMgr.end() - 1))->BaseDeclID + 1 && Context) { // Is it the TU? + if (ID == PREDEF_DECL_TRANSLATION_UNIT_ID && Context) { // Is it the TU? DeclContextInfo Info = { &F, Table, /* No lexical information */ 0, 0 }; - DeclContextOffsets[Context->getTranslationUnitDecl()].push_back(Info); + + DeclContext *TU = Context->getTranslationUnitDecl(); + DeclContextOffsets[TU].push_back(Info); + TU->setHasExternalVisibleStorage(true); } else PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F)); break; @@ -2948,17 +2956,27 @@ void ASTReader::InitializeContext(ASTContext &Ctx) { // If we have an update block for the TU waiting, we have to add it before // deserializing the decl. + TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl(); DeclContextOffsetsMap::iterator DCU = DeclContextOffsets.find(0); if (DCU != DeclContextOffsets.end()) { // Insertion could invalidate map, so grab vector. DeclContextInfos T; T.swap(DCU->second); DeclContextOffsets.erase(DCU); - DeclContextOffsets[Ctx.getTranslationUnitDecl()].swap(T); + DeclContextOffsets[TU].swap(T); } + + // If there's a listener, notify them that we "read" the translation unit. + if (DeserializationListener) + DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID, TU); - // Load the translation unit declaration - GetTranslationUnitDecl(); + // Make sure we load the declaration update records for the translation unit, + // if there are any. + loadDeclUpdateRecords(PREDEF_DECL_TRANSLATION_UNIT_ID, TU); + + // Note that the translation unit has external lexical and visible storage. + TU->setHasExternalLexicalStorage(true); + TU->setHasExternalVisibleStorage(true); // FIXME: Find a better way to deal with collisions between these // built-in types. Right now, we just ignore the problem. @@ -4186,21 +4204,6 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { return Bases; } -TranslationUnitDecl *ASTReader::GetTranslationUnitDecl() { - // 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(TranslationUnitID, - DeclsLoaded[TranslationUnitID - 1]); - } - - return cast<TranslationUnitDecl>(DeclsLoaded[TranslationUnitID - 1]); -} - serialization::DeclID ASTReader::getGlobalDeclID(Module &F, unsigned LocalID) const { if (LocalID < NUM_PREDEF_DECL_IDS) @@ -4216,20 +4219,25 @@ ASTReader::getGlobalDeclID(Module &F, unsigned LocalID) const { Decl *ASTReader::GetDecl(DeclID ID) { if (ID < NUM_PREDEF_DECL_IDS) { switch ((PredefinedDeclIDs)ID) { - case serialization::PREDEF_DECL_NULL_ID: + case PREDEF_DECL_NULL_ID: return 0; + + case PREDEF_DECL_TRANSLATION_UNIT_ID: + assert(Context && "No context available?"); + return Context->getTranslationUnitDecl(); } return 0; } - if (ID > DeclsLoaded.size()) { + unsigned Index = ID - NUM_PREDEF_DECL_IDS; + + if (Index > DeclsLoaded.size()) { Error("declaration ID out-of-range for AST file"); return 0; } - - unsigned Index = ID - NUM_PREDEF_DECL_IDS; - if (!DeclsLoaded[Index]) { + +if (!DeclsLoaded[Index]) { ReadDeclRecord(ID); if (DeserializationListener) DeserializationListener->DeclRead(ID, DeclsLoaded[Index]); @@ -5666,7 +5674,7 @@ void Module::dump() { llvm::errs() << " Base preprocessed entity ID: " << BasePreprocessedEntityID << '\n' - << "Number of preprocessed entities: " + << " Number of preprocessed entities: " << NumPreallocatedPreprocessingEntities << '\n'; dumpLocalRemap("Preprocessed entity ID local -> global map", PreprocessedEntityRemap); diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 707ee8a8bb..02bd21fef0 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -243,8 +243,7 @@ void ASTDeclReader::VisitDecl(Decl *D) { } void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { - VisitDecl(TU); - TU->setAnonymousNamespace(ReadDeclAs<NamespaceDecl>(Record, Idx)); + llvm_unreachable("Translation units are not serialized"); } void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) { @@ -1444,7 +1443,7 @@ void ASTReader::loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID) { /// \brief Read the declaration at the given offset from the AST file. Decl *ASTReader::ReadDeclRecord(DeclID ID) { - unsigned Index = ID - 1; + unsigned Index = ID - NUM_PREDEF_DECL_IDS; RecordLocation Loc = DeclCursorForID(ID); llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; // Keep track of where we are in the stream, then jump back there @@ -1468,11 +1467,6 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_CONTEXT_VISIBLE: assert(false && "Record cannot be de-serialized with ReadDeclRecord"); break; - case DECL_TRANSLATION_UNIT: - assert(Index == Loc.F->BaseDeclID && - "Translation unit must be at first index in file"); - D = Context->getTranslationUnitDecl(); - break; case DECL_TYPEDEF: D = TypedefDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 0, 0); @@ -1727,6 +1721,20 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { } assert(Idx == Record.size()); + // Load any relevant update records. + loadDeclUpdateRecords(ID, D); + + // If we have deserialized a declaration that has a definition the + // AST consumer might need to know about, queue it. + // We don't pass it to the consumer immediately because we may be in recursive + // loading, and some declarations may still be initializing. + if (isConsumerInterestedIn(D)) + InterestingDecls.push_back(D); + + return D; +} + +void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { // The declaration may have been modified by files later in the chain. // If this is the case, read the record containing the updates from each file // and pass it to ASTDeclReader to make the modifications. @@ -1734,7 +1742,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { if (UpdI != DeclUpdateOffsets.end()) { FileOffsetsTy &UpdateOffsets = UpdI->second; for (FileOffsetsTy::iterator - I = UpdateOffsets.begin(), E = UpdateOffsets.end(); I != E; ++I) { + I = UpdateOffsets.begin(), E = UpdateOffsets.end(); I != E; ++I) { Module *F = I->first; uint64_t Offset = I->second; llvm::BitstreamCursor &Cursor = F->DeclsCursor; @@ -1745,20 +1753,15 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { unsigned RecCode = Cursor.ReadRecord(Code, Record); (void)RecCode; assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!"); + + unsigned Idx = 0; + ASTDeclReader Reader(*this, *F, Cursor, ID, Record, Idx); Reader.UpdateDecl(D, *F, Record); } } - - // If we have deserialized a declaration that has a definition the - // AST consumer might need to know about, queue it. - // We don't pass it to the consumer immediately because we may be in recursive - // loading, and some declarations may still be initializing. - if (isConsumerInterestedIn(D)) - InterestingDecls.push_back(D); - - return D; } + void ASTDeclReader::UpdateDecl(Decl *D, Module &Module, const RecordData &Record) { unsigned Idx = 0; diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index fe747a5150..5b93de4d30 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -841,7 +841,6 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(TYPE_PACK_EXPANSION); RECORD(TYPE_ATTRIBUTED); RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK); - RECORD(DECL_TRANSLATION_UNIT); RECORD(DECL_TYPEDEF); RECORD(DECL_ENUM); RECORD(DECL_RECORD); @@ -2810,10 +2809,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, ASTContext &Context = SemaRef.Context; Preprocessor &PP = SemaRef.PP; - // The translation unit is the first declaration we'll emit. - DeclIDs[Context.getTranslationUnitDecl()] = 1; - ++NextDeclID; - DeclTypesToEmit.push(Context.getTranslationUnitDecl()); + // Set up predefined declaration IDs. + DeclIDs[Context.getTranslationUnitDecl()] = PREDEF_DECL_TRANSLATION_UNIT_ID; // Make sure that we emit IdentifierInfos (and any attached // declarations) for builtins. @@ -2942,6 +2939,45 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, AddTypeRef(Context.ObjCSelRedefinitionType, SpecialTypes); SpecialTypes.push_back(Context.isInt128Installed()); + // We don't start with the translation unit, but with its decls that + // don't come from the chained PCH. + const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); + SmallVector<KindDeclIDPair, 64> NewGlobalDecls; + for (DeclContext::decl_iterator I = TU->noload_decls_begin(), + E = TU->noload_decls_end(); + I != E; ++I) { + if ((*I)->getPCHLevel() == 0) + NewGlobalDecls.push_back(std::make_pair((*I)->getKind(), GetDeclRef(*I))); + else if ((*I)->isChangedSinceDeserialization()) + (void)GetDeclRef(*I); // Make sure it's written, but don't record it. + } + // We also need to write a lexical updates block for the TU. + llvm::BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev(); + Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); + unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(Abv); + Record.clear(); + Record.push_back(TU_UPDATE_LEXICAL); + Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, + data(NewGlobalDecls)); + + // And a visible updates block for the DeclContexts. + Abv = new llvm::BitCodeAbbrev(); + Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, 32)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); + UpdateVisibleAbbrev = Stream.EmitAbbrev(Abv); + WriteDeclContextVisibleUpdate(TU); + + // If the translation unit has an anonymous namespace, write it as an + // update block. + if (NamespaceDecl *NS = TU->getAnonymousNamespace()) { + ASTWriter::UpdateRecord &Record = DeclUpdates[TU]; + Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE); + AddDeclRef(NS, Record); + } + // Keep writing types and declarations until all types and // declarations have been written. Stream.EnterSubblock(DECLTYPES_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE); @@ -3025,6 +3061,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, if (!KnownNamespaces.empty()) Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces); + WriteDeclUpdatesBlocks(); + // Some simple statistics Record.clear(); Record.push_back(NumStatements); @@ -3042,6 +3080,9 @@ void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, ASTContext &Context = SemaRef.Context; Preprocessor &PP = SemaRef.PP; + // Set up predefined declaration IDs. + DeclIDs[Context.getTranslationUnitDecl()] = PREDEF_DECL_TRANSLATION_UNIT_ID; + RecordData Record; Stream.EnterSubblock(AST_BLOCK_ID, 5); WriteMetadata(Context, isysroot, ""); diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 45f8a32df0..98dad1c90e 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -157,9 +157,7 @@ void ASTDeclWriter::VisitDecl(Decl *D) { } void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { - VisitDecl(D); - Writer.AddDeclRef(D->getAnonymousNamespace(), Record); - Code = serialization::DECL_TRANSLATION_UNIT; + llvm_unreachable("Translation units aren't directly serialized"); } void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) { @@ -819,7 +817,7 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { // anonymous namespace. Decl *Parent = cast<Decl>( D->getParent()->getRedeclContext()->getPrimaryContext()); - if (Parent->getPCHLevel() > 0) { + if (Parent->getPCHLevel() > 0 || isa<TranslationUnitDecl>(Parent)) { ASTWriter::UpdateRecord &Record = Writer.DeclUpdates[Parent]; Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE); Writer.AddDeclRef(D, Record); |