Skip to content

Commit 6cb0e16

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 3c260bb commit 6cb0e16

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
@@ -561,6 +561,7 @@ NON_SIL_TYPE(LValue)
561561
CanSILFunctionType getNativeSILFunctionType(SILModule &M,
562562
Lowering::AbstractionPattern orig,
563563
CanAnyFunctionType substInterface,
564+
Optional<SILDeclRef> constant = None,
564565
SILDeclRef::Kind kind = SILDeclRef::Kind::Func);
565566

566567
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
@@ -1021,6 +1021,7 @@ static CanSILFunctionType getNativeSILFunctionType(SILModule &M,
10211021
CanSILFunctionType swift::getNativeSILFunctionType(SILModule &M,
10221022
AbstractionPattern origType,
10231023
CanAnyFunctionType substInterfaceType,
1024+
Optional<SILDeclRef> constant,
10241025
SILDeclRef::Kind kind) {
10251026
AnyFunctionType::ExtInfo extInfo;
10261027

@@ -1033,7 +1034,7 @@ CanSILFunctionType swift::getNativeSILFunctionType(SILModule &M,
10331034
extInfo = substInterfaceType->getExtInfo();
10341035
}
10351036
return ::getNativeSILFunctionType(M, origType, substInterfaceType,
1036-
extInfo, None, kind);
1037+
extInfo, constant, kind);
10371038
}
10381039

10391040
//===----------------------------------------------------------------------===//
@@ -2070,6 +2071,7 @@ SILConstantInfo TypeConverter::getConstantOverrideInfo(SILDeclRef derived,
20702071
// Build the SILFunctionType for the vtable thunk.
20712072
CanSILFunctionType fnTy = getNativeSILFunctionType(M, basePattern,
20722073
overrideLoweredInterfaceTy,
2074+
derived,
20732075
derived.kind);
20742076

20752077
{

lib/SILGen/SILGenDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1737,7 +1737,8 @@ SILGenModule::emitProtocolWitness(ProtocolConformance *conformance,
17371737
// Lower the witness type with the requirement's abstraction level.
17381738
auto witnessSILFnType = getNativeSILFunctionType(M,
17391739
AbstractionPattern(reqtOrigTy),
1740-
reqtSubstTy);
1740+
reqtSubstTy,
1741+
witness);
17411742

17421743
// Mangle the name of the witness thunk.
17431744
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({{4|8}}), %swift.type*{{( %Self)?}}, i8**{{( %SelfWitnessTable)?}})

0 commit comments

Comments
 (0)