Skip to content

Commit f7d610d

Browse files
committed
IRGen: don't create ObjC methods with the unnamed_addr attribute
In some places, Foundation is comparing ObjC method pointers. Therefore LLVM's function merging pass must not create aliases for identica; functions, but instead create thunks. This can be ensured by not creating ObjC methods with the unnamed_addr attribute. rdar://problem/58483698
1 parent 5e155d9 commit f7d610d

File tree

7 files changed

+116
-57
lines changed

7 files changed

+116
-57
lines changed

lib/IRGen/GenObjC.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -919,8 +919,11 @@ static llvm::Constant *findSwiftAsObjCThunk(IRGenModule &IGM, SILDeclRef ref,
919919
assert(SILFn && "no IR function for swift-as-objc thunk");
920920
auto fn = IGM.getAddrOfSILFunction(SILFn, NotForDefinition);
921921
ApplyIRLinkage(IRLinkage::Internal).to(fn);
922-
fn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
923-
922+
// Don't add the unnamed_addr attribute: in some places Foundation is
923+
// comparing ObjC method pointers. Therefore LLVM's function merging pass must
924+
// not create aliases for identical functions, but create thunks.
925+
// This can be ensured if ObjC methods are not created with the unnamed_addr
926+
// attribute.
924927
return llvm::ConstantExpr::getBitCast(fn, IGM.Int8PtrTy);
925928
}
926929

test/IRGen/abitypes.swift

Lines changed: 35 additions & 35 deletions
Large diffs are not rendered by default.

test/IRGen/objc_bridge.swift

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -130,57 +130,57 @@ var NSS : NSString = NSString()
130130

131131
// -- NSString methods don't convert 'self'
132132
extension NSString {
133-
// CHECK: define internal [[OPAQUE:.*]]* @"$sSo8NSStringC11objc_bridgeE13nsstrFakePropABvgTo"([[OPAQUE:.*]]*, i8*) unnamed_addr
134-
// CHECK: define internal void @"$sSo8NSStringC11objc_bridgeE13nsstrFakePropABvsTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) unnamed_addr
133+
// CHECK: define internal [[OPAQUE:.*]]* @"$sSo8NSStringC11objc_bridgeE13nsstrFakePropABvgTo"([[OPAQUE:.*]]*, i8*) {{[#0-9]*}} {
134+
// CHECK: define internal void @"$sSo8NSStringC11objc_bridgeE13nsstrFakePropABvsTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) {{[#0-9]*}} {
135135
@objc var nsstrFakeProp : NSString {
136136
get {
137137
return NSS
138138
}
139139
set {}
140140
}
141141

142-
// CHECK: define internal [[OPAQUE:.*]]* @"$sSo8NSStringC11objc_bridgeE11nsstrResultAByFTo"([[OPAQUE:.*]]*, i8*) unnamed_addr
142+
// CHECK: define internal [[OPAQUE:.*]]* @"$sSo8NSStringC11objc_bridgeE11nsstrResultAByFTo"([[OPAQUE:.*]]*, i8*) {{[#0-9]*}} {
143143
@objc func nsstrResult() -> NSString { return NSS }
144144

145-
// CHECK: define internal void @"$sSo8NSStringC11objc_bridgeE8nsstrArg1syAB_tFTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) unnamed_addr
145+
// CHECK: define internal void @"$sSo8NSStringC11objc_bridgeE8nsstrArg1syAB_tFTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) {{[#0-9]*}} {
146146
@objc func nsstrArg(s s: NSString) { }
147147
}
148148

