Skip to content

Commit 23cac67

Browse files
committed
IRGen: Enable dynamic replacement with library evolution
It looks like the only thing that fails is the linkage computation for the dynamic replacement key of class methods. Even though methods have hidden linkage to prevent them from being directly referenced from outside a resilient module, we need to ensure the dynamic replacement key is visible. Fixes <rdar://problem/58457716>.
1 parent 120840e commit 23cac67

9 files changed

+85
-26
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4460,11 +4460,6 @@ ERROR(dynamic_with_transparent,none,
44604460
"a declaration cannot be both '@_tranparent' and 'dynamic'",
44614461
())
44624462

4463-
ERROR(dynamic_and_library_evolution_not_supported,none,
4464-
"marking non-'@objc' Swift declaration 'dynamic' in library evolution mode is not supported",
4465-
())
4466-
4467-
44684463
//------------------------------------------------------------------------------
44694464
// MARK: @_dynamicReplacement(for:)
44704465
//------------------------------------------------------------------------------

lib/IRGen/Linking.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,8 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
629629
return SILLinkage::Private;
630630

631631
case Kind::DynamicallyReplaceableFunctionKey:
632+
return getSILFunction()->getLinkage();
633+
632634
case Kind::SILFunction:
633635
return getSILFunction()->getEffectiveSymbolLinkage();
634636

lib/Sema/TypeCheckAttr.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -347,10 +347,6 @@ void AttributeChecker::visitDynamicAttr(DynamicAttr *attr) {
347347
// Members cannot be both dynamic and @_transparent.
348348
if (D->getAttrs().hasAttribute<TransparentAttr>())
349349
diagnoseAndRemoveAttr(attr, diag::dynamic_with_transparent);
350-
if (!D->getAttrs().hasAttribute<ObjCAttr>() &&
351-
D->getModuleContext()->isResilient())
352-
diagnoseAndRemoveAttr(attr,
353-
diag::dynamic_and_library_evolution_not_supported);
354350
}
355351

356352
static bool
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-swift-frontend -emit-ir -enable-library-evolution %s | %FileCheck %s
2+
3+
public class ResilientClass {
4+
public dynamic func resilientMethod() {}
5+
}
6+
7+
// The dynamic replacement key should be public even though the method
8+
// implementation is hidden.
9+
10+
// CHECK-LABEL: @"$s36class_resilience_dynamic_replacement14ResilientClassC15resilientMethodyyFTx" = {{(protected )?}}constant %swift.dyn_repl_key
11+
// CHECK-LABEL: define hidden swiftcc void @"$s36class_resilience_dynamic_replacement14ResilientClassC15resilientMethodyyF"

test/Interpreter/Inputs/dynamic_replacement_module.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,15 @@ public func replacement_for_public_global_generic_func<T>(_ t: T.Type) -> String
162162
}
163163

164164
extension PublicClass {
165+
166+
// Designated initializers of resilient classes cannot be
167+
// dynamically replaced.
168+
#if !EVOLUTION
165169
@_dynamicReplacement(for: init(x:))
166170
public init(y: Int) {
167171
str = "replacement of public_class_init"
168172
}
173+
#endif
169174

170175
@_dynamicReplacement(for: function())
171176
public func replacement_function() -> String {

test/Interpreter/dynamic_replacement.swift

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,58 @@
4646
// RUN: %target-codesign %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
4747
// RUN: %target-run %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
4848

49+
///////////////////////////////////////////////////////////////////////////////
50+
// Now repeat all of the same tests, but with library evolution enabled:
51+
///////////////////////////////////////////////////////////////////////////////
52+
53+
// RUN: %empty-directory(%t)
54+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module1)) -DMODULE -module-name Module1 -emit-module -emit-module-path %t/Module1.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -enable-library-evolution
55+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module2)) -I%t -L%t -lModule1 %target-rpath(%t) -DMODULE2 -module-name Module2 -emit-module -emit-module-path %t/Module2.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -DEVOLUTION
56+
// RUN: %target-build-swift -I%t -L%t -lModule1 -DMAIN -o %t/main %target-rpath(%t) %s -swift-version 5 -DEVOLUTION
57+
// RUN: %target-codesign %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
58+
// RUN: %target-run %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
59+
60+
// Now the same in optimized mode.
61+
// RUN: %empty-directory(%t)
62+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module1)) -O -DMODULE -module-name Module1 -emit-module -emit-module-path %t/Module1.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -enable-library-evolution
63+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module2)) -O -I%t -L%t -lModule1 %target-rpath(%t) -DMODULE2 -module-name Module2 -emit-module -emit-module-path %t/Module2.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -DEVOLUTION
64+
// RUN: %target-build-swift -O -I%t -L%t -lModule1 -DMAIN -o %t/main %target-rpath(%t) %s -swift-version 5 -DEVOLUTION
65+
// RUN: %target-codesign %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
66+
// RUN: %target-run %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
67+
68+
// Now the same in size mode.
69+
// RUN: %empty-directory(%t)
70+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module1)) -Osize -DMODULE -module-name Module1 -emit-module -emit-module-path %t/Module1.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -enable-library-evolution
71+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module2)) -Osize -I%t -L%t -lModule1 %target-rpath(%t) -DMODULE2 -module-name Module2 -emit-module -emit-module-path %t/Module2.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -DEVOLUTION
72+
// RUN: %target-build-swift -Osize -I%t -L%t -lModule1 -DMAIN -o %t/main %target-rpath(%t) %s -swift-version 5 -DEVOLUTION
73+
// RUN: %target-codesign %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
74+
// RUN: %target-run %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
75+
76+
// Now the same in optimized wholemodule mode.
77+
// RUN: %empty-directory(%t)
78+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module1)) -O -wmo -DMODULE -module-name Module1 -emit-module -emit-module-path %t/Module1.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -enable-library-evolution
79+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module2)) -O -wmo -I%t -L%t -lModule1 %target-rpath(%t) -DMODULE2 -module-name Module2 -emit-module -emit-module-path %t/Module2.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -DEVOLUTION
80+
// RUN: %target-build-swift -O -wmo -I%t -L%t -lModule1 -DMAIN -o %t/main %target-rpath(%t) %s -swift-version 5 -DEVOLUTION
81+
// RUN: %target-codesign %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
82+
// RUN: %target-run %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
83+
84+
// Test the -enable-implicit-dynamic flag.
85+
86+
// RUN: %empty-directory(%t)
87+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module1)) -DMODULENODYNAMIC -module-name Module1 -emit-module -emit-module-path %t/Module1.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -Xfrontend -enable-implicit-dynamic -enable-library-evolution
88+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module2)) -I%t -L%t -lModule1 %target-rpath(%t) -DMODULE2 -module-name Module2 -emit-module -emit-module-path %t/Module2.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -DEVOLUTION
89+
// RUN: %target-build-swift -I%t -L%t -lModule1 -DMAIN -o %t/main %target-rpath(%t) %s -swift-version 5 -DEVOLUTION
90+
// RUN: %target-codesign %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
91+
// RUN: %target-run %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
92+
93+
// Test the -enable-implicit-dynamic flag in optimized wholemodule mode.
94+
// RUN: %empty-directory(%t)
95+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module1)) -O -wmo -DMODULENODYNAMIC -module-name Module1 -emit-module -emit-module-path %t/Module1.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -Xfrontend -enable-implicit-dynamic -enable-library-evolution
96+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module2)) -O -wmo -I%t -L%t -lModule1 %target-rpath(%t) -DMODULE2 -module-name Module2 -emit-module -emit-module-path %t/Module2.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -DEVOLUTION
97+
// RUN: %target-build-swift -O -wmo -I%t -L%t -lModule1 -DMAIN -o %t/main %target-rpath(%t) %s -swift-version 5 -DEVOLUTION
98+
// RUN: %target-codesign %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
99+
// RUN: %target-run %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
100+
49101

