Skip to content

Commit 3aec862

Browse files
Merge pull request #34848 from aschwaighofer/make_prespecialization_experimental
Pre-specialization: This is an experimental feature
2 parents 158427b + 1d45e2f commit 3aec862

25 files changed

+158
-98
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,6 +1567,9 @@ ERROR(attr_specialize_missing_comma,none,
15671567
ERROR(attr_specialize_unknown_parameter_name,none,
15681568
"unknown parameter %0 in '_specialize attribute'", (StringRef))
15691569

1570+
ERROR(attr_specialize_unsupported_exported_true ,none,
1571+
"'exported: true' has no effect in '_specialize' attribute", (StringRef))
1572+
15701573
ERROR(attr_specialize_expected_bool_value,none,
15711574
"expected a boolean true or false value in '_specialize' attribute", ())
15721575

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@ namespace swift {
248248
/// Disable the implicit import of the _Concurrency module.
249249
bool DisableImplicitConcurrencyModuleImport = false;
250250

251+
/// Enable experimental support for `@_specialize(exported: true,...)` .
252+
bool EnableExperimentalPrespecialization = false;
253+
251254
/// Should we check the target OSs of serialized modules to see that they're
252255
/// new enough?
253256
bool EnableTargetOSChecking = true;

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@ let Flags = [FrontendOption, NoDriverOption, HelpHidden, ModuleInterfaceOption]
223223
HelpText<"Disable requiring uses of @objc to require importing the "
224224
"Foundation module">;
225225

226+
def enable_experimental_prespecialization :
227+
Flag<["-"], "enable-experimental-prespecialization">,
228+
HelpText<"Enable experimental pre-specialization support">;
229+
226230
def enable_experimental_concurrency :
227231
Flag<["-"], "enable-experimental-concurrency">,
228232
HelpText<"Enable experimental concurrency model">;

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
481481
= A->getOption().matches(OPT_enable_objc_attr_requires_foundation_module);
482482
}
483483

484+
Opts.EnableExperimentalPrespecialization |=
485+
Args.hasArg(OPT_enable_experimental_prespecialization);
486+
484487
if (auto A = Args.getLastArg(OPT_enable_testable_attr_requires_testable_module,
485488
OPT_disable_testable_attr_requires_testable_module)) {
486489
Opts.EnableTestableAttrRequiresTestableModule

lib/Parse/ParseDecl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,14 @@ bool Parser::parseSpecializeAttributeArguments(
644644
if (ParamLabel == "exported") {
645645
Exported = isTrue;
646646
}
647+
if (Exported == true) {
648+
const LangOptions &LangOpts = Context.LangOpts;
649+
if (!LangOpts.EnableExperimentalPrespecialization) {
650+
diagnose(Tok.getLoc(),
651+
diag::attr_specialize_unsupported_exported_true,
652+
ParamLabel);
653+
}
654+
}
647655
}
648656
if (ParamLabel == "kind") {
649657
SourceLoc paramValueLoc;

lib/SILGen/SILGen.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2105,6 +2105,20 @@ static void transferSpecializeAttributeTargets(SILGenModule &SGM, SILModule &M,
21052105
}
21062106

21072107
void SILGenModule::visitImportDecl(ImportDecl *import) {
2108+
// Importing `@_specializet(targetFunction: otherFunc)` only supported in
2109+
// experimental pre-specialization mode.
2110+
if (!getASTContext().LangOpts.EnableExperimentalPrespecialization)
2111+
return;
2112+
2113+
// TODO: this horrible full AST deserializing walk should be replaced by a
2114+
// 'single place' to lookup those declarations in the module
2115+
// E.g
2116+
// prespecializations {
2117+
// extension Array {
2118+
// @_specialize(exported: true, targetFunction: other(_:), T == Int)
2119+
// func prespecialzie_other() {}
2120+
// }
2121+
// }
21082122
auto *module = import->getModule();
21092123
if (module->isNonSwiftModule())
21102124
return;

test/IRGen/pre_specialize.swift

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
11
// RUN: %empty-directory(%t)
22

33
// Module A code generation.
4-
// RUN: %target-swift-frontend -emit-ir -primary-file %S/Inputs/pre_specialize_module.swift -module-name A | %FileCheck %s -check-prefix=CHECK-A -check-prefix=CHECK-A-FRAG
5-
// RUN: %target-swift-frontend -O -emit-ir -primary-file %S/Inputs/pre_specialize_module.swift -module-name A | %FileCheck %s -check-prefix=CHECK-A -check-prefix=CHECK-A-FRAG
6-
// RUN: %target-swift-frontend -enable-library-evolution -emit-ir -primary-file %S/Inputs/pre_specialize_module.swift -module-name A | %FileCheck %s -check-prefix=CHECK-A -check-prefix=CHECK-A-RES
7-
// RUN: %target-swift-frontend -O -enable-library-evolution -emit-ir -primary-file %S/Inputs/pre_specialize_module.swift -module-name A | %FileCheck %s -check-prefix=CHECK-A -check-prefix=CHECK-A-RES
4+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -emit-ir -primary-file %S/Inputs/pre_specialize_module.swift -module-name A | %FileCheck %s -check-prefix=CHECK-A -check-prefix=CHECK-A-FRAG
5+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -O -emit-ir -primary-file %S/Inputs/pre_specialize_module.swift -module-name A | %FileCheck %s -check-prefix=CHECK-A -check-prefix=CHECK-A-FRAG
6+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -enable-library-evolution -emit-ir -primary-file %S/Inputs/pre_specialize_module.swift -module-name A | %FileCheck %s -check-prefix=CHECK-A -check-prefix=CHECK-A-RES
7+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -O -enable-library-evolution -emit-ir -primary-file %S/Inputs/pre_specialize_module.swift -module-name A | %FileCheck %s -check-prefix=CHECK-A -check-prefix=CHECK-A-RES
88

99
// Module B code generation with A.swiftmodule.
1010
// RUN: %empty-directory(%t)
11-
// RUN: %target-build-swift -Xfrontend -validate-tbd-against-ir=missing -emit-module -emit-module-path=%t/A.swiftmodule -module-name A %S/Inputs/pre_specialize_module.swift -emit-library -o %t/%target-library-name(A)
12-
// RUN: %target-swift-frontend -I %t -emit-ir -primary-file %S/Inputs/pre_specialize_module_B.swift -module-name B | %FileCheck %s -check-prefix=CHECK-B
13-
// RUN: %target-swift-frontend -I %t -O -emit-ir -primary-file %S/Inputs/pre_specialize_module_B.swift -module-name B | %FileCheck %s -check-prefix=CHECK-B
14-
// RUN: %target-build-swift -I %t -Xfrontend -validate-tbd-against-ir=missing -emit-module -emit-module-path=%t/B.swiftmodule -module-name B %S/Inputs/pre_specialize_module_B.swift -emit-library -o %t/%target-library-name(B) -L %t -lA
15-
// RUN: %target-build-swift -swift-version 5 -I %t -Xfrontend -validate-tbd-against-ir=all -enable-library-evolution -emit-module-interface-path %t/B.swiftinterface -module-name B %S/Inputs/pre_specialize_module_B.swift -emit-library -o %t/%target-library-name(B) -L %t -lA
11+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -Xfrontend -validate-tbd-against-ir=missing -emit-module -emit-module-path=%t/A.swiftmodule -module-name A %S/Inputs/pre_specialize_module.swift -emit-library -o %t/%target-library-name(A)
12+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -I %t -emit-ir -primary-file %S/Inputs/pre_specialize_module_B.swift -module-name B | %FileCheck %s -check-prefix=CHECK-B
13+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -I %t -O -emit-ir -primary-file %S/Inputs/pre_specialize_module_B.swift -module-name B | %FileCheck %s -check-prefix=CHECK-B
14+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -I %t -Xfrontend -validate-tbd-against-ir=missing -emit-module -emit-module-path=%t/B.swiftmodule -module-name B %S/Inputs/pre_specialize_module_B.swift -emit-library -o %t/%target-library-name(B) -L %t -lA
15+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -swift-version 5 -I %t -Xfrontend -validate-tbd-against-ir=all -enable-library-evolution -emit-module-interface-path %t/B.swiftinterface -module-name B %S/Inputs/pre_specialize_module_B.swift -emit-library -o %t/%target-library-name(B) -L %t -lA
1616

1717
// Module B code generation with A.swiftmodule with library evolution.
1818
// RUN: %empty-directory(%t)
19-
// RUN: %target-build-swift -enable-library-evolution -Xfrontend -validate-tbd-against-ir=all -emit-module -emit-module-path=%t/A.swiftmodule -module-name A %S/Inputs/pre_specialize_module.swift -emit-library -o %t/%target-library-name(A)
20-
// RUN: %target-swift-frontend -I %t -emit-ir -primary-file %S/Inputs/pre_specialize_module_B.swift -module-name B | %FileCheck %s -check-prefix=CHECK-B
21-
// RUN: %target-swift-frontend -I %t -O -emit-ir -primary-file %S/Inputs/pre_specialize_module_B.swift -module-name B | %FileCheck %s -check-prefix=CHECK-B
22-
// RUN: %target-build-swift -I %t -Xfrontend -validate-tbd-against-ir=missing -emit-module -emit-module-path=%t/B.swiftmodule -module-name B %S/Inputs/pre_specialize_module_B.swift -emit-library -o %t/%target-library-name(B) -L %t -lA
23-
// RUN: %target-build-swift -swift-version 5 -I %t -Xfrontend -validate-tbd-against-ir=all -enable-library-evolution -emit-module-interface-path %t/B.swiftinterface -module-name B %S/Inputs/pre_specialize_module_B.swift -emit-library -o %t/%target-library-name(B) -L %t -lA
19+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -enable-library-evolution -Xfrontend -validate-tbd-against-ir=all -emit-module -emit-module-path=%t/A.swiftmodule -module-name A %S/Inputs/pre_specialize_module.swift -emit-library -o %t/%target-library-name(A)
20+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -I %t -emit-ir -primary-file %S/Inputs/pre_specialize_module_B.swift -module-name B | %FileCheck %s -check-prefix=CHECK-B
21+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -I %t -O -emit-ir -primary-file %S/Inputs/pre_specialize_module_B.swift -module-name B | %FileCheck %s -check-prefix=CHECK-B
22+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -I %t -Xfrontend -validate-tbd-against-ir=missing -emit-module -emit-module-path=%t/B.swiftmodule -module-name B %S/Inputs/pre_specialize_module_B.swift -emit-library -o %t/%target-library-name(B) -L %t -lA
23+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -swift-version 5 -I %t -Xfrontend -validate-tbd-against-ir=all -enable-library-evolution -emit-module-interface-path %t/B.swiftinterface -module-name B %S/Inputs/pre_specialize_module_B.swift -emit-library -o %t/%target-library-name(B) -L %t -lA
2424

2525
// Module B code generation with A.swiftinterface with library evolution.
2626
// RUN: %empty-directory(%t)
27-
// RUN: %target-build-swift -enable-library-evolution -Xfrontend -validate-tbd-against-ir=all -emit-module-interface-path %t/A.swiftinterface -module-name A %S/Inputs/pre_specialize_module.swift -emit-library -o %t/%target-library-name(A) -swift-version 5
28-
// RUN: %target-swift-frontend -I %t -emit-ir -primary-file %S/Inputs/pre_specialize_module_B.swift -module-name B | %FileCheck %s -check-prefix=CHECK-B
29-
// RUN: %target-swift-frontend -I %t -O -emit-ir -primary-file %S/Inputs/pre_specialize_module_B.swift -module-name B | %FileCheck %s -check-prefix=CHECK-B
30-
// RUN: %target-build-swift -I %t -Xfrontend -validate-tbd-against-ir=missing -emit-module -emit-module-path=%t/B.swiftmodule -module-name B %S/Inputs/pre_specialize_module_B.swift -emit-library -o %t/%target-library-name(B) -L %t -lA
31-
// RUN: %target-build-swift -swift-version 5 -I %t -Xfrontend -validate-tbd-against-ir=all -enable-library-evolution -emit-module-interface-path %t/B.swiftinterface -module-name B %S/Inputs/pre_specialize_module_B.swift -emit-library -o %t/%target-library-name(B) -L %t -lA
27+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -enable-library-evolution -Xfrontend -validate-tbd-against-ir=all -emit-module-interface-path %t/A.swiftinterface -module-name A %S/Inputs/pre_specialize_module.swift -emit-library -o %t/%target-library-name(A) -swift-version 5
28+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -I %t -emit-ir -primary-file %S/Inputs/pre_specialize_module_B.swift -module-name B | %FileCheck %s -check-prefix=CHECK-B
29+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -I %t -O -emit-ir -primary-file %S/Inputs/pre_specialize_module_B.swift -module-name B | %FileCheck %s -check-prefix=CHECK-B
30+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -I %t -Xfrontend -validate-tbd-against-ir=missing -emit-module -emit-module-path=%t/B.swiftmodule -module-name B %S/Inputs/pre_specialize_module_B.swift -emit-library -o %t/%target-library-name(B) -L %t -lA
31+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -swift-version 5 -I %t -Xfrontend -validate-tbd-against-ir=all -enable-library-evolution -emit-module-interface-path %t/B.swiftinterface -module-name B %S/Inputs/pre_specialize_module_B.swift -emit-library -o %t/%target-library-name(B) -L %t -lA
3232

3333
// Module A tests
3434
// --------------
@@ -104,39 +104,39 @@
104104

105105
// Fragile .swiftmodule
106106
// RUN: %empty-directory(%t)
107-
// RUN: %target-build-swift -emit-module -emit-module-path=%t/A.swiftmodule -module-name A %S/Inputs/pre_specialize_module.swift
108-
// RUN: %target-build-swift -I %t -emit-module -emit-module-path=%t/B.swiftmodule -module-name B %S/Inputs/pre_specialize_module_B.swift
109-
// RUN: %target-swift-frontend -O -I %t -emit-ir -primary-file %s -module-name C | %FileCheck %s -check-prefix=CHECK-C
107+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -emit-module -emit-module-path=%t/A.swiftmodule -module-name A %S/Inputs/pre_specialize_module.swift
108+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -I %t -emit-module -emit-module-path=%t/B.swiftmodule -module-name B %S/Inputs/pre_specialize_module_B.swift
109+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -O -I %t -emit-ir -primary-file %s -module-name C | %FileCheck %s -check-prefix=CHECK-C
110110

111111
// Fragile optimized .swiftmodule
112112
// RUN: %empty-directory(%t)
113-
// RUN: %target-build-swift -O -emit-module -emit-module-path=%t/A.swiftmodule -module-name A %S/Inputs/pre_specialize_module.swift
114-
// RUN: %target-build-swift -O -I %t -emit-module -emit-module-path=%t/B.swiftmodule -module-name B %S/Inputs/pre_specialize_module_B.swift
115-
// RUN: %target-swift-frontend -O -I %t -emit-ir -primary-file %s -module-name C | %FileCheck %s -check-prefix=CHECK-C
113+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -O -emit-module -emit-module-path=%t/A.swiftmodule -module-name A %S/Inputs/pre_specialize_module.swift
114+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -O -I %t -emit-module -emit-module-path=%t/B.swiftmodule -module-name B %S/Inputs/pre_specialize_module_B.swift
115+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -O -I %t -emit-ir -primary-file %s -module-name C | %FileCheck %s -check-prefix=CHECK-C
116116

117117
// Resilient .swiftmodule
118118
// RUN: %empty-directory(%t)
119-
// RUN: %target-build-swift -enable-library-evolution -emit-module -emit-module-path=%t/A.swiftmodule -module-name A %S/Inputs/pre_specialize_module.swift
120-
// RUN: %target-build-swift -enable-library-evolution -I %t -emit-module -emit-module-path=%t/B.swiftmodule -module-name B %S/Inputs/pre_specialize_module_B.swift
121-
// RUN: %target-swift-frontend -O -I %t -emit-ir -primary-file %s -module-name C | %FileCheck %s -check-prefix=CHECK-C
119+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -enable-library-evolution -emit-module -emit-module-path=%t/A.swiftmodule -module-name A %S/Inputs/pre_specialize_module.swift
120+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -enable-library-evolution -I %t -emit-module -emit-module-path=%t/B.swiftmodule -module-name B %S/Inputs/pre_specialize_module_B.swift
121+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -O -I %t -emit-ir -primary-file %s -module-name C | %FileCheck %s -check-prefix=CHECK-C
122122

123123
// Resilient optimized .swiftmodule
124124
// RUN: %empty-directory(%t)
125-
// RUN: %target-build-swift -O -enable-library-evolution -emit-module -emit-module-path=%t/A.swiftmodule -module-name A %S/Inputs/pre_specialize_module.swift
126-
// RUN: %target-build-swift -O -enable-library-evolution -I %t -emit-module -emit-module-path=%t/B.swiftmodule -module-name B %S/Inputs/pre_specialize_module_B.swift
127-
// RUN: %target-swift-frontend -O -I %t -emit-ir -primary-file %s -module-name C | %FileCheck %s -check-prefix=CHECK-C
125+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -O -enable-library-evolution -emit-module -emit-module-path=%t/A.swiftmodule -module-name A %S/Inputs/pre_specialize_module.swift
126+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -O -enable-library-evolution -I %t -emit-module -emit-module-path=%t/B.swiftmodule -module-name B %S/Inputs/pre_specialize_module_B.swift
127+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -O -I %t -emit-ir -primary-file %s -module-name C | %FileCheck %s -check-prefix=CHECK-C
128128

129129
// .swiftinterface
130130
// RUN: %empty-directory(%t)
131-
// RUN: %target-build-swift -c -enable-library-evolution -emit-module-interface-path %t/A.swiftinterface -module-name A %S/Inputs/pre_specialize_module.swift -o %t/A.o -swift-version 5
132-
// RUN: %target-build-swift -c -enable-library-evolution -I %t -emit-module-interface-path %t/B.swiftinterface -module-name B %S/Inputs/pre_specialize_module_B.swift -o %t/B.o -swift-version 5
133-
// RUN: %target-swift-frontend -O -I %t -emit-ir -primary-file %s -module-name C | %FileCheck %s -check-prefix=CHECK-C
131+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -c -enable-library-evolution -emit-module-interface-path %t/A.swiftinterface -module-name A %S/Inputs/pre_specialize_module.swift -o %t/A.o -swift-version 5
132+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -c -enable-library-evolution -I %t -emit-module-interface-path %t/B.swiftinterface -module-name B %S/Inputs/pre_specialize_module_B.swift -o %t/B.o -swift-version 5
133+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -O -I %t -emit-ir -primary-file %s -module-name C | %FileCheck %s -check-prefix=CHECK-C
134134

135135
// Optimized .swiftinterface
136136
// RUN: %empty-directory(%t)
137-
// RUN: %target-build-swift -O -c -enable-library-evolution -emit-module-interface-path %t/A.swiftinterface -module-name A %S/Inputs/pre_specialize_module.swift -o %t/A.o -swift-version 5
138-
// RUN: %target-build-swift -O -c -enable-library-evolution -I %t -emit-module-interface-path %t/B.swiftinterface -module-name B %S/Inputs/pre_specialize_module_B.swift -o %t/B.o -swift-version 5
139-
// RUN: %target-swift-frontend -O -I %t -emit-ir -primary-file %s -module-name C | %FileCheck %s -check-prefix=CHECK-C
137+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -O -c -enable-library-evolution -emit-module-interface-path %t/A.swiftinterface -module-name A %S/Inputs/pre_specialize_module.swift -o %t/A.o -swift-version 5
138+
// RUN: %target-build-swift -Xfrontend -enable-experimental-prespecialization -O -c -enable-library-evolution -I %t -emit-module-interface-path %t/B.swiftinterface -module-name B %S/Inputs/pre_specialize_module_B.swift -o %t/B.o -swift-version 5
139+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -O -I %t -emit-ir -primary-file %s -module-name C | %FileCheck %s -check-prefix=CHECK-C
140140

141141
import A
142142
import B

0 commit comments

Comments
 (0)