Skip to content

Commit c13a4c5

Browse files
authored
Merge pull request #71617 from xymus/swiftinterface-by-default-mode
ModuleInterface: Setup logic to load distributed swiftinterfaces over swiftmodules by default
2 parents 7cee7e9 + 4945cfc commit c13a4c5

File tree

3 files changed

+201
-20
lines changed

3 files changed

+201
-20
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,11 +446,19 @@ NOTE(compiled_module_ignored_reason,none,
446446
"|it belongs to a framework in the SDK"
447447
"|loading from module interfaces is preferred"
448448
"|it's a compiler host module"
449-
"|the module name is blocklisted}1",
449+
"|the module name is blocklisted,"
450+
"|the default is to load from module interfaces}1",
450451
(StringRef, unsigned))
451452
NOTE(out_of_date_module_here,none,
452453
"%select{compiled|cached|forwarding|prebuilt}0 module is out of date: '%1'",
453454
(unsigned, StringRef))
455+
NOTE(module_interface_ignored_reason,none,
456+
"not defaulting to module interface because %select{%error"
457+
"|it is a local module"
458+
"|it was blocklisted"
459+
"|the reader is a debugger}1"
460+
", preferring binary module at '%0'",
461+
(StringRef, unsigned))
454462
NOTE(module_interface_dependency_out_of_date,none,
455463
"dependency is out of date: '%0'",
456464
(StringRef))

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 97 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -240,12 +240,21 @@ struct ModuleRebuildInfo {
240240
InterfacePreferred,
241241
CompilerHostModule,
242242
Blocklisted,
243+
DistributedInterfaceByDefault,
244+
};
245+
// Keep aligned with diag::module_interface_ignored_reason.
246+
enum class ReasonModuleInterfaceIgnored {
247+
NotIgnored,
248+
LocalModule,
249+
Blocklisted,
250+
Debugger,
243251
};
244252
struct CandidateModule {
245253
std::string path;
246254
std::optional<serialization::Status> serializationStatus;
247255
ModuleKind kind;
248256
ReasonIgnored reasonIgnored;
257+
ReasonModuleInterfaceIgnored reasonModuleInterfaceIgnored;
249258
SmallVector<std::string, 10> outOfDateDependencies;
250259
SmallVector<std::string, 10> missingDependencies;
251260
};
@@ -259,6 +268,7 @@ struct ModuleRebuildInfo {
259268
std::nullopt,
260269
ModuleKind::Normal,
261270
ReasonIgnored::NotIgnored,
271+
ReasonModuleInterfaceIgnored::NotIgnored,
262272
{},
263273
{}});
264274
return candidateModules.back();
@@ -290,13 +300,21 @@ struct ModuleRebuildInfo {
290300
.missingDependencies.push_back(depPath.str());
291301
}
292302

293-
/// Sets the reason that the module at \c path was ignored. If this is
303+
/// Sets the reason that the module at \c modulePath was ignored. If this is
294304
/// anything besides \c NotIgnored a note will be added stating why the module
295305
/// was ignored.
296306
void addIgnoredModule(StringRef modulePath, ReasonIgnored reasonIgnored) {
297307
getOrInsertCandidateModule(modulePath).reasonIgnored = reasonIgnored;
298308
}
299309

