[Dependency Scanning] Fix optional import statement serialization logic

Previously, serialization of optional import statement node arrays erroneously used the node layout of a non-optional import node array while maintaining a separate index for these arrays which got serialized into each module's info node. This meant it got serialized out in a sequence of non-optional import arrays, and as a result, the consumer deserialized them as such, which broke ordering of which arrays of import nodes belong which module, causing mismatches between a module's actual import set and the import which got deserialized for it.

This change fixes the optional import serialization routine to use the purpose-made separate layout which gets read out according to the separate optional import array index.
This commit is contained in:
Artem Chikin
2025-08-14 14:01:11 -07:00
parent 030564b9db
commit bc30953c15
2 changed files with 39 additions and 8 deletions

View File

@@ -49,8 +49,8 @@ class ModuleDependenciesCacheDeserializer {
std::vector<std::vector<uint64_t>> ArraysOfMacroDependenciesIDs;
std::vector<ScannerImportStatementInfo> ImportStatements;
std::vector<std::vector<uint64_t>> ArraysOfImportStatementIDs;
std::vector<std::vector<uint64_t>> ArraysOfSearchPathIDs;
std::vector<std::vector<uint64_t>> ArraysOfOptionalImportStatementIDs;
std::vector<std::vector<uint64_t>> ArraysOfSearchPathIDs;
llvm::BitstreamCursor Cursor;
SmallVector<uint64_t, 64> Scratch;
@@ -1170,6 +1170,7 @@ class ModuleDependenciesCacheSerializer {
unsigned writeImportStatementInfos(const ModuleDependencyInfo &dependencyInfo,
bool optional);
void writeImportStatementInfosArray(unsigned startIndex, unsigned count);
void writeOptionalImportStatementInfosArray(unsigned startIndex, unsigned count);
void writeModuleInfo(ModuleDependencyID moduleID,
const ModuleDependencyInfo &dependencyInfo);
@@ -1478,7 +1479,7 @@ void ModuleDependenciesCacheSerializer::writeImportStatementInfos(
}
auto optionalEntries = optionalImportInfoArrayMap.at(moduleID);
if (optionalEntries.second != 0) {
writeImportStatementInfosArray(optionalEntries.first, optionalEntries.second);
writeOptionalImportStatementInfosArray(optionalEntries.first, optionalEntries.second);
OptionalImportInfosArrayIDsMap.insert({moduleID, lastOptionalImportInfoArrayIndex++});
}
}
@@ -1530,6 +1531,15 @@ void ModuleDependenciesCacheSerializer::writeImportStatementInfosArray(
Out, ScratchRecord, AbbrCodes[ImportStatementArrayLayout::Code], vec);
}
void ModuleDependenciesCacheSerializer::writeOptionalImportStatementInfosArray(
unsigned startIndex, unsigned count) {
using namespace graph_block;
std::vector<unsigned> vec(count);
std::iota(vec.begin(), vec.end(), startIndex);
OptionalImportStatementArrayLayout::emitRecord(
Out, ScratchRecord, AbbrCodes[OptionalImportStatementArrayLayout::Code], vec);
}
void ModuleDependenciesCacheSerializer::writeModuleInfo(
ModuleDependencyID moduleID, const ModuleDependencyInfo &dependencyInfo) {
using namespace graph_block;
@@ -1965,6 +1975,7 @@ void ModuleDependenciesCacheSerializer::writeInterModuleDependenciesCache(
registerRecordAbbr<SearchPathArrayLayout>();
registerRecordAbbr<ImportStatementLayout>();
registerRecordAbbr<ImportStatementArrayLayout>();
registerRecordAbbr<OptionalImportStatementArrayLayout>();
registerRecordAbbr<ModuleInfoLayout>();
registerRecordAbbr<SwiftSourceModuleDetailsLayout>();
registerRecordAbbr<SwiftInterfaceModuleDetailsLayout>();