diff options
Diffstat (limited to 'clang/lib/Serialization/ASTWriter.cpp')
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 273 |
1 files changed, 213 insertions, 60 deletions
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 345d496..a6f8c60 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1088,6 +1088,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(DECL_BLOCK); RECORD(DECL_CONTEXT_LEXICAL); RECORD(DECL_CONTEXT_VISIBLE); + RECORD(DECL_CONTEXT_MODULE_LOCAL_VISIBLE); RECORD(DECL_NAMESPACE); RECORD(DECL_NAMESPACE_ALIAS); RECORD(DECL_USING); @@ -4024,15 +4025,13 @@ void ASTWriter::handleVTable(CXXRecordDecl *RD) { namespace { -// Trait used for the on-disk hash table used in the method pool. -class ASTDeclContextNameLookupTrait { +class ASTDeclContextNameLookupTraitBase { +protected: ASTWriter &Writer; - llvm::SmallVector<LocalDeclID, 64> DeclIDs; + using DeclIDsTy = llvm::SmallVector<LocalDeclID, 64>; + DeclIDsTy DeclIDs; public: - using key_type = DeclarationNameKey; - using key_type_ref = key_type; - /// A start and end index into DeclIDs, representing a sequence of decls. using data_type = std::pair<unsigned, unsigned>; using data_type_ref = const data_type &; @@ -4040,31 +4039,11 @@ public: using hash_value_type = unsigned; using offset_type = unsigned; - explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) {} - - template<typename Coll> - data_type getData(const Coll &Decls) { - unsigned Start = DeclIDs.size(); - for (NamedDecl *D : Decls) { - NamedDecl *DeclForLocalLookup = - getDeclForLocalLookup(Writer.getLangOpts(), D); - - if (Writer.getDoneWritingDeclsAndTypes() && - !Writer.wasDeclEmitted(DeclForLocalLookup)) - continue; - - // Try to avoid writing internal decls to reduced BMI. - // See comments in ASTWriter::WriteDeclContextLexicalBlock for details. - if (Writer.isGeneratingReducedBMI() && - !DeclForLocalLookup->isFromExplicitGlobalModule() && - IsInternalDeclFromFileContext(DeclForLocalLookup)) - continue; - - DeclIDs.push_back(Writer.GetDeclRef(DeclForLocalLookup)); - } - return std::make_pair(Start, DeclIDs.size()); - } +protected: + explicit ASTDeclContextNameLookupTraitBase(ASTWriter &Writer) + : Writer(Writer) {} +public: data_type ImportData(const reader::ASTDeclContextNameLookupTrait::data_type &FromReader) { unsigned Start = DeclIDs.size(); DeclIDs.insert( @@ -4074,14 +4053,6 @@ public: return std::make_pair(Start, DeclIDs.size()); } - static bool EqualKey(key_type_ref a, key_type_ref b) { - return a == b; - } - - hash_value_type ComputeHash(DeclarationNameKey Name) { - return Name.getHash(); - } - void EmitFileRef(raw_ostream &Out, ModuleFile *F) const { assert(Writer.hasChain() && "have reference to loaded module file but no chain?"); @@ -4092,9 +4063,9 @@ public: llvm::endianness::little); } - std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &Out, - DeclarationNameKey Name, - data_type_ref Lookup) { + std::pair<unsigned, unsigned> EmitKeyDataLengthBase(raw_ostream &Out, + DeclarationNameKey Name, + data_type_ref Lookup) { unsigned KeyLen = 1; switch (Name.getKind()) { case DeclarationName::Identifier: @@ -4120,10 +4091,10 @@ public: // length of DeclIDs. unsigned DataLen = sizeof(DeclID) * (Lookup.second - Lookup.first); - return emitULEBKeyDataLength(KeyLen, DataLen, Out); + return {KeyLen, DataLen}; } - void EmitKey(raw_ostream &Out, DeclarationNameKey Name, unsigned) { + void EmitKeyBase(raw_ostream &Out, DeclarationNameKey Name) { using namespace llvm::support; endian::Writer LE(Out, llvm::endianness::little); @@ -4154,8 +4125,7 @@ public: llvm_unreachable("Invalid name kind?"); } - void EmitData(raw_ostream &Out, key_type_ref, data_type Lookup, - unsigned DataLen) { + void EmitDataBase(raw_ostream &Out, data_type Lookup, unsigned DataLen) { using namespace llvm::support; endian::Writer LE(Out, llvm::endianness::little); @@ -4166,6 +4136,129 @@ public: } }; +class ModuleLocalNameLookupTrait : public ASTDeclContextNameLookupTraitBase { +public: + using primary_module_hash_type = unsigned; + + using key_type = std::pair<DeclarationNameKey, primary_module_hash_type>; + using key_type_ref = key_type; + + explicit ModuleLocalNameLookupTrait(ASTWriter &Writer) + : ASTDeclContextNameLookupTraitBase(Writer) {} + + data_type getData(const DeclIDsTy &LocalIDs) { + unsigned Start = DeclIDs.size(); + for (auto ID : LocalIDs) + DeclIDs.push_back(ID); + return std::make_pair(Start, DeclIDs.size()); + } + + static bool EqualKey(key_type_ref a, key_type_ref b) { return a == b; } + + hash_value_type ComputeHash(key_type Key) { + llvm::FoldingSetNodeID ID; + ID.AddInteger(Key.first.getHash()); + ID.AddInteger(Key.second); + return ID.computeStableHash(); + } + + std::pair<unsigned, unsigned> + EmitKeyDataLength(raw_ostream &Out, key_type Key, data_type_ref Lookup) { + auto [KeyLen, DataLen] = EmitKeyDataLengthBase(Out, Key.first, Lookup); + KeyLen += sizeof(Key.second); + return emitULEBKeyDataLength(KeyLen, DataLen, Out); + } + + void EmitKey(raw_ostream &Out, key_type Key, unsigned) { + EmitKeyBase(Out, Key.first); + llvm::support::endian::Writer LE(Out, llvm::endianness::little); + LE.write<primary_module_hash_type>(Key.second); + } + + void EmitData(raw_ostream &Out, key_type_ref, data_type Lookup, + unsigned DataLen) { + EmitDataBase(Out, Lookup, DataLen); + } +}; + +// Trait used for the on-disk hash table used in the method pool. +class ASTDeclContextNameLookupTrait : public ASTDeclContextNameLookupTraitBase { +public: + using ModuleLocalDeclsMapTy = + llvm::DenseMap<ModuleLocalNameLookupTrait::key_type, DeclIDsTy>; + +private: + ModuleLocalDeclsMapTy ModuleLocalDeclsMap; + +public: + using key_type = DeclarationNameKey; + using key_type_ref = key_type; + + explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) + : ASTDeclContextNameLookupTraitBase(Writer) {} + + template <typename Coll> data_type getData(const Coll &Decls) { + unsigned Start = DeclIDs.size(); + for (NamedDecl *D : Decls) { + NamedDecl *DeclForLocalLookup = + getDeclForLocalLookup(Writer.getLangOpts(), D); + + if (Writer.getDoneWritingDeclsAndTypes() && + !Writer.wasDeclEmitted(DeclForLocalLookup)) + continue; + + // Try to avoid writing internal decls to reduced BMI. + // See comments in ASTWriter::WriteDeclContextLexicalBlock for details. + if (Writer.isGeneratingReducedBMI() && + !DeclForLocalLookup->isFromExplicitGlobalModule() && + IsInternalDeclFromFileContext(DeclForLocalLookup)) + continue; + + auto ID = Writer.GetDeclRef(DeclForLocalLookup); + + if (D->getFormalLinkage() == Linkage::Module) { + if (std::optional<unsigned> PrimaryModuleHash = + getPrimaryModuleHash(D->getOwningModule())) { + auto Key = std::make_pair(D->getDeclName(), *PrimaryModuleHash); + auto Iter = ModuleLocalDeclsMap.find(Key); + if (Iter == ModuleLocalDeclsMap.end()) + ModuleLocalDeclsMap.insert({Key, DeclIDsTy{ID}}); + else + Iter->second.push_back(ID); + continue; + } + } + + DeclIDs.push_back(ID); + } + return std::make_pair(Start, DeclIDs.size()); + } + + const ModuleLocalDeclsMapTy &getModuleLocalDecls() { + return ModuleLocalDeclsMap; + } + + static bool EqualKey(key_type_ref a, key_type_ref b) { return a == b; } + + hash_value_type ComputeHash(key_type Name) { return Name.getHash(); } + + std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &Out, + DeclarationNameKey Name, + data_type_ref Lookup) { + auto [KeyLen, DataLen] = EmitKeyDataLengthBase(Out, Name, Lookup); + return emitULEBKeyDataLength(KeyLen, DataLen, Out); + } + + void EmitKey(raw_ostream &Out, DeclarationNameKey Name, unsigned) { + return EmitKeyBase(Out, Name); + } + + void EmitData(raw_ostream &Out, key_type_ref, data_type Lookup, + unsigned DataLen) { + EmitDataBase(Out, Lookup, DataLen); + } +}; + } // namespace namespace { @@ -4371,7 +4464,8 @@ static bool isLookupResultNotInteresting(ASTWriter &Writer, void ASTWriter::GenerateNameLookupTable( ASTContext &Context, const DeclContext *ConstDC, - llvm::SmallVectorImpl<char> &LookupTable) { + llvm::SmallVectorImpl<char> &LookupTable, + llvm::SmallVectorImpl<char> &ModuleLocalLookupTable) { assert(!ConstDC->hasLazyLocalLexicalLookups() && !ConstDC->hasLazyExternalLexicalLookups() && "must call buildLookups first"); @@ -4553,6 +4647,28 @@ void ASTWriter::GenerateNameLookupTable( // merged table if there is one. auto *Lookups = Chain ? Chain->getLoadedLookupTables(DC) : nullptr; Generator.emit(LookupTable, Trait, Lookups ? &Lookups->Table : nullptr); + + const auto &ModuleLocalDecls = Trait.getModuleLocalDecls(); + if (ModuleLocalDecls.empty()) + return; + + MultiOnDiskHashTableGenerator<reader::ModuleLocalNameLookupTrait, + ModuleLocalNameLookupTrait> + ModuleLocalLookupGenerator; + ModuleLocalNameLookupTrait ModuleLocalTrait(*this); + + for (const auto &ModuleLocalIter : ModuleLocalDecls) { + const auto &Key = ModuleLocalIter.first; + const auto &IDs = ModuleLocalIter.second; + ModuleLocalLookupGenerator.insert(Key, ModuleLocalTrait.getData(IDs), + ModuleLocalTrait); + } + + auto *ModuleLocalLookups = + Chain ? Chain->getModuleLocalLookupTables(DC) : nullptr; + ModuleLocalLookupGenerator.emit( + ModuleLocalLookupTable, ModuleLocalTrait, + ModuleLocalLookups ? &ModuleLocalLookups->Table : nullptr); } /// Write the block containing all of the declaration IDs @@ -4560,8 +4676,10 @@ void ASTWriter::GenerateNameLookupTable( /// /// \returns the offset of the DECL_CONTEXT_VISIBLE block within the /// bitstream, or 0 if no block was written. -uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, - DeclContext *DC) { +void ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, + DeclContext *DC, + uint64_t &VisibleBlockOffset, + uint64_t &ModuleLocalBlockOffset) { // If we imported a key declaration of this namespace, write the visible // lookup results as an update record for it rather than including them // on this declaration. We will only look at key declarations on reload. @@ -4571,7 +4689,7 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, for (auto *Prev = cast<NamespaceDecl>(DC)->getPreviousDecl(); Prev; Prev = Prev->getPreviousDecl()) if (!Prev->isFromASTFile()) - return 0; + return; // Note that we need to emit an update record for the primary context. UpdatedDeclContexts.insert(DC->getPrimaryContext()); @@ -4620,41 +4738,53 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, } } - return 0; + return; } if (DC->getPrimaryContext() != DC) - return 0; + return; // Skip contexts which don't support name lookup. if (!DC->isLookupContext()) - return 0; + return; // If not in C++, we perform name lookup for the translation unit via the // IdentifierInfo chains, don't bother to build a visible-declarations table. if (DC->isTranslationUnit() && !Context.getLangOpts().CPlusPlus) - return 0; + return; // Serialize the contents of the mapping used for lookup. Note that, // although we have two very different code paths, the serialized // representation is the same for both cases: a declaration name, // followed by a size, followed by references to the visible // declarations that have that name. - uint64_t Offset = Stream.GetCurrentBitNo(); StoredDeclsMap *Map = DC->buildLookup(); if (!Map || Map->empty()) - return 0; + return; + VisibleBlockOffset = Stream.GetCurrentBitNo(); // Create the on-disk hash table in a buffer. SmallString<4096> LookupTable; - GenerateNameLookupTable(Context, DC, LookupTable); + SmallString<4096> ModuleLocalLookupTable; + GenerateNameLookupTable(Context, DC, LookupTable, ModuleLocalLookupTable); // Write the lookup table RecordData::value_type Record[] = {DECL_CONTEXT_VISIBLE}; Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record, LookupTable); ++NumVisibleDeclContexts; - return Offset; + + if (ModuleLocalLookupTable.empty()) + return; + + ModuleLocalBlockOffset = Stream.GetCurrentBitNo(); + assert(ModuleLocalBlockOffset > VisibleBlockOffset); + // Write the lookup table + RecordData::value_type ModuleLocalRecord[] = { + DECL_CONTEXT_MODULE_LOCAL_VISIBLE}; + Stream.EmitRecordWithBlob(DeclModuleLocalVisibleLookupAbbrev, + ModuleLocalRecord, ModuleLocalLookupTable); + ++NumModuleLocalDeclContexts; } /// Write an UPDATE_VISIBLE block for the given context. @@ -4671,7 +4801,8 @@ void ASTWriter::WriteDeclContextVisibleUpdate(ASTContext &Context, // Create the on-disk hash table in a buffer. SmallString<4096> LookupTable; - GenerateNameLookupTable(Context, DC, LookupTable); + SmallString<4096> ModuleLocalLookupTable; + GenerateNameLookupTable(Context, DC, LookupTable, ModuleLocalLookupTable); // If we're updating a namespace, select a key declaration as the key for the // update record; those are the only ones that will be checked on reload. @@ -4682,6 +4813,15 @@ void ASTWriter::WriteDeclContextVisibleUpdate(ASTContext &Context, RecordData::value_type Record[] = {UPDATE_VISIBLE, getDeclID(cast<Decl>(DC)).getRawValue()}; Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable); + + if (ModuleLocalLookupTable.empty()) + return; + + // Write the module local lookup table + RecordData::value_type ModuleLocalRecord[] = { + UPDATE_MODULE_LOCAL_VISIBLE, getDeclID(cast<Decl>(DC)).getRawValue()}; + Stream.EmitRecordWithBlob(ModuleLocalUpdateVisibleAbbrev, ModuleLocalRecord, + ModuleLocalLookupTable); } /// Write an FP_PRAGMA_OPTIONS block for the given FPOptions. @@ -5865,7 +6005,8 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema *SemaPtr, StringRef isysroot, // Some simple statistics RecordData::value_type Record[] = { - NumStatements, NumMacros, NumLexicalDeclContexts, NumVisibleDeclContexts}; + NumStatements, NumMacros, NumLexicalDeclContexts, NumVisibleDeclContexts, + NumModuleLocalDeclContexts}; Stream.EmitRecord(STATISTICS, Record); Stream.ExitBlock(); Stream.FlushToWord(); @@ -5942,7 +6083,9 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) { RecordData DelayedNamespaceRecord; for (NamespaceDecl *NS : DelayedNamespace) { uint64_t LexicalOffset = WriteDeclContextLexicalBlock(Context, NS); - uint64_t VisibleOffset = WriteDeclContextVisibleBlock(Context, NS); + uint64_t VisibleOffset = 0; + uint64_t ModuleLocalOffset = 0; + WriteDeclContextVisibleBlock(Context, NS, VisibleOffset, ModuleLocalOffset); // Write the offset relative to current block. if (LexicalOffset) @@ -5951,9 +6094,13 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) { if (VisibleOffset) VisibleOffset -= DeclTypesBlockStartOffset; + if (ModuleLocalOffset) + ModuleLocalOffset -= DeclTypesBlockStartOffset; + AddDeclRef(NS, DelayedNamespaceRecord); DelayedNamespaceRecord.push_back(LexicalOffset); DelayedNamespaceRecord.push_back(VisibleOffset); + DelayedNamespaceRecord.push_back(ModuleLocalOffset); } // The process of writing lexical and visible block for delayed namespace @@ -6033,6 +6180,12 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) { Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv)); + Abv = std::make_shared<llvm::BitCodeAbbrev>(); + Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_MODULE_LOCAL_VISIBLE)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); + ModuleLocalUpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv)); + // And a visible updates block for the translation unit. WriteDeclContextVisibleUpdate(Context, TU); |