Skip to content

Commit 259c988

Browse files
committed
IRGen: Use clang's objc encoding for types when there is a ClangNode
We do this because the swift code does not support all attributes and does not support generics. rdar://60474785
1 parent a1fdad7 commit 259c988

File tree

3 files changed

+71
-11
lines changed

3 files changed

+71
-11
lines changed

lib/IRGen/GenObjC.cpp

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,29 @@ static llvm::Constant *getObjCEncodingForMethodType(IRGenModule &IGM,
11161116
ptrSize * 2, useExtendedEncoding);
11171117
}
11181118

1119+
static llvm::Constant *
1120+
getObjectEncodingFromClangNode(IRGenModule &IGM, Decl *d,
1121+
bool useExtendedEncoding) {
1122+
// Use the clang node's encoding if there is a clang node.
1123+
if (d->getClangNode()) {
1124+
auto clangDecl = d->getClangNode().castAsDecl();
1125+
auto &clangASTContext = IGM.getClangASTContext();
1126+
std::string typeStr;
1127+
if (auto objcMethodDecl = dyn_cast<clang::ObjCMethodDecl>(clangDecl)) {
1128+
typeStr = clangASTContext.getObjCEncodingForMethodDecl(
1129+
objcMethodDecl, useExtendedEncoding /*extended*/);
1130+
}
1131+
if (auto objcPropertyDecl = dyn_cast<clang::ObjCPropertyDecl>(clangDecl)) {
1132+
typeStr = clangASTContext.getObjCEncodingForPropertyDecl(objcPropertyDecl,
1133+
nullptr);
1134+
}
1135+
if (!typeStr.empty()) {
1136+
return IGM.getAddrOfGlobalString(typeStr.c_str());
1137+
}
1138+
}
1139+
return nullptr;
1140+
}
1141+
11191142
/// Emit the components of an Objective-C method descriptor: its selector,
11201143
/// type encoding, and IMP pointer.
11211144
ObjCMethodDescriptor
@@ -1128,11 +1151,18 @@ irgen::emitObjCMethodDescriptorParts(IRGenModule &IGM,
11281151
/// The first element is the selector.
11291152
descriptor.selectorRef = IGM.getAddrOfObjCMethodName(selector.str());
11301153

1131-
/// The second element is the method signature. A method signature is made of
1132-
/// the return type @encoding and every parameter type @encoding, glued with
1133-
/// numbers that used to represent stack offsets for each of these elements.
1134-
CanSILFunctionType methodType = getObjCMethodType(IGM, method);
1135-
descriptor.typeEncoding = getObjCEncodingForMethodType(IGM, methodType, /*extended*/false);
1154+
if (auto e =
1155+
getObjectEncodingFromClangNode(IGM, method, false /*extended*/)) {
1156+
descriptor.typeEncoding = e;
1157+
} else {
1158+
/// The second element is the method signature. A method signature is made
1159+
/// of the return type @encoding and every parameter type @encoding, glued
1160+
/// with numbers that used to represent stack offsets for each of these
1161+
/// elements.
1162+
CanSILFunctionType methodType = getObjCMethodType(IGM, method);
1163+
descriptor.typeEncoding =
1164+
getObjCEncodingForMethodType(IGM, methodType, /*extended*/ false);
1165+
}
11361166

11371167
/// The third element is the method implementation pointer.
11381168
if (!concrete) {
@@ -1191,10 +1221,17 @@ irgen::emitObjCGetterDescriptorParts(IRGenModule &IGM,
11911221
Selector getterSel(subscript, Selector::ForGetter);
11921222
ObjCMethodDescriptor descriptor{};
11931223
descriptor.selectorRef = IGM.getAddrOfObjCMethodName(getterSel.str());
1194-
auto methodTy = getObjCMethodType(IGM,
1195-
subscript->getOpaqueAccessor(AccessorKind::Get));
1196-
descriptor.typeEncoding = getObjCEncodingForMethodType(IGM, methodTy,
1197-
/*extended*/false);
1224+
1225+
if (auto e =
1226+
getObjectEncodingFromClangNode(IGM, subscript, false /*extended*/)) {
1227+
descriptor.typeEncoding = e;
1228+
} else {
1229+
auto methodTy =
1230+
getObjCMethodType(IGM, subscript->getOpaqueAccessor(AccessorKind::Get));
1231+
descriptor.typeEncoding = getObjCEncodingForMethodType(IGM, methodTy,
1232+
/*extended*/ false);
1233+
}
1234+
11981235
descriptor.silFunction = nullptr;
11991236
descriptor.impl = getObjCGetterPointer(IGM, subscript,
12001237
descriptor.silFunction);
@@ -1266,8 +1303,13 @@ irgen::emitObjCSetterDescriptorParts(IRGenModule &IGM,
12661303
descriptor.selectorRef = IGM.getAddrOfObjCMethodName(setterSel.str());
12671304
auto methodTy = getObjCMethodType(IGM,
12681305
subscript->getOpaqueAccessor(AccessorKind::Set));
1269-
descriptor.typeEncoding = getObjCEncodingForMethodType(IGM, methodTy,
1270-
/*extended*/false);
1306+
if (auto e =
1307+
getObjectEncodingFromClangNode(IGM, subscript, false /*extended*/)) {
1308+
descriptor.typeEncoding = e;
1309+
} else {
1310+
descriptor.typeEncoding = getObjCEncodingForMethodType(IGM, methodTy,
1311+
/*extended*/ false);
1312+
}
12711313
descriptor.silFunction = nullptr;
12721314
descriptor.impl = getObjCSetterPointer(IGM, subscript,
12731315
descriptor.silFunction);
@@ -1359,9 +1401,15 @@ void irgen::emitObjCIVarInitDestroyDescriptor(IRGenModule &IGM,
13591401
buildMethodDescriptor(IGM, descriptors, descriptor);
13601402
}
13611403

1404+
13621405
llvm::Constant *
13631406
irgen::getMethodTypeExtendedEncoding(IRGenModule &IGM,
13641407
AbstractFunctionDecl *method) {
1408+
// Use the clang node's encoding if there is a clang node.
1409+
if (auto e = getObjectEncodingFromClangNode(IGM, method, true /*extended*/)) {
1410+
return e;
1411+
}
1412+
13651413
CanSILFunctionType methodType = getObjCMethodType(IGM, method);
13661414
return getObjCEncodingForMethodType(IGM, methodType, true/*Extended*/);
13671415
}

test/IRGen/Inputs/usr/include/Gizmo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,7 @@ struct StructOfNSStrings useStructOfNSStringsInObjC(struct StructOfNSStrings);
159159
__attribute__((swift_name("OuterType.InnerType")))
160160
@interface OuterTypeInnerType : NSObject<NSRuncing>
161161
@end
162+
163+
@protocol P
164+
- (oneway void)stuff;
165+
@end

test/IRGen/objc_type_encoding.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ import gizmo
166166
func subclassComposition(_: MyCustomObject & NSRuncing & NSFunging)
167167
}
168168

169+
169170
// CHECK-macosx: [[ENC1:@.*]] = private unnamed_addr constant [35 x i8] c"v24@0:8@\22<NSFunging><NSRuncing>\2216\00"
170171
// CHECK-macosx: [[ENC2:@.*]] = private unnamed_addr constant [46 x i8] c"v32@0:8@\22Gizmo\2216@?<v@?@\22NSView\22@\22NSSpoon\22>24\00"
171172
// CHECK-macosx: [[ENC3:@.*]] = private unnamed_addr constant [53 x i8] c"v24@0:8@\22_TtC18objc_type_encoding14MyCustomObject\2216\00"
@@ -181,3 +182,10 @@ import gizmo
181182
// CHECK-tvos: [[ENC3:@.*]] = private unnamed_addr constant [53 x i8] c"v24@0:8@\22_TtC18objc_type_encoding14MyCustomObject\2216\00"
182183
// CHECK-tvos: [[ENC4:@.*]] = private unnamed_addr constant [75 x i8] c"v24@0:8@\22_TtC18objc_type_encoding14MyCustomObject<NSFunging><NSRuncing>\2216\00"
183184
// 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)]
185+
186+
class C: P {
187+
func stuff() {}
188+
}
189+
190+
// CHECK-macosx: [[ENC5:@.*]] = private unnamed_addr constant [9 x i8] c"Vv16@0:8\00"
191+
// CHECK-macosx: @_PROTOCOL_INSTANCE_METHODS_P = {{.*}}@"\01L_selector_data(stuff)"{{.*}}[[ENC5]]{{.*}}, section "__DATA, __objc_const", align 8

0 commit comments

Comments
 (0)