Skip to content

Commit 0b93060

Browse files
committed
NCGenerics: fix runtime demangling strategy
We can obtain metadata on older runtimes for a concrete type with a Copyable generic parameter via demangling. But if the generic argument is noncopyable, we should use the metadata response strategy instead. resolves rdar://131337585
1 parent 84a0779 commit 0b93060

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

lib/IRGen/GenReflection.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,39 @@ getRuntimeVersionThatSupportsDemanglingType(CanType type) {
226226
// involving them.
227227
}
228228

229+
// Any nominal type that has an inverse requirement in its generic signature
230+
// uses NoncopyableGenerics. Since inverses are mangled into symbols,
231+
// a Swift 6.0+ runtime is needed to demangle them.
232+
if (auto nominalTy = dyn_cast<NominalOrBoundGenericNominalType>(t)) {
233+
auto *nom = nominalTy->getDecl();
234+
if (auto sig = nom->getGenericSignature()) {
235+
SmallVector<InverseRequirement, 2> inverses;
236+
SmallVector<Requirement, 2> reqs;
237+
sig->getRequirementsWithInverses(reqs, inverses);
238+
if (!inverses.empty()) {
239+
if (!isa<BoundGenericType>(nominalTy))
240+
return addRequirement(Swift_6_0);
241+
242+
// If all of the generic arguments in this BGT are Copyable/Escapable,
243+
// then it should not require the newer runtime.
244+
auto boundTy = cast<BoundGenericType>(nominalTy);
245+
for (auto arg : boundTy->getGenericArgs()) {
246+
for (auto ip : InvertibleProtocolSet::allKnown()) {
247+
switch (ip) {
248+
case InvertibleProtocolKind::Copyable:
249+
if (arg->isNoncopyable())
250+
return addRequirement(Swift_6_0);
251+
break;
252+
case InvertibleProtocolKind::Escapable:
253+
if (!arg->isEscapable())
254+
return addRequirement(Swift_6_0);
255+
}
256+
}
257+
}
258+
}
259+
}
260+
}
261+
229262
return false;
230263
});
231264

@@ -358,6 +391,7 @@ getTypeRefByFunction(IRGenModule &IGM,
358391
Address(bindingsBufPtr, IGM.Int8Ty, IGM.getPointerAlignment()),
359392
MetadataState::Complete, subs);
360393

