Skip to content

Commit 781582b

Browse files
committed
IRGen: Add addLoweredTypeRef API and use it for capture and
box descriptors We want to substitute opaque result types in addTypeRef but when we pass SILFunctionTypes this would fail because AST type substitution does not support lowered SIL types. Instead add addLoweredTypeRef which substitutes based on SILTypes. rdar://54529445
1 parent 76fec49 commit 781582b

File tree

6 files changed

+126
-21
lines changed

6 files changed

+126
-21
lines changed

lib/IRGen/GenHeap.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1457,7 +1457,9 @@ class FixedBoxTypeInfoBase : public BoxTypeInfo {
14571457
}
14581458

14591459
auto boxDescriptor = IGF.IGM.getAddrOfBoxDescriptor(
1460-
boxedInterfaceType.getASTType());
1460+
boxedInterfaceType,
1461+
env ? env->getGenericSignature()->getCanonicalSignature()
1462+
: CanGenericSignature());
14611463
llvm::Value *allocation = IGF.emitUnmanagedAlloc(layout, name,
14621464
boxDescriptor);
14631465
Address rawAddr = project(IGF, allocation, boxedType);

lib/IRGen/GenReflection.cpp

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,35 @@ IRGenModule::getTypeRef(Type type, GenericSignature *genericSig,
174174
return getTypeRef(type->getCanonicalType(genericSig), role);
175175
}
176176

