Skip to content

Commit c4d61f5

Browse files
author
Harlan Haskins
authored
Merge pull request #23866 from harlanhaskins/shock-and-awe-5.1
[5.1] [ParseableInterfaces] Short-circuit module loading in the PIML
2 parents b2904fb + 9d25741 commit c4d61f5

File tree

4 files changed

+83
-6
lines changed

4 files changed

+83
-6
lines changed

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,18 @@ class SerializedModuleLoaderBase : public ModuleLoader {
5151
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
5252
bool &isFramework);
5353

54+
/// Attempts to search the provided directory for a loadable serialized
55+
/// .swiftmodule with the provided `ModuleFilename`. Subclasses must
56+
/// override this method to perform their custom module lookup behavior.
57+
///
58+
/// If such a module could not be loaded, the subclass must return a
59+
/// `std::error_code` indicating the failure. There are two specific error
60+
/// codes that will be treated specially:
61+
/// - `errc::no_such_file_or_directory`: The module loader will stop looking
62+
/// for loadable modules and will diagnose the lookup failure.
63+
/// - `errc::not_supported`: The module loader will stop looking for loadable
64+
/// modules and will defer to the remaining module loaders to look up this
65+
/// module.
5466
virtual std::error_code findModuleFilesInDirectory(
5567
AccessPathElem ModuleID, StringRef DirPath, StringRef ModuleFilename,
5668
StringRef ModuleDocFilename,

lib/Frontend/ParseableInterfaceModuleLoader.cpp

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -864,13 +864,25 @@ class ParseableInterfaceModuleLoaderImpl {
864864
if (isForwardingModule) {
865865
if (auto forwardingModule = ForwardingModule::load(*buf)) {
866866
std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
867-
if (forwardingModuleIsUpToDate(*forwardingModule, deps, moduleBuffer))
867+
if (forwardingModuleIsUpToDate(*forwardingModule, deps,
868+
moduleBuffer)) {
869+
LLVM_DEBUG(llvm::dbgs() << "Found up-to-date forwarding module at "
870+
<< cachedOutputPath << "\n");
868871
return DiscoveredModule::forwarded(
869872
forwardingModule->underlyingModulePath, std::move(moduleBuffer));
873+
}
874+
875+
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date forwarding module at "
876+
<< cachedOutputPath << "\n");
870877
}
871878
// Otherwise, check if the AST buffer itself is up to date.
872879
} else if (serializedASTBufferIsUpToDate(*buf, deps)) {
880+
LLVM_DEBUG(llvm::dbgs() << "Found up-to-date cached module at "
881+
<< cachedOutputPath << "\n");
873882
return DiscoveredModule::normal(cachedOutputPath, std::move(buf));
883+
} else {
884+
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date cached module at "
885+
<< cachedOutputPath << "\n");
874886
}
875887
}
876888

@@ -883,23 +895,39 @@ class ParseableInterfaceModuleLoaderImpl {
883895
llvm::SmallString<256> scratch;
884896
std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
885897
auto path = computePrebuiltModulePath(scratch);
886-
if (path && swiftModuleIsUpToDate(*path, deps, moduleBuffer))
887-
return DiscoveredModule::prebuilt(*path, std::move(moduleBuffer));
898+
if (path) {
899+
if (swiftModuleIsUpToDate(*path, deps, moduleBuffer)) {
900+
LLVM_DEBUG(llvm::dbgs() << "Found up-to-date prebuilt module at "
901+
<< path->str() << "\n");
902+
return DiscoveredModule::prebuilt(*path, std::move(moduleBuffer));
903+
} else {
904+
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date prebuilt module at "
905+
<< modulePath << "\n");
906+
}
907+
}
888908
}
889909

890910
// Finally, if there's a module adjacent to the .swiftinterface that we can
891911
// _likely_ load (it validates OK and is up to date), bail early with
892912
// errc::not_supported, so the next (serialized) loader in the chain will
893-
// load it. Alternately, if there's a .swiftmodule present but we can't even
913+
// load it.
914+
// Alternately, if there's a .swiftmodule present but we can't even
894915
// read it (for whatever reason), we should let the other module loader
895916
// diagnose it.
896917
if (!shouldLoadAdjacentModule)
897918
return notFoundError;
898919

