Skip to content

Commit abcf7ce

Browse files
committed
[clang][modules] Serialize Module::DefinitionLoc
This is a prep patch for avoiding the quadratic number of calls to `HeaderSearch::lookupModule()` in `ASTReader` for each (transitively) loaded PCM file. (Specifically in the context of `clang-scan-deps`). This patch explicitly serializes `Module::DefinitionLoc` so that we can stop relying on it being filled by the module map parser. This change also required change to the module map parser, where we used the absence of `DefinitionLoc` to determine whether a file came from a PCM file. We also need to make sure we consider the "containing" module map affecting when writing a PCM, so that it's not stripped during serialization, which ensures `DefinitionLoc` still ends up pointing to the correct offset. This is intended to be a NFC change. Reviewed By: benlangmuir Differential Revision: https://reviews.llvm.org/D150292
1 parent cbc4bbb commit abcf7ce

File tree

4 files changed

+29
-12
lines changed

4 files changed

+29
-12
lines changed

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ namespace serialization {
4141
/// Version 4 of AST files also requires that the version control branch and
4242
/// revision match exactly, since there is no backward compatibility of
4343
/// AST files at this time.
44-
const unsigned VERSION_MAJOR = 26;
44+
const unsigned VERSION_MAJOR = 27;
4545

4646
/// AST file minor version number supported by this version of
4747
/// Clang.

clang/lib/Lex/ModuleMap.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,18 +2016,20 @@ void ModuleMapParser::parseModuleDecl() {
20162016
Module *ShadowingModule = nullptr;
20172017
if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
20182018
// We might see a (re)definition of a module that we already have a
2019-
// definition for in two cases:
2019+
// definition for in three cases:
20202020
// - If we loaded one definition from an AST file and we've just found a
20212021
// corresponding definition in a module map file, or
2022-
bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
2022+
bool LoadedFromASTFile = Existing->IsFromModuleFile;
2023+
// - If we previously inferred this module from different module map file.
2024+
bool Inferred = Existing->IsInferred;
20232025
// - If we're building a (preprocessed) module and we've just loaded the
20242026
// module map file from which it was created.
20252027
bool ParsedAsMainInput =
20262028
Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
20272029
Map.LangOpts.CurrentModule == ModuleName &&
20282030
SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
20292031
SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
2030-
if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
2032+
if (!ActiveModule && (LoadedFromASTFile || Inferred || ParsedAsMainInput)) {
20312033
// Skip the module definition.
20322034
skipUntil(MMToken::RBrace);
20332035
if (Tok.is(MMToken::RBrace))

clang/lib/Serialization/ASTReader.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5607,7 +5607,7 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F,
56075607
break;
56085608

56095609
case SUBMODULE_DEFINITION: {
5610-
if (Record.size() < 12)
5610+
if (Record.size() < 13)
56115611
return llvm::createStringError(std::errc::illegal_byte_sequence,
56125612
"malformed module definition");
56135613

@@ -5616,6 +5616,7 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F,
56165616
SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[Idx++]);
56175617
SubmoduleID Parent = getGlobalSubmoduleID(F, Record[Idx++]);
56185618
Module::ModuleKind Kind = (Module::ModuleKind)Record[Idx++];
5619+
SourceLocation DefinitionLoc = ReadSourceLocation(F, Record[Idx++]);
56195620
bool IsFramework = Record[Idx++];
56205621
bool IsExplicit = Record[Idx++];
56215622
bool IsSystem = Record[Idx++];
@@ -5636,8 +5637,7 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F,
56365637
ModMap.findOrCreateModule(Name, ParentModule, IsFramework, IsExplicit)
56375638
.first;
56385639

5639-
// FIXME: set the definition loc for CurrentModule, or call
5640-
// ModMap.setInferredModuleAllowedBy()
5640+
// FIXME: Call ModMap.setInferredModuleAllowedBy()
56415641

56425642
SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS;
56435643
if (GlobalIndex >= SubmodulesLoaded.size() ||
@@ -5666,6 +5666,7 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F,
56665666
}
56675667

56685668
CurrentModule->Kind = Kind;
5669+
CurrentModule->DefinitionLoc = DefinitionLoc;
56695670
CurrentModule->Signature = F.Signature;
56705671
CurrentModule->IsFromModuleFile = true;
56715672
CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,9 @@ std::set<const FileEntry *> GetAffectingModuleMaps(const Preprocessor &PP,
200200
CB(F);
201201
FileID FID = SourceMgr.translateFile(F);
202202
SourceLocation Loc = SourceMgr.getIncludeLoc(FID);
203-
while (Loc.isValid()) {
203+
// The include location of inferred module maps can point into the header
204+
// file that triggered the inferring. Cut off the walk if that's the case.
205+
while (Loc.isValid() && isModuleMap(SourceMgr.getFileCharacteristic(Loc))) {
204206
FID = SourceMgr.getFileID(Loc);
205207
CB(*SourceMgr.getFileEntryRefForID(FID));
206208
Loc = SourceMgr.getIncludeLoc(FID);
@@ -209,11 +211,18 @@ std::set<const FileEntry *> GetAffectingModuleMaps(const Preprocessor &PP,
209211

210212
auto ProcessModuleOnce = [&](const Module *M) {
211213
for (const Module *Mod = M; Mod; Mod = Mod->Parent)
212-
if (ProcessedModules.insert(Mod).second)
214+
if (ProcessedModules.insert(Mod).second) {
215+
auto Insert = [&](FileEntryRef F) { ModuleMaps.insert(F); };
216+
// The containing module map is affecting, because it's being pointed
217+
// into by Module::DefinitionLoc.
218+
if (auto ModuleMapFile = MM.getContainingModuleMapFile(Mod))
219+
ForIncludeChain(*ModuleMapFile, Insert);
220+
// For inferred modules, the module map that allowed inferring is not in
221+
// the include chain of the virtual containing module map file. It did
222+
// affect the compilation, though.
213223
if (auto ModuleMapFile = MM.getModuleMapFileForUniquing(Mod))
214-
ForIncludeChain(*ModuleMapFile, [&](FileEntryRef F) {
215-
ModuleMaps.insert(F);
216-
});
224+
ForIncludeChain(*ModuleMapFile, Insert);
225+
}
217226
};
218227

219228
for (const Module *CurrentModule : ModulesToProcess) {
@@ -2687,6 +2696,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
26872696
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID
26882697
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent
26892698
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // Kind
2699+
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Definition location
26902700
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
26912701
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit
26922702
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem
@@ -2787,12 +2797,16 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
27872797
ParentID = SubmoduleIDs[Mod->Parent];
27882798
}
27892799

2800+
uint64_t DefinitionLoc =
2801+
SourceLocationEncoding::encode(getAdjustedLocation(Mod->DefinitionLoc));
2802+
27902803
// Emit the definition of the block.
27912804
{
27922805
RecordData::value_type Record[] = {SUBMODULE_DEFINITION,
27932806
ID,
27942807
ParentID,
27952808
(RecordData::value_type)Mod->Kind,
2809+
DefinitionLoc,
27962810
Mod->IsFramework,
27972811
Mod->IsExplicit,
27982812
Mod->IsSystem,

0 commit comments

Comments
 (0)