Skip to content

Commit f5fa481

Browse files
authored
[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
1 parent 331f098 commit f5fa481

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
@@ -15,7 +15,13 @@ import CountedByLifetimeboundClang
1515
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
1616
// CHECK-NEXT: @lifetime(copy p)
1717
// CHECK-NEXT: @lifetime(p: copy p)
18-
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func complexExpr(_ len: Int32, _ offset: Int32, _ len2: Int32, _ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>
18+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func complexExpr(_ len: Int32, _ offset: Int32, _ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>
19+
20+
// CHECK: /// This is an auto-generated wrapper for safer interop
21+
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
22+
// CHECK-NEXT: @lifetime(copy p)
23+
// CHECK-NEXT: @lifetime(p: copy p)
24+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func constant(_ p: inout MutableSpan<Int32>?) -> MutableSpan<Int32>?
1925

2026
// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
2127
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@@ -44,7 +50,7 @@ import CountedByLifetimeboundClang
4450
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
4551
// CHECK-NEXT: @lifetime(copy p)
4652
// CHECK-NEXT: @lifetime(p: copy p)
47-
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ len: Int32, _ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>
53+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>
4854

4955
// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
5056
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@@ -56,7 +62,7 @@ import CountedByLifetimeboundClang
5662
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
5763
@inlinable
5864
public func callComplexExpr(_ p: inout MutableSpan<CInt>) {
59-
let _: MutableSpan<CInt> = complexExpr(73, 37, 42, &p)
65+
let _: MutableSpan<CInt> = complexExpr(73, 37, &p)
6066
}
6167

6268
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@@ -80,7 +86,7 @@ public func callNullable(_ p: inout MutableSpan<CInt>?) {
8086
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
8187
@inlinable
8288
public func callShared(_ p: inout MutableSpan<CInt>) {
83-
let _: MutableSpan<CInt> = shared(CInt(p.count), &p)
89+
let _: MutableSpan<CInt> = shared(&p)
8490
}
8591

8692
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@@ -94,3 +100,9 @@ public func callSimple(_ p: inout MutableSpan<CInt>) {
94100
public func callNoncountedLifetime(_ p: UnsafeMutablePointer<CInt>) {
95101
let _: MutableSpan<CInt> = noncountedLifetime(73, p)
96102
}
103+
104+
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
105+
@inlinable
106+
public func callConstant(_ p: inout MutableSpan<CInt>?) {
107+
let _: MutableSpan<CInt>? = constant(&p)
108+
}

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
@@ -14,7 +14,7 @@ import SizedByLifetimeboundClang
1414
// CHECK: /// This is an auto-generated wrapper for safer interop
1515
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
1616
// CHECK-NEXT: @lifetime(copy p)
17-
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func complexExpr(_ len: Int32, _ offset: Int32, _ len2: Int32, _ p: RawSpan) -> RawSpan
17+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func complexExpr(_ len: Int32, _ offset: Int32, _ p: RawSpan) -> RawSpan
1818

1919
// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
2020
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@@ -44,7 +44,7 @@ import SizedByLifetimeboundClang
4444
// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
4545
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
4646
// CHECK-NEXT: @lifetime(copy p)
47-
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ len: Int32, _ p: RawSpan) -> RawSpan
47+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ p: RawSpan) -> RawSpan
4848

4949
// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
5050
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@@ -55,7 +55,7 @@ import SizedByLifetimeboundClang
5555
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
5656
@inlinable
5757
public func callComplexExpr(_ p: RawSpan) {
58-
let _: RawSpan = complexExpr(73, 37, 42, p)
58+
let _: RawSpan = complexExpr(73, 37, p)
5959
}
6060

6161
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@@ -79,7 +79,7 @@ public func callNullable(_ p: RawSpan?) {
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) {
82-
let _: RawSpan = shared(CInt(p.byteCount), p)
82+
let _: RawSpan = shared(p)
8383
}
8484

8585
@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)