899920
auto adjacentModuleBuffer = fs.getBufferForFile(modulePath);
900921
if (adjacentModuleBuffer) {
901-
if (serializedASTBufferIsUpToDate(*adjacentModuleBuffer.get(), deps))
922+
if (serializedASTBufferIsUpToDate(*adjacentModuleBuffer.get(), deps)) {
923+
LLVM_DEBUG(llvm::dbgs() << "Found up-to-date module at "
924+
<< modulePath
925+
<< "; deferring to serialized module loader\n");
902926
return std::make_error_code(std::errc::not_supported);
927+
} else {
928+
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date module at "
929+
<< modulePath << "\n");
930+
}
903931
} else if (adjacentModuleBuffer.getError() != notFoundError) {
904932
return std::make_error_code(std::errc::not_supported);
905933
}
@@ -1053,8 +1081,15 @@ std::error_code ParseableInterfaceModuleLoader::findModuleFilesInDirectory(
10531081
auto Ext = file_types::getExtension(file_types::TY_SwiftParseableInterfaceFile);
10541082
InPath = ModPath;
10551083
path::replace_extension(InPath, Ext);
1056-
if (!fs.exists(InPath))
1084+
if (!fs.exists(InPath)) {
1085+
if (fs.exists(ModPath)) {
1086+
LLVM_DEBUG(llvm::dbgs()
1087+
<< "No .swiftinterface file found adjacent to module file "
1088+
<< ModPath.str() << "\n");
1089+
return std::make_error_code(std::errc::not_supported);
1090+
}
10571091
return std::make_error_code(std::errc::no_such_file_or_directory);
1092+
}
10581093

10591094
// Create an instance of the Impl to do the heavy lifting.
10601095
ParseableInterfaceModuleLoaderImpl Impl(

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
218218
moduleBuffer, moduleDocBuffer);
219219
if (!result) {
220220
return true;
221+
} else if (result == std::errc::not_supported) {
222+
return false;
221223
} else if (result != std::errc::no_such_file_or_directory) {
222224
return None;
223225
}
@@ -251,6 +253,8 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
251253
moduleBuffer, moduleDocBuffer);
252254
if (!result)
253255
return true;
256+
else if (result == std::errc::not_supported)
257+
return false;
254258
}
255259
}
256260

@@ -320,6 +324,8 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
320324
moduleBuffer, moduleDocBuffer);
321325
if (!result)
322326
return true;
327+
else if (result == std::errc::not_supported)
328+
return false;
323329
}
324330
}
325331

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %empty-directory(%t/BuildDir)
2+
// RUN: %empty-directory(%t/SecondBuildDir/Lib.swiftmodule)
3+
// RUN: %empty-directory(%t/ModuleCache)
4+
5+
// RUN: echo 'public func showsUpInBothPlaces() {}' > %t/Lib.swift
6+
7+
// 1. Create a .swiftinterface file containing just one API, and put it inside a second build dir (without a .swiftmodule)
8+
// RUN: %target-swift-frontend -typecheck %t/Lib.swift -emit-parseable-module-interface-path %t/SecondBuildDir/Lib.swiftmodule/%target-cpu.swiftinterface
9+
10+
// 2. Add a new API to the module, and compile just the serialized version in the build dir.
11+
// RUN: echo 'public func onlyInTheCompiledModule() {}' >> %t/Lib.swift
12+
// RUN: %target-swift-frontend -emit-module %t/Lib.swift -o %t/BuildDir/Lib.swiftmodule -emit-parseable-module-interface-path %t/BuildDir/Lib.swiftinterface
13+
14+
// 3. Make sure when we compile this test file, we can access both APIs since we'll
15+
// load the compiled .swiftmodule instead of the .swiftinterface in the SDK.
16+
// RUN: %target-swift-frontend -typecheck %s -I %t/BuildDir -I %t/SecondBuildDir -module-cache-path %t/ModuleCache
17+
18+
// 4. Make sure we didn't compile any .swiftinterfaces into the module cache.
19+
// RUN: ls %t/ModuleCache | not grep 'swiftmodule'
20+
21+
import Lib
22+
23+
showsUpInBothPlaces()
24+
onlyInTheCompiledModule()

0 commit comments

Comments
 (0)