Skip to content

Commit 01efb6d

Browse files
committed
Make BufferView prototype more realistic
1 parent c628bc1 commit 01efb6d

File tree

1 file changed

+123
-25
lines changed

1 file changed

+123
-25
lines changed

test/SIL/buffer_view_prototype.swift

Lines changed: 123 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,131 @@
44
// RUN: -enable-experimental-feature NoncopyableGenerics \
55
// RUN: -enable-experimental-lifetime-dependence-inference \
66
// RUN: -Xllvm -enable-lifetime-dependence-diagnostics
7+
8+
// REQUIRES: asserts
9+
// REQUIRES: swift_in_compiler
710
// REQUIRES: noncopyable_generics
811

12+
// Incrementally testing https://github.pie.apple.com/guillaume-l/BufferView with lifetime dependence
13+
14+
// TODO: Use real Range
15+
public struct FakeRange<Bound> {
16+
public let lowerBound: Bound
17+
public let upperBound: Bound
18+
}
19+
20+
// TODO: Use real Optional
21+
public enum FakeOptional<T> {
22+
case none
23+
case some(T)
24+
}
25+
26+
public struct BufferViewIndex<Element> {
27+
let _rawValue: UnsafeRawPointer
28+
29+
internal init(rawValue: UnsafeRawPointer) {
30+
_rawValue = rawValue
31+
}
32+
33+
var isAligned: Bool {
34+
(Int(bitPattern: _rawValue) & (MemoryLayout<Element>.alignment-1)) == 0
35+
}
36+
}
37+
38+
extension BufferViewIndex: Equatable {}
39+
40+
extension BufferViewIndex: Hashable {}
41+
42+
extension BufferViewIndex: Strideable {
43+
public typealias Stride = Int
44+
45+
public func distance(to other: BufferViewIndex) -> Int {
46+
let bytes = _rawValue.distance(to: other._rawValue)
47+
let (q, r) = bytes.quotientAndRemainder(dividingBy: MemoryLayout<Element>.stride)
48+
precondition(r == 0)
49+
return q
50+
}
51+
52+
public func advanced(by n: Int) -> BufferViewIndex {
53+
.init(rawValue: _rawValue.advanced(by: n &* MemoryLayout<Element>.stride))
54+
}
55+
}
56+
57+
extension BufferViewIndex: Comparable {
58+
public static func <(lhs: BufferViewIndex, rhs: BufferViewIndex) -> Bool {
59+
lhs._rawValue < rhs._rawValue
60+
}
61+
}
62+
963
public struct BufferView<Element> : ~Escapable {
10-
public typealias Index = Int
11-
public typealias Pointer = UnsafePointer<Element>
12-
public let baseAddress: Pointer
64+
let start: BufferViewIndex<Element>
1365
public let count: Int
14-
15-
// TODO: This should be a failable initializer
16-
// Currently optional is Escapable, so we cant yet write it.
17-
public init<Storage>(unsafeBuffer: UnsafeBufferPointer<Element>,
18-
storage: borrowing Storage)
19-
-> _borrow(storage) Self {
20-
let baseAddress = unsafeBuffer.baseAddress!
21-
self = BufferView<Element>(baseAddress: baseAddress,
22-
count: unsafeBuffer.count)
23-
return self
24-
}
25-
// unsafe private API
66+
private var baseAddress: UnsafeRawPointer { start._rawValue }
67+
68+
public init<Owner>(
69+
baseAddress: UnsafeRawPointer,
70+
count: Int,
71+
dependsOn owner: borrowing Owner
72+
) {
73+
self.init(
74+
start: .init(rawValue: baseAddress), count: count, dependsOn: owner
75+
)
76+
}
77+
init<Owner>(
78+
start index: BufferViewIndex<Element>,
79+
count: Int,
80+
dependsOn owner: borrowing Owner
81+
) {
82+
precondition(count >= 0, "Count must not be negative")
83+
if !_isPOD(Element.self) {
84+
precondition(
85+
index.isAligned,
86+
"baseAddress must be properly aligned for \(Element.self)"
87+
)
88+
}
89+
self.start = index
90+
self.count = count
91+
}
2692
@_unsafeNonescapableResult
27-
init(baseAddress: Pointer, count: Int) {
93+
init(start index: BufferViewIndex<Element>,
94+
count: Int) {
2895
precondition(count >= 0, "Count must not be negative")
29-
self.baseAddress = baseAddress
96+
if !_isPOD(Element.self) {
97+
precondition(
98+
index.isAligned,
99+
"baseAddress must be properly aligned for \(Element.self)"
100+
)
101+
}
102+
self.start = index
30103
self.count = count
31104
}
32-
subscript(_ index: Index) -> Element? {
33-
if (index < 0 || index >= count) {
34-
return nil
105+
}
106+
// TODO: extend Collection, BidirectionalCollection, RandomAccessCollection {
107+
extension BufferView {
108+
public typealias Index = BufferViewIndex<Element>
109+
public typealias SubSequence = Self
110+
111+
public var startIndex: Index { start }
112+
public var endIndex: Index { start.advanced(by: count) }
113+
114+
public subscript(position: Index) -> Element {
115+
get {
116+
if _isPOD(Element.self) {
117+
return position._rawValue.loadUnaligned(as: Element.self)
118+
}
119+
else {
120+
return position._rawValue.load(as: Element.self)
121+
}
122+
}
123+
}
124+
125+
public subscript(bounds: FakeRange<BufferViewIndex<Element>>) -> Self {
126+
get {
127+
BufferView(
128+
start: bounds.lowerBound,
129+
count: bounds.upperBound.distance(to:bounds.lowerBound) / MemoryLayout<Element>.stride
130+
)
35131
}
36-
return baseAddress[index]
37132
}
38133
}
39134

@@ -47,14 +142,17 @@ extension Array {
47142
// rdar://123071321
48143
var view: BufferView<Element> {
49144
var _view : BufferView<Element>?
50-
withUnsafeBufferPointer {
51-
_view = BufferView(unsafeBuffer: $0, storage: self)
145+
withUnsafePointer(to:self) {
146+
_view = BufferView(baseAddress: $0, count: self.count, dependsOn: self)
52147
}
53148
return _view!
54149
}
55150
}
56151

57-
public func array_view_element(a: [Int] , i: Int) -> Int {
58-
a.view[i]!
152+
public func array_view_element(a: [Int] , i: BufferViewIndex<Int>) -> Int {
153+
a.view[i]
59154
}
60155

156+
public func array_view_slice_element(a: [Int] , sliceIdx: FakeRange<BufferViewIndex<Int>>, Idx: BufferViewIndex<Int>) -> Int {
157+
a.view[sliceIdx][Idx]
158+
}

0 commit comments

Comments
 (0)