@@ -223,27 +223,19 @@ static bool serializedASTLooksValid(const llvm::MemoryBuffer &buf) {
223
223
}
224
224
225
225
static std::unique_ptr<llvm::MemoryBuffer> getBufferOfDependency (
226
- llvm::vfs::FileSystem &fs, StringRef depPath, StringRef interfacePath,
227
- DiagnosticEngine &diags, SourceLoc diagnosticLoc) {
226
+ llvm::vfs::FileSystem &fs, StringRef depPath) {
228
227
auto depBuf = fs.getBufferForFile (depPath, /* FileSize=*/ -1 ,
229
228
/* RequiresNullTerminator=*/ false );
230
229
if (!depBuf) {
231
- diags.diagnose (diagnosticLoc,
232
- diag::missing_dependency_of_module_interface,
233
- depPath, interfacePath, depBuf.getError ().message ());
234
230
return nullptr ;
235
231
}
236
232
return std::move (depBuf.get ());
237
233
}
238
234
239
235
static Optional<llvm::vfs::Status> getStatusOfDependency (
240
- llvm::vfs::FileSystem &fs, StringRef depPath, StringRef interfacePath,
241
- DiagnosticEngine &diags, SourceLoc diagnosticLoc) {
236
+ llvm::vfs::FileSystem &fs, StringRef depPath) {
242
237
auto status = fs.status (depPath);
243
238
if (!status) {
244
- diags.diagnose (diagnosticLoc,
245
- diag::missing_dependency_of_module_interface,
246
- depPath, interfacePath, status.getError ().message ());
247
239
return None;
248
240
}
249
241
return status.get ();
@@ -293,6 +285,7 @@ class swift::ParseableInterfaceBuilder {
293
285
const SourceLoc diagnosticLoc;
294
286
DependencyTracker *const dependencyTracker;
295
287
CompilerInvocation subInvocation;
288
+ SmallVector<StringRef, 3 > extraDependencies;
296
289
297
290
void configureSubInvocationInputsAndOutputs (StringRef OutPath) {
298
291
auto &SubFEOpts = subInvocation.getFrontendOptions ();
@@ -406,6 +399,8 @@ class swift::ParseableInterfaceBuilder {
406
399
auto DTDeps = SubInstance.getDependencyTracker ()->getDependencies ();
407
400
SmallVector<StringRef, 16 > InitialDepNames (DTDeps.begin (), DTDeps.end ());
408
401
InitialDepNames.push_back (interfacePath);
402
+ InitialDepNames.insert (InitialDepNames.end (),
403
+ extraDependencies.begin (), extraDependencies.end ());
409
404
llvm::StringSet<> AllDepNames;
410
405
SmallString<128 > Scratch;
411
406
@@ -433,8 +428,7 @@ class swift::ParseableInterfaceBuilder {
433
428
if (DepName.startswith (ResourcePath))
434
429
continue ;
435
430
436
- auto Status = getStatusOfDependency (fs, DepName, interfacePath,
437
- diags, diagnosticLoc);
431
+ auto Status = getStatusOfDependency (fs, DepName);
438
432
if (!Status)
439
433
return true ;
440
434
@@ -444,8 +438,7 @@ class swift::ParseableInterfaceBuilder {
444
438
std::unique_ptr<llvm::MemoryBuffer> DepBuf = nullptr ;
445
439
auto getDepBuf = [&]() -> llvm::MemoryBuffer * {
446
440
if (DepBuf) return DepBuf.get ();
447
- if (auto Buf = getBufferOfDependency (fs, DepName, interfacePath,
448
- diags, diagnosticLoc)) {
441
+ if (auto Buf = getBufferOfDependency (fs, DepName)) {
449
442
DepBuf = std::move (Buf);
450
443
return DepBuf.get ();
451
444
}
@@ -498,6 +491,12 @@ class swift::ParseableInterfaceBuilder {
498
491
return subInvocation;
499
492
}
500
493
494
+ // / Ensures the requested file name is added as a dependency of the resulting
495
+ // / module.
496
+ void addExtraDependency (StringRef path) {
497
+ extraDependencies.push_back (path);
498
+ }
499
+
501
500
bool buildSwiftModule (StringRef OutPath, bool ShouldSerializeDeps,
502
501
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer) {
503
502
bool SubError = false ;
@@ -656,14 +655,15 @@ struct ModuleRebuildInfo {
656
655
Optional<serialization::Status> serializationStatus;
657
656
ModuleKind kind;
658
657
SmallVector<std::string, 10 > outOfDateDependencies;
658
+ SmallVector<std::string, 10 > missingDependencies;
659
659
};
660
660
SmallVector<OutOfDateModule, 3 > outOfDateModules;
661
661
662
662
OutOfDateModule &getOrInsertOutOfDateModule (StringRef path) {
663
663
for (auto &mod : outOfDateModules) {
664
664
if (mod.path == path) return mod;
665
665
}
666
- outOfDateModules.push_back ({path, None, ModuleKind::Normal, {}});
666
+ outOfDateModules.push_back ({path, None, ModuleKind::Normal, {}, {} });
667
667
return outOfDateModules.back ();
668
668
}
669
669
@@ -686,6 +686,22 @@ struct ModuleRebuildInfo {
686
686
.outOfDateDependencies .push_back (depPath);
687
687
}
688
688
689
+ // / Registers a missing dependency at \c depPath for the module
690
+ // / at \c modulePath.
691
+ void addMissingDependency (StringRef modulePath, StringRef depPath) {
692
+ getOrInsertOutOfDateModule (modulePath)
693
+ .missingDependencies .push_back (depPath);
694
+ }
695
+
696
+ // / Determines if we saw the given module path and registered is as out of
697
+ // / date.
698
+ bool sawOutOfDateModule (StringRef modulePath) {
699
+ for (auto &mod : outOfDateModules)
700
+ if (mod.path == modulePath)
701
+ return true ;
702
+ return false ;
703
+ }
704
+
689
705
const char *invalidModuleReason (serialization::Status status) {
690
706
using namespace serialization ;
691
707
switch (status) {
@@ -722,6 +738,11 @@ struct ModuleRebuildInfo {
722
738
dep);
723
739
}
724
740
741
+ // Diagnose any missing dependencies in this module.
742
+ for (auto &dep : mod.missingDependencies ) {
743
+ ctx.Diags .diagnose (loc, diag::module_interface_dependency_missing, dep);
744
+ }
745
+
725
746
// If there was a compiled module that wasn't able to be read, diagnose
726
747
// the reason we couldn't read it.
727
748
if (auto status = mod.serializationStatus ) {
@@ -835,31 +856,44 @@ class ParseableInterfaceModuleLoaderImpl {
835
856
return StringRef (scratch.data (), scratch.size ());
836
857
}
837
858
859
+ enum class DependencyStatus {
860
+ UpToDate,
861
+ OutOfDate,
862
+ Missing
863
+ };
864
+
838
865
// Checks that a dependency read from the cached module is up to date compared
839
866
// to the interface file it represents.
840
- bool dependencyIsUpToDate (const FileDependency &dep, StringRef fullPath) {
841
- auto status = getStatusOfDependency (fs, fullPath, interfacePath,
842
- diags, diagnosticLoc);
843
- if (!status) return false ;
867
+ DependencyStatus checkDependency (StringRef modulePath,
868
+ const FileDependency &dep,
869
+ StringRef fullPath) {
870
+ auto status = getStatusOfDependency (fs, fullPath);
871
+ if (!status)
872
+ return DependencyStatus::Missing;
844
873
845
874
// If the sizes differ, then we know the file has changed.
846
- if (status->getSize () != dep.getSize ()) return false ;
875
+ if (status->getSize () != dep.getSize ())
876
+ return DependencyStatus::OutOfDate;
847
877
848
878
// Otherwise, if this dependency is verified by modification time, check
849
879
// it vs. the modification time of the file.
850
880
if (dep.isModificationTimeBased ()) {
851
881
uint64_t mtime =
852
882
status->getLastModificationTime ().time_since_epoch ().count ();
853
- return mtime == dep.getModificationTime ();
883
+ return mtime == dep.getModificationTime () ?
884
+ DependencyStatus::UpToDate :
885
+ DependencyStatus::OutOfDate;
854
886
}
855
887
856
888
// Slow path: if the dependency is verified by content hash, check it vs.
857
889
// the hash of the file.
858
- auto buf = getBufferOfDependency (fs, fullPath, interfacePath,
859
- diags, diagnosticLoc);
860
- if (!buf) return false ;
890
+ auto buf = getBufferOfDependency (fs, fullPath);
891
+ if (!buf)
892
+ return DependencyStatus::Missing ;
861
893
862
- return xxHash64 (buf->getBuffer ()) == dep.getContentHash ();
894
+ return xxHash64 (buf->getBuffer ()) == dep.getContentHash () ?
895
+ DependencyStatus::UpToDate :
896
+ DependencyStatus::OutOfDate;
863
897
}
864
898
865
899
// Check if all the provided file dependencies are up-to-date compared to
@@ -869,13 +903,19 @@ class ParseableInterfaceModuleLoaderImpl {
869
903
SmallString<128 > SDKRelativeBuffer;
870
904
for (auto &in : deps) {
871
905
StringRef fullPath = getFullDependencyPath (in, SDKRelativeBuffer);
872
- if (!dependencyIsUpToDate (in, fullPath)) {
873
- LLVM_DEBUG (llvm::dbgs () << " Dep " << fullPath
874
- << " is directly out of date\n " );
906
+ switch (checkDependency (modulePath, in, fullPath)) {
907
+ case DependencyStatus::UpToDate:
908
+ LLVM_DEBUG (llvm::dbgs () << " Dep " << fullPath << " is up to date\n " );
909
+ break ;
910
+ case DependencyStatus::OutOfDate:
911
+ LLVM_DEBUG (llvm::dbgs () << " Dep " << fullPath << " is out of date\n " );
875
912
rebuildInfo.addOutOfDateDependency (modulePath, fullPath);
876
913
return false ;
914
+ case DependencyStatus::Missing:
915
+ LLVM_DEBUG (llvm::dbgs () << " Dep " << fullPath << " is missing\n " );
916
+ rebuildInfo.addMissingDependency (modulePath, fullPath);
917
+ return false ;
877
918
}
878
- LLVM_DEBUG (llvm::dbgs () << " Dep " << fullPath << " is up to date\n " );
879
919
}
880
920
return true ;
881
921
}
@@ -885,7 +925,12 @@ class ParseableInterfaceModuleLoaderImpl {
885
925
bool serializedASTBufferIsUpToDate (
886
926
StringRef path, const llvm::MemoryBuffer &buf,
887
927
SmallVectorImpl<FileDependency> &allDeps) {
888
- LLVM_DEBUG (llvm::dbgs () << " Validating deps of " << modulePath << " \n " );
928
+
929
+ // Clear the existing dependencies, because we're going to re-fill them
930
+ // in validateSerializedAST.
931
+ allDeps.clear ();
932
+
933
+ LLVM_DEBUG (llvm::dbgs () << " Validating deps of " << path << " \n " );
889
934
auto validationInfo = serialization::validateSerializedAST (
890
935
buf.getBuffer (), /* ExtendedValidationInfo=*/ nullptr , &allDeps);
891
936
@@ -916,6 +961,13 @@ class ParseableInterfaceModuleLoaderImpl {
916
961
StringRef path, const ForwardingModule &fwd,
917
962
SmallVectorImpl<FileDependency> &deps,
918
963
std::unique_ptr<llvm::MemoryBuffer> &moduleBuffer) {
964
+
965
+ // Clear the existing dependencies, because we're going to re-fill them
966
+ // from the forwarding module.
967
+ deps.clear ();
968
+
969
+ LLVM_DEBUG (llvm::dbgs () << " Validating deps of " << path << " \n " );
970
+
919
971
// First, make sure the underlying module path exists and is valid.
920
972
auto modBuf = fs.getBufferForFile (fwd.underlyingModulePath );
921
973
if (!modBuf || !serializedASTLooksValid (*modBuf.get ()))
@@ -1160,6 +1212,9 @@ class ParseableInterfaceModuleLoaderImpl {
1160
1212
ModuleRebuildInfo::ModuleKind::Normal);
1161
1213
}
1162
1214
} else if (adjacentModuleBuffer.getError () != notFoundError) {
1215
+ LLVM_DEBUG (llvm::dbgs () << " Found unreadable module at "
1216
+ << modulePath
1217
+ << " ; deferring to serialized module loader\n " );
1163
1218
return std::make_error_code (std::errc::not_supported);
1164
1219
}
1165
1220
@@ -1306,6 +1361,14 @@ class ParseableInterfaceModuleLoaderImpl {
1306
1361
interfacePath);
1307
1362
}
1308
1363
1364
+ // If we found an out-of-date .swiftmodule, we still want to add it as
1365
+ // a dependency of the .swiftinterface. That way if it's updated, but
1366
+ // the .swiftinterface remains the same, we invalidate the cache and
1367
+ // check the new .swiftmodule, because it likely has more information
1368
+ // about the state of the world.
1369
+ if (rebuildInfo.sawOutOfDateModule (modulePath))
1370
+ builder.addExtraDependency (modulePath);
1371
+
1309
1372
if (builder.buildSwiftModule (cachedOutputPath, /* shouldSerializeDeps*/ true ,
1310
1373
&moduleBuffer))
1311
1374
return std::make_error_code (std::errc::invalid_argument);
0 commit comments