Skip to content

Commit 5a77383

Browse files
authored
Merge pull request #32432 from xymus/module-loading-order-5.3
[5.3][ModuleInterface] Prefer the swiftmodule in the SDK over the prebuilt-module cache
2 parents d972a95 + 737afe5 commit 5a77383

File tree

2 files changed

+87
-49
lines changed

2 files changed

+87
-49
lines changed

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 46 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -738,8 +738,52 @@ class ModuleInterfaceLoaderImpl {
738738
}
739739
}
740740

741-
// If we weren't able to open the file for any reason, including it not
742-
// existing, keep going.
741+
// [Note: ModuleInterfaceLoader-defer-to-SerializedModuleLoader]
742+
// If there's a module adjacent to the .swiftinterface that we can
743+
// _likely_ load (it validates OK and is up to date), bail early with
744+
// errc::not_supported, so the next (serialized) loader in the chain will
745+
// load it.
746+
// Alternately, if there's a .swiftmodule present but we can't even
747+
// read it (for whatever reason), we should let the other module loader
748+
// diagnose it.
749+
750+
if (shouldLoadAdjacentModule) {
751+
auto adjacentModuleBuffer = fs.getBufferForFile(modulePath);
752+
if (adjacentModuleBuffer) {
753+
if (serializedASTBufferIsUpToDate(modulePath, *adjacentModuleBuffer.get(),
754+
deps)) {
755+
LLVM_DEBUG(llvm::dbgs() << "Found up-to-date module at "
756+
<< modulePath
757+
<< "; deferring to serialized module loader\n");
758+
return std::make_error_code(std::errc::not_supported);
759+
} else if (isInResourceDir(modulePath) &&
760+
loadMode == ModuleLoadingMode::PreferSerialized) {
761+
// Special-case here: If we're loading a .swiftmodule from the resource
762+
// dir adjacent to the compiler, defer to the serialized loader instead
763+
// of falling back. This is mainly to support development of Swift,
764+
// where one might change the module format version but forget to
765+
// recompile the standard library. If that happens, don't fall back
766+
// and silently recompile the standard library -- instead, error like
767+
// we used to.
768+
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date module in the "
769+
"resource-dir at "
770+
<< modulePath
771+
<< "; deferring to serialized module loader "
772+
"to diagnose\n");
773+
return std::make_error_code(std::errc::not_supported);
774+
} else {
775+
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date module at "
776+
<< modulePath << "\n");
777+
rebuildInfo.setModuleKind(modulePath,
778+
ModuleRebuildInfo::ModuleKind::Normal);
779+
}
780+
} else if (adjacentModuleBuffer.getError() != notFoundError) {
781+
LLVM_DEBUG(llvm::dbgs() << "Found unreadable module at "
782+
<< modulePath
783+
<< "; deferring to serialized module loader\n");
784+
return std::make_error_code(std::errc::not_supported);
785+
}
786+
}
743787

744788
// If we have a prebuilt cache path, check that too if the interface comes
745789
// from the SDK.
@@ -766,53 +810,6 @@ class ModuleInterfaceLoaderImpl {
766810
}
767811
}
768812

