Skip to content

Commit 7e0e5f1

Browse files
committed
IRGen: Clang type lowering for subclass existentials
It looks like this is really only used in one place, the "extended encoding" for @objc protocol metadata. If it wasn't for that, we could just lower all class and existential types as 'id'.
1 parent 8037458 commit 7e0e5f1

File tree

2 files changed

+29
-13
lines changed

2 files changed

+29
-13
lines changed

lib/IRGen/GenClangType.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -599,27 +599,39 @@ clang::CanQualType GenClangType::visitSILBlockStorageType(CanSILBlockStorageType
599599

600600
clang::CanQualType GenClangType::visitProtocolCompositionType(
601601
CanProtocolCompositionType type) {
602+
auto &clangCtx = getClangASTContext();
603+
602604
// FIXME. Eventually, this will have its own helper routine.
603605
SmallVector<const clang::ObjCProtocolDecl *, 4> Protocols;
604606
auto layout = type.getExistentialLayout();
605-
assert(layout.requiresClass && "Cannot represent opaque existential in Clang");
606-
assert(!layout.superclass && "Subclass existentials not supported here yet");
607+
assert(layout.isObjC() && "Cannot represent opaque existential in Clang");
608+
609+
auto superclassTy = clangCtx.ObjCBuiltinIdTy;
610+
if (layout.superclass) {
611+
superclassTy = clangCtx.getCanonicalType(
612+
cast<clang::ObjCObjectPointerType>(
613+
Converter.convert(IGM, CanType(layout.superclass)))
614+
->getPointeeType());
615+
}
616+
607617
for (Type t : layout.getProtocols()) {
608618
auto opt = cast<clang::ObjCObjectPointerType>(
609619
Converter.convert(IGM, CanType(t)));
610620
for (auto p : opt->quals())
611621
Protocols.push_back(p);
612622
}
613623

614-
auto &clangCtx = getClangASTContext();
615624
if (Protocols.empty())
616-
return getClangIdType(clangCtx);
625+
return superclassTy;
626+
617627
// id<protocol-list>
618-
clang::ObjCProtocolDecl **ProtoQuals = new(clangCtx) clang::ObjCProtocolDecl*[Protocols.size()];
619-
memcpy(ProtoQuals, Protocols.data(), sizeof(clang::ObjCProtocolDecl*)*Protocols.size());
620-
auto clangType = clangCtx.getObjCObjectType(clangCtx.ObjCBuiltinIdTy,
621-
ProtoQuals,
622-
Protocols.size());
628+
clang::ObjCProtocolDecl **ProtoQuals =
629+
new(clangCtx) clang::ObjCProtocolDecl*[Protocols.size()];
630+
memcpy(ProtoQuals, Protocols.data(),
631+
sizeof(clang::ObjCProtocolDecl*)*Protocols.size());
632+
auto clangType = clangCtx.getObjCObjectType(superclassTy,
633+
ProtoQuals,
634+
Protocols.size());
623635
auto ptrTy = clangCtx.getObjCObjectPointerType(clangType);
624636
return clangCtx.getCanonicalType(ptrTy);
625637
}

test/IRGen/objc_type_encoding.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: rm -rf %t && mkdir -p %t
22
// RUN: %build-irgen-test-overlays
3-
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) %s -emit-ir -disable-objc-attr-requires-foundation-module | %FileCheck %s -check-prefix=CHECK-%target-os
3+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) %s -emit-ir -disable-objc-attr-requires-foundation-module -enable-experimental-subclass-existentials | %FileCheck %s -check-prefix=CHECK-%target-os
44

55
// REQUIRES: CPU=x86_64
66
// REQUIRES: objc_interop
@@ -163,17 +163,21 @@ import gizmo
163163
func myMethod2(_ arg : NSRuncing & NSFunging)
164164
func readWithAuthorization(_ authData : Gizmo, reply : (NSView, NSSpoon) -> Void)
165165
func doSomething(_ context: MyCustomObject)
166+
func subclassComposition(_: MyCustomObject & NSRuncing & NSFunging)
166167
}
167168