310+
/// Record why no swiftinterfaces were preferred over the binary swiftmodule
311+
/// at \c modulePath.
312+
void addIgnoredModuleInterface(StringRef modulePath,
313+
ReasonModuleInterfaceIgnored reasonIgnored) {
314+
getOrInsertCandidateModule(modulePath).reasonModuleInterfaceIgnored =
315+
reasonIgnored;
316+
}
317+
300318
/// Determines if we saw the given module path and registered is as out of
301319
/// date.
302320
bool sawOutOfDateModule(StringRef modulePath) {
@@ -367,7 +385,7 @@ struct ModuleRebuildInfo {
367385
// We may have found multiple failing modules, that failed for different
368386
// reasons. Emit a note for each of them.
369387
for (auto &mod : candidateModules) {
370-
// If a the compiled module was ignored, diagnose the reason.
388+
// If the compiled module was ignored, diagnose the reason.
371389
if (mod.reasonIgnored != ReasonIgnored::NotIgnored) {
372390
diags.diagnose(loc, diag::compiled_module_ignored_reason, mod.path,
373391
(unsigned)mod.reasonIgnored);
@@ -399,6 +417,19 @@ struct ModuleRebuildInfo {
399417
}
400418
}
401419
}
420+
421+
/// Emits a diagnostic for the reason why binary swiftmodules were preferred
422+
/// over textual swiftinterfaces.
423+
void diagnoseIgnoredModuleInterfaces(ASTContext &ctx, SourceLoc loc) {
424+
for (auto &mod : candidateModules) {
425+
auto interfaceIgnore = mod.reasonModuleInterfaceIgnored;
426+
if (interfaceIgnore == ReasonModuleInterfaceIgnored::NotIgnored)
427+
continue;
428+
429+
ctx.Diags.diagnose(loc, diag::module_interface_ignored_reason,
430+
mod.path, (unsigned)interfaceIgnore);
431+
}
432+
}
402433
};
403434

404435
/// Constructs the full path of the dependency \p dep by prepending the SDK
@@ -761,6 +792,12 @@ class ModuleInterfaceLoaderImpl {
761792
return pathStartsWith(hostPath, path);
762793
}
763794

795+
bool isInSDK(StringRef path) {
796+
StringRef sdkPath = ctx.SearchPathOpts.getSDKPath();
797+
if (sdkPath.empty()) return false;
798+
return pathStartsWith(sdkPath, path);
799+
}
800+
764801
bool isInSystemFrameworks(StringRef path, bool publicFramework) {
765802
StringRef sdkPath = ctx.SearchPathOpts.getSDKPath();
766803
if (sdkPath.empty()) return false;
@@ -775,26 +812,64 @@ class ModuleInterfaceLoaderImpl {
775812

776813
std::pair<std::string, std::string> getCompiledModuleCandidates() {
777814
using ReasonIgnored = ModuleRebuildInfo::ReasonIgnored;
815+
using ReasonModuleInterfaceIgnored =
816+
ModuleRebuildInfo::ReasonModuleInterfaceIgnored;
778817
std::pair<std::string, std::string> result;
779-
// Should we attempt to load a swiftmodule adjacent to the swiftinterface?
780-
bool shouldLoadAdjacentModule = !ctx.IgnoreAdjacentModules;
781818

782-
if (modulePath.contains(".sdk")) {
783-
if (ctx.blockListConfig.hasBlockListAction(moduleName,
784-
BlockListKeyKind::ModuleName, BlockListAction::ShouldUseTextualModule)) {
785-
shouldLoadAdjacentModule = false;
786-
rebuildInfo.addIgnoredModule(modulePath, ReasonIgnored::Blocklisted);
819+
bool ignoreByDefault = ctx.blockListConfig.hasBlockListAction(
820+
"Swift_UseSwiftinterfaceByDefault",
821+
BlockListKeyKind::ModuleName,
822+
BlockListAction::ShouldUseBinaryModule);
823+
bool shouldLoadAdjacentModule;
824+
if (ignoreByDefault) {
825+
ReasonModuleInterfaceIgnored ignore =
826+
ReasonModuleInterfaceIgnored::NotIgnored;
827+
828+
if (!isInSDK(modulePath) &&
829+
!isInResourceHostDir(modulePath)) {
830+
ignore = ReasonModuleInterfaceIgnored::LocalModule;
831+
} else if (ctx.blockListConfig.hasBlockListAction(moduleName,
832+
BlockListKeyKind::ModuleName,
833+
BlockListAction::ShouldUseBinaryModule)) {
834+
ignore = ReasonModuleInterfaceIgnored::Blocklisted;
835+
} else if (ctx.LangOpts.DebuggerSupport) {
836+
ignore = ReasonModuleInterfaceIgnored::Debugger;
787837
}
788-
}
789838

790-
// Don't use the adjacent swiftmodule for frameworks from the public
791-
// Frameworks folder of the SDK.
792-
if (isInSystemFrameworks(modulePath, /*publicFramework*/true)) {
793-
shouldLoadAdjacentModule = false;
794-
rebuildInfo.addIgnoredModule(modulePath, ReasonIgnored::PublicFramework);
795-
} else if (isInResourceHostDir(modulePath)) {
796-
shouldLoadAdjacentModule = false;
797-
rebuildInfo.addIgnoredModule(modulePath, ReasonIgnored::CompilerHostModule);
839+
shouldLoadAdjacentModule =
840+
ignore != ReasonModuleInterfaceIgnored::NotIgnored;
841+
if (shouldLoadAdjacentModule) {
842+
// Prefer the swiftmodule.
843+
rebuildInfo.addIgnoredModuleInterface(modulePath, ignore);
844+
} else {
845+
// Prefer the swiftinterface.
846+
rebuildInfo.addIgnoredModule(modulePath,
847+
ReasonIgnored::DistributedInterfaceByDefault);
848+
}
849+
} else {
850+
// Should we attempt to load a swiftmodule adjacent to the swiftinterface?
851+
shouldLoadAdjacentModule = !ctx.IgnoreAdjacentModules;
852+
853+
if (modulePath.contains(".sdk")) {
854+
if (ctx.blockListConfig.hasBlockListAction(moduleName,
855+
BlockListKeyKind::ModuleName,
856+
BlockListAction::ShouldUseTextualModule)) {
857+
shouldLoadAdjacentModule = false;
858+
rebuildInfo.addIgnoredModule(modulePath, ReasonIgnored::Blocklisted);
859+
}
860+
}
861+
862+
// Don't use the adjacent swiftmodule for frameworks from the public
863+
// Frameworks folder of the SDK.
864+
if (isInSystemFrameworks(modulePath, /*publicFramework*/true)) {
865+
shouldLoadAdjacentModule = false;
866+
rebuildInfo.addIgnoredModule(modulePath,
867+
ReasonIgnored::PublicFramework);
868+
} else if (isInResourceHostDir(modulePath)) {
869+
shouldLoadAdjacentModule = false;
870+
rebuildInfo.addIgnoredModule(modulePath,
871+
ReasonIgnored::CompilerHostModule);
872+
}
798873
}
799874

800875
switch (loadMode) {
@@ -1081,8 +1156,10 @@ class ModuleInterfaceLoaderImpl {
10811156
// If we errored with anything other than 'no such file or directory',
10821157
// fail this load and let the other module loader diagnose it.
10831158
if (!moduleOrErr &&
1084-
moduleOrErr.getError() != std::errc::no_such_file_or_directory)
1159+
moduleOrErr.getError() != std::errc::no_such_file_or_directory) {
1160+
rebuildInfo.diagnoseIgnoredModuleInterfaces(ctx, diagnosticLoc);
10851161
return moduleOrErr.getError();
1162+
}
10861163

10871164
// We discovered a module! Return that module's buffer so we can load it.
10881165
if (moduleOrErr) {
@@ -1105,6 +1182,7 @@ class ModuleInterfaceLoaderImpl {
11051182
}
11061183
}
11071184

1185+
11081186
return std::move(module.moduleBuffer);
11091187
}
11101188
// If building from interface is disabled, return error.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/// The blocklist can enable loading distributed swiftinterfaces by default.
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: split-file %s %t --leading-lines
5+
// REQUIRES: VENDOR=apple
6+
7+
/// Setup the SDK and local modules.
8+
//// SDK module in S/L/F.
9+
// RUN: %target-swift-frontend -emit-module -module-name SDKModule %t/Empty.swift \
10+
// RUN: -enable-library-evolution -swift-version 5 -parse-stdlib \
11+
// RUN: -emit-module-path %t/sdk/System/Library/Frameworks/SDKModule.framework/Modules/SDKModule.swiftmodule/%target-swiftmodule-name \
12+
// RUN: -emit-module-interface-path %t/sdk/System/Library/Frameworks/SDKModule.framework/Modules/SDKModule.swiftmodule/%target-swiftinterface-name
13+
// RUN: %target-swift-typecheck-module-from-interface(%t/sdk/System/Library/Frameworks/SDKModule.framework/Modules/SDKModule.swiftmodule/%target-swiftinterface-name) -module-name SDKModule
14+
15+
//// SDK module not in S/L/F.
16+
// RUN: %target-swift-frontend -emit-module -module-name SDKModuleAtUnusualPath %t/Empty.swift \
17+
// RUN: -enable-library-evolution -swift-version 5 -parse-stdlib \
18+
// RUN: -emit-module-path %t/sdk/System/Library/OtherFrameworks/SDKModuleAtUnusualPath.framework/Modules/SDKModuleAtUnusualPath.swiftmodule/%target-swiftmodule-name \
19+
// RUN: -emit-module-interface-path %t/sdk/System/Library/OtherFrameworks/SDKModuleAtUnusualPath.framework/Modules/SDKModuleAtUnusualPath.swiftmodule/%target-swiftinterface-name
20+
// RUN: %target-swift-typecheck-module-from-interface(%t/sdk/System/Library/OtherFrameworks/SDKModuleAtUnusualPath.framework/Modules/SDKModuleAtUnusualPath.swiftmodule/%target-swiftinterface-name) -module-name SDKModuleAtUnusualPath
21+
22+
//// Local module.
23+
// RUN: %target-swift-frontend -emit-module -module-name LocalModule %t/Empty.swift \
24+
// RUN: -enable-library-evolution -swift-version 5 -parse-stdlib \
25+
// RUN: -emit-module-path %t/not_sdk/LocalModule.swiftmodule \
26+
// RUN: -emit-module-interface-path %t/not_sdk/LocalModule.swiftinterface
27+
// RUN: %target-swift-typecheck-module-from-interface(%t/not_sdk/LocalModule.swiftinterface) -module-name LocalModule
28+
29+
//// Host resource-dir module.
30+
// RUN: %target-swift-frontend -emit-module -module-name HostResourceDirModule %t/Empty.swift \
31+
// RUN: -enable-library-evolution -swift-version 5 -parse-stdlib \
32+
// RUN: -emit-module-path %t/res/host/HostResourceDirModule.swiftmodule \
33+
// RUN: -emit-module-interface-path %t/res/host/HostResourceDirModule.swiftinterface
34+
// RUN: %target-swift-typecheck-module-from-interface(%t/res/host/HostResourceDirModule.swiftinterface) -module-name HostResourceDirModule
35+
36+
//// Blocklisted module.
37+
// RUN: %target-swift-frontend -emit-module -module-name BlocklistedModule %t/Empty.swift \
38+
// RUN: -enable-library-evolution -swift-version 5 -parse-stdlib \
39+
// RUN: -emit-module-path %t/sdk/System/Library/Frameworks/BlocklistedModule.framework/Modules/BlocklistedModule.swiftmodule/%target-swiftmodule-name \
40+
// RUN: -emit-module-interface-path %t/sdk/System/Library/Frameworks/BlocklistedModule.framework/Modules/BlocklistedModule.swiftmodule/%target-swiftinterface-name
41+
// RUN: %target-swift-typecheck-module-from-interface(%t/sdk/System/Library/Frameworks/BlocklistedModule.framework/Modules/BlocklistedModule.swiftmodule/%target-swiftinterface-name) -module-name BlocklistedModule
42+
43+
/// Build a client preferring swiftinterfaces.
44+
// RUN: %target-swift-frontend -typecheck -module-name Main %t/Client_SwiftinterfacesByDefault.swift \
45+
// RUN: -parse-stdlib -module-cache-path %t/cache \
46+
// RUN: -blocklist-file %t/blocklistEnabled.yml \
47+
// RUN: -sdk %t/sdk -I %t/not_sdk -resource-dir %t/res -I %t/res/host/ \
48+
// RUN: -F %t/sdk/System/Library/OtherFrameworks/ \
49+
// RUN: -Rmodule-interface-rebuild -verify
50+
51+
/// Build a client preferring swiftmodules.
52+
// RUN: %empty-directory(%t/cache)
53+
// RUN: %target-swift-frontend -typecheck -module-name Main %t/Client_SwiftmodulesByDefault.swift \
54+
// RUN: -parse-stdlib -module-cache-path %t/cache \
55+
// RUN: -blocklist-file %t/blocklistDisabled.yml \
56+
// RUN: -sdk %t/sdk -I %t/not_sdk -resource-dir %t/res -I %t/res/host/ \
57+
// RUN: -F %t/sdk/System/Library/OtherFrameworks/ \
58+
// RUN: -Rmodule-interface-rebuild -verify
59+
60+
//--- Empty.swift
61+
62+
//--- Client_SwiftinterfacesByDefault.swift
63+
/// New behavior
64+
import SDKModule // expected-remark {{rebuilding module 'SDKModule' from interface}}
65+
// expected-note @-1 {{was ignored because the default is to load from module interfaces}}
66+
import SDKModuleAtUnusualPath // expected-remark {{rebuilding module 'SDKModuleAtUnusualPath' from interface}}
67+
// expected-note @-1 {{was ignored because the default is to load from module interfaces}}
68+
import HostResourceDirModule // expected-remark {{rebuilding module 'HostResourceDirModule' from interface}}
69+
// expected-note @-1 {{was ignored because the default is to load from module interfaces}}
70+
import LocalModule // expected-note {{not defaulting to module interface because it is a local module, preferring binary module at}}
71+
import BlocklistedModule // expected-note {{not defaulting to module interface because it was blocklisted, preferring binary module at}}
72+
73+
//--- Client_SwiftmodulesByDefault.swift
74+
/// Old behavior
75+
import SDKModule // expected-remark {{rebuilding module 'SDKModule' from interface}}
76+
// expected-note @-1 {{was ignored because it belongs to a framework in the SDK}}
77+
import SDKModuleAtUnusualPath
78+
import HostResourceDirModule // expected-remark {{rebuilding module 'HostResourceDirModule' from interface}}
79+
// expected-note @-1 {{was ignored because it's a compiler host module}}
80+
import LocalModule
81+
import BlocklistedModule // expected-remark {{rebuilding module 'BlocklistedModule' from interface}}
82+
// expected-note @-1 {{was ignored because it belongs to a framework in the SDK}}
83+
84+
//--- blocklistDisabled.yml
85+
---
86+
ShouldUseBinaryModule:
87+
ModuleName:
88+
- BlocklistedModule
89+
90+
//--- blocklistEnabled.yml
91+
---
92+
ShouldUseBinaryModule:
93+
ModuleName:
94+
- Swift_UseSwiftinterfaceByDefault
95+
- BlocklistedModule

0 commit comments

Comments
 (0)