Skip to content

Commit 0d3af14

Browse files
committed
IRGen: Fix using weak linkage to avoid duplicate metadata by only applying this to PROTOCOL related data
rdar://86256970
1 parent 7fd49f1 commit 0d3af14

14 files changed

+116
-100
lines changed

lib/IRGen/GenClass.cpp

Lines changed: 80 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,22 +1319,25 @@ namespace {
13191319
assert(TheExtension && "can't emit category data for a class");
13201320
ConstantInitBuilder builder(IGM);
13211321
auto fields = builder.beginStruct();
1322+
auto internalLinkage = llvm::GlobalVariable::InternalLinkage;
13221323

13231324
// struct category_t {
13241325
// char const *name;
13251326
fields.add(IGM.getAddrOfGlobalString(CategoryName));
13261327
// const class_t *theClass;
13271328
fields.add(getClassMetadataRef());
13281329
// const method_list_t *instanceMethods;
1329-
emitAndAddMethodList(fields, MethodListKind::InstanceMethods);
1330+
emitAndAddMethodList(fields, MethodListKind::InstanceMethods,
1331+
internalLinkage);
13301332
// const method_list_t *classMethods;
1331-
emitAndAddMethodList(fields, MethodListKind::ClassMethods);
1333+
emitAndAddMethodList(fields, MethodListKind::ClassMethods,
1334+
internalLinkage);
13321335
// const protocol_list_t *baseProtocols;
1333-
fields.add(buildProtocolList());
1336+
fields.add(buildProtocolList(internalLinkage));
13341337
// const property_list_t *properties;
1335-
fields.add(buildPropertyList(ForClass));
1338+
fields.add(buildPropertyList(ForClass, internalLinkage));
13361339
// const property_list_t *classProperties;
1337-
fields.add(buildPropertyList(ForMetaClass));
1340+
fields.add(buildPropertyList(ForMetaClass, internalLinkage));
13381341
// uint32_t size;
13391342
// FIXME: Clang does this by using non-ad-hoc types for ObjC runtime
13401343
// structures.
@@ -1344,13 +1347,14 @@ namespace {
13441347

13451348
assert(fields.getNextOffsetFromGlobal() == size);
13461349
return buildGlobalVariable(fields, "_CATEGORY_", /*const*/ true,
1347-
llvm::GlobalVariable::InternalLinkage);
1350+
internalLinkage);
13481351
}
13491352