177+
std::pair<llvm::Constant *, unsigned>
178+
IRGenModule::getLoweredTypeRef(SILType loweredType,
179+
CanGenericSignature genericSig,
180+
MangledTypeRefRole role) {
181+
auto type =
182+
substOpaqueTypesWithUnderlyingTypes(loweredType, genericSig).getASTType();
183+
184+
switch (role) {
185+
case MangledTypeRefRole::DefaultAssociatedTypeWitness:
186+
case MangledTypeRefRole::Metadata:
187+
// Note that we're using all of the nominal types referenced by this type,
188+
// ensuring that we can always reconstruct type metadata from a mangled name
189+
// in-process.
190+
IRGen.noteUseOfTypeMetadata(type);
191+
break;
192+
193+
case MangledTypeRefRole::Reflection:
194+
// For reflection records only used for out-of-process reflection, we do not
195+
// need to force emission of runtime type metadata.
196+
IRGen.noteUseOfFieldDescriptors(type);
197+
break;
198+
}
199+
200+
IRGenMangler Mangler;
201+
auto SymbolicName = Mangler.mangleTypeForReflection(*this, type);
202+
return {getAddrOfStringForTypeRef(SymbolicName, role),
203+
SymbolicName.runtimeSizeInBytes()};
204+
}
205+
177206
std::pair<llvm::Constant *, unsigned>
178207
IRGenModule::getTypeRef(CanType type, MangledTypeRefRole role) {
179208
type = substOpaqueTypesWithUnderlyingTypes(type);
@@ -399,6 +428,15 @@ class ReflectionMetadataBuilder {
399428
addBuiltinTypeRefs(type);
400429
}
401430

431+
void
432+
addLoweredTypeRef(SILType loweredType,
433+
CanGenericSignature genericSig,
434+
MangledTypeRefRole role = MangledTypeRefRole::Reflection) {
435+
B.addRelativeAddress(
436+
IGM.getLoweredTypeRef(loweredType, genericSig, role).first);
437+
addBuiltinTypeRefs(loweredType.getASTType());
438+
}
439+
402440
/// Add a 32-bit relative offset to a mangled nominal type string
403441
/// in the typeref reflection section.
404442
///
@@ -725,17 +763,20 @@ void IRGenModule::emitBuiltinTypeMetadataRecord(CanType builtinType) {
725763
/// SIL @box. These look like closure contexts, but without any necessary
726764
/// bindings or metadata sources, and only a single captured value.
727765
class BoxDescriptorBuilder : public ReflectionMetadataBuilder {
728-
CanType BoxedType;
766+
SILType BoxedType;
767+
CanGenericSignature genericSig;
729768
public:
730-
BoxDescriptorBuilder(IRGenModule &IGM, CanType BoxedType)
731-
: ReflectionMetadataBuilder(IGM), BoxedType(BoxedType) {}
732-
769+
BoxDescriptorBuilder(IRGenModule &IGM, SILType BoxedType,
770+
CanGenericSignature genericSig)
771+
: ReflectionMetadataBuilder(IGM), BoxedType(BoxedType),
772+
genericSig(genericSig) {}
773+
733774
void layout() override {
734775
B.addInt32(1);
735776
B.addInt32(0); // Number of sources
736777
B.addInt32(0); // Number of generic bindings
737778

738-
addTypeRef(BoxedType);
779+
addLoweredTypeRef(BoxedType, genericSig);
739780
}
740781

741782
llvm::GlobalVariable *emit() {
@@ -896,8 +937,8 @@ class CaptureDescriptorBuilder : public ReflectionMetadataBuilder {
896937

897938
/// Get the interface types of all of the captured values, mapped out of the
898939
/// context of the callee we're partially applying.
899-
std::vector<CanType> getCaptureTypes() {
900-
std::vector<CanType> CaptureTypes;
940+
std::vector<SILType> getCaptureTypes() {
941+
std::vector<SILType> CaptureTypes;
901942

902943
for (auto ElementType : getElementTypes()) {
903944
auto SwiftType = ElementType.getASTType();
@@ -914,7 +955,8 @@ class CaptureDescriptorBuilder : public ReflectionMetadataBuilder {
914955
}
915956

916957
auto InterfaceType = SwiftType->mapTypeOutOfContext();
917-
CaptureTypes.push_back(InterfaceType->getCanonicalType());
958+
CaptureTypes.push_back(
959+
SILType::getPrimitiveObjectType(InterfaceType->getCanonicalType()));
918960
}
919961

920962
return CaptureTypes;
@@ -930,8 +972,11 @@ class CaptureDescriptorBuilder : public ReflectionMetadataBuilder {
930972

931973
// Now add typerefs of all of the captures.
932974
for (auto CaptureType : CaptureTypes) {
933-
addTypeRef(CaptureType);
934-
addBuiltinTypeRefs(CaptureType);
975+
addLoweredTypeRef(
976+
CaptureType,
977+
OrigCalleeType->getGenericSignature()
978+
? OrigCalleeType->getGenericSignature()->getCanonicalSignature()
979+
: CanGenericSignature());
935980
}
936981

937982
// Add the pairs that make up the generic param -> metadata source map
@@ -1025,11 +1070,12 @@ llvm::Constant *IRGenModule::getAddrOfFieldName(StringRef Name) {
10251070
}
10261071

10271072
llvm::Constant *
1028-
IRGenModule::getAddrOfBoxDescriptor(CanType BoxedType) {
1073+
IRGenModule::getAddrOfBoxDescriptor(SILType BoxedType,
1074+
CanGenericSignature genericSig) {
10291075
if (!IRGen.Opts.EnableReflectionMetadata)
10301076
return llvm::Constant::getNullValue(CaptureDescriptorPtrTy);
10311077

1032-
BoxDescriptorBuilder builder(*this, BoxedType);
1078+
BoxDescriptorBuilder builder(*this, BoxedType, genericSig);
10331079
auto var = builder.emit();
10341080

10351081
return llvm::ConstantExpr::getBitCast(var, CaptureDescriptorPtrTy);

lib/IRGen/IRGenModule.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ class IRGenModule {
823823

824824
CanType getRuntimeReifiedType(CanType type);
825825
CanType substOpaqueTypesWithUnderlyingTypes(CanType type);
826-
SILType substOpaqueTypesWithUnderlyingTypes(SILType type);
826+
SILType substOpaqueTypesWithUnderlyingTypes(SILType type, CanGenericSignature genericSig);
827827
std::pair<CanType, ProtocolConformanceRef>
828828
substOpaqueTypesWithUnderlyingTypes(CanType type,
829829
ProtocolConformanceRef conformance);
@@ -1071,7 +1071,11 @@ class IRGenModule {
10711071

10721072
std::pair<llvm::Constant *, unsigned>
10731073
getTypeRef(CanType type, MangledTypeRefRole role);
1074-
1074+
1075+
std::pair<llvm::Constant *, unsigned>
1076+
getLoweredTypeRef(SILType loweredType, CanGenericSignature genericSig,
1077+
MangledTypeRefRole role);
1078+
10751079
llvm::Constant *emitWitnessTableRefString(CanType type,
10761080
ProtocolConformanceRef conformance,
10771081
GenericSignature *genericSig,
@@ -1109,7 +1113,8 @@ class IRGenModule {
11091113
CanSILFunctionType substCalleeType,
11101114
SubstitutionMap subs,
11111115
const HeapLayout &layout);
1112-
llvm::Constant *getAddrOfBoxDescriptor(CanType boxedType);
1116+
llvm::Constant *getAddrOfBoxDescriptor(SILType boxedType,
1117+
CanGenericSignature genericSig);
11131118

11141119
/// Produce an associated type witness that refers to the given type.
11151120
llvm::Constant *getAssociatedTypeWitness(Type type, bool inProtocolContext);

lib/IRGen/MetadataRequest.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -526,14 +526,14 @@ CanType IRGenModule::substOpaqueTypesWithUnderlyingTypes(CanType type) {
526526
return type;
527527
}
528528

529-
SILType IRGenModule::substOpaqueTypesWithUnderlyingTypes(SILType type) {
529+
SILType IRGenModule::substOpaqueTypesWithUnderlyingTypes(
530+
SILType type, CanGenericSignature genericSig) {
530531
// Substitute away opaque types whose underlying types we're allowed to
531532
// assume are constant.
532533
if (type.getASTType()->hasOpaqueArchetype()) {
533534
ReplaceOpaqueTypesWithUnderlyingTypes replacer(getSwiftModule(),
534535
ResilienceExpansion::Maximal);
535-
type = type.subst(getSILModule(), replacer, replacer,
536-
CanGenericSignature(),
536+
type = type.subst(getSILModule(), replacer, replacer, genericSig,
537537
/*substitute opaque*/ true);
538538
}
539539

lib/IRGen/Outlining.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ void OutliningMetadataCollector::collectTypeMetadataForLayout(SILType type) {
3737

3838
// Substitute opaque types if allowed.
3939
auto origType = type;
40-
type = IGF.IGM.substOpaqueTypesWithUnderlyingTypes(type);
40+
type =
41+
IGF.IGM.substOpaqueTypesWithUnderlyingTypes(type, CanGenericSignature());
4142

4243
auto formalType = type.getASTType();
4344
auto &ti = IGF.IGM.getTypeInfoForLowered(formalType);

test/IRGen/opaque_result_type_substitution.swift

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -disable-availability-checking -emit-ir %s | %FileCheck %s
1+
// RUN: %target-swift-frontend -disable-availability-checking -emit-ir -primary-file %s | %FileCheck %s
22

33
protocol E {}
44

@@ -67,3 +67,54 @@ public func test2<S : Hashable, T, V>(_ s: S, _ t: T, _ v: V) {
6767
// CHECK: [[PAIR_OPAQUE:%.*]] = call swiftcc %swift.metadata_response @"$s31opaque_result_type_substitution4PairVMa"({{.*}}, %swift.type* [[MD]], %swift.type* [[MD]])
6868
// CHECK: [[MD2:%.*]] = extractvalue %swift.metadata_response [[PAIR_OPAQUE]], 0
6969
// CHECK: call {{.*}}* @"$s31opaque_result_type_substitution4PairVyAC6foobarQryFQOyxq__Qo_AEGr0_lWOh"({{.*}}, %swift.type* {{.*}}, %swift.type* [[MD2]])
70+
71+
public protocol Thing { }
72+
73+
public struct Thingy : Thing {}
74+
75+
public protocol KeyProto {
76+
associatedtype Value
77+
}
78+
79+
extension KeyProto {
80+
public static func transform3<T : Thing>(
81+
_ transform: @escaping (A<Self>) -> T)
82+
-> some Thing {
83+
return Thingy()
84+
}
85+
}
86+
87+
public struct A<Key : KeyProto> {}
88+
89+
extension A {
90+
public func transform2<T>(_ transform: @escaping (Key.Value) -> T) -> Thingy {
91+
return Thingy()
92+
}
93+
}
94+
95+
struct AKey : KeyProto {
96+
typealias Value = Int
97+
}
98+
99+
extension Thing {
100+
public func transform<K>(key _: K.Type = K.self, transform: @escaping (inout K) -> Void) -> some Thing {
101+
return Thingy()
102+
}
103+
}
104+
105+
struct OutterThing<Content : Thing> : Thing {
106+
let content: Content
107+
108+
init(_ c: Content) {
109+
self.content = c
110+
}
111+
112+
var body: some Thing {
113+
return AKey.transform3 { y in
114+
y.transform2 { i in
115+
self.content.transform(
116+
key: Thingy.self) { value in }
117+
}
118+
}
119+
}
120+
}

0 commit comments

Comments
 (0)