Skip to content

Commit 39a65ab

Browse files
committed
IRGen: Outlined thunks don't need to receive fixed-size metadata
They're not used inside the thunk so it's a waste passing them in, and if they involve private types from a different translation unit we will get a linking error from referencing the metadata accessor function. Fixes the test case in <rdar://problem/39470607>, but the more general problem remains.
1 parent c4121c7 commit 39a65ab

File tree

5 files changed

+56
-7
lines changed

5 files changed

+56
-7
lines changed

lib/IRGen/GenArchetype.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class OpaqueArchetypeTypeInfo
9999
void collectMetadataForOutlining(OutliningMetadataCollector &collector,
100100
SILType T) const override {
101101
// We'll need formal type metadata for this archetype.
102-
collector.collectFormalTypeMetadata(T.getSwiftRValueType());
102+
collector.collectTypeMetadataForLayout(T);
103103
}
104104
};
105105

lib/IRGen/Outlining.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,14 @@ void OutliningMetadataCollector::collectTypeMetadataForLayout(SILType type) {
3535
return;
3636
}
3737

38+
CanType formalType = type.getSwiftRValueType();
39+
if (isa<FixedTypeInfo>(IGF.IGM.getTypeInfoForLowered(formalType))) {
40+
return;
41+
}
42+
3843
// If the type is a legal formal type, add it as a formal type.
3944
// FIXME: does this force us to emit a more expensive metadata than we need
4045
// to?
41-
CanType formalType = type.getSwiftRValueType();
4246
if (formalType->isLegalFormalType()) {
4347
return collectFormalTypeMetadata(formalType);
4448
}
@@ -53,9 +57,7 @@ void OutliningMetadataCollector::collectTypeMetadataForLayout(SILType type) {
5357

5458
void OutliningMetadataCollector::collectFormalTypeMetadata(CanType type) {
5559
// If the type has no archetypes, we can emit it from scratch in the callee.
56-
if (!type->hasArchetype()) {
57-
return;
58-
}
60+
assert(type->hasArchetype());
5961

6062
auto key = LocalTypeDataKey(type, LocalTypeDataKind::forFormalTypeMetadata());
6163
if (Values.count(key)) return;

test/IRGen/outlined_copy_addr.swift

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,33 @@ public struct StructWithBaseStruct<T: BaseProt> {
1818
var elem2: BaseStruct<Element>
1919
}
2020

21-
// CHECK-LABEL: define hidden swiftcc void @"$S11outcopyaddr010StructWithbc4BaseB0V4elemAA0bcdB0VyxGvg"(%T11outcopyaddr014StructWithBaseB0V.0* noalias nocapture sret, %swift.type* %"StructWithStructWithBaseStruct<T>", %T11outcopyaddr010StructWithbc4BaseB0V* noalias nocapture swiftself)
22-
// CHECK: call %T11outcopyaddr014StructWithBaseB0V.0* @"$S11outcopyaddr014StructWithBaseB0VyxGAA9ChildProtRzlWOc"
21+
// CHECK-LABEL: define hidden swiftcc void @"$S11outcopyaddr010StructWithbc4BaseB0V4elemAA0bcdB0VyxGvg"(%T11outcopyaddr014StructWithBaseB0V.4* noalias nocapture sret, %swift.type* %"StructWithStructWithBaseStruct<T>", %T11outcopyaddr010StructWithbc4BaseB0V* noalias nocapture swiftself)
22+
// CHECK: call %T11outcopyaddr014StructWithBaseB0V.4* @"$S11outcopyaddr014StructWithBaseB0VyxGAA9ChildProtRzlWOc"
2323
public struct StructWithStructWithBaseStruct<T: ChildProt> {
2424
public typealias Element = T
2525
let elem: StructWithBaseStruct<Element>
2626
}
27+
28+
protocol P { }
29+
30+
class OtherPrivate<T> { }
31+
32+
struct OtherInternal<T> {
33+
var myPrivate: OtherPrivate<T>? = nil
34+
}
35+
36+
struct MyPrivate<T: P> {
37+
var otherHelper: OtherInternal<T>? = nil
38+
39+
// CHECK-LABEL: define hidden swiftcc {{i32|i64}} @"$S11outcopyaddr9MyPrivateVyACyxGxcfC"(%swift.opaque* noalias nocapture, %swift.type* %T, i8** %T.P) {{.*}} {
40+
// CHECK: call %T11outcopyaddr9MyPrivateV* @"$S11outcopyaddr9MyPrivateVyxGAA1PRzlWOh"(%T11outcopyaddr9MyPrivateV* %self)
41+
// CHECK: ret
42+
init(_: T) { }
43+
}
44+
45+
extension P {
46+
func foo(data: Any) {
47+
_ = MyPrivate(data as! Self)
48+
}
49+
}
50+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
private class OtherPrivate<T> { }
2+
3+
struct OtherInternal<T> {
4+
fileprivate var myPrivate: OtherPrivate<T>? = nil
5+
}

test/multifile/outlined-thunks.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -emit-library -module-name outlined_thunks %S/Inputs/outlined-thunks-other.swift %s
3+
// RUN: %target-build-swift -emit-library -module-name outlined_thunks -whole-module-optimization %S/Inputs/outlined-thunks-other.swift %s
4+
5+
// rdar://problem/39470607
6+
7+
protocol P { }
8+
9+
private struct MyPrivate<T: P> {
10+
private var otherHelper: OtherInternal<T>? = nil
11+
init(_: T) { }
12+
}
13+
14+
extension P {
15+
func foo(data: Any) {
16+
_ = MyPrivate(data as! Self)
17+
}
18+
}

0 commit comments

Comments
 (0)