From 2373f22332e74e7314e8639e9af659202f2f118c Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 16 Apr 2018 23:49:14 -0700 Subject: [PATCH] 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 , but the more general problem remains. --- lib/IRGen/GenArchetype.cpp | 2 +- lib/IRGen/Outlining.cpp | 10 ++++--- test/IRGen/outlined_copy_addr.swift | 28 +++++++++++++++++-- .../Inputs/outlined-thunks-other.swift | 5 ++++ test/multifile/outlined-thunks.swift | 18 ++++++++++++ 5 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 test/multifile/Inputs/outlined-thunks-other.swift create mode 100644 test/multifile/outlined-thunks.swift diff --git a/lib/IRGen/GenArchetype.cpp b/lib/IRGen/GenArchetype.cpp index a74471d787b2a..9b04b4e87dfad 100644 --- a/lib/IRGen/GenArchetype.cpp +++ b/lib/IRGen/GenArchetype.cpp @@ -99,7 +99,7 @@ class OpaqueArchetypeTypeInfo void collectMetadataForOutlining(OutliningMetadataCollector &collector, SILType T) const override { // We'll need formal type metadata for this archetype. - collector.collectFormalTypeMetadata(T.getSwiftRValueType()); + collector.collectTypeMetadataForLayout(T); } }; diff --git a/lib/IRGen/Outlining.cpp b/lib/IRGen/Outlining.cpp index cae28be03c47a..c4c60dc6ed573 100644 --- a/lib/IRGen/Outlining.cpp +++ b/lib/IRGen/Outlining.cpp @@ -35,10 +35,14 @@ void OutliningMetadataCollector::collectTypeMetadataForLayout(SILType type) { return; } + CanType formalType = type.getSwiftRValueType(); + if (isa(IGF.IGM.getTypeInfoForLowered(formalType))) { + return; + } + // If the type is a legal formal type, add it as a formal type. // FIXME: does this force us to emit a more expensive metadata than we need // to? - CanType formalType = type.getSwiftRValueType(); if (formalType->isLegalFormalType()) { return collectFormalTypeMetadata(formalType); } @@ -53,9 +57,7 @@ void OutliningMetadataCollector::collectTypeMetadataForLayout(SILType type) { void OutliningMetadataCollector::collectFormalTypeMetadata(CanType type) { // If the type has no archetypes, we can emit it from scratch in the callee. - if (!type->hasArchetype()) { - return; - } + assert(type->hasArchetype()); auto key = LocalTypeDataKey(type, LocalTypeDataKind::forFormalTypeMetadata()); if (Values.count(key)) return; diff --git a/test/IRGen/outlined_copy_addr.swift b/test/IRGen/outlined_copy_addr.swift index a4973b40cc1a4..b68a57b5bab25 100644 --- a/test/IRGen/outlined_copy_addr.swift +++ b/test/IRGen/outlined_copy_addr.swift @@ -18,9 +18,33 @@ public struct StructWithBaseStruct { var elem2: BaseStruct } -// CHECK-LABEL: define hidden swiftcc void @"$S11outcopyaddr010StructWithbc4BaseB0V4elemAA0bcdB0VyxGvg"(%T11outcopyaddr014StructWithBaseB0V.0* noalias nocapture sret, %swift.type* %"StructWithStructWithBaseStruct", %T11outcopyaddr010StructWithbc4BaseB0V* noalias nocapture swiftself) -// CHECK: call %T11outcopyaddr014StructWithBaseB0V.0* @"$S11outcopyaddr014StructWithBaseB0VyxGAA9ChildProtRzlWOc" +// CHECK-LABEL: define hidden swiftcc void @"$S11outcopyaddr010StructWithbc4BaseB0V4elemAA0bcdB0VyxGvg"(%T11outcopyaddr014StructWithBaseB0V.4* noalias nocapture sret, %swift.type* %"StructWithStructWithBaseStruct", %T11outcopyaddr010StructWithbc4BaseB0V* noalias nocapture swiftself) +// CHECK: call %T11outcopyaddr014StructWithBaseB0V.4* @"$S11outcopyaddr014StructWithBaseB0VyxGAA9ChildProtRzlWOc" public struct StructWithStructWithBaseStruct { public typealias Element = T let elem: StructWithBaseStruct } + +protocol P { } + +class OtherPrivate { } + +struct OtherInternal { + var myPrivate: OtherPrivate? = nil +} + +struct MyPrivate { + var otherHelper: OtherInternal? = nil + + // CHECK-LABEL: define hidden swiftcc {{i32|i64}} @"$S11outcopyaddr9MyPrivateVyACyxGxcfC"(%swift.opaque* noalias nocapture, %swift.type* %T, i8** %T.P) {{.*}} { + // CHECK: call %T11outcopyaddr9MyPrivateV* @"$S11outcopyaddr9MyPrivateVyxGAA1PRzlWOh"(%T11outcopyaddr9MyPrivateV* %self) + // CHECK: ret + init(_: T) { } +} + +extension P { + func foo(data: Any) { + _ = MyPrivate(data as! Self) + } +} + diff --git a/test/multifile/Inputs/outlined-thunks-other.swift b/test/multifile/Inputs/outlined-thunks-other.swift new file mode 100644 index 0000000000000..95da4035497e4 --- /dev/null +++ b/test/multifile/Inputs/outlined-thunks-other.swift @@ -0,0 +1,5 @@ +private class OtherPrivate { } + +struct OtherInternal { + fileprivate var myPrivate: OtherPrivate? = nil +} diff --git a/test/multifile/outlined-thunks.swift b/test/multifile/outlined-thunks.swift new file mode 100644 index 0000000000000..b24a959ca7b81 --- /dev/null +++ b/test/multifile/outlined-thunks.swift @@ -0,0 +1,18 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift -emit-library -module-name outlined_thunks %S/Inputs/outlined-thunks-other.swift %s +// RUN: %target-build-swift -emit-library -module-name outlined_thunks -whole-module-optimization %S/Inputs/outlined-thunks-other.swift %s + +// rdar://problem/39470607 + +protocol P { } + +private struct MyPrivate { + private var otherHelper: OtherInternal? = nil + init(_: T) { } +} + +extension P { + func foo(data: Any) { + _ = MyPrivate(data as! Self) + } +}