168169
// CHECK-macosx: [[ENC1:@.*]] = private unnamed_addr constant [35 x i8] c"v24@0:8@\22<NSFunging><NSRuncing>\2216\00"
169170
// CHECK-macosx: [[ENC2:@.*]] = private unnamed_addr constant [46 x i8] c"v32@0:8@\22Gizmo\2216@?<v@?@\22NSView\22@\22NSSpoon\22>24\00"
170171
// CHECK-macosx: [[ENC3:@.*]] = private unnamed_addr constant [53 x i8] c"v24@0:8@\22_TtC18objc_type_encoding14MyCustomObject\2216\00"
171-
// CHECK-macosx: @_PROTOCOL_METHOD_TYPES__TtP18objc_type_encoding10MyProtocol_ = private constant [3 x i8*] [i8* getelementptr inbounds ([35 x i8], [35 x i8]* [[ENC1]], i64 0, i64 0), i8* getelementptr inbounds ([46 x i8], [46 x i8]* [[ENC2]], i64 0, i64 0), i8* getelementptr inbounds ([53 x i8], [53 x i8]* [[ENC3]], i64 0, i64 0)]
172+
// CHECK-macosx: [[ENC4:@.*]] = private unnamed_addr constant [75 x i8] c"v24@0:8@\22_TtC18objc_type_encoding14MyCustomObject<NSFunging><NSRuncing>\2216\00"
173+
// CHECK-macosx: @_PROTOCOL_METHOD_TYPES__TtP18objc_type_encoding10MyProtocol_ = private constant [4 x i8*] [i8* getelementptr inbounds ([35 x i8], [35 x i8]* [[ENC1]], i64 0, i64 0), i8* getelementptr inbounds ([46 x i8], [46 x i8]* [[ENC2]], i64 0, i64 0), i8* getelementptr inbounds ([53 x i8], [53 x i8]* [[ENC3]], i64 0, i64 0), i8* getelementptr inbounds ([75 x i8], [75 x i8]* [[ENC4]], i64 0, i64 0)]
172174
// CHECK-ios: [[ENC1:@.*]] = private unnamed_addr constant [35 x i8] c"v24@0:8@\22<NSFunging><NSRuncing>\2216\00"
173175
// CHECK-ios: [[ENC2:@.*]] = private unnamed_addr constant [46 x i8] c"v32@0:8@\22Gizmo\2216@?<v@?@\22NSView\22@\22NSSpoon\22>24\00"
174176
// CHECK-ios: [[ENC3:@.*]] = private unnamed_addr constant [53 x i8] c"v24@0:8@\22_TtC18objc_type_encoding14MyCustomObject\2216\00"
175-
// CHECK-ios: @_PROTOCOL_METHOD_TYPES__TtP18objc_type_encoding10MyProtocol_ = private constant [3 x i8*] [i8* getelementptr inbounds ([35 x i8], [35 x i8]* [[ENC1]], i64 0, i64 0), i8* getelementptr inbounds ([46 x i8], [46 x i8]* [[ENC2]], i64 0, i64 0), i8* getelementptr inbounds ([53 x i8], [53 x i8]* [[ENC3]], i64 0, i64 0)]
177+
// CHECK-ios: [[ENC4:@.*]] = private unnamed_addr constant [75 x i8] c"v24@0:8@\22_TtC18objc_type_encoding14MyCustomObject<NSFunging><NSRuncing>\2216\00"
178+
// CHECK-ios: @_PROTOCOL_METHOD_TYPES__TtP18objc_type_encoding10MyProtocol_ = private constant [4 x i8*] [i8* getelementptr inbounds ([35 x i8], [35 x i8]* [[ENC1]], i64 0, i64 0), i8* getelementptr inbounds ([46 x i8], [46 x i8]* [[ENC2]], i64 0, i64 0), i8* getelementptr inbounds ([53 x i8], [53 x i8]* [[ENC3]], i64 0, i64 0), i8* getelementptr inbounds ([75 x i8], [75 x i8]* [[ENC4]], i64 0, i64 0)]
176179
// CHECK-tvos: [[ENC1:@.*]] = private unnamed_addr constant [35 x i8] c"v24@0:8@\22<NSFunging><NSRuncing>\2216\00"
177180
// CHECK-tvos: [[ENC2:@.*]] = private unnamed_addr constant [46 x i8] c"v32@0:8@\22Gizmo\2216@?<v@?@\22NSView\22@\22NSSpoon\22>24\00"
178181
// CHECK-tvos: [[ENC3:@.*]] = private unnamed_addr constant [53 x i8] c"v24@0:8@\22_TtC18objc_type_encoding14MyCustomObject\2216\00"
179-
// CHECK-tvos: @_PROTOCOL_METHOD_TYPES__TtP18objc_type_encoding10MyProtocol_ = private constant [3 x i8*] [i8* getelementptr inbounds ([35 x i8], [35 x i8]* [[ENC1]], i64 0, i64 0), i8* getelementptr inbounds ([46 x i8], [46 x i8]* [[ENC2]], i64 0, i64 0), i8* getelementptr inbounds ([53 x i8], [53 x i8]* [[ENC3]], i64 0, i64 0)]
182+
// CHECK-tvos: [[ENC4:@.*]] = private unnamed_addr constant [75 x i8] c"v24@0:8@\22_TtC18objc_type_encoding14MyCustomObject<NSFunging><NSRuncing>\2216\00"
183+
// CHECK-tvos: @_PROTOCOL_METHOD_TYPES__TtP18objc_type_encoding10MyProtocol_ = private constant [4 x i8*] [i8* getelementptr inbounds ([35 x i8], [35 x i8]* [[ENC1]], i64 0, i64 0), i8* getelementptr inbounds ([46 x i8], [46 x i8]* [[ENC2]], i64 0, i64 0), i8* getelementptr inbounds ([53 x i8], [53 x i8]* [[ENC3]], i64 0, i64 0), i8* getelementptr inbounds ([75 x i8], [75 x i8]* [[ENC4]], i64 0, i64 0)]

0 commit comments

Comments
 (0)