From: Douglas Gregor Date: Thu, 1 Dec 2011 00:59:36 +0000 (+0000) Subject: Switch the ID numbers used for submodule IDs in the AST reader over to X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=26ced127b7d443fcf3472463c9f39c2376bd9d70;p=clang Switch the ID numbers used for submodule IDs in the AST reader over to a standard global/local scheme, so that submodule definitions will eventually be able to refer to submodules in other top-level modules. We'll need this functionality soonish. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145549 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 22dc0b974c..3cfafd192e 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -127,7 +127,7 @@ namespace clang { /// \brief The number of predefined identifier IDs. const unsigned int NUM_PREDEF_IDENT_IDS = 1; - /// \brief An ID number that refers to an ObjC selctor in an AST file. + /// \brief An ID number that refers to an ObjC selector in an AST file. typedef uint32_t SelectorID; /// \brief The number of predefined selector IDs. @@ -141,6 +141,12 @@ namespace clang { /// preprocessing record. typedef uint32_t PreprocessedEntityID; + /// \brief An ID number that refers to a submodule in a module file. + typedef uint32_t SubmoduleID; + + /// \brief The number of predefined submodule IDs. + const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1; + /// \brief Source range/offset of a preprocessed entity. struct PPEntityOffset { /// \brief Raw source location of beginning of range. @@ -504,7 +510,9 @@ namespace clang { /// if any. SUBMODULE_UMBRELLA = 1, /// \brief Specifies a header that falls into this (sub)module. - SUBMODULE_HEADER = 2 + SUBMODULE_HEADER = 2, + /// \brief Metadata for submodules as a whole. + SUBMODULE_METADATA = 3 }; /// \defgroup ASTAST AST file AST constants diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index c38ceb94c5..0e659acfa0 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -369,6 +369,20 @@ private: /// global identifier ID to produce a local ID. GlobalIdentifierMapType GlobalIdentifierMap; + /// \brief A vector containing submodules that have already been loaded. + /// + /// This vector is indexed by the Submodule ID (-1). NULL submodule entries + /// indicate that the particular submodule ID has not yet been loaded. + SmallVector SubmodulesLoaded; + + typedef ContinuousRangeMap + GlobalSubmoduleMapType; + + /// \brief Mapping from global submodule IDs to the module file in which the + /// submodule resides along with the offset that should be added to the + /// global submodule ID to produce a local ID. + GlobalSubmoduleMapType GlobalSubmoduleMap; + /// \brief A vector containing selectors that have already been loaded. /// /// This vector is indexed by the Selector ID (-1). NULL selector @@ -866,6 +880,11 @@ public: return static_cast(DeclsLoaded.size()); } + /// \brief Returns the number of submodules known. + unsigned getTotalNumSubmodules() const { + return static_cast(SubmodulesLoaded.size()); + } + /// \brief Returns the number of selectors found in the chain. unsigned getTotalNumSelectors() const { return static_cast(SelectorsLoaded.size()); @@ -1146,6 +1165,15 @@ public: /// \brief Read the source location entry with index ID. virtual bool ReadSLocEntry(int ID); + /// \brief Retrieve the global submodule ID given a module and its local ID + /// number. + serialization::SubmoduleID + getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID); + + /// \brief Retrieve the submodule that corresponds to a global submodule ID. + /// + Module *getSubmodule(serialization::SubmoduleID GlobalID); + /// \brief Retrieve a selector from the given module with its local ID /// number. Selector getLocalSelector(ModuleFile &M, unsigned LocalID); diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index b2ea48d5ae..ca29517d81 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -204,10 +204,16 @@ private: /// table. std::vector IdentifierOffsets; + /// \brief The first ID number we can use for our own submodules. + serialization::SubmoduleID FirstSubmoduleID; + + /// \brief The submodule ID that will be assigned to the next new submodule. + serialization::SubmoduleID NextSubmoduleID; + /// \brief The first ID number we can use for our own selectors. serialization::SelectorID FirstSelectorID; - /// \brief The selector ID that will be assigned to the next new identifier. + /// \brief The selector ID that will be assigned to the next new selector. serialization::SelectorID NextSelectorID; /// \brief Map that provides the ID numbers of each Selector. diff --git a/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h index 8874679eea..16d9779e04 100644 --- a/include/clang/Serialization/Module.h +++ b/include/clang/Serialization/Module.h @@ -201,8 +201,15 @@ public: /// search information. const char *HeaderFileFrameworkStrings; - // === Submodule information === - llvm::SmallVector Submodules; + // === Submodule information === + /// \brief The number of submodules in this module. + unsigned LocalNumSubmodules; + + /// \brief Base submodule ID for submodules local to this module. + serialization::SubmoduleID BaseSubmoduleID; + + /// \brief Remapping table for submodule IDs in this module. + ContinuousRangeMap SubmoduleRemap; // === Selectors === diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 48912e362e..d43f8c1f45 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2061,6 +2061,8 @@ ASTReader::ReadASTBlock(ModuleFile &F) { IdentifierRemap(F.IdentifierRemap); ContinuousRangeMap::Builder PreprocessedEntityRemap(F.PreprocessedEntityRemap); + ContinuousRangeMap::Builder + SubmoduleRemap(F.SubmoduleRemap); ContinuousRangeMap::Builder SelectorRemap(F.SelectorRemap); ContinuousRangeMap::Builder DeclRemap(F.DeclRemap); @@ -2079,6 +2081,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) { uint32_t SLocOffset = io::ReadUnalignedLE32(Data); uint32_t IdentifierIDOffset = io::ReadUnalignedLE32(Data); uint32_t PreprocessedEntityIDOffset = io::ReadUnalignedLE32(Data); + uint32_t SubmoduleIDOffset = io::ReadUnalignedLE32(Data); uint32_t SelectorIDOffset = io::ReadUnalignedLE32(Data); uint32_t DeclIDOffset = io::ReadUnalignedLE32(Data); uint32_t TypeIndexOffset = io::ReadUnalignedLE32(Data); @@ -2092,6 +2095,8 @@ ASTReader::ReadASTBlock(ModuleFile &F) { PreprocessedEntityRemap.insert( std::make_pair(PreprocessedEntityIDOffset, OM->BasePreprocessedEntityID - PreprocessedEntityIDOffset)); + SubmoduleRemap.insert(std::make_pair(SubmoduleIDOffset, + OM->BaseSubmoduleID - SubmoduleIDOffset)); SelectorRemap.insert(std::make_pair(SelectorIDOffset, OM->BaseSelectorID - SelectorIDOffset)); DeclRemap.insert(std::make_pair(DeclIDOffset, @@ -2828,8 +2833,10 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) { } ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap(); + bool First = true; Module *CurrentModule = 0; RecordData Record; + SubmoduleID CurrentModuleGlobalIndex = 0; while (true) { unsigned Code = F.Stream.ReadCode(); if (Code == llvm::bitc::END_BLOCK) { @@ -2864,31 +2871,41 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) { break; case SUBMODULE_DEFINITION: { + if (First) { + Error("missing submodule metadata record at beginning of block"); + return Failure; + } + StringRef Name(BlobStart, BlobLen); - unsigned Parent = Record[0]; + unsigned Parent = getGlobalSubmoduleID(F, Record[0]); bool IsFramework = Record[1]; bool IsExplicit = Record[2]; Module *ParentModule = 0; - if (Parent) { - if (Parent > F.Submodules.size()) { - Error("malformed submodule parent entry"); - return Failure; - } - - ParentModule = F.Submodules[Parent - 1]; - } + if (Parent) + ParentModule = getSubmodule(Parent); // Retrieve this (sub)module from the module map, creating it if // necessary. CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, IsFramework, IsExplicit).first; - F.Submodules.push_back(CurrentModule); + + if (CurrentModuleGlobalIndex >= SubmodulesLoaded.size() || + SubmodulesLoaded[CurrentModuleGlobalIndex]) { + Error("too many submodules"); + return Failure; + } + SubmodulesLoaded[CurrentModuleGlobalIndex++] = CurrentModule; break; } case SUBMODULE_UMBRELLA: { + if (First) { + Error("missing submodule metadata record at beginning of block"); + return Failure; + } + if (!CurrentModule) break; @@ -2905,6 +2922,11 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) { } case SUBMODULE_HEADER: { + if (First) { + Error("missing submodule metadata record at beginning of block"); + return Failure; + } + if (!CurrentModule) break; @@ -2918,6 +2940,33 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) { } break; } + + case SUBMODULE_METADATA: { + if (!First) { + Error("submodule metadata record not at beginning of block"); + return Failure; + } + First = false; + + F.BaseSubmoduleID = getTotalNumSubmodules(); + CurrentModuleGlobalIndex = F.BaseSubmoduleID; + F.LocalNumSubmodules = Record[0]; + unsigned LocalBaseSubmoduleID = Record[1]; + if (F.LocalNumSubmodules > 0) { + // Introduce the global -> local mapping for submodules within this + // module. + GlobalSubmoduleMap.insert(std::make_pair(getTotalNumSubmodules()+1,&F)); + + // Introduce the local -> global mapping for submodules within this + // module. + F.SubmoduleRemap.insert( + std::make_pair(LocalBaseSubmoduleID, + F.BaseSubmoduleID - LocalBaseSubmoduleID)); + + SubmodulesLoaded.resize(SubmodulesLoaded.size() + F.LocalNumSubmodules); + } + break; + } } } @@ -4652,6 +4701,7 @@ void ASTReader::dump() { dumpModuleIDMap("Global type map", GlobalTypeMap); dumpModuleIDMap("Global declaration map", GlobalDeclMap); dumpModuleIDMap("Global identifier map", GlobalIdentifierMap); + dumpModuleIDMap("Global submodule map", GlobalSubmoduleMap); dumpModuleIDMap("Global selector map", GlobalSelectorMap); dumpModuleIDMap("Global preprocessed entity map", GlobalPreprocessedEntityMap); @@ -5120,6 +5170,33 @@ bool ASTReader::ReadSLocEntry(int ID) { return ReadSLocEntryRecord(ID) != Success; } +serialization::SubmoduleID +ASTReader::getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID) { + if (LocalID < NUM_PREDEF_SUBMODULE_IDS) + return LocalID; + + ContinuousRangeMap::iterator I + = M.SubmoduleRemap.find(LocalID - NUM_PREDEF_SUBMODULE_IDS); + assert(I != M.SubmoduleRemap.end() + && "Invalid index into identifier index remap"); + + return LocalID + I->second; +} + +Module *ASTReader::getSubmodule(SubmoduleID GlobalID) { + if (GlobalID < NUM_PREDEF_SUBMODULE_IDS) { + assert(GlobalID == 0 && "Unhandled global submodule ID"); + return 0; + } + + if (GlobalID > SubmodulesLoaded.size()) { + Error("submodule ID out of range in AST file"); + return 0; + } + + return SubmodulesLoaded[GlobalID - NUM_PREDEF_SUBMODULE_IDS]; +} + Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) { return DecodeSelector(getGlobalSelectorID(M, LocalID)); } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 0acc760ee2..28668904d5 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1845,6 +1845,18 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { } } +/// \brief Compute the number of modules within the given tree (including the +/// given module). +static unsigned getNumberOfModules(Module *Mod) { + unsigned ChildModules = 0; + for (llvm::StringMap::iterator Sub = Mod->SubModules.begin(), + SubEnd = Mod->SubModules.end(); + Sub != SubEnd; ++Sub) + ChildModules += getNumberOfModules(Sub->getValue()); + + return ChildModules + 1; +} + void ASTWriter::WriteSubmodules(Module *WritingModule) { // Enter the submodule description block. Stream.EnterSubblock(SUBMODULE_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE); @@ -1868,16 +1880,20 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_HEADER)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned HeaderAbbrev = Stream.EmitAbbrev(Abbrev); - + + // Write the submodule metadata block. + RecordData Record; + Record.push_back(getNumberOfModules(WritingModule)); + Record.push_back(FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS); + Stream.EmitRecord(SUBMODULE_METADATA, Record); + // Write all of the submodules. - unsigned SubmoduleID = 1; std::queue Q; Q.push(WritingModule); - RecordData Record; while (!Q.empty()) { Module *Mod = Q.front(); Q.pop(); - SubmoduleIDs[Mod] = SubmoduleID++; + SubmoduleIDs[Mod] = NextSubmoduleID++; // Emit the definition of the block. Record.clear(); @@ -2850,6 +2866,8 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID), FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID), FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID), + FirstSubmoduleID(NUM_PREDEF_SUBMODULE_IDS), + NextSubmoduleID(FirstSubmoduleID), FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID), CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0), @@ -3137,6 +3155,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, // identifier-id:i32 // preprocessed-entity-id:i32 // macro-definition-id:i32 + // submodule-id:i32 // selector-id:i32 // declaration-id:i32 // c++-base-specifiers-id:i32 @@ -3158,6 +3177,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, io::Emit32(Out, (*M)->SLocEntryBaseOffset); io::Emit32(Out, (*M)->BaseIdentifierID); io::Emit32(Out, (*M)->BasePreprocessedEntityID); + io::Emit32(Out, (*M)->BaseSubmoduleID); io::Emit32(Out, (*M)->BaseSelectorID); io::Emit32(Out, (*M)->BaseDeclID); io::Emit32(Out, (*M)->BaseTypeIndex); @@ -4055,6 +4075,7 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { assert(FirstDeclID == NextDeclID && FirstTypeID == NextTypeID && FirstIdentID == NextIdentID && + FirstSubmoduleID == NextSubmoduleID && FirstSelectorID == NextSelectorID && "Setting chain after writing has started."); @@ -4063,11 +4084,13 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { FirstDeclID = NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls(); FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes(); FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers(); + FirstSubmoduleID = NUM_PREDEF_SUBMODULE_IDS + Chain->getTotalNumSubmodules(); FirstSelectorID = NUM_PREDEF_SELECTOR_IDS + Chain->getTotalNumSelectors(); NextDeclID = FirstDeclID; NextTypeID = FirstTypeID; NextIdentID = FirstIdentID; NextSelectorID = FirstSelectorID; + NextSubmoduleID = FirstSubmoduleID; } void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) { diff --git a/lib/Serialization/Module.cpp b/lib/Serialization/Module.cpp index 241b6ba88c..11e7243cd5 100644 --- a/lib/Serialization/Module.cpp +++ b/lib/Serialization/Module.cpp @@ -30,7 +30,7 @@ ModuleFile::ModuleFile(ModuleKind Kind) PreprocessedEntityOffsets(0), NumPreprocessedEntities(0), LocalNumHeaderFileInfos(0), HeaderFileInfoTableData(0), HeaderFileInfoTable(0), - HeaderFileFrameworkStrings(0), + HeaderFileFrameworkStrings(0), LocalNumSubmodules(0), LocalNumSelectors(0), SelectorOffsets(0), BaseSelectorID(0), SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0), DeclOffsets(0), BaseDeclID(0), @@ -88,7 +88,11 @@ void ModuleFile::dump() { llvm::errs() << " Base identifier ID: " << BaseIdentifierID << '\n' << " Number of identifiers: " << LocalNumIdentifiers << '\n'; dumpLocalRemap("Identifier ID local -> global map", IdentifierRemap); - + + llvm::errs() << " Base submodule ID: " << BaseSubmoduleID << '\n' + << " Number of submodules: " << LocalNumSubmodules << '\n'; + dumpLocalRemap("Submodule ID local -> global map", SubmoduleRemap); + llvm::errs() << " Base selector ID: " << BaseSelectorID << '\n' << " Number of selectors: " << LocalNumSelectors << '\n'; dumpLocalRemap("Selector ID local -> global map", SelectorRemap);