50102
// REQUIRES: executable_test
51103

@@ -82,8 +134,13 @@ func checkExpectedResults(forOriginalLibrary useOrig: Bool) {
82134
expectTrue(public_global_generic_func(Int.self) ==
83135
expectedResult(useOrig, "public_global_generic_func"))
84136

137+
// Designated initializers of resilient classes cannot be
138+
// dynamically replaced.
139+
#if !EVOLUTION
85140
expectTrue(PublicClass(x: 0).str ==
86141
expectedResult(useOrig, "public_class_init"))
142+
#endif
143+
87144
expectTrue(PublicClass().function() ==
88145
expectedResult(useOrig, "public_class_func"))
89146
expectTrue(PublicClass().finalFunction() ==

test/Interpreter/dynamic_replacement_opaque_result2.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
// RUN: %target-codesign %t/main
44
// RUN: %target-run %t/main | %FileCheck %s
55

6+
// RUN: %target-build-swift -o %t/main %target-rpath(%t) %s -swift-version 5 -enable-library-evolution
7+
// RUN: %target-codesign %t/main
8+
// RUN: %target-run %t/main | %FileCheck %s
9+
610
// REQUIRES: executable_test
711
// REQUIRES: swift_test_mode_optimize_none
812
// REQUIRES: CPU=arm64 || CPU=arm64e || CPU=x86_64

test/Interpreter/dynamic_replacement_protocol_self.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
// RUN: %empty-directory(%t)
2+
23
// RUN: %target-build-swift-dylib(%t/%target-library-name(TestModuleLinking)) -module-name TestModuleLinking -emit-module -emit-module-path %t/TestModuleLinking.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_protocol_self_orig.swift -Xfrontend -enable-private-imports -Xfrontend -enable-implicit-dynamic
34
// RUN: %target-build-swift -I%t -L%t -lTestModuleLinking -o %t/main %target-rpath(%t) %s -swift-version 5
45
// RUN: %target-codesign %t/main %t/%target-library-name(TestModuleLinking)
56
// RUN: %target-run %t/main %t/%target-library-name(TestModuleLinking) %t/%target-library-name(TestModuleLinking)
67

8+
// RUN: %target-build-swift-dylib(%t/%target-library-name(TestModuleLinking)) -module-name TestModuleLinking -emit-module -emit-module-path %t/TestModuleLinking.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_protocol_self_orig.swift -Xfrontend -enable-private-imports -Xfrontend -enable-implicit-dynamic -enable-library-evolution
9+
// RUN: %target-build-swift -I%t -L%t -lTestModuleLinking -o %t/main %target-rpath(%t) %s -swift-version 5
10+
// RUN: %target-codesign %t/main %t/%target-library-name(TestModuleLinking)
11+
// RUN: %target-run %t/main %t/%target-library-name(TestModuleLinking) %t/%target-library-name(TestModuleLinking)
12+
713
// N.B. We're not actually executing anything here - all we care about is
814
// if the linker is content.
915

test/attr/dynamicReplacement_library_evolution.swift

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)