394+
substT = substT.getReferenceStorageReferent();
361395
auto ret = IGF.emitTypeMetadataRef(substT);
362396
IGF.Builder.CreateRet(ret);
363397
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %swift-frontend %s -swift-version 6 -module-name main -emit-ir -o %t/new.ir
3+
// RUN: %FileCheck %s --check-prefix=NEW < %t/new.ir
4+
// RUN: %target-swift-frontend %s -target %target-cpu-apple-macosx11 -module-name main -emit-ir -o %t/old.ir
5+
// RUN: %FileCheck %s --check-prefix=OLD < %t/old.ir
6+
7+
// Check that we add extra type metadata accessors for types with generic
8+
// parameters that have an inverse. These are used instead of using demangling
9+
// cache variables since old runtimes cannot synthesize type metadata based on
10+
// the new mangling.
11+
12+
// RUN: %target-build-swift -target %target-cpu-apple-macosx11 %s -o %t/test_mangling
13+
// RUN: %target-run %t/test_mangling | %FileCheck %s
14+
15+
// REQUIRES: OS=macosx
16+
// REQUIRES: executable_test
17+
18+
19+
// This type's generic parameter is noncopyable, so older runtimes can't
20+
// demangle the type's name to build the metadata.
21+
struct Foo<T: ~Copyable>: ~Copyable {
22+
mutating func bar(_ i: Int) { print("Foo.bar(\(i))") }
23+
}
24+
25+
func test() {
26+
var foo = Foo<Int>()
27+
foo.bar(1)
28+
}
29+
test()
30+
// CHECK: Foo.bar(1)
31+
32+
// NEW: define hidden swiftcc void @"$s4main4testyyF"()
33+
// NEW-NOT: %swift.metadata_response
34+
// NEW: call ptr @__swift_instantiateConcreteTypeFromMangledName(ptr @"$s4main3FooVySiGMD")
35+
// NEW-NOT: %swift.metadata_response
36+
// NEW: }
37+
38+
// OLD: define hidden swiftcc void @"$s4main4testyyF"()
39+
// OLD-NOT: %swift.metadata_response
40+
// OLD: call ptr @__swift_instantiateConcreteTypeFromMangledName(ptr @"$s4main3FooVySiGMD")
41+
// OLD-NOT: %swift.metadata_response
42+
// OLD: }
43+
44+
struct NC: ~Copyable {}
45+
46+
// NEW: define hidden swiftcc void @"$s4main10testWithNCyyF"()
47+
// NEW-NOT: %swift.metadata_response
48+
// NEW: call ptr @__swift_instantiateConcreteTypeFromMangledName(ptr @"$s4main3FooVyAA2NCVGMD")
49+
// NEW-NOT: %swift.metadata_response
50+
// NEW: }
51+
52+
// OLD: define hidden swiftcc void @"$s4main10testWithNCyyF"()
53+
// OLD-NOT: __swift_instantiateConcreteTypeFromMangledName
54+
// OLD: call swiftcc %swift.metadata_response @"$s4main3FooVyAA2NCVGMa"(i64 0)
55+
// OLD-NOT: __swift_instantiateConcreteTypeFromMangledName
56+
// OLD: }
57+
func testWithNC() {
58+
var foo = Foo<NC>()
59+
foo.bar(2)
60+
}
61+
testWithNC()
62+
// CHECK: Foo.bar(2)
63+
64+
65+
// NEW: define hidden swiftcc void @"$s4main17testWithNCGenericyyxnRi_zlF"
66+
// NEW-NOT: __swift_instantiateConcreteTypeFromMangledName
67+
// NEW: call swiftcc %swift.metadata_response @"$s4main3FooVMa"
68+
// NEW-NOT: __swift_instantiateConcreteTypeFromMangledName
69+
// NEW: }
70+
71+
// OLD: define hidden swiftcc void @"$s4main17testWithNCGenericyyxnRi_zlF"
72+
// OLD-NOT: __swift_instantiateConcreteTypeFromMangledName
73+
// OLD: call swiftcc %swift.metadata_response @"$s4main3FooVMa"
74+
// OLD-NOT: __swift_instantiateConcreteTypeFromMangledName
75+
// OLD: }
76+
func testWithNCGeneric<T: ~Copyable>(_ t: consuming T) {
77+
var foo = Foo<T>()
78+
foo.bar(3)
79+
}
80+
testWithNCGeneric(Foo<NC>())
81+
// CHECK: Foo.bar(3)
82+
83+
84+
// This type does not need a Swift 6.0 runtime, despite being noncopyable,
85+
// because it doesn't have a noncopyable generic parameter.
86+
struct JustNoncopyable<T>: ~Copyable {
87+
mutating func bar() { print("JustNoncopyable.bar") }
88+
}
89+
90+
func testNonGeneric() {
91+
var ng = JustNoncopyable<Int>()
92+
ng.bar()
93+
}
94+
testNonGeneric()
95+
// CHECK: JustNoncopyable.bar
96+
97+
// NEW: define hidden swiftcc void @"$s4main14testNonGenericyyF"()
98+
// NEW-NOT: %swift.metadata_response
99+
// NEW: call ptr @__swift_instantiateConcreteTypeFromMangledName(ptr @"$s4main15JustNoncopyableVySiGMD")
100+
// NEW-NOT: %swift.metadata_response
101+
// NEW: }
102+
103+
// OLD: define hidden swiftcc void @"$s4main14testNonGenericyyF"()
104+
// OLD-NOT: %swift.metadata_response
105+
// OLD: call ptr @__swift_instantiateConcreteTypeFromMangledName(ptr @"$s4main15JustNoncopyableVySiGMD")
106+
// OLD-NOT: %swift.metadata_response
107+
// OLD: }

0 commit comments

Comments
 (0)