diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 5f19af1891b742..600ce73c7f0199 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -708,7 +708,10 @@ class alignas(8) Decl { /// Set the owning module ID. This may only be called for /// deserialized Decls. - void setOwningModuleID(unsigned ID); + void setOwningModuleID(unsigned ID) { + assert(isFromASTFile() && "Only works on a deserialized declaration"); + *((unsigned*)this - 2) = ID; + } public: /// Determine the availability of the given declaration. @@ -781,11 +784,19 @@ class alignas(8) Decl { /// Retrieve the global declaration ID associated with this /// declaration, which specifies where this Decl was loaded from. - GlobalDeclID getGlobalID() const; + GlobalDeclID getGlobalID() const { + if (isFromASTFile()) + return (*((const GlobalDeclID *)this - 1)); + return GlobalDeclID(); + } /// Retrieve the global ID of the module that owns this particular /// declaration. - unsigned getOwningModuleID() const; + unsigned getOwningModuleID() const { + if (isFromASTFile()) + return *((const unsigned*)this - 2); + return 0; + } private: Module *getOwningModuleSlow() const; diff --git a/clang/include/clang/AST/DeclID.h b/clang/include/clang/AST/DeclID.h index 32d2ed41a374a0..614ba06b63860c 100644 --- a/clang/include/clang/AST/DeclID.h +++ b/clang/include/clang/AST/DeclID.h @@ -19,8 +19,6 @@ #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/iterator.h" -#include - namespace clang { /// Predefined declaration IDs. @@ -109,16 +107,12 @@ class DeclIDBase { /// /// DeclID should only be used directly in serialization. All other users /// should use LocalDeclID or GlobalDeclID. - using DeclID = uint64_t; + using DeclID = uint32_t; protected: DeclIDBase() : ID(PREDEF_DECL_NULL_ID) {} explicit DeclIDBase(DeclID ID) : ID(ID) {} - explicit DeclIDBase(unsigned LocalID, unsigned ModuleFileIndex) { - ID = (DeclID)LocalID | ((DeclID)ModuleFileIndex << 32); - } - public: DeclID get() const { return ID; } @@ -130,10 +124,6 @@ class DeclIDBase { bool isInvalid() const { return ID == PREDEF_DECL_NULL_ID; } - unsigned getModuleFileIndex() const { return ID >> 32; } - - unsigned getLocalDeclIndex() const; - friend bool operator==(const DeclIDBase &LHS, const DeclIDBase &RHS) { return LHS.ID == RHS.ID; } @@ -166,9 +156,6 @@ class LocalDeclID : public DeclIDBase { LocalDeclID(PredefinedDeclIDs ID) : Base(ID) {} explicit LocalDeclID(DeclID ID) : Base(ID) {} - explicit LocalDeclID(unsigned LocalID, unsigned ModuleFileIndex) - : Base(LocalID, ModuleFileIndex) {} - LocalDeclID &operator++() { ++ID; return *this; @@ -188,9 +175,6 @@ class GlobalDeclID : public DeclIDBase { GlobalDeclID() : Base() {} explicit GlobalDeclID(DeclID ID) : Base(ID) {} - explicit GlobalDeclID(unsigned LocalID, unsigned ModuleFileIndex) - : Base(LocalID, ModuleFileIndex) {} - // For DeclIDIterator to be able to convert a GlobalDeclID // to a LocalDeclID. explicit operator LocalDeclID() const { return LocalDeclID(this->ID); } diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 3f3fb8869f5f4d..f59ff6af4c764c 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -255,12 +255,6 @@ class DeclOffset { } }; -// The unaligned decl ID used in the Blobs of bistreams. -using unaligned_decl_id_t = - llvm::support::detail::packed_endian_specific_integral< - serialization::DeclID, llvm::endianness::native, - llvm::support::unaligned>; - /// The number of predefined preprocessed entity IDs. const unsigned int NUM_PREDEF_PP_ENTITY_IDS = 1; @@ -1986,46 +1980,33 @@ enum CleanupObjectKind { COK_Block, COK_CompoundLiteral }; /// Describes the categories of an Objective-C class. struct ObjCCategoriesInfo { - // The ID of the definition. Use unaligned_decl_id_t to keep - // ObjCCategoriesInfo 32-bit aligned. - unaligned_decl_id_t DefinitionID; + // The ID of the definition + LocalDeclID DefinitionID; // Offset into the array of category lists. unsigned Offset; - ObjCCategoriesInfo() = default; - ObjCCategoriesInfo(LocalDeclID ID, unsigned Offset) - : DefinitionID(ID.get()), Offset(Offset) {} - - LocalDeclID getDefinitionID() const { - return LocalDeclID(DefinitionID); - } - friend bool operator<(const ObjCCategoriesInfo &X, const ObjCCategoriesInfo &Y) { - return X.getDefinitionID() < Y.getDefinitionID(); + return X.DefinitionID < Y.DefinitionID; } friend bool operator>(const ObjCCategoriesInfo &X, const ObjCCategoriesInfo &Y) { - return X.getDefinitionID() > Y.getDefinitionID(); + return X.DefinitionID > Y.DefinitionID; } friend bool operator<=(const ObjCCategoriesInfo &X, const ObjCCategoriesInfo &Y) { - return X.getDefinitionID() <= Y.getDefinitionID(); + return X.DefinitionID <= Y.DefinitionID; } friend bool operator>=(const ObjCCategoriesInfo &X, const ObjCCategoriesInfo &Y) { - return X.getDefinitionID() >= Y.getDefinitionID(); + return X.DefinitionID >= Y.DefinitionID; } }; -static_assert(alignof(ObjCCategoriesInfo) <= 4); -static_assert(std::is_standard_layout_v && - std::is_trivial_v); - /// A key used when looking up entities by \ref DeclarationName. /// /// Different \ref DeclarationNames are mapped to different keys, but the diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 0a9006223dcbd5..bea58d60d36c41 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -504,6 +504,12 @@ class ASTReader /// = I + 1 has already been loaded. llvm::PagedVector DeclsLoaded; + using GlobalDeclMapType = ContinuousRangeMap; + + /// Mapping from global declaration IDs to the module in which the + /// declaration resides. + GlobalDeclMapType GlobalDeclMap; + using FileOffset = std::pair; using FileOffsetsTy = SmallVector; using DeclUpdateOffsetsMap = llvm::DenseMap; @@ -586,11 +592,10 @@ class ASTReader struct FileDeclsInfo { ModuleFile *Mod = nullptr; - ArrayRef Decls; + ArrayRef Decls; FileDeclsInfo() = default; - FileDeclsInfo(ModuleFile *Mod, - ArrayRef Decls) + FileDeclsInfo(ModuleFile *Mod, ArrayRef Decls) : Mod(Mod), Decls(Decls) {} }; @@ -599,7 +604,11 @@ class ASTReader /// An array of lexical contents of a declaration context, as a sequence of /// Decl::Kind, DeclID pairs. - using LexicalContents = ArrayRef; + using unaligned_decl_id_t = + llvm::support::detail::packed_endian_specific_integral< + serialization::DeclID, llvm::endianness::native, + llvm::support::unaligned>; + using LexicalContents = ArrayRef; /// Map from a DeclContext to its lexical contents. llvm::DenseMap> @@ -1480,11 +1489,10 @@ class ASTReader unsigned ClientLoadCapabilities); public: - class ModuleDeclIterator - : public llvm::iterator_adaptor_base< - ModuleDeclIterator, const serialization::unaligned_decl_id_t *, - std::random_access_iterator_tag, const Decl *, ptrdiff_t, - const Decl *, const Decl *> { + class ModuleDeclIterator : public llvm::iterator_adaptor_base< + ModuleDeclIterator, const LocalDeclID *, + std::random_access_iterator_tag, const Decl *, + ptrdiff_t, const Decl *, const Decl *> { ASTReader *Reader = nullptr; ModuleFile *Mod = nullptr; @@ -1492,11 +1500,11 @@ class ASTReader ModuleDeclIterator() : iterator_adaptor_base(nullptr) {} ModuleDeclIterator(ASTReader *Reader, ModuleFile *Mod, - const serialization::unaligned_decl_id_t *Pos) + const LocalDeclID *Pos) : iterator_adaptor_base(Pos), Reader(Reader), Mod(Mod) {} value_type operator*() const { - return Reader->GetDecl(Reader->getGlobalDeclID(*Mod, (LocalDeclID)*I)); + return Reader->GetDecl(Reader->getGlobalDeclID(*Mod, *I)); } value_type operator->() const { return **this; } @@ -1536,9 +1544,6 @@ class ASTReader StringRef Arg2 = StringRef(), StringRef Arg3 = StringRef()) const; void Error(llvm::Error &&Err) const; - /// Translate a \param GlobalDeclID to the index of DeclsLoaded array. - unsigned translateGlobalDeclIDToIndex(GlobalDeclID ID) const; - public: /// Load the AST file and validate its contents against the given /// Preprocessor. @@ -1910,8 +1915,7 @@ class ASTReader /// Retrieve the module file that owns the given declaration, or NULL /// if the declaration is not from a module file. - ModuleFile *getOwningModuleFile(const Decl *D) const; - ModuleFile *getOwningModuleFile(GlobalDeclID ID) const; + ModuleFile *getOwningModuleFile(const Decl *D); /// Returns the source location for the decl \p ID. SourceLocation getSourceLocationForDeclID(GlobalDeclID ID); diff --git a/clang/include/clang/Serialization/ModuleFile.h b/clang/include/clang/Serialization/ModuleFile.h index 56193d44dd6f33..992d26a8b88c12 100644 --- a/clang/include/clang/Serialization/ModuleFile.h +++ b/clang/include/clang/Serialization/ModuleFile.h @@ -454,11 +454,23 @@ class ModuleFile { /// by the declaration ID (-1). const DeclOffset *DeclOffsets = nullptr; - /// Base declaration index in ASTReader for declarations local to this module. - unsigned BaseDeclIndex = 0; + /// Base declaration ID for declarations local to this module. + serialization::DeclID BaseDeclID = 0; + + /// Remapping table for declaration IDs in this module. + ContinuousRangeMap DeclRemap; + + /// Mapping from the module files that this module file depends on + /// to the base declaration ID for that module as it is understood within this + /// module. + /// + /// This is effectively a reverse global-to-local mapping for declaration + /// IDs, so that we can interpret a true global ID (for this translation unit) + /// as a local ID (for this module file). + llvm::DenseMap GlobalToLocalDeclIDs; /// Array of file-level DeclIDs sorted by file. - const serialization::unaligned_decl_id_t *FileSortedDecls = nullptr; + const LocalDeclID *FileSortedDecls = nullptr; unsigned NumFileSortedDecls = 0; /// Array of category list location information within this diff --git a/clang/include/clang/Serialization/ModuleManager.h b/clang/include/clang/Serialization/ModuleManager.h index f898dab39f06d3..d770bc52eaf4f7 100644 --- a/clang/include/clang/Serialization/ModuleManager.h +++ b/clang/include/clang/Serialization/ModuleManager.h @@ -45,7 +45,7 @@ namespace serialization { /// Manages the set of modules loaded by an AST reader. class ModuleManager { /// The chain of AST files, in the order in which we started to load - /// them. + /// them (this order isn't really useful for anything). SmallVector, 2> Chain; /// The chain of non-module PCH files. The first entry is the one named diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 7f1ed9c691e988..1e9c879e371bc1 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -74,17 +74,18 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Context, GlobalDeclID ID, std::size_t Extra) { // Allocate an extra 8 bytes worth of storage, which ensures that the // resulting pointer will still be 8-byte aligned. - static_assert(sizeof(uint64_t) >= alignof(Decl), "Decl won't be misaligned"); + static_assert(sizeof(unsigned) * 2 >= alignof(Decl), + "Decl won't be misaligned"); void *Start = Context.Allocate(Size + Extra + 8); void *Result = (char*)Start + 8; - uint64_t *PrefixPtr = (uint64_t *)Result - 1; + unsigned *PrefixPtr = (unsigned *)Result - 2; - *PrefixPtr = ID.get(); + // Zero out the first 4 bytes; this is used to store the owning module ID. + PrefixPtr[0] = 0; - // We leave the upper 16 bits to store the module IDs. 48 bits should be - // sufficient to store a declaration ID. - assert(*PrefixPtr < llvm::maskTrailingOnes(48)); + // Store the global declaration ID in the second 4 bytes. + PrefixPtr[1] = ID.get(); return Result; } @@ -110,29 +111,6 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx, return ::operator new(Size + Extra, Ctx); } -GlobalDeclID Decl::getGlobalID() const { - if (!isFromASTFile()) - return GlobalDeclID(); - // See the comments in `Decl::operator new` for details. - uint64_t ID = *((const uint64_t *)this - 1); - return GlobalDeclID(ID & llvm::maskTrailingOnes(48)); -} - -unsigned Decl::getOwningModuleID() const { - if (!isFromASTFile()) - return 0; - - uint64_t ID = *((const uint64_t *)this - 1); - return ID >> 48; -} - -void Decl::setOwningModuleID(unsigned ID) { - assert(isFromASTFile() && "Only works on a deserialized declaration"); - uint64_t *IDAddress = (uint64_t *)this - 1; - *IDAddress &= llvm::maskTrailingOnes(48); - *IDAddress |= (uint64_t)ID << 48; -} - Module *Decl::getOwningModuleSlow() const { assert(isFromASTFile() && "Not from AST file?"); return getASTContext().getExternalSource()->getModule(getOwningModuleID()); @@ -2185,7 +2163,3 @@ DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C, return DD; } - -unsigned DeclIDBase::getLocalDeclIndex() const { - return ID & llvm::maskTrailingOnes(32); -} diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 1ff770b055849a..33cea32c3be612 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -1658,7 +1658,7 @@ bool ASTReader::ReadSLocEntry(int ID) { unsigned NumFileDecls = Record[7]; if (NumFileDecls && ContextObj) { - const unaligned_decl_id_t *FirstDecl = F->FileSortedDecls + Record[6]; + const LocalDeclID *FirstDecl = F->FileSortedDecls + Record[6]; assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?"); FileDeclIDs[FID] = FileDeclsInfo(F, llvm::ArrayRef(FirstDecl, NumFileDecls)); @@ -3377,11 +3377,26 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, "duplicate DECL_OFFSET record in AST file"); F.DeclOffsets = (const DeclOffset *)Blob.data(); F.LocalNumDecls = Record[0]; - F.BaseDeclIndex = getTotalNumDecls(); + unsigned LocalBaseDeclID = Record[1]; + F.BaseDeclID = getTotalNumDecls(); - if (F.LocalNumDecls > 0) - 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( + GlobalDeclID(getTotalNumDecls() + NUM_PREDEF_DECL_IDS), &F)); + + // Introduce the local -> global mapping for declarations within this + // module. + F.DeclRemap.insertOrReplace( + std::make_pair(LocalBaseDeclID, F.BaseDeclID - LocalBaseDeclID)); + + // Introduce the global -> local mapping for declarations within this + // module. + F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID; + DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls); + } break; } @@ -3616,7 +3631,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, break; case FILE_SORTED_DECLS: - F.FileSortedDecls = (const unaligned_decl_id_t *)Blob.data(); + F.FileSortedDecls = (const LocalDeclID *)Blob.data(); F.NumFileSortedDecls = Record[0]; break; @@ -4043,6 +4058,7 @@ void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const { RemapBuilder PreprocessedEntityRemap(F.PreprocessedEntityRemap); RemapBuilder SubmoduleRemap(F.SubmoduleRemap); RemapBuilder SelectorRemap(F.SelectorRemap); + RemapBuilder DeclRemap(F.DeclRemap); RemapBuilder TypeRemap(F.TypeRemap); auto &ImportedModuleVector = F.TransitiveImports; @@ -4081,6 +4097,8 @@ void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const { endian::readNext(Data); uint32_t SelectorIDOffset = endian::readNext(Data); + uint32_t DeclIDOffset = + endian::readNext(Data); uint32_t TypeIndexOffset = endian::readNext(Data); @@ -4098,7 +4116,11 @@ void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const { PreprocessedEntityRemap); mapOffset(SubmoduleIDOffset, OM->BaseSubmoduleID, SubmoduleRemap); mapOffset(SelectorIDOffset, OM->BaseSelectorID, SelectorRemap); + mapOffset(DeclIDOffset, OM->BaseDeclID, DeclRemap); mapOffset(TypeIndexOffset, OM->BaseTypeIndex, TypeRemap); + + // Global -> local mappings. + F.GlobalToLocalDeclIDs[OM] = DeclIDOffset; } } @@ -4623,7 +4645,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, ModuleKind Type, // that we load any additional categories. if (ContextObj) { for (unsigned I = 0, N = ObjCClassesLoaded.size(); I != N; ++I) { - loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(), + loadObjCCategories(GlobalDeclID(ObjCClassesLoaded[I]->getGlobalID()), ObjCClassesLoaded[I], PreviousGeneration); } } @@ -7622,25 +7644,18 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { GlobalDeclID ASTReader::getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const { - if (LocalID.get() < NUM_PREDEF_DECL_IDS) - return GlobalDeclID(LocalID.get()); - - unsigned OwningModuleFileIndex = LocalID.getModuleFileIndex(); - DeclID ID = LocalID.getLocalDeclIndex(); + DeclID ID = LocalID.get(); + if (ID < NUM_PREDEF_DECL_IDS) + return GlobalDeclID(ID); if (!F.ModuleOffsetMap.empty()) ReadModuleOffsetMap(F); - ModuleFile *OwningModuleFile = - OwningModuleFileIndex == 0 - ? &F - : F.TransitiveImports[OwningModuleFileIndex - 1]; - - if (OwningModuleFileIndex == 0) - ID -= NUM_PREDEF_DECL_IDS; + ContinuousRangeMap::iterator I = + F.DeclRemap.find(ID - NUM_PREDEF_DECL_IDS); + assert(I != F.DeclRemap.end() && "Invalid index into decl index remap"); - uint64_t NewModuleFileIndex = OwningModuleFile->Index + 1; - return GlobalDeclID(ID, NewModuleFileIndex); + return GlobalDeclID(ID + I->second); } bool ASTReader::isDeclIDFromModule(GlobalDeclID ID, ModuleFile &M) const { @@ -7648,33 +7663,31 @@ bool ASTReader::isDeclIDFromModule(GlobalDeclID ID, ModuleFile &M) const { if (ID.get() < NUM_PREDEF_DECL_IDS) return false; - unsigned ModuleFileIndex = ID.getModuleFileIndex(); - return M.Index == ModuleFileIndex - 1; -} - -ModuleFile *ASTReader::getOwningModuleFile(GlobalDeclID ID) const { - // Predefined decls aren't from any module. - if (ID.get() < NUM_PREDEF_DECL_IDS) - return nullptr; - - uint64_t ModuleFileIndex = ID.getModuleFileIndex(); - assert(ModuleFileIndex && "Untranslated Local Decl?"); - - return &getModuleManager()[ModuleFileIndex - 1]; + return ID.get() - NUM_PREDEF_DECL_IDS >= M.BaseDeclID && + ID.get() - NUM_PREDEF_DECL_IDS < M.BaseDeclID + M.LocalNumDecls; } -ModuleFile *ASTReader::getOwningModuleFile(const Decl *D) const { +ModuleFile *ASTReader::getOwningModuleFile(const Decl *D) { if (!D->isFromASTFile()) return nullptr; - - return getOwningModuleFile(D->getGlobalID()); + GlobalDeclMapType::const_iterator I = + GlobalDeclMap.find(GlobalDeclID(D->getGlobalID())); + assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); + return I->second; } SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) { if (ID.get() < NUM_PREDEF_DECL_IDS) return SourceLocation(); - if (Decl *D = GetExistingDecl(ID)) + unsigned Index = ID.get() - NUM_PREDEF_DECL_IDS; + + if (Index > DeclsLoaded.size()) { + Error("declaration ID out-of-range for AST file"); + return SourceLocation(); + } + + if (Decl *D = DeclsLoaded[Index]) return D->getLocation(); SourceLocation Loc; @@ -7741,19 +7754,8 @@ static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) { llvm_unreachable("PredefinedDeclIDs unknown enum value"); } -unsigned ASTReader::translateGlobalDeclIDToIndex(GlobalDeclID GlobalID) const { - ModuleFile *OwningModuleFile = getOwningModuleFile(GlobalID); - if (!OwningModuleFile) { - assert(GlobalID.get() < NUM_PREDEF_DECL_IDS && "Untransalted Global ID?"); - return GlobalID.get(); - } - - return OwningModuleFile->BaseDeclIndex + GlobalID.getLocalDeclIndex(); -} - Decl *ASTReader::GetExistingDecl(GlobalDeclID ID) { assert(ContextObj && "reading decl with no AST context"); - if (ID.get() < NUM_PREDEF_DECL_IDS) { Decl *D = getPredefinedDecl(*ContextObj, (PredefinedDeclIDs)ID); if (D) { @@ -7766,7 +7768,7 @@ Decl *ASTReader::GetExistingDecl(GlobalDeclID ID) { return D; } - unsigned Index = translateGlobalDeclIDToIndex(ID); + unsigned Index = ID.get() - NUM_PREDEF_DECL_IDS; if (Index >= DeclsLoaded.size()) { assert(0 && "declaration ID out-of-range for AST file"); @@ -7781,7 +7783,7 @@ Decl *ASTReader::GetDecl(GlobalDeclID ID) { if (ID.get() < NUM_PREDEF_DECL_IDS) return GetExistingDecl(ID); - unsigned Index = translateGlobalDeclIDToIndex(ID); + unsigned Index = ID.get() - NUM_PREDEF_DECL_IDS; if (Index >= DeclsLoaded.size()) { assert(0 && "declaration ID out-of-range for AST file"); @@ -7800,31 +7802,20 @@ Decl *ASTReader::GetDecl(GlobalDeclID ID) { LocalDeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M, GlobalDeclID GlobalID) { - if (GlobalID.get() < NUM_PREDEF_DECL_IDS) - return LocalDeclID(GlobalID.get()); - - if (!M.ModuleOffsetMap.empty()) - ReadModuleOffsetMap(M); - - ModuleFile *Owner = getOwningModuleFile(GlobalID); - DeclID ID = GlobalID.getLocalDeclIndex(); - - if (Owner == &M) { - ID += NUM_PREDEF_DECL_IDS; + DeclID ID = GlobalID.get(); + if (ID < NUM_PREDEF_DECL_IDS) return LocalDeclID(ID); - } - uint64_t OrignalModuleFileIndex = 0; - for (unsigned I = 0; I < M.TransitiveImports.size(); I++) - if (M.TransitiveImports[I] == Owner) { - OrignalModuleFileIndex = I + 1; - break; - } + GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(GlobalID); + assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); + ModuleFile *Owner = I->second; - if (!OrignalModuleFileIndex) + llvm::DenseMap::iterator Pos = + M.GlobalToLocalDeclIDs.find(Owner); + if (Pos == M.GlobalToLocalDeclIDs.end()) return LocalDeclID(); - return LocalDeclID(ID, OrignalModuleFileIndex); + return LocalDeclID(ID - Owner->BaseDeclID + Pos->second); } GlobalDeclID ASTReader::ReadDeclID(ModuleFile &F, const RecordData &Record, @@ -7903,34 +7894,32 @@ void ASTReader::FindExternalLexicalDecls( namespace { -class UnalignedDeclIDComp { +class DeclIDComp { ASTReader &Reader; ModuleFile &Mod; public: - UnalignedDeclIDComp(ASTReader &Reader, ModuleFile &M) - : Reader(Reader), Mod(M) {} + DeclIDComp(ASTReader &Reader, ModuleFile &M) : Reader(Reader), Mod(M) {} - bool operator()(unaligned_decl_id_t L, unaligned_decl_id_t R) const { + bool operator()(LocalDeclID L, LocalDeclID R) const { SourceLocation LHS = getLocation(L); SourceLocation RHS = getLocation(R); return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); } - bool operator()(SourceLocation LHS, unaligned_decl_id_t R) const { + bool operator()(SourceLocation LHS, LocalDeclID R) const { SourceLocation RHS = getLocation(R); return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); } - bool operator()(unaligned_decl_id_t L, SourceLocation RHS) const { + bool operator()(LocalDeclID L, SourceLocation RHS) const { SourceLocation LHS = getLocation(L); return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); } - SourceLocation getLocation(unaligned_decl_id_t ID) const { + SourceLocation getLocation(LocalDeclID ID) const { return Reader.getSourceManager().getFileLoc( - Reader.getSourceLocationForDeclID( - Reader.getGlobalDeclID(Mod, (LocalDeclID)ID))); + Reader.getSourceLocationForDeclID(Reader.getGlobalDeclID(Mod, ID))); } }; @@ -7953,8 +7942,8 @@ void ASTReader::FindFileRegionDecls(FileID File, BeginLoc = SM.getLocForStartOfFile(File).getLocWithOffset(Offset); SourceLocation EndLoc = BeginLoc.getLocWithOffset(Length); - UnalignedDeclIDComp DIDComp(*this, *DInfo.Mod); - ArrayRef::iterator BeginIt = + DeclIDComp DIDComp(*this, *DInfo.Mod); + ArrayRef::iterator BeginIt = llvm::lower_bound(DInfo.Decls, BeginLoc, DIDComp); if (BeginIt != DInfo.Decls.begin()) --BeginIt; @@ -7963,18 +7952,17 @@ void ASTReader::FindFileRegionDecls(FileID File, // to backtrack until we find it otherwise we will fail to report that the // region overlaps with an objc container. while (BeginIt != DInfo.Decls.begin() && - GetDecl(getGlobalDeclID(*DInfo.Mod, (LocalDeclID)(*BeginIt))) + GetDecl(getGlobalDeclID(*DInfo.Mod, *BeginIt)) ->isTopLevelDeclInObjCContainer()) --BeginIt; - ArrayRef::iterator EndIt = + ArrayRef::iterator EndIt = llvm::upper_bound(DInfo.Decls, EndLoc, DIDComp); if (EndIt != DInfo.Decls.end()) ++EndIt; - for (ArrayRef::iterator DIt = BeginIt; DIt != EndIt; - ++DIt) - Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, (LocalDeclID)(*DIt)))); + for (ArrayRef::iterator DIt = BeginIt; DIt != EndIt; ++DIt) + Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt))); } bool @@ -8181,6 +8169,7 @@ LLVM_DUMP_METHOD void ASTReader::dump() { dumpModuleIDMap("Global bit offset map", GlobalBitOffsetsMap); dumpModuleIDMap("Global source location entry map", GlobalSLocEntryMap); dumpModuleIDMap("Global type map", GlobalTypeMap); + dumpModuleIDMap("Global declaration map", GlobalDeclMap); dumpModuleIDMap("Global identifier map", GlobalIdentifierMap); dumpModuleIDMap("Global macro map", GlobalMacroMap); dumpModuleIDMap("Global submodule map", GlobalSubmoduleMap); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index cf2dc32e30b91e..765c083ce8df8c 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2924,7 +2924,7 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, auto *ExistingPattern = Existing->getTemplatedDecl(); RedeclarableResult Result( /*MergeWith*/ ExistingPattern, - DPattern->getCanonicalDecl()->getGlobalID(), IsKeyDecl); + GlobalDeclID(DPattern->getCanonicalDecl()->getGlobalID()), IsKeyDecl); if (auto *DClass = dyn_cast(DPattern)) { // Merge with any existing definition. @@ -3245,10 +3245,11 @@ bool ASTReader::isConsumerInterestedIn(Decl *D) { /// Get the correct cursor and offset for loading a declaration. ASTReader::RecordLocation ASTReader::DeclCursorForID(GlobalDeclID ID, SourceLocation &Loc) { - ModuleFile *M = getOwningModuleFile(ID); - assert(M); - unsigned LocalDeclIndex = ID.getLocalDeclIndex(); - const DeclOffset &DOffs = M->DeclOffsets[LocalDeclIndex]; + GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID); + assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); + ModuleFile *M = I->second; + const DeclOffset &DOffs = + M->DeclOffsets[ID.get() - M->BaseDeclID - NUM_PREDEF_DECL_IDS]; Loc = ReadSourceLocation(*M, DOffs.getRawLoc()); return RecordLocation(M, DOffs.getBitOffset(M->DeclsBlockStartOffset)); } @@ -3791,6 +3792,7 @@ void ASTReader::markIncompleteDeclChain(Decl *D) { /// Read the declaration at the given offset from the AST file. Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) { + unsigned Index = ID.get() - NUM_PREDEF_DECL_IDS; SourceLocation DeclLoc; RecordLocation Loc = DeclCursorForID(ID, DeclLoc); llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; @@ -4121,7 +4123,7 @@ Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) { } assert(D && "Unknown declaration reading AST file"); - LoadedDecl(translateGlobalDeclIDToIndex(ID), D); + LoadedDecl(Index, D); // Set the DeclContext before doing any deserialization, to make sure internal // calls to Decl::getASTContext() by Decl's methods will find the // TranslationUnitDecl without crashing. @@ -4447,7 +4449,7 @@ namespace { M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap, Compare); if (Result == M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap || - Result->getDefinitionID() != LocalID) { + Result->DefinitionID != LocalID) { // We didn't find anything. If the class definition is in this module // file, then the module files it depends on cannot have any categories, // so suppress further lookup. diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index ee3e687636e6a0..953990a4aca6db 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -3357,10 +3357,12 @@ void ASTWriter::WriteTypeDeclOffsets() { Abbrev = std::make_shared(); 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(std::move(Abbrev)); { - RecordData::value_type Record[] = {DECL_OFFSET, DeclOffsets.size()}; + RecordData::value_type Record[] = {DECL_OFFSET, DeclOffsets.size(), + FirstDeclID.get() - NUM_PREDEF_DECL_IDS}; Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, bytes(DeclOffsets)); } } @@ -5421,6 +5423,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, M.NumPreprocessedEntities); writeBaseIDOrNone(M.BaseSubmoduleID, M.LocalNumSubmodules); writeBaseIDOrNone(M.BaseSelectorID, M.LocalNumSelectors); + writeBaseIDOrNone(M.BaseDeclID, M.LocalNumDecls); writeBaseIDOrNone(M.BaseTypeIndex, M.LocalNumTypes); } } @@ -6615,11 +6618,13 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { // Note, this will get called multiple times, once one the reader starts up // and again each time it's done reading a PCH or module. + FirstDeclID = LocalDeclID(NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls()); FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes(); FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers(); FirstMacroID = NUM_PREDEF_MACRO_IDS + Chain->getTotalNumMacros(); FirstSubmoduleID = NUM_PREDEF_SUBMODULE_IDS + Chain->getTotalNumSubmodules(); FirstSelectorID = NUM_PREDEF_SELECTOR_IDS + Chain->getTotalNumSelectors(); + NextDeclID = FirstDeclID; NextTypeID = FirstTypeID; NextIdentID = FirstIdentID; NextMacroID = FirstMacroID; diff --git a/clang/lib/Serialization/ModuleFile.cpp b/clang/lib/Serialization/ModuleFile.cpp index f64a59bd948914..2c42d33a8f5dd3 100644 --- a/clang/lib/Serialization/ModuleFile.cpp +++ b/clang/lib/Serialization/ModuleFile.cpp @@ -87,6 +87,7 @@ LLVM_DUMP_METHOD void ModuleFile::dump() { << " Number of types: " << LocalNumTypes << '\n'; dumpLocalRemap("Type index local -> global map", TypeRemap); - llvm::errs() << " Base decl index: " << BaseDeclIndex << '\n' + llvm::errs() << " Base decl ID: " << BaseDeclID << '\n' << " Number of decls: " << LocalNumDecls << '\n'; + dumpLocalRemap("Decl ID local -> global map", DeclRemap); } diff --git a/clang/test/Modules/no-transitive-decls-change.cppm b/clang/test/Modules/no-transitive-decls-change.cppm deleted file mode 100644 index 42ac061bc90b3f..00000000000000 --- a/clang/test/Modules/no-transitive-decls-change.cppm +++ /dev/null @@ -1,112 +0,0 @@ -// Testing that changing a declaration in an unused module file won't change -// the BMI of the current module file. -// -// RUN: rm -rf %t -// RUN: split-file %s %t -// -// RUN: %clang_cc1 -std=c++20 %t/m-partA.cppm -emit-reduced-module-interface -o %t/m-partA.pcm -// RUN: %clang_cc1 -std=c++20 %t/m-partA.v1.cppm -emit-reduced-module-interface -o \ -// RUN: %t/m-partA.v1.pcm -// RUN: %clang_cc1 -std=c++20 %t/m-partB.cppm -emit-reduced-module-interface -o %t/m-partB.pcm -// RUN: %clang_cc1 -std=c++20 %t/m.cppm -emit-reduced-module-interface -o %t/m.pcm \ -// RUN: -fmodule-file=m:partA=%t/m-partA.pcm -fmodule-file=m:partB=%t/m-partB.pcm -// RUN: %clang_cc1 -std=c++20 %t/m.cppm -emit-reduced-module-interface -o %t/m.v1.pcm \ -// RUN: -fmodule-file=m:partA=%t/m-partA.v1.pcm -fmodule-file=m:partB=%t/m-partB.pcm -// -// RUN: %clang_cc1 -std=c++20 %t/useBOnly.cppm -emit-reduced-module-interface -o %t/useBOnly.pcm \ -// RUN: -fmodule-file=m=%t/m.pcm -fmodule-file=m:partA=%t/m-partA.pcm \ -// RUN: -fmodule-file=m:partB=%t/m-partB.pcm -// RUN: %clang_cc1 -std=c++20 %t/useBOnly.cppm -emit-reduced-module-interface -o %t/useBOnly.v1.pcm \ -// RUN: -fmodule-file=m=%t/m.v1.pcm -fmodule-file=m:partA=%t/m-partA.v1.pcm \ -// RUN: -fmodule-file=m:partB=%t/m-partB.pcm -// Since useBOnly only uses partB from module M, the change in partA shouldn't affect -// useBOnly. -// RUN: diff %t/useBOnly.pcm %t/useBOnly.v1.pcm &> /dev/null - -//--- m-partA.cppm -export module m:partA; - -namespace A_Impl { - inline int getAImpl() { - return 43; - } - - inline int getA2Impl() { - return 43; - } -} - -namespace A { - using A_Impl::getAImpl; -} - -export inline int getA() { - return 43; -} - -export inline int getA2(int) { - return 88; -} - -//--- m-partA.v1.cppm -export module m:partA; - -namespace A_Impl { - inline int getAImpl() { - return 43; - } - - inline int getA2Impl() { - return 43; - } -} - -namespace A { - using A_Impl::getAImpl; - // Adding a new declaration without introducing a new declaration name. - using A_Impl::getA2Impl; -} - -inline int getA() { - return 43; -} - -inline int getA2(int) { - return 88; -} - -// Now we add a new declaration without introducing new identifier and new types. -// The consuming module which didn't use m:partA completely is expected to be -// not changed. -inline int getA(int) { - return 88; -} - -//--- m-partB.cppm -export module m:partB; - -export inline int getB() { - return 430; -} - -//--- m.cppm -export module m; -export import :partA; -export import :partB; - -//--- useBOnly.cppm -export module useBOnly; -import m; - -export inline int get() { - return getB(); -} - -//--- useAOnly.cppm -export module useAOnly; -import m; - -export inline int get() { - A a; - return a.getValue(); -}