769-
// [Note: ModuleInterfaceLoader-defer-to-SerializedModuleLoader]
770-
// Finally, if there's a module adjacent to the .swiftinterface that we can
771-
// _likely_ load (it validates OK and is up to date), bail early with
772-
// errc::not_supported, so the next (serialized) loader in the chain will
773-
// load it.
774-
// Alternately, if there's a .swiftmodule present but we can't even
775-
// read it (for whatever reason), we should let the other module loader
776-
// diagnose it.
777-
if (!shouldLoadAdjacentModule)
778-
return notFoundError;
779-
780-
auto adjacentModuleBuffer = fs.getBufferForFile(modulePath);
781-
if (adjacentModuleBuffer) {
782-
if (serializedASTBufferIsUpToDate(modulePath, *adjacentModuleBuffer.get(),
783-
deps)) {
784-
LLVM_DEBUG(llvm::dbgs() << "Found up-to-date module at "
785-
<< modulePath
786-
<< "; deferring to serialized module loader\n");
787-
return std::make_error_code(std::errc::not_supported);
788-
} else if (isInResourceDir(modulePath) &&
789-
loadMode == ModuleLoadingMode::PreferSerialized) {
790-
// Special-case here: If we're loading a .swiftmodule from the resource
791-
// dir adjacent to the compiler, defer to the serialized loader instead
792-
// of falling back. This is mainly to support development of Swift,
793-
// where one might change the module format version but forget to
794-
// recompile the standard library. If that happens, don't fall back
795-
// and silently recompile the standard library -- instead, error like
796-
// we used to.
797-
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date module in the "
798-
"resource-dir at "
799-
<< modulePath
800-
<< "; deferring to serialized module loader "
801-
"to diagnose\n");
802-
return std::make_error_code(std::errc::not_supported);
803-
} else {
804-
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date module at "
805-
<< modulePath << "\n");
806-
rebuildInfo.setModuleKind(modulePath,
807-
ModuleRebuildInfo::ModuleKind::Normal);
808-
}
809-
} else if (adjacentModuleBuffer.getError() != notFoundError) {
810-
LLVM_DEBUG(llvm::dbgs() << "Found unreadable module at "
811-
<< modulePath
812-
<< "; deferring to serialized module loader\n");
813-
return std::make_error_code(std::errc::not_supported);
814-
}
815-
816813
// Couldn't find an up-to-date .swiftmodule, will need to build module from
817814
// interface.
818815
return notFoundError;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/// Test the loading order of module interfaces between the SDK and the
2+
/// prebuilt cache. The order should be:
3+
///
4+
/// 1. Local cache (not tested here)
5+
/// 2. Next to the swiftinterface file
6+
/// 3. Prebuilt-module cache
7+
8+
/// Create folders for a) our Swift module, b) the module cache, and c) a
9+
/// fake resource dir with a default prebuilt module cache inside.
10+
// RUN: %empty-directory(%t/MyModule.swiftmodule)
11+
// RUN: %empty-directory(%t/ModuleCache)
12+
// RUN: %empty-directory(%t/ResourceDir/%target-sdk-name/prebuilt-modules/MyModule.swiftmodule)
13+
14+
/// Define two sets of public API.
15+
// RUN: echo 'public func nextToSwiftinterface() {}' > %t/NextToSwiftinterface.swift
16+
// RUN: echo 'public func prebuiltModule() {}' > %t/PrebuiltModule.swift
17+
18+
/// Compile this into a module in the SDK.
19+
// RUN: %target-swift-frontend -emit-module %t/NextToSwiftinterface.swift -o %t/MyModule.swiftmodule/%target-cpu.swiftmodule -module-name MyModule -parse-stdlib -emit-module-interface-path %t/MyModule.swiftmodule/%target-cpu.swiftinterface
20+
21+
/// Also put a module with a different API into the default prebuilt cache under the same name.
22+
// RUN: %target-swift-frontend -emit-module %t/PrebuiltModule.swift -o %t/ResourceDir/%target-sdk-name/prebuilt-modules/MyModule.swiftmodule/%target-cpu.swiftmodule -module-name MyModule -parse-stdlib
23+
24+
/// Import this module and expect to use the swiftmodule next to the swiftinterface.
25+
// RUN: %target-swift-frontend -typecheck -resource-dir %t/ResourceDir -I %t %s -parse-stdlib -module-cache-path %t/ModuleCache -sdk %t -D FIRST_NEXT_TO_SWIFTINTERFACE
26+
27+
/// Remove the first swiftmodule and import again to use the prebuilt swiftmodule.
28+
// RUN: rm %t/MyModule.swiftmodule/%target-cpu.swiftmodule
29+
// RUN: %target-swift-frontend -typecheck -resource-dir %t/ResourceDir -I %t %s -parse-stdlib -module-cache-path %t/ModuleCache -sdk %t -D THEN_PREBUILT_MODULE
30+
31+
import MyModule
32+
33+
#if FIRST_NEXT_TO_SWIFTINTERFACE
34+
35+
nextToSwiftinterface()
36+
37+
#elseif THEN_PREBUILT_MODULE
38+
39+
prebuiltModule()
40+
41+
#endif

0 commit comments

Comments
 (0)