Skip to content

Commit 7277d86

Browse files
committed
[5.6] IRGen: Fix using weak linkage to avoid duplicate metadata by only applying weak linkage to PROTOCOL related data
This adjusts PR#40342 with a fix for category linker errors. We will now only apply weak linkage to PROTOCOL metadata. Cherry-pick of commits from #40486. rdar://86256970
1 parent e8a7081 commit 7277d86

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
@@ -1317,22 +1317,25 @@ namespace {
13171317
assert(TheExtension && "can't emit category data for a class");
13181318
ConstantInitBuilder builder(IGM);
13191319
auto fields = builder.beginStruct();
1320+
auto internalLinkage = llvm::GlobalVariable::InternalLinkage;
13201321

13211322
// struct category_t {
13221323
// char const *name;
13231324
fields.add(IGM.getAddrOfGlobalString(CategoryName));
13241325
// const class_t *theClass;
13251326
fields.add(getClassMetadataRef());
13261327
// const method_list_t *instanceMethods;
1327-
emitAndAddMethodList(fields, MethodListKind::InstanceMethods);
1328+
emitAndAddMethodList(fields, MethodListKind::InstanceMethods,
1329+
internalLinkage);
13281330
// const method_list_t *classMethods;
1329-
emitAndAddMethodList(fields, MethodListKind::ClassMethods);
1331+
emitAndAddMethodList(fields, MethodListKind::ClassMethods,
1332+
internalLinkage);
13301333
// const protocol_list_t *baseProtocols;
1331-
fields.add(buildProtocolList());
1334+
fields.add(buildProtocolList(internalLinkage));
13321335
// const property_list_t *properties;
1333-
fields.add(buildPropertyList(ForClass));
1336+
fields.add(buildPropertyList(ForClass, internalLinkage));
13341337
// const property_list_t *classProperties;
1335-
fields.add(buildPropertyList(ForMetaClass));
1338+
fields.add(buildPropertyList(ForMetaClass, internalLinkage));
13361339
// uint32_t size;
13371340
// FIXME: Clang does this by using non-ad-hoc types for ObjC runtime
13381341
// structures.
@@ -1342,13 +1345,14 @@ namespace {
13421345

13431346
assert(fields.getNextOffsetFromGlobal() == size);
13441347
return buildGlobalVariable(fields, "_CATEGORY_", /*const*/ true,
1345-
llvm::GlobalVariable::InternalLinkage);
1348+
internalLinkage);
13461349
}
13471350