13501353
llvm::Constant *emitProtocol() {
13511354
ConstantInitBuilder builder(IGM);
13521355
auto fields = builder.beginStruct();
13531356
llvm::SmallString<64> nameBuffer;
1357+
auto weakLinkage = llvm::GlobalVariable::WeakAnyLinkage;
13541358

13551359
assert(isBuildingProtocol() && "not emitting a protocol");
13561360

@@ -1360,17 +1364,20 @@ namespace {
13601364
// char const *name;
13611365
fields.add(IGM.getAddrOfGlobalString(getEntityName(nameBuffer)));
13621366
// const protocol_list_t *baseProtocols;
1363-
fields.add(buildProtocolList());
1367+
fields.add(buildProtocolList(weakLinkage));
13641368
// const method_list_t *requiredInstanceMethods;
1365-
emitAndAddMethodList(fields, MethodListKind::InstanceMethods);
1369+
emitAndAddMethodList(fields, MethodListKind::InstanceMethods,
1370+
weakLinkage);
13661371
// const method_list_t *requiredClassMethods;
1367-
emitAndAddMethodList(fields, MethodListKind::ClassMethods);
1372+
emitAndAddMethodList(fields, MethodListKind::ClassMethods, weakLinkage);
13681373
// const method_list_t *optionalInstanceMethods;
1369-
emitAndAddMethodList(fields, MethodListKind::OptionalInstanceMethods);
1374+
emitAndAddMethodList(fields, MethodListKind::OptionalInstanceMethods,
1375+
weakLinkage);
13701376
// const method_list_t *optionalClassMethods;
1371-
emitAndAddMethodList(fields, MethodListKind::OptionalClassMethods);
1377+
emitAndAddMethodList(fields, MethodListKind::OptionalClassMethods,
1378+
weakLinkage);
13721379
// const property_list_t *properties;
1373-
fields.add(buildPropertyList(ForClass));
1380+
fields.add(buildPropertyList(ForClass, weakLinkage));
13741381

13751382
// uint32_t size;
13761383
// FIXME: Clang does this by using non-ad-hoc types for ObjC runtime
@@ -1392,11 +1399,12 @@ namespace {
13921399
// const char *demangledName;
13931400
fields.addNullPointer(IGM.Int8PtrTy);
13941401
// const property_list_t *classProperties;
1395-
fields.add(buildPropertyList(ForMetaClass));
1402+
fields.add(buildPropertyList(ForMetaClass, weakLinkage));
13961403
// };
13971404

13981405
assert(fields.getNextOffsetFromGlobal() == size);
1399-
return buildGlobalVariable(fields, "_PROTOCOL_", /*const*/ true);
1406+
return buildGlobalVariable(fields, "_PROTOCOL_", /*const*/ true,
1407+
weakLinkage);
14001408
}
14011409

14021410
void emitRODataFields(ConstantStructBuilder &b,
@@ -1457,12 +1465,14 @@ namespace {
14571465
b.add(buildName());
14581466

14591467
// const method_list_t *baseMethods;
1460-
emitAndAddMethodList(b, forMeta ? MethodListKind::ClassMethods
1461-
: MethodListKind::InstanceMethods);
1468+
emitAndAddMethodList(b,
1469+
forMeta ? MethodListKind::ClassMethods
1470+
: MethodListKind::InstanceMethods,
1471+
llvm::GlobalVariable::InternalLinkage);
14621472

14631473
// const protocol_list_t *baseProtocols;
14641474
// Apparently, this list is the same in the class and the metaclass.
1465-
b.add(buildProtocolList());
1475+
b.add(buildProtocolList(llvm::GlobalVariable::InternalLinkage));
14661476

14671477
// const ivar_list_t *ivars;
14681478
if (forMeta) {
@@ -1476,7 +1486,7 @@ namespace {
14761486
b.addNullPointer(IGM.Int8PtrTy);
14771487

14781488
// const property_list_t *baseProperties;
1479-
b.add(buildPropertyList(forMeta));
1489+
b.add(buildPropertyList(forMeta, llvm::GlobalVariable::InternalLinkage));
14801490

14811491
// If hasUpdater is true, the metadata update callback goes here.
14821492
if (hasUpdater) {
@@ -1725,7 +1735,8 @@ namespace {
17251735

17261736
/// Emit the method list and add the pointer to the `builder`.
17271737
void emitAndAddMethodList(ConstantInitBuilder::StructBuilder &builder,
1728-
MethodListKind kind) {
1738+
MethodListKind kind,
1739+
llvm::GlobalValue::LinkageTypes linkage) {
17291740
ArrayRef<MethodDescriptor> methods;
17301741
StringRef namePrefix;
17311742
switch (kind) {
@@ -1750,7 +1761,8 @@ namespace {
17501761
namePrefix = "_PROTOCOL_INSTANCE_METHODS_OPT_";
17511762
break;
17521763
}
1753-
llvm::Constant *methodListPtr = buildMethodList(methods, namePrefix);
1764+
llvm::Constant *methodListPtr =
1765+
buildMethodList(methods, namePrefix, linkage);
17541766
builder.add(methodListPtr);
17551767
}
17561768

@@ -1771,7 +1783,8 @@ namespace {
17711783
}
17721784

17731785
return buildGlobalVariable(array, "_PROTOCOL_METHOD_TYPES_",
1774-
/*const*/ true);
1786+
/*const*/ true,
1787+
llvm::GlobalVariable::WeakAnyLinkage);
17751788
}
17761789

17771790
void buildExtMethodTypes(ConstantArrayBuilder &array,
@@ -1794,13 +1807,14 @@ namespace {
17941807
///
17951808
/// This method does not return a value of a predictable type.
17961809
llvm::Constant *buildMethodList(ArrayRef<MethodDescriptor> methods,
1797-
StringRef name) {
1798-
return buildOptionalList(methods, 3 * IGM.getPointerSize(), name,
1799-
/*isConst*/ false,
1800-
[&](ConstantArrayBuilder &descriptors,
1801-
MethodDescriptor descriptor) {
1802-
buildMethod(descriptors, descriptor);
1803-
});
1810+
StringRef name,
1811+
llvm::GlobalValue::LinkageTypes linkage) {
1812+
return buildOptionalList(
1813+
methods, 3 * IGM.getPointerSize(), name,
1814+
/*isConst*/ false, linkage,
1815+
[&](ConstantArrayBuilder &descriptors, MethodDescriptor descriptor) {
1816+
buildMethod(descriptors, descriptor);
1817+
});
18041818
}
18051819

18061820
/*** Protocols *********************************************************/
@@ -1817,16 +1831,15 @@ namespace {
18171831
/// };
18181832
///
18191833
/// This method does not return a value of a predictable type.
1820-
llvm::Constant *buildProtocolList() {
1821-
return buildOptionalList(Protocols, Size(0),
1822-
chooseNamePrefix("_PROTOCOLS_",
1823-
"_CATEGORY_PROTOCOLS_",
1824-
"_PROTOCOL_PROTOCOLS_"),
1825-
/*isConst*/ true,
1826-
[&](ConstantArrayBuilder &descriptors,
1827-
ProtocolDecl *protocol) {
1828-
buildProtocol(descriptors, protocol);
1829-
});
1834+
llvm::Constant *buildProtocolList(llvm::GlobalValue::LinkageTypes linkage) {
1835+
return buildOptionalList(
1836+
Protocols, Size(0),
1837+
chooseNamePrefix("_PROTOCOLS_", "_CATEGORY_PROTOCOLS_",
1838+
"_PROTOCOL_PROTOCOLS_"),
1839+
/*isConst*/ true, linkage,
1840+
[&](ConstantArrayBuilder &descriptors, ProtocolDecl *protocol) {
1841+
buildProtocol(descriptors, protocol);
1842+
});
18301843
}
18311844

18321845
void buildProtocol(ConstantArrayBuilder &array, ProtocolDecl *protocol) {
@@ -1947,12 +1960,12 @@ namespace {
19471960
/// This method does not return a value of a predictable type.
19481961
llvm::Constant *buildIvarList() {
19491962
Size eltSize = 3 * IGM.getPointerSize() + Size(8);
1950-
return buildOptionalList(Ivars, eltSize, "_IVARS_",
1951-
/*constant*/ true,
1952-
[&](ConstantArrayBuilder &descriptors,
1953-
Field field) {
1954-
buildIvar(descriptors, field);
1955-
});
1963+
return buildOptionalList(
1964+
Ivars, eltSize, "_IVARS_",
1965+
/*constant*/ true, llvm::GlobalVariable::InternalLinkage,
1966+
[&](ConstantArrayBuilder &descriptors, Field field) {
1967+
buildIvar(descriptors, field);
1968+
});
19561969
}
19571970

19581971
/*** Properties ********************************************************/
@@ -2060,12 +2073,14 @@ namespace {
20602073
/// };
20612074
///
20622075
/// This method does not return a value of a predictable type.
2063-
llvm::Constant *buildPropertyList(ForMetaClass_t classOrMeta) {
2076+
llvm::Constant *buildPropertyList(ForMetaClass_t classOrMeta,
2077+
llvm::GlobalValue::LinkageTypes linkage) {
20642078
if (classOrMeta == ForClass) {
20652079
return buildPropertyList(InstanceProperties,
20662080
chooseNamePrefix("_PROPERTIES_",
20672081
"_CATEGORY_PROPERTIES_",
2068-
"_PROTOCOL_PROPERTIES_"));
2082+
"_PROTOCOL_PROPERTIES_"),
2083+
linkage);
20692084
}
20702085

20712086
// Older OSs' libobjcs can't handle class property data.
@@ -2077,18 +2092,20 @@ namespace {
20772092
return buildPropertyList(ClassProperties,
20782093
chooseNamePrefix("_CLASS_PROPERTIES_",
20792094
"_CATEGORY_CLASS_PROPERTIES_",
2080-
"_PROTOCOL_CLASS_PROPERTIES_"));
2095+
"_PROTOCOL_CLASS_PROPERTIES_"),
2096+
linkage);
20812097
}
20822098

2083-
llvm::Constant *buildPropertyList(ArrayRef<VarDecl*> properties,
2084-
StringRef namePrefix) {
2099+
llvm::Constant *buildPropertyList(ArrayRef<VarDecl *> properties,
2100+
StringRef namePrefix,
2101+
llvm::GlobalValue::LinkageTypes linkage) {
20852102
Size eltSize = 2 * IGM.getPointerSize();
2086-
return buildOptionalList(properties, eltSize, namePrefix,
2087-
/*constant*/ true,
2088-
[&](ConstantArrayBuilder &descriptors,
2089-
VarDecl *property) {
2090-
buildProperty(descriptors, property);
2091-
});
2103+
return buildOptionalList(
2104+
properties, eltSize, namePrefix,
2105+
/*constant*/ true, linkage,
2106+
[&](ConstantArrayBuilder &descriptors, VarDecl *property) {
2107+
buildProperty(descriptors, property);
2108+
});
20922109
}
20932110

20942111
/*** General ***********************************************************/
@@ -2100,10 +2117,9 @@ namespace {
21002117
/// \param optionalEltSize - if non-zero, a size which needs
21012118
/// to be placed in the list header
21022119
template <class C, class Fn>
2103-
llvm::Constant *buildOptionalList(const C &objects,
2104-
Size optionalEltSize,
2105-
StringRef nameBase,
2106-
bool isConst,
2120+
llvm::Constant *buildOptionalList(const C &objects, Size optionalEltSize,
2121+
StringRef nameBase, bool isConst,
2122+
llvm::GlobalValue::LinkageTypes linkage,
21072123
Fn &&buildElement) {
21082124
if (objects.empty())
21092125
return null();
@@ -2142,9 +2158,9 @@ namespace {
21422158

21432159
fields.fillPlaceholderWithInt(countPosition, countType, count);
21442160

2145-
return buildGlobalVariable(fields, nameBase, isConst);
2161+
return buildGlobalVariable(fields, nameBase, isConst, linkage);
21462162
}
2147-
2163+
21482164
/// Get the name of the class or protocol to mangle into the ObjC symbol
21492165
/// name.
21502166
StringRef getEntityName(llvm::SmallVectorImpl<char> &buffer) const {
@@ -2171,9 +2187,9 @@ namespace {
21712187
/// Build a private global variable as a structure containing the
21722188
/// given fields.
21732189
template <class B>
2174-
llvm::Constant *buildGlobalVariable(B &fields, StringRef nameBase, bool isConst,
2175-
llvm::GlobalValue::LinkageTypes linkage =
2176-
llvm::GlobalVariable::WeakAnyLinkage) {
2190+
llvm::Constant *
2191+
buildGlobalVariable(B &fields, StringRef nameBase, bool isConst,
2192+
llvm::GlobalValue::LinkageTypes linkage) {
21772193
llvm::SmallString<64> nameBuffer;
21782194
auto var =
21792195
fields.finishAndCreateGlobal(Twine(nameBase)

test/IRGen/generic_casts.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import gizmo
1616
// CHECK: @"\01l_OBJC_LABEL_PROTOCOL_$_NSRuncing" = weak hidden global i8* bitcast ({{.*}} @_PROTOCOL_NSRuncing to i8*), section {{"__DATA,__objc_protolist,coalesced,no_dead_strip"|"objc_protolist"|".objc_protolist\$B"}}
1717
// CHECK: @"\01l_OBJC_PROTOCOL_REFERENCE_$_NSRuncing" = weak hidden global i8* bitcast ({{.*}} @_PROTOCOL_NSRuncing to i8*), section {{"__DATA,__objc_protorefs,coalesced,no_dead_strip"|"objc_protorefs"|".objc_protorefs\$B"}}
1818

19-
// CHECK: @_PROTOCOLS__TtC13generic_casts10ObjCClass2 = weak hidden constant { i64, [1 x i8*] } {
19+
// CHECK: @_PROTOCOLS__TtC13generic_casts10ObjCClass2 = internal constant { i64, [1 x i8*] } {
2020
// CHECK: i64 1,
2121
// CHECK: @_PROTOCOL__TtP13generic_casts10ObjCProto2_
2222
// CHECK: }

test/IRGen/objc_async_metadata.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import Foundation
1212
// CHECK: [[ENCODE_ASYNC_STRING:@.*]] = private unnamed_addr constant [28 x i8] c"v24@0:8@?<v@?@\22NSString\22>16\00"
1313
// CHECK: [[ENCODE_ASYNC_THROWS_STRING:@.*]] = private unnamed_addr constant [38 x i8] c"v24@0:8@?<v@?@\22NSString\22@\22NSError\22>16\00"
1414

15-
// CHECK: @_INSTANCE_METHODS__TtC19objc_async_metadata7MyClass = weak hidden constant
15+
// CHECK: @_INSTANCE_METHODS__TtC19objc_async_metadata7MyClass = internal constant
1616
// CHECK-SAME: methodWithCompletionHandler:
1717
// CHECK-SAME: [[ENCODE_ASYNC_STRING]]
1818
// CHECK-SAME: throwingMethodWithCompletionHandler:

test/IRGen/objc_attr_NSManaged.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ import Foundation
1717
sil_vtable X {}
1818

1919
// The getter/setter should not show up in the Objective-C metadata.
20-
// CHECK: @_INSTANCE_METHODS__TtC19objc_attr_NSManaged10SwiftGizmo = weak hidden constant { i32, i32, [2 x { i8*, i8*, i8* }] } { i32 24, i32 2, {{.*}} @"\01L_selector_data(initWithBellsOn:)", {{.*}} @"\01L_selector_data(init)",
20+
// CHECK: @_INSTANCE_METHODS__TtC19objc_attr_NSManaged10SwiftGizmo = internal constant { i32, i32, [2 x { i8*, i8*, i8* }] } { i32 24, i32 2, {{.*}} @"\01L_selector_data(initWithBellsOn:)", {{.*}} @"\01L_selector_data(init)",
2121

2222
// CHECK: [[X:@[0-9]+]] = private unnamed_addr constant [2 x i8] c"x\00"
2323

2424
// The property 'x' should show up in the Objective-C metadata.
25-
// CHECK: @_PROPERTIES__TtC19objc_attr_NSManaged10SwiftGizmo = weak hidden constant { {{.*}}i32, i32, [1 x { i8*, i8* }] } { i32 16, i32 1, [1 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([2 x i8], [2 x i8]* [[X]], i64 0, i64 0),
25+
// CHECK: @_PROPERTIES__TtC19objc_attr_NSManaged10SwiftGizmo = internal constant { {{.*}}i32, i32, [1 x { i8*, i8* }] } { i32 16, i32 1, [1 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([2 x i8], [2 x i8]* [[X]], i64 0, i64 0),
2626

2727
// The getter/setter should not show up in the Swift metadata.
2828
// CHECK: @"$s19objc_attr_NSManaged10SwiftGizmoCMf" = internal global <{ {{.*}} }> <{ void (%T19objc_attr_NSManaged10SwiftGizmoC*)* {{.*}}@"$s19objc_attr_NSManaged10SwiftGizmoCfD{{(\.ptrauth)?}}"{{.*}}, i8**{{.*}} @"$sBOWV{{(.ptrauth)?(.)?[0-9]?}}"{{.*}}, {{.*}} @"OBJC_METACLASS_$__TtC19objc_attr_NSManaged10SwiftGizmo{{(.ptrauth)?}}"{{.*}}, %objc_class*{{.*}} @"OBJC_CLASS_$_Gizmo{{(.ptrauth)?}}"{{.*}}, %swift.opaque* @_objc_empty_cache, %swift.opaque* null,{{.*}}@_DATA__TtC19objc_attr_NSManaged10SwiftGizmo{{.*}}i64 {{1|2}}){{.*}}, i32 {{1|0}}, i32 0, i32 8, i16 7, i16 0, i32 96, i32 16, {{.*}}* @"$s19objc_attr_NSManaged10SwiftGizmoCMn{{(\.ptrauth)?}}"{{.*}}, i8* null }>

test/IRGen/objc_bridge.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Foundation
1111
// CHECK: [[SETTER_SIGNATURE:@.*]] = private unnamed_addr constant [11 x i8] c"v24@0:8@16\00"
1212
// CHECK: [[DEALLOC_SIGNATURE:@.*]] = private unnamed_addr constant [8 x i8] c"v16@0:8\00"
1313

14-
// CHECK: @_INSTANCE_METHODS__TtC11objc_bridge3Bas = weak hidden constant { i32, i32, [17 x { i8*, i8*, i8* }] } {
14+
// CHECK: @_INSTANCE_METHODS__TtC11objc_bridge3Bas = internal constant { i32, i32, [17 x { i8*, i8*, i8* }] } {
1515
// CHECK: i32 24,
1616
// CHECK: i32 17,
1717
// CHECK: [17 x { i8*, i8*, i8* }] [
@@ -114,10 +114,10 @@ import Foundation
114114
// CHECK: ]
115115
// CHECK: }, section "__DATA, {{.*}}", align 8
116116

117-
// CHECK: @_PROPERTIES__TtC11objc_bridge3Bas = weak hidden constant { i32, i32, [5 x { i8*, i8* }] } {
117+
// CHECK: @_PROPERTIES__TtC11objc_bridge3Bas = internal constant { i32, i32, [5 x { i8*, i8* }] } {
118118

119119
// CHECK: [[OBJC_BLOCK_PROPERTY:@.*]] = private unnamed_addr constant [8 x i8] c"T@?,N,C\00"
120-
// CHECK: @_PROPERTIES__TtC11objc_bridge21OptionalBlockProperty = weak hidden constant {{.*}} [[OBJC_BLOCK_PROPERTY]]
120+
// CHECK: @_PROPERTIES__TtC11objc_bridge21OptionalBlockProperty = internal constant {{.*}} [[OBJC_BLOCK_PROPERTY]]
121121

122122
func getDescription(_ o: NSObject) -> String {
123123
return o.description

test/IRGen/objc_class_property.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
// class properties, so no ObjC property is reflected.
77

88
// CHECK-NOT: @_PROPERTIES__TtC19objc_class_property7Smashed
9-
// CHECK: @_CLASS_METHODS__TtC19objc_class_property7Smashed = weak hidden constant { i32, i32, [1 x { i8*, i8*, i8* }] } {
9+
// CHECK: @_CLASS_METHODS__TtC19objc_class_property7Smashed = internal constant { i32, i32, [1 x { i8*, i8*, i8* }] } {
1010
// CHECK: i8* getelementptr inbounds ([14 x i8], [14 x i8]* @"\01L_selector_data(sharedSmashed)"
1111
// CHECK-NOT: @_PROPERTIES__TtC19objc_class_property7Smashed
12-
// CHECK: @_INSTANCE_METHODS__TtC19objc_class_property7Smashed = weak hidden constant { i32, i32, [1 x { i8*, i8*, i8* }] } {
12+
// CHECK: @_INSTANCE_METHODS__TtC19objc_class_property7Smashed = internal constant { i32, i32, [1 x { i8*, i8*, i8* }] } {
1313
// CHECK: i8* getelementptr inbounds ([5 x i8], [5 x i8]* @"\01L_selector_data(init)"
1414
// CHECK-NOT: @_PROPERTIES__TtC19objc_class_property7Smashed
1515

0 commit comments

Comments
 (0)