Skip to content

Commit 2aa3ee0

Browse files
committed
[Swiftify] Always remove count parameters when possible (#81585)
Previously we did not remove count parameters if any count parameters were shared between count expressions, or if any count expression contained operations. Buffer sizes were also just checked to be larger than or equal than the given count. We now extract the count from Spans/BufferPointers whenever possible, and store that value in a variable at the start of the function. If multiple parameters share the same count, a bounds check is emitted to make sure that they have the same size. Subspans can be used if one span is larger than necessary. The message in the bounds check is changed so that it includes the expected and actual value, to aid in debugging. This patch also fixes some incorrect indentation, and adds the Whitespace.swift test case to act as a regression test in case the indentation changes, since the other test cases don't use significant whitespace. rdar://151488820 rdar://151511090 rdar://146333006 rdar://147715799 (cherry picked from commit f5fa481)
1 parent 7e678c9 commit 2aa3ee0

40 files changed

+669
-265
lines changed

lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift

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

test/Interop/C/swiftify-import/Inputs/counted-by-lifetimebound.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ typedef struct foo opaque_t;
1919
opaque_t * __counted_by(len) opaque(int len, int len2, opaque_t * __counted_by(len2) __lifetimebound p);
2020

2121
int * __counted_by(len) noncountedLifetime(int len, int * __lifetimebound p);
22+
23+
int * __counted_by(13) _Nullable constant(int * __counted_by(13) __lifetimebound _Nullable p);

test/Interop/C/swiftify-import/counted-by-lifetimebound.swift

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ import CountedByLifetimeboundClang
1414
// CHECK: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
1515
// CHECK-NEXT: @lifetime(copy p)
1616
// CHECK-NEXT: @lifetime(p: copy p)
17-
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func complexExpr(_ len: Int32, _ offset: Int32, _ len2: Int32, _ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>
17+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func complexExpr(_ len: Int32, _ offset: Int32, _ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>
18+
19+
// CHECK: /// This is an auto-generated wrapper for safer interop
20+
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
21+
// CHECK-NEXT: @lifetime(copy p)
22+
// CHECK-NEXT: @lifetime(p: copy p)
23+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func constant(_ p: inout MutableSpan<Int32>?) -> MutableSpan<Int32>?
1824

1925
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
2026
// CHECK-NEXT: @lifetime(borrow p)
@@ -38,7 +44,7 @@ import CountedByLifetimeboundClang
3844
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
3945
// CHECK-NEXT: @lifetime(copy p)
4046
// CHECK-NEXT: @lifetime(p: copy p)
41-
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ len: Int32, _ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>
47+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>
4248

4349
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
4450
// CHECK-NEXT: @lifetime(copy p)
@@ -49,7 +55,7 @@ import CountedByLifetimeboundClang
4955
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
5056
@inlinable
5157
public func callComplexExpr(_ p: inout MutableSpan<CInt>) {
52-
let _: MutableSpan<CInt> = complexExpr(73, 37, 42, &p)
58+
let _: MutableSpan<CInt> = complexExpr(73, 37, &p)
5359
}
5460

5561
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@@ -73,7 +79,7 @@ public func callNullable(_ p: inout MutableSpan<CInt>?) {
7379
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
7480
@inlinable
7581
public func callShared(_ p: inout MutableSpan<CInt>) {
76-
let _: MutableSpan<CInt> = shared(CInt(p.count), &p)
82+
let _: MutableSpan<CInt> = shared(&p)
7783
}
7884

7985
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@@ -87,3 +93,9 @@ public func callSimple(_ p: inout MutableSpan<CInt>) {
8793
public func callNoncountedLifetime(_ p: UnsafeMutablePointer<CInt>) {
8894
let _: MutableSpan<CInt> = noncountedLifetime(73, p)
8995
}
96+
97+
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
98+
@inlinable
99+
public func callConstant(_ p: inout MutableSpan<CInt>?) {
100+
let _: MutableSpan<CInt>? = constant(&p)
101+
}

test/Interop/C/swiftify-import/counted-by-noescape.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ import CountedByNoEscapeClang
106106
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
107107
// CHECK-NEXT: @lifetime(p1: copy p1)
108108
// CHECK-NEXT: @lifetime(p2: copy p2)
109-
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ len: Int32, _ p1: inout MutableSpan<Int32>, _ p2: inout MutableSpan<Int32>)
109+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ p1: inout MutableSpan<Int32>, _ p2: inout MutableSpan<Int32>)
110110

111111
// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
112112
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@@ -165,7 +165,7 @@ public func callReturnPointer() {
165165
@lifetime(p2: copy p2)
166166
@inlinable
167167
public func callShared(_ p: inout MutableSpan<CInt>, _ p2: inout MutableSpan<CInt>) {
168-
shared(CInt(p.count), &p, &p2)
168+
shared(&p, &p2)
169169
}
170170

171171
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)

test/Interop/C/swiftify-import/counted-by.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ import CountedByClang
4848
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func scalar(_ m: Int32, _ n: Int32, _ p: UnsafeMutableBufferPointer<Int32>)
4949

5050
// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
51-
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ len: Int{{.*}}, _ p1: UnsafeMutableBufferPointer<Int{{.*}}>, _ p2: UnsafeMutableBufferPointer<Int{{.*}}>)
51+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ p1: UnsafeMutableBufferPointer<Int{{.*}}>, _ p2: UnsafeMutableBufferPointer<Int{{.*}}>)
5252

5353
// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
5454
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func simple(_ p: UnsafeMutableBufferPointer<Int{{.*}}>)
@@ -108,7 +108,7 @@ public func callScalar(_ p: UnsafeMutableBufferPointer<CInt>) {
108108

109109
@inlinable
110110
public func callShared(_ p: UnsafeMutableBufferPointer<CInt>, _ p2: UnsafeMutableBufferPointer<CInt>) {
111-
shared(CInt(p.count), p, p2)
111+
shared(p, p2)
112112
}
113113

114114
@inlinable
@@ -136,4 +136,4 @@ public func callSimpleFlipped(_ p: UnsafeMutableBufferPointer<CInt>) {
136136
@inlinable
137137
public func callSwiftAttr(_ p: UnsafeMutableBufferPointer<CInt>) {
138138
swiftAttr(p)
139-
}
139+
}

test/Interop/C/swiftify-import/sized-by-lifetimebound.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import SizedByLifetimeboundClang
1313

1414
// CHECK: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
1515
// CHECK-NEXT: @lifetime(copy p)
16-
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func complexExpr(_ len: Int32, _ offset: Int32, _ len2: Int32, _ p: RawSpan) -> RawSpan
16+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func complexExpr(_ len: Int32, _ offset: Int32, _ p: RawSpan) -> RawSpan
1717

1818
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
1919
// CHECK-NEXT: @lifetime(copy p)
@@ -37,7 +37,7 @@ import SizedByLifetimeboundClang
3737

3838
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
3939
// CHECK-NEXT: @lifetime(copy p)
40-
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ len: Int32, _ p: RawSpan) -> RawSpan
40+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ p: RawSpan) -> RawSpan
4141

