Skip to content

Commit 88ad116

Browse files
committed
SILGen/IRGen: Lower protocol witness thunks for ObjC lightweight generics as pseudogeneric.
Fixes rdar://problem/28873860, where we would miscompile when lightweight generic classes were extended to conform to Swift protocols because we tried to emit parameters for the class's generic parameters for the witness entry points. Prevent this by lowering the witness into a pseudogeneric function in SILGen, and teaching IRGen to do the right thing for a witness with pseudogeneric parameters.
1 parent 4b0e0b2 commit 88ad116

File tree

6 files changed

+33
-4
lines changed

6 files changed

+33
-4
lines changed

include/swift/SIL/SILType.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,7 @@ NON_SIL_TYPE(LValue)
548548
CanSILFunctionType getNativeSILFunctionType(SILModule &M,
549549
Lowering::AbstractionPattern orig,
550550
CanAnyFunctionType substInterface,
551+
Optional<SILDeclRef> constant = None,
551552
SILDeclRef::Kind kind = SILDeclRef::Kind::Func);
552553

553554
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SILType T) {

lib/IRGen/GenProto.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,18 @@ PolymorphicConvention::PolymorphicConvention(IRGenModule &IGM,
143143
: IGM(IGM), M(*IGM.getSwiftModule()), FnType(fnType) {
144144
initGenerics();
145145

146+
auto rep = fnType->getRepresentation();
147+
146148
if (fnType->isPseudogeneric()) {
149+
// Protocol witnesses still get Self metadata no matter what. The type
150+
// parameters of Self are pseudogeneric, though.
151+
if (rep == SILFunctionTypeRepresentation::WitnessMethod)
152+
considerWitnessSelf(fnType);
153+
147154
addPseudogenericFulfillments();
148155
return;
149156
}
150157

151-
auto rep = fnType->getRepresentation();
152-
153158
if (rep == SILFunctionTypeRepresentation::WitnessMethod) {
154159
// Protocol witnesses always derive all polymorphic parameter
155160
// information from the Self argument. We also *cannot* consider other

lib/SIL/SILFunctionType.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,7 @@ static CanSILFunctionType getNativeSILFunctionType(SILModule &M,
10311031
CanSILFunctionType swift::getNativeSILFunctionType(SILModule &M,
10321032
AbstractionPattern origType,
10331033
CanAnyFunctionType substInterfaceType,
1034+
Optional<SILDeclRef> constant,
10341035
SILDeclRef::Kind kind) {
10351036
AnyFunctionType::ExtInfo extInfo;
10361037

@@ -1043,7 +1044,7 @@ CanSILFunctionType swift::getNativeSILFunctionType(SILModule &M,
10431044
extInfo = substInterfaceType->getExtInfo();
10441045
}
10451046
return ::getNativeSILFunctionType(M, origType, substInterfaceType,
1046-
extInfo, None, kind);
1047+
extInfo, constant, kind);
10471048
}
10481049

10491050
//===----------------------------------------------------------------------===//
@@ -2066,6 +2067,7 @@ SILConstantInfo TypeConverter::getConstantOverrideInfo(SILDeclRef derived,
20662067
// Build the SILFunctionType for the vtable thunk.
20672068
CanSILFunctionType fnTy = getNativeSILFunctionType(M, basePattern,
20682069
overrideLoweredInterfaceTy,
2070+
derived,
20692071
derived.kind);
20702072

20712073
{

lib/SILGen/SILGenDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1889,7 +1889,8 @@ SILGenModule::emitProtocolWitness(ProtocolConformance *conformance,
18891889
// Lower the witness thunk type with the requirement's abstraction level.
18901890
auto witnessSILFnType = getNativeSILFunctionType(M,
18911891
AbstractionPattern(reqtOrigTy),
1892-
reqtSubstTy);
1892+
reqtSubstTy,
1893+
witness);
18931894

18941895
// Mangle the name of the witness thunk.
18951896
std::string nameBuffer;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@import Foundation;
2+
3+
@interface Foo <T> : NSObject
4+
5+
- (void)foo;
6+
7+
@end
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen %s -import-objc-header %S/Inputs/objc_generic_protocol_conformance.h | %FileCheck --check-prefix=SIL %s
2+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-ir %s -import-objc-header %S/Inputs/objc_generic_protocol_conformance.h | %FileCheck --check-prefix=IR %s
3+
4+
// REQUIRES: objc_interop
5+
6+
protocol P {
7+
func foo()
8+
}
9+
10+
extension Foo: P {}
11+
12+
// SIL-LABEL: sil hidden [transparent] [thunk] @_TTWuRxs9AnyObjectrGCSo3Foo{{.*}} @pseudogeneric
13+
// IR-LABEL: define hidden void @_TTWuRxs9AnyObjectrGCSo3Foo{{.*}}(%CSo3Foo** noalias nocapture dereferenceable(8), %swift.type*{{( %Self)?}}, i8**{{( %SelfWitnessTable)?}})

0 commit comments

Comments
 (0)