Skip to content

Commit 1c8ad2f

Browse files
authored
Merge pull request swiftlang#32423 from xymus/module-loading-order
[ModuleInterface] Prefer the swiftmodule in the SDK over the prebuilt-cache
2 parents c17966e + b4f2e63 commit 1c8ad2f

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
@@ -662,8 +662,52 @@ class ModuleInterfaceLoaderImpl {
662662
}
663663
}
664664

665-
// If we weren't able to open the file for any reason, including it not
666-
// existing, keep going.
665+
// [Note: ModuleInterfaceLoader-defer-to-SerializedModuleLoader]
666+
// If there's a module adjacent to the .swiftinterface that we can
667+
// _likely_ load (it validates OK and is up to date), bail early with
668+
// errc::not_supported, so the next (serialized) loader in the chain will
669+
// load it.
670+
// Alternately, if there's a .swiftmodule present but we can't even
671+
// read it (for whatever reason), we should let the other module loader
672+
// diagnose it.
673+
674+
if (shouldLoadAdjacentModule) {
675+
auto adjacentModuleBuffer = fs.getBufferForFile(modulePath);
676+
if (adjacentModuleBuffer) {
677+
if (serializedASTBufferIsUpToDate(modulePath, *adjacentModuleBuffer.get(),
678+
deps)) {
679+
LLVM_DEBUG(llvm::dbgs() << "Found up-to-date module at "
680+
<< modulePath
681+
<< "; deferring to serialized module loader\n");
682+
return std::make_error_code(std::errc::not_supported);
683+
} else if (isInResourceDir(modulePath) &&
684+
loadMode == ModuleLoadingMode::PreferSerialized) {
685+
// Special-case here: If we're loading a .swiftmodule from the resource
686+
// dir adjacent to the compiler, defer to the serialized loader instead
687+
// of falling back. This is mainly to support development of Swift,
688+
// where one might change the module format version but forget to
689+
// recompile the standard library. If that happens, don't fall back
690+
// and silently recompile the standard library -- instead, error like
691+
// we used to.
692+
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date module in the "
693+
"resource-dir at "
694+
<< modulePath
695+
<< "; deferring to serialized module loader "
696+
"to diagnose\n");
697+
return std::make_error_code(std::errc::not_supported);
698+
} else {
699+
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date module at "
700+
<< modulePath << "\n");
701+
rebuildInfo.setModuleKind(modulePath,
702+
ModuleRebuildInfo::ModuleKind::Normal);
703+
}
704+
} else if (adjacentModuleBuffer.getError() != notFoundError) {
705+
LLVM_DEBUG(llvm::dbgs() << "Found unreadable module at "
706+
<< modulePath
707+
<< "; deferring to serialized module loader\n");
708+
return std::make_error_code(std::errc::not_supported);
709+
}
710+
}
667711

668712
// If we have a prebuilt cache path, check that too if the interface comes
669713
// from the SDK.
@@ -690,53 +734,6 @@ class ModuleInterfaceLoaderImpl {
690734
}
691735
}
692736

693-
// [Note: ModuleInterfaceLoader-defer-to-SerializedModuleLoader]
694-
// Finally, if there's a module adjacent to the .swiftinterface that we can
695-
// _likely_ load (it validates OK and is up to date), bail early with
696-
// errc::not_supported, so the next (serialized) loader in the chain will
697-
// load it.
698-
// Alternately, if there's a .swiftmodule present but we can't even
699-
// read it (for whatever reason), we should let the other module loader
700-
// diagnose it.
701-
if (!shouldLoadAdjacentModule)
702-
return notFoundError;
703-
704-
auto adjacentModuleBuffer = fs.getBufferForFile(modulePath);
705-
if (adjacentModuleBuffer) {
706-
if (serializedASTBufferIsUpToDate(modulePath, *adjacentModuleBuffer.get(),
707-
deps)) {
708-
LLVM_DEBUG(llvm::dbgs() << "Found up-to-date module at "
709-
<< modulePath
710-
<< "; deferring to serialized module loader\n");
711-
return std::make_error_code(std::errc::not_supported);
712-
} else if (isInResourceDir(modulePath) &&
713-
loadMode == ModuleLoadingMode::PreferSerialized) {
714-
// Special-case here: If we're loading a .swiftmodule from the resource
715-
// dir adjacent to the compiler, defer to the serialized loader instead
716-
// of falling back. This is mainly to support development of Swift,
717-
// where one might change the module format version but forget to
718-
// recompile the standard library. If that happens, don't fall back
719-
// and silently recompile the standard library -- instead, error like
720-
// we used to.
721-
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date module in the "
722-
"resource-dir at "
723-
<< modulePath
724-
<< "; deferring to serialized module loader "
725-
"to diagnose\n");
726-
return std::make_error_code(std::errc::not_supported);
727-
} else {
728-
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date module at "
729-
<< modulePath << "\n");
730-
rebuildInfo.setModuleKind(modulePath,
731-
ModuleRebuildInfo::ModuleKind::Normal);
732-
}
733-
} else if (adjacentModuleBuffer.getError() != notFoundError) {
734-
LLVM_DEBUG(llvm::dbgs() << "Found unreadable module at "
735-
<< modulePath
736-
<< "; deferring to serialized module loader\n");
737-
return std::make_error_code(std::errc::not_supported);
738-
}
739-
740737
// Couldn't find an up-to-date .swiftmodule, will need to build module from
741738
// interface.
742739
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-swiftmodule-name -module-name MyModule -parse-stdlib -emit-module-interface-path %t/MyModule.swiftmodule/%target-swiftinterface-name
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-swiftmodule-name -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-swiftmodule-name
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)