4242
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
4343
// CHECK-NEXT: @lifetime(copy p)
@@ -47,7 +47,7 @@ import SizedByLifetimeboundClang
4747
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
4848
@inlinable
4949
public func callComplexExpr(_ p: RawSpan) {
50-
let _: RawSpan = complexExpr(73, 37, 42, p)
50+
let _: RawSpan = complexExpr(73, 37, p)
5151
}
5252

5353
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@@ -71,7 +71,7 @@ public func callNullable(_ p: RawSpan?) {
7171
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
7272
@inlinable
7373
public func callShared(_ p: RawSpan) {
74-
let _: RawSpan = shared(CInt(p.byteCount), p)
74+
let _: RawSpan = shared(p)
7575
}
7676

7777
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)

test/Interop/C/swiftify-import/sized-by-noescape.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import SizedByNoEscapeClang
3535

3636
// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
3737
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
38-
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ len: Int{{.*}}, _ p1: RawSpan, _ p2: RawSpan)
38+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ p1: RawSpan, _ p2: RawSpan)
3939

4040
// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
4141
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@@ -79,7 +79,7 @@ public func callReturnPointer() {
7979
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
8080
@inlinable
8181
public func callShared(_ p: RawSpan, _ p2: RawSpan) {
82-
shared(CInt(p.byteCount), p, p2)
82+
shared(p, p2)
8383
}
8484

8585
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@@ -92,4 +92,4 @@ public func callSimple(_ p: RawSpan) {
9292
@inlinable
9393
public func callSwiftAttr(_ p: RawSpan) {
9494
swiftAttr(p)
95-
}
95+
}

test/Interop/C/swiftify-import/sized-by.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import SizedByClang
2929
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func returnPointer(_ len: Int{{.*}}) -> UnsafeMutableRawBufferPointer
3030

3131
// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
32-
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ len: Int{{.*}}, _ p1: UnsafeMutableRawBufferPointer, _ p2: UnsafeMutableRawBufferPointer)
32+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ p1: UnsafeMutableRawBufferPointer, _ p2: UnsafeMutableRawBufferPointer)
3333

