Skip to content

Commit 77af77f

Browse files
Merge pull request #30433 from aschwaighofer/irgen_no_duplicate_objc_method_descriptor_entries
IRGen: Unique method descriptors in objc method lists
2 parents 841eeb0 + a5b277b commit 77af77f

File tree

4 files changed

+51
-17
lines changed

4 files changed

+51
-17
lines changed

lib/IRGen/GenClass.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,27 +1521,33 @@ namespace {
15211521
}
15221522

15231523
void buildMethod(ConstantArrayBuilder &descriptors,
1524-
MethodDescriptor descriptor) {
1524+
MethodDescriptor descriptor,
1525+
llvm::StringSet<> &uniqueSelectors) {
15251526
switch (descriptor.getKind()) {
15261527
case MethodDescriptor::Kind::Method:
1527-
return buildMethod(descriptors, descriptor.getMethod());
1528+
return buildMethod(descriptors, descriptor.getMethod(),
1529+
uniqueSelectors);
15281530
case MethodDescriptor::Kind::IVarInitializer:
15291531
emitObjCIVarInitDestroyDescriptor(IGM, descriptors, getClass(),
1530-
descriptor.getImpl(), false);
1532+
descriptor.getImpl(), false,
1533+
uniqueSelectors);
15311534
return;
15321535
case MethodDescriptor::Kind::IVarDestroyer:
15331536
emitObjCIVarInitDestroyDescriptor(IGM, descriptors, getClass(),
1534-
descriptor.getImpl(), true);
1537+
descriptor.getImpl(), true,
1538+
uniqueSelectors);
15351539
return;
15361540
}
15371541
llvm_unreachable("bad method descriptor kind");
15381542
}
15391543

15401544
void buildMethod(ConstantArrayBuilder &descriptors,
1541-
AbstractFunctionDecl *method) {
1545+
AbstractFunctionDecl *method,
1546+
llvm::StringSet<> &uniqueSelectors) {
15421547
auto accessor = dyn_cast<AccessorDecl>(method);
15431548
if (!accessor)
1544-
return emitObjCMethodDescriptor(IGM, descriptors, method);
1549+
return emitObjCMethodDescriptor(IGM, descriptors, method,
1550+
uniqueSelectors);
15451551

15461552
switch (accessor->getAccessorKind()) {
15471553
case AccessorKind::Get:
@@ -1610,7 +1616,9 @@ namespace {
16101616
namePrefix = "_PROTOCOL_INSTANCE_METHODS_OPT_";
16111617
break;
16121618
}
1613-
llvm::Constant *methodListPtr = buildMethodList(methods, namePrefix);
1619+
llvm::StringSet<> uniqueSelectors;
1620+
llvm::Constant *methodListPtr =
1621+
buildMethodList(methods, namePrefix, uniqueSelectors);
16141622
builder.add(methodListPtr);
16151623
}
16161624

@@ -1653,11 +1661,12 @@ namespace {
16531661
///
16541662
/// This method does not return a value of a predictable type.
16551663
llvm::Constant *buildMethodList(ArrayRef<MethodDescriptor> methods,
1656-
StringRef name) {
1664+
StringRef name,
1665+
llvm::StringSet<> &uniqueSelectors) {
16571666
return buildOptionalList(methods, 3 * IGM.getPointerSize(), name,
16581667
[&](ConstantArrayBuilder &descriptors,
16591668
MethodDescriptor descriptor) {
1660-
buildMethod(descriptors, descriptor);
1669+
buildMethod(descriptors, descriptor, uniqueSelectors);
16611670
});
16621671
}
16631672

lib/IRGen/GenObjC.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,24 +1323,34 @@ static void emitObjCDescriptor(IRGenModule &IGM,
13231323
/// };
13241324
void irgen::emitObjCMethodDescriptor(IRGenModule &IGM,
13251325
ConstantArrayBuilder &descriptors,
1326-
AbstractFunctionDecl *method) {
1326+
AbstractFunctionDecl *method,
1327+
llvm::StringSet<> &uniqueSelectors) {
1328+
// Don't emit a selector twice.
1329+
Selector selector(method);
1330+
if (!uniqueSelectors.insert(selector.str()).second)
1331+
return;
1332+
13271333
ObjCMethodDescriptor descriptor(
13281334
emitObjCMethodDescriptorParts(IGM, method, /*concrete*/ true));
13291335
emitObjCDescriptor(IGM, descriptors, descriptor);
13301336
}
13311337

1332-
void irgen::emitObjCIVarInitDestroyDescriptor(IRGenModule &IGM,
1333-
ConstantArrayBuilder &descriptors,
1334-
ClassDecl *cd,
1335-
llvm::Function *objcImpl,
1336-
bool isDestroyer) {
1338+
void irgen::emitObjCIVarInitDestroyDescriptor(
1339+
IRGenModule &IGM, ConstantArrayBuilder &descriptors, ClassDecl *cd,
1340+
llvm::Function *objcImpl, bool isDestroyer,
1341+
llvm::StringSet<> &uniqueSelectors) {
13371342
/// The first element is the selector.
13381343
SILDeclRef declRef = SILDeclRef(cd,
13391344
isDestroyer? SILDeclRef::Kind::IVarDestroyer
13401345
: SILDeclRef::Kind::IVarInitializer,
13411346
1,
13421347
/*foreign*/ true);
13431348
Selector selector(declRef);
1349+
1350+
// Don't emit a selector twice.
1351+
if (!uniqueSelectors.insert(selector.str()).second)
1352+
return;
1353+
13441354
ObjCMethodDescriptor descriptor{};
13451355
descriptor.selectorRef = IGM.getAddrOfObjCMethodName(selector.str());
13461356

lib/IRGen/GenObjC.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,17 @@ namespace irgen {
155155
/// constructor, or destructor implementation.
156156
void emitObjCMethodDescriptor(IRGenModule &IGM,
157157
ConstantArrayBuilder &descriptors,
158-
AbstractFunctionDecl *method);
158+
AbstractFunctionDecl *method,
159+
llvm::StringSet<> &uniqueSelectors);
159160

160161
/// Build an Objective-C method descriptor for the ivar initializer
161162
/// or destroyer of a class (-.cxx_construct or -.cxx_destruct).
162163
void emitObjCIVarInitDestroyDescriptor(IRGenModule &IGM,
163164
ConstantArrayBuilder &descriptors,
164165
ClassDecl *cd,
165166
llvm::Function *impl,
166-
bool isDestroyer);
167+
bool isDestroyer,
168+
llvm::StringSet<> &uniqueSelectors);
167169

168170
/// Get the type encoding for an ObjC property.
169171
void getObjCEncodingForPropertyType(IRGenModule &IGM, VarDecl *property,
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-ir %s | %FileCheck %s
2+
3+
// REQUIRES: OS=macosx
4+
5+
6+
// Make sure we don't emit duplicate method descriptors
7+
8+
// CHECK-NOT: _PROTOCOL_INSTANCE_METHODS_NSObject{{.*}}"\01L_selector_data(conformsToProtocol:)"{{.*}}"\01L_selector_data(conformsToProtocol:)"
9+
10+
import Foundation
11+
12+
@objc protocol P: NSObjectProtocol {}
13+
class C: NSObject, P {}

0 commit comments

Comments
 (0)