149149
class Bas : NSObject {
150-
// CHECK: define internal [[OPAQUE:.*]]* @"$s11objc_bridge3BasC11strRealPropSSvgTo"([[OPAQUE:.*]]*, i8*) unnamed_addr {{.*}} {
151-
// CHECK: define internal void @"$s11objc_bridge3BasC11strRealPropSSvsTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) unnamed_addr {{.*}} {
150+
// CHECK: define internal [[OPAQUE:.*]]* @"$s11objc_bridge3BasC11strRealPropSSvgTo"([[OPAQUE:.*]]*, i8*) {{[#0-9]*}} {
151+
// CHECK: define internal void @"$s11objc_bridge3BasC11strRealPropSSvsTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) {{[#0-9]*}} {
152152
@objc var strRealProp : String
153153

154-
// CHECK: define internal [[OPAQUE:.*]]* @"$s11objc_bridge3BasC11strFakePropSSvgTo"([[OPAQUE:.*]]*, i8*) unnamed_addr {{.*}} {
155-
// CHECK: define internal void @"$s11objc_bridge3BasC11strFakePropSSvsTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) unnamed_addr {{.*}} {
154+
// CHECK: define internal [[OPAQUE:.*]]* @"$s11objc_bridge3BasC11strFakePropSSvgTo"([[OPAQUE:.*]]*, i8*) {{[#0-9]*}} {
155+
// CHECK: define internal void @"$s11objc_bridge3BasC11strFakePropSSvsTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) {{[#0-9]*}} {
156156
@objc var strFakeProp : String {
157157
get {
158158
return ""
159159
}
160160
set {}
161161
}
162162

163-
// CHECK: define internal [[OPAQUE:.*]]* @"$s11objc_bridge3BasC13nsstrRealPropSo8NSStringCvgTo"([[OPAQUE:.*]]*, i8*) unnamed_addr {{.*}} {
164-
// CHECK: define internal void @"$s11objc_bridge3BasC13nsstrRealPropSo8NSStringCvsTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) unnamed_addr {{.*}} {
163+
// CHECK: define internal [[OPAQUE:.*]]* @"$s11objc_bridge3BasC13nsstrRealPropSo8NSStringCvgTo"([[OPAQUE:.*]]*, i8*) {{[#0-9]*}} {
164+
// CHECK: define internal void @"$s11objc_bridge3BasC13nsstrRealPropSo8NSStringCvsTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) {{[#0-9]*}} {
165165
@objc var nsstrRealProp : NSString
166166

167167
// CHECK: define hidden swiftcc %TSo8NSStringC* @"$s11objc_bridge3BasC13nsstrFakePropSo8NSStringCvg"(%T11objc_bridge3BasC* swiftself) {{.*}} {
168-
// CHECK: define internal void @"$s11objc_bridge3BasC13nsstrFakePropSo8NSStringCvsTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) unnamed_addr {{.*}} {
168+
// CHECK: define internal void @"$s11objc_bridge3BasC13nsstrFakePropSo8NSStringCvsTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) {{[#0-9]*}} {
169169
@objc var nsstrFakeProp : NSString {
170170
get {
171171
return NSS
172172
}
173173
set {}
174174
}
175175

176-
// CHECK: define internal [[OPAQUE:.*]]* @"$s11objc_bridge3BasC9strResultSSyFTo"([[OPAQUE:.*]]*, i8*) unnamed_addr {{.*}} {
176+
// CHECK: define internal [[OPAQUE:.*]]* @"$s11objc_bridge3BasC9strResultSSyFTo"([[OPAQUE:.*]]*, i8*) {{[#0-9]*}} {
177177
@objc func strResult() -> String { return "" }
178-
// CHECK: define internal void @"$s11objc_bridge3BasC6strArg1sySS_tFTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) unnamed_addr {{.*}} {
178+
// CHECK: define internal void @"$s11objc_bridge3BasC6strArg1sySS_tFTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) {{[#0-9]*}} {
179179
@objc func strArg(s s: String) { }
180180

181-
// CHECK: define internal [[OPAQUE:.*]]* @"$s11objc_bridge3BasC11nsstrResultSo8NSStringCyFTo"([[OPAQUE:.*]]*, i8*) unnamed_addr {{.*}} {
181+
// CHECK: define internal [[OPAQUE:.*]]* @"$s11objc_bridge3BasC11nsstrResultSo8NSStringCyFTo"([[OPAQUE:.*]]*, i8*) {{[#0-9]*}} {
182182
@objc func nsstrResult() -> NSString { return NSS }
183-
// CHECK: define internal void @"$s11objc_bridge3BasC8nsstrArg1sySo8NSStringC_tFTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) unnamed_addr {{.*}} {
183+
// CHECK: define internal void @"$s11objc_bridge3BasC8nsstrArg1sySo8NSStringC_tFTo"([[OPAQUE:.*]]*, i8*, [[OPAQUE:.*]]*) {{[#0-9]*}} {
184184
@objc func nsstrArg(s s: NSString) { }
185185

186186
override init() {

test/IRGen/objc_class_export.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ struct BigStructWithNativeObjects {
8181

8282
@objc func drawInRect(dirty dirty: NSRect) {
8383
}
84-
// CHECK: define internal void @"$s17objc_class_export3FooC10drawInRect5dirtyySo6NSRectV_tFTo"([[OPAQUE:%.*]]*, i8*, [[NSRECT]]* byval align 8) unnamed_addr {{.*}} {
84+
// CHECK: define internal void @"$s17objc_class_export3FooC10drawInRect5dirtyySo6NSRectV_tFTo"([[OPAQUE:%.*]]*, i8*, [[NSRECT]]* byval align 8) {{[#0-9]*}} {
8585
// CHECK: [[CAST:%[a-zA-Z0-9]+]] = bitcast [[OPAQUE]]* %0 to [[FOO]]*
8686
// CHECK: call swiftcc void @"$s17objc_class_export3FooC10drawInRect5dirtyySo6NSRectV_tF"(double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, [[FOO]]* swiftself [[CAST]])
8787
// CHECK: }
@@ -90,14 +90,14 @@ struct BigStructWithNativeObjects {
9090
return NSRect(origin: NSPoint(x: 0, y: 0),
9191
size: NSSize(width: 0, height: 0))
9292
}
93-
// CHECK: define internal void @"$s17objc_class_export3FooC6boundsSo6NSRectVyFTo"([[NSRECT]]* noalias nocapture sret, [[OPAQUE4:%.*]]*, i8*) unnamed_addr {{.*}} {
93+
// CHECK: define internal void @"$s17objc_class_export3FooC6boundsSo6NSRectVyFTo"([[NSRECT]]* noalias nocapture sret, [[OPAQUE4:%.*]]*, i8*) {{[#0-9]*}} {
9494
// CHECK: [[CAST:%[a-zA-Z0-9]+]] = bitcast [[OPAQUE4]]* %1 to [[FOO]]*
9595
// CHECK: call swiftcc { double, double, double, double } @"$s17objc_class_export3FooC6boundsSo6NSRectVyF"([[FOO]]* swiftself [[CAST]])
9696

9797
@objc func convertRectToBacking(r r: NSRect) -> NSRect {
9898
return r
9999
}
100-
// CHECK: define internal void @"$s17objc_class_export3FooC20convertRectToBacking1rSo6NSRectVAG_tFTo"([[NSRECT]]* noalias nocapture sret, [[OPAQUE5:%.*]]*, i8*, [[NSRECT]]* byval align 8) unnamed_addr {{.*}} {
100+
// CHECK: define internal void @"$s17objc_class_export3FooC20convertRectToBacking1rSo6NSRectVAG_tFTo"([[NSRECT]]* noalias nocapture sret, [[OPAQUE5:%.*]]*, i8*, [[NSRECT]]* byval align 8) {{[#0-9]*}} {
101101
// CHECK: [[CAST:%[a-zA-Z0-9]+]] = bitcast [[OPAQUE5]]* %1 to [[FOO]]*
102102
// CHECK: call swiftcc { double, double, double, double } @"$s17objc_class_export3FooC20convertRectToBacking1rSo6NSRectVAG_tF"(double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, [[FOO]]* swiftself [[CAST]])
103103

test/IRGen/objc_dealloc.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ bb0(%0 : @unowned $X, %1 : @unowned $SwiftGizmo):
7070
return %7 : $() // id: %8
7171
}
7272

73-
// CHECK: define internal void @"$s12objc_dealloc10SwiftGizmoCfDTo"([[OPAQUE:%.*]]*, i8*) unnamed_addr
73+
// CHECK: define internal void @"$s12objc_dealloc10SwiftGizmoCfDTo"([[OPAQUE:%.*]]*, i8*) {{[#0-9]*}} {
7474
sil [ossa] @$s12objc_dealloc10SwiftGizmoCfDTo : $@convention(objc_method) (SwiftGizmo) -> () {
7575
bb0(%0 : @unowned $SwiftGizmo):
7676
// CHECK-NEXT: entry

test/IRGen/objc_function_merge.swift

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -O %s -module-name=test -o %t/a.out
3+
// RUN: %target-build-swift -O %s -module-name=test -emit-ir | %FileCheck --check-prefix=CHECK-IR %s
4+
// RUN: %target-codesign %t/a.out
5+
// RUN: %target-run %t/a.out | %FileCheck %s
6+
// REQUIRES: executable_test
7+
// REQUIRES: objc_interop
8+
9+
// In some places Foundation is comparing ObjC method pointers.
10+
// Therefore LLVM's function merging pass must not create aliases for identical
11+
// functions, but create thunks. This can be ensured if ObjC methods are not
12+
// created with the unnamed_addr attribute.
13+
14+
import Foundation
15+
16+
class Base: NSObject, NSSecureCoding {
17+
@objc public class var supportsSecureCoding: Bool {
18+
return true
19+
}
20+
21+
@objc let s: String
22+
23+
func encode(with coder: NSCoder) {
24+
coder.encode(s, forKey: #keyPath(s))
25+
}
26+
27+
init(s: String) {
28+
self.s = s
29+
}
30+
31+
required init?(coder: NSCoder) {
32+
self.s = coder.value(forKey: #keyPath(s)) as! String
33+
}
34+
}
35+
36+
class Derived : Base {
37+
// Make sure the overridden method is not merged with the base method (without
38+
// creating a thunk), so that the method pointers remain distinct.
39+
@objc public class override var supportsSecureCoding: Bool {
40+
return true
41+
}
42+
}
43+
44+
45+
// Check if the objc methods are not generated with the unnamed_addr attribute.
46+
// CHECK-IR-DAG: define {{.*}} @"$s4test4BaseC20supportsSecureCodingSbvgZTo"({{[^\)]*}}) #{{[0-9]+}} {
47+
// CHECK-IR-DAG: define {{.*}} @"$s4test4BaseC6encode4withySo7NSCoderC_tFTo"({{[^\)]*}}) #{{[0-9]+}} {
48+
// CHECK-IR-DAG: define {{.*}} @"$s4test7DerivedC20supportsSecureCodingSbvgZTo"({{[^\)]*}}) #{{[0-9]+}} {
49+
50+
let d = Derived(s: "")
51+
if #available(macOS 10.13, iOS 11, tvOS 11, watchOS 4, *) {
52+
// Check that we don't crash here.
53+
_ = try NSKeyedArchiver.archivedData(withRootObject: d, requiringSecureCoding: true)
54+
}
55+
// CHECK: okay
56+
print("okay")

test/IRGen/objc_subscripts.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
@objc class SomeObject {
4444
@objc subscript (i : Int) -> SomeObject {
45-
// CHECK: define internal [[OPAQUE0:%.*]]* @"$s15objc_subscripts10SomeObjectCyACSicigTo"([[OPAQUE1]]*, i8*, i64) unnamed_addr
45+
// CHECK: define internal [[OPAQUE0:%.*]]* @"$s15objc_subscripts10SomeObjectCyACSicigTo"([[OPAQUE1]]*, i8*, i64) {{[#0-9]*}} {
4646
get {
4747
// CHECK: call swiftcc %T15objc_subscripts10SomeObjectC* @"$s15objc_subscripts10SomeObjectCyACSicig"
4848
return self

0 commit comments

Comments
 (0)