Skip to content

Commit fdba5be

Browse files
authored
Merge pull request #9634 from swiftlang/jan_svoboda/stable-blobify-imports
🍒 [clang][serialization] Blobify IMPORTS strings and signatures
2 parents 87ce170 + 9a0958e commit fdba5be

File tree

6 files changed

+239
-200
lines changed

6 files changed

+239
-200
lines changed

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ namespace serialization {
4444
/// Version 4 of AST files also requires that the version control branch and
4545
/// revision match exactly, since there is no backward compatibility of
4646
/// AST files at this time.
47-
const unsigned VERSION_MAJOR = 33;
47+
const unsigned VERSION_MAJOR = 34;
4848

4949
/// AST file minor version number supported by this version of
5050
/// Clang.
@@ -350,9 +350,8 @@ enum ControlRecordTypes {
350350
/// and information about the compiler used to build this AST file.
351351
METADATA = 1,
352352

353-
/// Record code for the list of other AST files imported by
354-
/// this AST file.
355-
IMPORTS,
353+
/// Record code for another AST file imported by this AST file.
354+
IMPORT,
356355

357356
/// Record code for the original file that was used to
358357
/// generate the AST file, including both its file ID and its

clang/include/clang/Serialization/ASTReader.h

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2361,23 +2361,17 @@ class ASTReader
23612361

23622362
// Read a string
23632363
static std::string ReadString(const RecordDataImpl &Record, unsigned &Idx);
2364-
2365-
// Skip a string
2366-
static void SkipString(const RecordData &Record, unsigned &Idx) {
2367-
Idx += Record[Idx] + 1;
2368-
}
2364+
static StringRef ReadStringBlob(const RecordDataImpl &Record, unsigned &Idx,
2365+
StringRef &Blob);
23692366

23702367
// Read a path
23712368
std::string ReadPath(ModuleFile &F, const RecordData &Record, unsigned &Idx);
23722369

23732370
// Read a path
23742371
std::string ReadPath(StringRef BaseDirectory, const RecordData &Record,
23752372
unsigned &Idx);
2376-
2377-
// Skip a path
2378-
static void SkipPath(const RecordData &Record, unsigned &Idx) {
2379-
SkipString(Record, Idx);
2380-
}
2373+
std::string ReadPathBlob(StringRef BaseDirectory, const RecordData &Record,
2374+
unsigned &Idx, StringRef &Blob);
23812375

23822376
/// Read a version tuple.
23832377
static VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx);

clang/include/clang/Serialization/ASTWriter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,13 +758,17 @@ class ASTWriter : public ASTDeserializationListener,
758758

759759
/// Add a string to the given record.
760760
void AddString(StringRef Str, RecordDataImpl &Record);
761+
void AddStringBlob(StringRef Str, RecordDataImpl &Record,
762+
SmallVectorImpl<char> &Blob);
761763

762764
/// Convert a path from this build process into one that is appropriate
763765
/// for emission in the module file.
764766
bool PreparePathForOutput(SmallVectorImpl<char> &Path);
765767

766768
/// Add a path to the given record.
767769
void AddPath(StringRef Path, RecordDataImpl &Record);
770+
void AddPathBlob(StringRef Str, RecordDataImpl &Record,
771+
SmallVectorImpl<char> &Blob);
768772

769773
/// Emit the current record with the given path as a blob.
770774
void EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record,

clang/lib/Serialization/ASTReader.cpp

Lines changed: 130 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -3071,112 +3071,112 @@ ASTReader::ReadControlBlock(ModuleFile &F,
30713071
break;
30723072
}
30733073

3074-
case IMPORTS: {
3074+
case IMPORT: {
30753075
// Validate the AST before processing any imports (otherwise, untangling
30763076
// them can be error-prone and expensive). A module will have a name and
30773077
// will already have been validated, but this catches the PCH case.
30783078
if (ASTReadResult Result = readUnhashedControlBlockOnce())
30793079
return Result;
30803080

3081-
// Load each of the imported PCH files.
3082-
unsigned Idx = 0, N = Record.size();
3083-
while (Idx < N) {
3084-
// Read information about the AST file.
3085-
ModuleKind ImportedKind = (ModuleKind)Record[Idx++];
3086-
// Whether we're importing a standard c++ module.
3087-
bool IsImportingStdCXXModule = Record[Idx++];
3088-
// The import location will be the local one for now; we will adjust
3089-
// all import locations of module imports after the global source
3090-
// location info are setup, in ReadAST.
3091-
auto [ImportLoc, ImportModuleFileIndex] =
3092-
ReadUntranslatedSourceLocation(Record[Idx++]);
3093-
// The import location must belong to the current module file itself.
3094-
assert(ImportModuleFileIndex == 0);
3095-
off_t StoredSize = !IsImportingStdCXXModule ? (off_t)Record[Idx++] : 0;
3096-
time_t StoredModTime =
3097-
!IsImportingStdCXXModule ? (time_t)Record[Idx++] : 0;
3098-
3099-
ASTFileSignature StoredSignature;
3100-
if (!IsImportingStdCXXModule) {
3101-
auto FirstSignatureByte = Record.begin() + Idx;
3102-
StoredSignature = ASTFileSignature::create(
3103-
FirstSignatureByte, FirstSignatureByte + ASTFileSignature::size);
3104-
Idx += ASTFileSignature::size;
3105-
}
3081+
unsigned Idx = 0;
3082+
// Read information about the AST file.
3083+
ModuleKind ImportedKind = (ModuleKind)Record[Idx++];
3084+
3085+
// The import location will be the local one for now; we will adjust
3086+
// all import locations of module imports after the global source
3087+
// location info are setup, in ReadAST.
3088+
auto [ImportLoc, ImportModuleFileIndex] =
3089+
ReadUntranslatedSourceLocation(Record[Idx++]);
3090+
// The import location must belong to the current module file itself.
3091+
assert(ImportModuleFileIndex == 0);
3092+
3093+
StringRef ImportedName = ReadStringBlob(Record, Idx, Blob);
3094+
3095+
bool IsImportingStdCXXModule = Record[Idx++];
3096+
3097+
off_t StoredSize = 0;
3098+
time_t StoredModTime = 0;
3099+
ASTFileSignature StoredSignature;
3100+
std::string ImportedFile;
3101+
StringRef ImportedCacheKey;
3102+
3103+
// For prebuilt and explicit modules first consult the file map for
3104+
// an override. Note that here we don't search prebuilt module
3105+
// directories if we're not importing standard c++ module, only the
3106+
// explicit name to file mappings. Also, we will still verify the
3107+
// size/signature making sure it is essentially the same file but
3108+
// perhaps in a different location.
3109+
if (ImportedKind == MK_PrebuiltModule || ImportedKind == MK_ExplicitModule)
3110+
ImportedFile = PP.getHeaderSearchInfo().getPrebuiltModuleFileName(
3111+
ImportedName, /*FileMapOnly*/ !IsImportingStdCXXModule);
3112+
3113+
if (IsImportingStdCXXModule && ImportedFile.empty()) {
3114+
Diag(diag::err_failed_to_find_module_file) << ImportedName;
3115+
return Missing;
3116+
}
31063117

3107-
std::string ImportedName = ReadString(Record, Idx);
3108-
std::string ImportedFile;
3109-
std::string ImportedCacheKey;
3110-
3111-
// For prebuilt and explicit modules first consult the file map for
3112-
// an override. Note that here we don't search prebuilt module
3113-
// directories if we're not importing standard c++ module, only the
3114-
// explicit name to file mappings. Also, we will still verify the
3115-
// size/signature making sure it is essentially the same file but
3116-
// perhaps in a different location.
3117-
if (ImportedKind == MK_PrebuiltModule || ImportedKind == MK_ExplicitModule)
3118-
ImportedFile = PP.getHeaderSearchInfo().getPrebuiltModuleFileName(
3119-
ImportedName, /*FileMapOnly*/ !IsImportingStdCXXModule);
3120-
3121-
// For C++20 Modules, we won't record the path to the imported modules
3122-
// in the BMI
3123-
if (!IsImportingStdCXXModule) {
3124-
if (ImportedFile.empty()) {
3125-
// Use BaseDirectoryAsWritten to ensure we use the same path in the
3126-
// ModuleCache as when writing.
3127-
ImportedFile = ReadPath(BaseDirectoryAsWritten, Record, Idx);
3128-
ImportedCacheKey = ReadString(Record, Idx);
3129-
} else {
3130-
SkipPath(Record, Idx);
3131-
SkipString(Record, Idx);
3132-
}
3133-
} else if (ImportedFile.empty()) {
3134-
Diag(clang::diag::err_failed_to_find_module_file) << ImportedName;
3135-
return Missing;
3118+
if (!IsImportingStdCXXModule) {
3119+
StoredSize = (off_t)Record[Idx++];
3120+
StoredModTime = (time_t)Record[Idx++];
3121+
3122+
StringRef SignatureBytes = Blob.substr(0, ASTFileSignature::size);
3123+
StoredSignature = ASTFileSignature::create(SignatureBytes.begin(),
3124+
SignatureBytes.end());
3125+
Blob = Blob.substr(ASTFileSignature::size);
3126+
3127+
if (ImportedFile.empty()) {
3128+
// Use BaseDirectoryAsWritten to ensure we use the same path in the
3129+
// ModuleCache as when writing.
3130+
ImportedFile =
3131+
ReadPathBlob(BaseDirectoryAsWritten, Record, Idx, Blob);
3132+
} else {
3133+
(void)ReadPathBlob(BaseDirectoryAsWritten, Record, Idx, Blob);
31363134
}
31373135

3136+
ImportedCacheKey = ReadStringBlob(Record, Idx, Blob);
3137+
31383138
if (!ImportedCacheKey.empty()) {
31393139
if (!Listener || Listener->readModuleCacheKey(
31403140
ImportedName, ImportedFile, ImportedCacheKey)) {
31413141
Diag(diag::err_ast_file_not_found)
31423142
<< moduleKindForDiagnostic(ImportedKind) << ImportedFile << true
3143-
<< std::string("missing or unloadable module cache key") +
3144-
ImportedCacheKey;
3143+
<< ("missing or unloadable module cache key" +
3144+
ImportedCacheKey).str();
31453145
return Failure;
31463146
}
31473147
}
3148+
}
31483149

3149-
// If our client can't cope with us being out of date, we can't cope with
3150-
// our dependency being missing.
3151-
unsigned Capabilities = ClientLoadCapabilities;
3152-
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
3153-
Capabilities &= ~ARR_Missing;
3154-
3155-
// Load the AST file.
3156-
auto Result = ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F,
3157-
Loaded, StoredSize, StoredModTime,
3158-
StoredSignature, Capabilities);
3159-
3160-
// If we diagnosed a problem, produce a backtrace.
3161-
bool recompilingFinalized =
3162-
Result == OutOfDate && (Capabilities & ARR_OutOfDate) &&
3163-
getModuleManager().getModuleCache().isPCMFinal(F.FileName);
3164-
if (isDiagnosedResult(Result, Capabilities) || recompilingFinalized)
3165-
Diag(diag::note_module_file_imported_by)
3166-
<< F.FileName << !F.ModuleName.empty() << F.ModuleName;
3167-
if (recompilingFinalized)
3168-
Diag(diag::note_module_file_conflict);
3169-
3170-
switch (Result) {
3171-
case Failure: return Failure;
3172-
// If we have to ignore the dependency, we'll have to ignore this too.
3173-
case Missing:
3174-
case OutOfDate: return OutOfDate;
3175-
case VersionMismatch: return VersionMismatch;
3176-
case ConfigurationMismatch: return ConfigurationMismatch;
3177-
case HadErrors: return HadErrors;
3178-
case Success: break;
3179-
}
3150+
// If our client can't cope with us being out of date, we can't cope with
3151+
// our dependency being missing.
3152+
unsigned Capabilities = ClientLoadCapabilities;
3153+
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
3154+
Capabilities &= ~ARR_Missing;
3155+
3156+
// Load the AST file.
3157+
auto Result = ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F,
3158+
Loaded, StoredSize, StoredModTime,
3159+
StoredSignature, Capabilities);
3160+
3161+
// If we diagnosed a problem, produce a backtrace.
3162+
bool recompilingFinalized =
3163+
Result == OutOfDate && (Capabilities & ARR_OutOfDate) &&
3164+
getModuleManager().getModuleCache().isPCMFinal(F.FileName);
3165+
if (isDiagnosedResult(Result, Capabilities) || recompilingFinalized)
3166+
Diag(diag::note_module_file_imported_by)
3167+
<< F.FileName << !F.ModuleName.empty() << F.ModuleName;
3168+
if (recompilingFinalized)
3169+
Diag(diag::note_module_file_conflict);
3170+
3171+
switch (Result) {
3172+
case Failure: return Failure;
3173+
// If we have to ignore the dependency, we'll have to ignore this too.
3174+
case Missing:
3175+
case OutOfDate: return OutOfDate;
3176+
case VersionMismatch: return VersionMismatch;
3177+
case ConfigurationMismatch: return ConfigurationMismatch;
3178+
case HadErrors: return HadErrors;
3179+
case Success: break;
31803180
}
31813181
break;
31823182
}
@@ -5619,39 +5619,41 @@ bool ASTReader::readASTFileControlBlock(
56195619
break;
56205620
}
56215621

5622-
case IMPORTS: {
5622+
case IMPORT: {
56235623
if (!NeedsImports)
56245624
break;
56255625

5626-
unsigned Idx = 0, N = Record.size();
5627-
while (Idx < N) {
5628-
// Read information about the AST file.
5626+
unsigned Idx = 0;
5627+
// Read information about the AST file.
56295628

5630-
// Skip Kind
5631-
Idx++;
5632-
bool IsStandardCXXModule = Record[Idx++];
5629+
// Skip Kind
5630+
Idx++;
56335631

5634-
// Skip ImportLoc
5635-
Idx++;
5632+
// Skip ImportLoc
5633+
Idx++;
56365634

5637-
// In C++20 Modules, we don't record the path to imported
5638-
// modules in the BMI files.
5639-
if (IsStandardCXXModule) {
5640-
std::string ModuleName = ReadString(Record, Idx);
5641-
Listener.visitImport(ModuleName, /*Filename=*/"");
5642-
continue;
5643-
}
5635+
StringRef ModuleName = ReadStringBlob(Record, Idx, Blob);
5636+
5637+
bool IsStandardCXXModule = Record[Idx++];
56445638

5645-
// Skip Size, ModTime and Signature
5646-
Idx += 1 + 1 + ASTFileSignature::size;
5647-
std::string ModuleName = ReadString(Record, Idx);
5648-
std::string FilenameStr = ReadString(Record, Idx);
5649-
auto Filename = ResolveImportedPath(PathBuf, FilenameStr, ModuleDir);
5650-
std::string CacheKey = ReadString(Record, Idx);
5651-
if (!CacheKey.empty())
5652-
Listener.readModuleCacheKey(ModuleName, *Filename, CacheKey);
5653-
Listener.visitImport(ModuleName, *Filename);
5639+
// In C++20 Modules, we don't record the path to imported
5640+
// modules in the BMI files.
5641+
if (IsStandardCXXModule) {
5642+
Listener.visitImport(ModuleName, /*Filename=*/"");
5643+
continue;
56545644
}
5645+
5646+
// Skip Size and ModTime.
5647+
Idx += 1 + 1;
5648+
// Skip signature.
5649+
Blob = Blob.substr(ASTFileSignature::size);
5650+
5651+
StringRef FilenameStr = ReadStringBlob(Record, Idx, Blob);
5652+
auto Filename = ResolveImportedPath(PathBuf, FilenameStr, ModuleDir);
5653+
StringRef CacheKey = ReadStringBlob(Record, Idx, Blob);
5654+
if (!CacheKey.empty())
5655+
Listener.readModuleCacheKey(ModuleName, *Filename, CacheKey);
5656+
Listener.visitImport(ModuleName, *Filename);
56555657
break;
56565658
}
56575659

@@ -9500,6 +9502,14 @@ std::string ASTReader::ReadString(const RecordDataImpl &Record, unsigned &Idx) {
95009502
return Result;
95019503
}
95029504

9505+
StringRef ASTReader::ReadStringBlob(const RecordDataImpl &Record, unsigned &Idx,
9506+
StringRef &Blob) {
9507+
unsigned Len = Record[Idx++];
9508+
StringRef Result = Blob.substr(0, Len);
9509+
Blob = Blob.substr(Len);
9510+
return Result;
9511+
}
9512+
95039513
std::string ASTReader::ReadPath(ModuleFile &F, const RecordData &Record,
95049514
unsigned &Idx) {
95059515
return ReadPath(F.BaseDirectory, Record, Idx);
@@ -9511,6 +9521,13 @@ std::string ASTReader::ReadPath(StringRef BaseDirectory,
95119521
return ResolveImportedPathAndAllocate(PathBuf, Filename, BaseDirectory);
95129522
}
95139523

9524+
std::string ASTReader::ReadPathBlob(StringRef BaseDirectory,
9525+
const RecordData &Record, unsigned &Idx,
9526+
StringRef &Blob) {
9527+
StringRef Filename = ReadStringBlob(Record, Idx, Blob);
9528+
return ResolveImportedPathAndAllocate(PathBuf, Filename, BaseDirectory);
9529+
}
9530+
95149531
VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record,
95159532
unsigned &Idx) {
95169533
unsigned Major = Record[Idx++];

0 commit comments

Comments
 (0)