13481351
llvm::Constant *emitProtocol() {
13491352
ConstantInitBuilder builder(IGM);
13501353
auto fields = builder.beginStruct();
13511354
llvm::SmallString<64> nameBuffer;
1355+
auto weakLinkage = llvm::GlobalVariable::WeakAnyLinkage;
13521356

13531357
assert(isBuildingProtocol() && "not emitting a protocol");
13541358

@@ -1358,17 +1362,20 @@ namespace {
13581362
// char const *name;
13591363
fields.add(IGM.getAddrOfGlobalString(getEntityName(nameBuffer)));
13601364
// const protocol_list_t *baseProtocols;
1361-
fields.add(buildProtocolList());
1365+
fields.add(buildProtocolList(weakLinkage));
13621366
// const method_list_t *requiredInstanceMethods;
1363-
emitAndAddMethodList(fields, MethodListKind::InstanceMethods);
1367+
emitAndAddMethodList(fields, MethodListKind::InstanceMethods,
1368+
weakLinkage);
13641369
// const method_list_t *requiredClassMethods;
1365-
emitAndAddMethodList(fields, MethodListKind::ClassMethods);
1370+
emitAndAddMethodList(fields, MethodListKind::ClassMethods, weakLinkage);
13661371
// const method_list_t *optionalInstanceMethods;
1367-
emitAndAddMethodList(fields, MethodListKind::OptionalInstanceMethods);
1372+
emitAndAddMethodList(fields, MethodListKind::OptionalInstanceMethods,
1373+
weakLinkage);
13681374
// const method_list_t *optionalClassMethods;
1369-
emitAndAddMethodList(fields, MethodListKind::OptionalClassMethods);
1375+
emitAndAddMethodList(fields, MethodListKind::OptionalClassMethods,
1376+
weakLinkage);
13701377
// const property_list_t *properties;
1371-
fields.add(buildPropertyList(ForClass));
1378+
fields.add(buildPropertyList(ForClass, weakLinkage));
13721379

13731380
// uint32_t size;
13741381
// FIXME: Clang does this by using non-ad-hoc types for ObjC runtime
@@ -1390,11 +1397,12 @@ namespace {
13901397
// const char *demangledName;
13911398
fields.addNullPointer(IGM.Int8PtrTy);
13921399
// const property_list_t *classProperties;
1393-
fields.add(buildPropertyList(ForMetaClass));
1400+
fields.add(buildPropertyList(ForMetaClass, weakLinkage));
13941401
// };
13951402

13961403
assert(fields.getNextOffsetFromGlobal() == size);
1397-
return buildGlobalVariable(fields, "_PROTOCOL_", /*const*/ true);
1404+
return buildGlobalVariable(fields, "_PROTOCOL_", /*const*/ true,
1405+
weakLinkage);
13981406
}
13991407

14001408
void emitRODataFields(ConstantStructBuilder &b,
@@ -1455,12 +1463,14 @@ namespace {
14551463
b.add(buildName());
14561464

14571465
// const method_list_t *baseMethods;
1458-
emitAndAddMethodList(b, forMeta ? MethodListKind::ClassMethods
1459-
: MethodListKind::InstanceMethods);
1466+
emitAndAddMethodList(b,
1467+
forMeta ? MethodListKind::ClassMethods
1468+
: MethodListKind::InstanceMethods,
1469+
llvm::GlobalVariable::InternalLinkage);
14601470

14611471
// const protocol_list_t *baseProtocols;
14621472
// Apparently, this list is the same in the class and the metaclass.
1463-
b.add(buildProtocolList());
1473+
b.add(buildProtocolList(llvm::GlobalVariable::InternalLinkage));
14641474

14651475
// const ivar_list_t *ivars;
14661476
if (forMeta) {
@@ -1474,7 +1484,7 @@ namespace {
14741484
b.addNullPointer(IGM.Int8PtrTy);
14751485

14761486
// const property_list_t *baseProperties;
1477-
b.add(buildPropertyList(forMeta));
1487+
b.add(buildPropertyList(forMeta, llvm::GlobalVariable::InternalLinkage));
14781488

14791489
// If hasUpdater is true, the metadata update callback goes here.
14801490
if (hasUpdater) {
@@ -1723,7 +1733,8 @@ namespace {
17231733

17241734
/// Emit the method list and add the pointer to the `builder`.
17251735
void emitAndAddMethodList(ConstantInitBuilder::StructBuilder &builder,
1726-
MethodListKind kind) {
1736+
MethodListKind kind,
1737+
llvm::GlobalValue::LinkageTypes linkage) {
17271738
ArrayRef<MethodDescriptor> methods;
17281739
StringRef namePrefix;
17291740
switch (kind) {
@@ -1748,7 +1759,8 @@ namespace {
17481759
namePrefix = "_PROTOCOL_INSTANCE_METHODS_OPT_";
17491760
break;
17501761
}
1751-
llvm::Constant *methodListPtr = buildMethodList(methods, namePrefix);
1762+
llvm::Constant *methodListPtr =
1763+
buildMethodList(methods, namePrefix, linkage);
17521764
builder.add(methodListPtr);
17531765
}
17541766

@@ -1769,7 +1781,8 @@ namespace {
17691781
}
17701782

17711783
return buildGlobalVariable(array, "_PROTOCOL_METHOD_TYPES_",
1772-
/*const*/ true);
1784+
/*const*/ true,
1785+
llvm::GlobalVariable::WeakAnyLinkage);
17731786
}
17741787

17751788
void buildExtMethodTypes(ConstantArrayBuilder &array,
@@ -1792,13 +1805,14 @@ namespace {
17921805
///
17931806
/// This method does not return a value of a predictable type.
17941807
llvm::Constant *buildMethodList(ArrayRef<MethodDescriptor> methods,
1795-
StringRef name) {
1796-
return buildOptionalList(methods, 3 * IGM.getPointerSize(), name,
1797-
/*isConst*/ false,
1798-
[&](ConstantArrayBuilder &descriptors,
1799-
MethodDescriptor descriptor) {
1800-
buildMethod(descriptors, descriptor);
1801-
});
1808+
StringRef name,
1809+
llvm::GlobalValue::LinkageTypes linkage) {
1810+
return buildOptionalList(
1811+
methods, 3 * IGM.getPointerSize(), name,
1812+
/*isConst*/ false, linkage,
1813+
[&](ConstantArrayBuilder &descriptors, MethodDescriptor descriptor) {
1814+
buildMethod(descriptors, descriptor);
1815+
});
18021816
}
18031817

18041818
/*** Protocols *********************************************************/
@@ -1815,16 +1829,15 @@ namespace {
18151829
/// };
18161830
///
18171831
/// This method does not return a value of a predictable type.
1818-
llvm::Constant *buildProtocolList() {
1819-
return buildOptionalList(Protocols, Size(0),
1820-
chooseNamePrefix("_PROTOCOLS_",
1821-
"_CATEGORY_PROTOCOLS_",
1822-
"_PROTOCOL_PROTOCOLS_"),
1823-
/*isConst*/ true,
1824-
[&](ConstantArrayBuilder &descriptors,
1825-
ProtocolDecl *protocol) {
1826-
buildProtocol(descriptors, protocol);
1827-
});
1832+
llvm::Constant *buildProtocolList(llvm::GlobalValue::LinkageTypes linkage) {
1833+
return buildOptionalList(
1834+
Protocols, Size(0),
1835+
chooseNamePrefix("_PROTOCOLS_", "_CATEGORY_PROTOCOLS_",
1836+
"_PROTOCOL_PROTOCOLS_"),
1837+
/*isConst*/ true, linkage,
1838+
[&](ConstantArrayBuilder &descriptors, ProtocolDecl *protocol) {
1839+
buildProtocol(descriptors, protocol);
1840+
});
18281841
}
18291842

18301843
void buildProtocol(ConstantArrayBuilder &array, ProtocolDecl *protocol) {
@@ -1945,12 +1958,12 @@ namespace {
19451958
/// This method does not return a value of a predictable type.
19461959
llvm::Constant *buildIvarList() {
19471960
Size eltSize = 3 * IGM.getPointerSize() + Size(8);
1948-
return buildOptionalList(Ivars, eltSize, "_IVARS_",
1949-
/*constant*/ true,
1950-
[&](ConstantArrayBuilder &descriptors,
1951-
Field field) {
1952-
buildIvar(descriptors, field);
1953-
});
1961+
return buildOptionalList(
1962+
Ivars, eltSize, "_IVARS_",
1963+
/*constant*/ true, llvm::GlobalVariable::InternalLinkage,
1964+
[&](ConstantArrayBuilder &descriptors, Field field) {
1965+
buildIvar(descriptors, field);
1966+
});
19541967
}
19551968

19561969
/*** Properties ********************************************************/
@@ -2058,12 +2071,14 @@ namespace {
20582071
/// };
20592072
///
20602073
/// This method does not return a value of a predictable type.
2061-
llvm::Constant *buildPropertyList(ForMetaClass_t classOrMeta) {
2074+
llvm::Constant *buildPropertyList(ForMetaClass_t classOrMeta,
2075+
llvm::GlobalValue::LinkageTypes linkage) {
20622076
if (classOrMeta == ForClass) {
20632077
return buildPropertyList(InstanceProperties,
20642078
chooseNamePrefix("_PROPERTIES_",
20652079
"_CATEGORY_PROPERTIES_",
2066-
"_PROTOCOL_PROPERTIES_"));
2080+
"_PROTOCOL_PROPERTIES_"),
2081+
linkage);
20672082
}
20682083

20692084
// Older OSs' libobjcs can't handle class property data.
@@ -2075,18 +2090,20 @@ namespace {
20752090
return buildPropertyList(ClassProperties,
20762091
chooseNamePrefix("_CLASS_PROPERTIES_",
20772092
"_CATEGORY_CLASS_PROPERTIES_",
2078-
"_PROTOCOL_CLASS_PROPERTIES_"));
2093+
"_PROTOCOL_CLASS_PROPERTIES_"),
2094+
linkage);
20792095
}
20802096

2081-
llvm::Constant *buildPropertyList(ArrayRef<VarDecl*> properties,
2082-
StringRef namePrefix) {
2097+
llvm::Constant *buildPropertyList(ArrayRef<VarDecl *> properties,
2098+
StringRef namePrefix,
2099+
llvm::GlobalValue::LinkageTypes linkage) {
20832100
Size eltSize = 2 * IGM.getPointerSize();
2084-
return buildOptionalList(properties, eltSize, namePrefix,
2085-
/*constant*/ true,
2086-
[&](ConstantArrayBuilder &descriptors,
2087-
VarDecl *property) {
2088-
buildProperty(descriptors, property);
2089-
});
2101+
return buildOptionalList(
2102+
properties, eltSize, namePrefix,
2103+
/*constant*/ true, linkage,
2104+
[&](ConstantArrayBuilder &descriptors, VarDecl *property) {
2105+
buildProperty(descriptors, property);
2106+
});
20902107
}
20912108

20922109
/*** General ***********************************************************/
@@ -2098,10 +2115,9 @@ namespace {
20982115
/// \param optionalEltSize - if non-zero, a size which needs
20992116
/// to be placed in the list header
21002117
template <class C, class Fn>
2101-
llvm::Constant *buildOptionalList(const C &objects,
2102-
Size optionalEltSize,
2103-
StringRef nameBase,
2104-
bool isConst,
2118+
llvm::Constant *buildOptionalList(const C &objects, Size optionalEltSize,
2119+
StringRef nameBase, bool isConst,
2120+
llvm::GlobalValue::LinkageTypes linkage,
21052121
Fn &&buildElement) {
21062122
if (objects.empty())
21072123
return null();
@@ -2140,9 +2156,9 @@ namespace {
21402156

21412157
fields.fillPlaceholderWithInt(countPosition, countType, count);
21422158

2143-
return buildGlobalVariable(fields, nameBase, isConst);
2159+
return buildGlobalVariable(fields, nameBase, isConst, linkage);
21442160
}
2145-
2161+
21462162
/// Get the name of the class or protocol to mangle into the ObjC symbol
21472163
/// name.
21482164
StringRef getEntityName(llvm::SmallVectorImpl<char> &buffer) const {
@@ -2169,9 +2185,9 @@ namespace {
21692185
/// Build a private global variable as a structure containing the
21702186
/// given fields.
21712187
template <class B>
2172-
llvm::Constant *buildGlobalVariable(B &fields, StringRef nameBase, bool isConst,
2173-
llvm::GlobalValue::LinkageTypes linkage =
2174-
llvm::GlobalVariable::WeakAnyLinkage) {
2188+
llvm::Constant *
2189+
buildGlobalVariable(B &fields, StringRef nameBase, bool isConst,
2190+
llvm::GlobalValue::LinkageTypes linkage) {
21752191
llvm::SmallString<64> nameBuffer;
21762192
auto var =
21772193
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)