3434
// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
3535
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func simple(_ p: UnsafeMutableRawBufferPointer)
@@ -70,7 +70,7 @@ public func callReturnPointer() {
7070

7171
@inlinable
7272
public func callShared(_ p: UnsafeMutableRawBufferPointer, _ p2: UnsafeMutableRawBufferPointer) {
73-
shared(CInt(p.count), p, p2)
73+
shared(p, p2)
7474
}
7575

7676
@inlinable

test/Macros/SwiftifyImport/CountedBy/Anonymous.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,28 @@ public func myFunc4(_: UnsafeMutablePointer<CInt>, _ len: CInt) {
2020

2121
// CHECK: @_alwaysEmitIntoClient @_disfavoredOverload
2222
// CHECK-NEXT: public func myFunc(_ _myFunc_param0: UnsafeBufferPointer<CInt>) {
23-
// CHECK-NEXT: return unsafe myFunc(_myFunc_param0.baseAddress!, CInt(exactly: _myFunc_param0.count)!)
23+
// CHECK-NEXT: let _myFunc_param1 = CInt(exactly: unsafe _myFunc_param0.count)!
24+
// CHECK-NEXT: return unsafe myFunc(_myFunc_param0.baseAddress!, _myFunc_param1)
2425
// CHECK-NEXT: }
2526

2627
// CHECK: @_alwaysEmitIntoClient @_disfavoredOverload
2728
// CHECK-NEXT: public func myFunc2(_ _myFunc2_param0: UnsafeBufferPointer<CInt>, _ _myFunc2_param2: CInt) {
28-
// CHECK-NEXT: return unsafe myFunc2(_myFunc2_param0.baseAddress!, CInt(exactly: _myFunc2_param0.count)!, _myFunc2_param2)
29+
// CHECK-NEXT: let _myFunc2_param1 = CInt(exactly: unsafe _myFunc2_param0.count)!
30+
// CHECK-NEXT: return unsafe myFunc2(_myFunc2_param0.baseAddress!, _myFunc2_param1, _myFunc2_param2)
2931
// CHECK-NEXT: }
3032

3133
// CHECK: @_alwaysEmitIntoClient @_disfavoredOverload
3234
// CHECK-NEXT: public func myFunc3(_ _myFunc3_param0: Span<CInt>) {
33-
// CHECK-NEXT: return unsafe _myFunc3_param0.withUnsafeBufferPointer { __myFunc3_param0Ptr in
34-
// CHECK-NEXT: return unsafe myFunc3(__myFunc3_param0Ptr.baseAddress!, CInt(exactly: __myFunc3_param0Ptr.count)!)
35-
// CHECK-NEXT: }
35+
// CHECK-NEXT: let _myFunc3_param1 = CInt(exactly: _myFunc3_param0.count)!
36+
// CHECK-NEXT: return unsafe _myFunc3_param0.withUnsafeBufferPointer { __myFunc3_param0Ptr in
37+
// CHECK-NEXT: return unsafe myFunc3(__myFunc3_param0Ptr.baseAddress!, _myFunc3_param1)
38+
// CHECK-NEXT: }
3639
// CHECK-NEXT: }
3740

3841
// CHECK: @_alwaysEmitIntoClient @lifetime(_myFunc4_param0: copy _myFunc4_param0) @_disfavoredOverload
3942
// CHECK-NEXT: public func myFunc4(_ _myFunc4_param0: inout MutableSpan<CInt>) {
40-
// CHECK-NEXT: return unsafe _myFunc4_param0.withUnsafeMutableBufferPointer { __myFunc4_param0Ptr in
41-
// CHECK-NEXT: return unsafe myFunc4(__myFunc4_param0Ptr.baseAddress!, CInt(exactly: __myFunc4_param0Ptr.count)!)
42-
// CHECK-NEXT: }
43+
// CHECK-NEXT: let _myFunc4_param1 = CInt(exactly: _myFunc4_param0.count)!
44+
// CHECK-NEXT: return unsafe _myFunc4_param0.withUnsafeMutableBufferPointer { __myFunc4_param0Ptr in
45+
// CHECK-NEXT: return unsafe myFunc4(__myFunc4_param0Ptr.baseAddress!, _myFunc4_param1)
46+
// CHECK-NEXT: }
4347
// CHECK-NEXT: }

0 commit comments

Comments
 (0)