|
| 1 | +// RUN: %target-swift-emit-irgen \ |
| 2 | +// RUN: -parse-as-library \ |
| 3 | +// RUN: -enable-builtin-module \ |
| 4 | +// RUN: -enable-experimental-feature NoncopyableGenerics \ |
| 5 | +// RUN: -enable-experimental-feature BorrowingSwitch \ |
| 6 | +// RUN: %s \ |
| 7 | +// RUN: | \ |
| 8 | +// RUN: %FileCheck %s --check-prefix=CHECK-IR |
| 9 | +// RUN: %target-run-simple-swift(-parse-as-library -enable-builtin-module -enable-experimental-feature NoncopyableGenerics -enable-experimental-feature BorrowingSwitch -Xfrontend -sil-verify-all) | %FileCheck %s |
| 10 | +// RUN: %target-run-simple-swift(-O -parse-as-library -enable-builtin-module -enable-experimental-feature NoncopyableGenerics -enable-experimental-feature BorrowingSwitch -Xfrontend -sil-verify-all) | %FileCheck %s |
| 11 | + |
| 12 | +// CHECK-IR-NOT: @"$sBpWV" |
| 13 | + |
| 14 | +// CHECK: hi end |
| 15 | +// CHECK: hi 3 |
| 16 | +// CHECK: hi 2 |
| 17 | +// CHECK: bye 2 |
| 18 | +// CHECK: bye 3 |
| 19 | +// CHECK: bye end |
| 20 | +@main struct App { static func main() { |
| 21 | + let l: List<Int> = .more( |
| 22 | + 2, |
| 23 | + Box( |
| 24 | + .more(3, |
| 25 | + Box( |
| 26 | + .end |
| 27 | + ) |
| 28 | + ) |
| 29 | + ) |
| 30 | + ) |
| 31 | + l.dump(prefix: "hi") |
| 32 | + l.dump(prefix: "bye") |
| 33 | +}} |
| 34 | + |
| 35 | +struct Box<Wrapped: ~Copyable & Dumpable>: ~Copyable { |
| 36 | + let ptr: MyLittlePointer<Wrapped> |
| 37 | + |
| 38 | + init(_ wrapped: consuming Wrapped) { |
| 39 | + wrapped.dump(prefix: "hi") |
| 40 | + ptr = .allocate(capacity: 1) |
| 41 | + ptr.initialize(to: wrapped) |
| 42 | + } |
| 43 | + |
| 44 | + deinit { |
| 45 | + ptr.move().dump(prefix: "bye") |
| 46 | + ptr.deallocate() |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +enum List<Element>: ~Copyable, Dumpable { |
| 51 | + case end |
| 52 | + case more(Element, Box<List<Element>>) |
| 53 | + func dump(prefix: String) { |
| 54 | + switch self { |
| 55 | + case .more(let element, _): |
| 56 | + print(prefix, element) |
| 57 | + case .end: |
| 58 | + print(prefix, "end") |
| 59 | + } |
| 60 | + } |
| 61 | +} |
| 62 | + |
| 63 | +protocol Dumpable : ~Copyable { |
| 64 | + func dump(prefix: String) |
| 65 | +} |
| 66 | + |
| 67 | + |
| 68 | +import Builtin |
| 69 | + |
| 70 | +@frozen |
| 71 | +public enum MyLittleLayout<T : ~Copyable> { |
| 72 | + @_transparent |
| 73 | + public static var size: Int { |
| 74 | + return Int(Builtin.sizeof(T.self)) |
| 75 | + } |
| 76 | + @_transparent |
| 77 | + public static var stride: Int { |
| 78 | + return Int(Builtin.strideof(T.self)) |
| 79 | + } |
| 80 | +} |
| 81 | + |
| 82 | +struct MyLittlePointer<Pointee : ~Copyable> : Copyable { |
| 83 | + public let _rawValue: Builtin.RawPointer |
| 84 | + |
| 85 | + @_transparent |
| 86 | + public init(_ _rawValue: Builtin.RawPointer) { |
| 87 | + self._rawValue = _rawValue |
| 88 | + } |
| 89 | + |
| 90 | + @inlinable |
| 91 | + public static func allocate(capacity count: Int) |
| 92 | + -> MyLittlePointer<Pointee> { |
| 93 | + let size = MyLittleLayout<Pointee>.stride * count |
| 94 | + let align = (0)._builtinWordValue |
| 95 | + let rawPtr = Builtin.allocRaw(size._builtinWordValue, align) |
| 96 | + Builtin.bindMemory(rawPtr, count._builtinWordValue, Pointee.self) |
| 97 | + return MyLittlePointer(rawPtr) |
| 98 | + } |
| 99 | + |
| 100 | + @inlinable |
| 101 | + public func deallocate() { |
| 102 | + Builtin.deallocRaw(_rawValue, (-1)._builtinWordValue, (0)._builtinWordValue) |
| 103 | + } |
| 104 | + |
| 105 | + @inlinable |
| 106 | + public func initialize(to value: consuming Pointee) { |
| 107 | + Builtin.initialize(value, self._rawValue) |
| 108 | + } |
| 109 | + @inlinable |
| 110 | + public func deinitialize(count: Int) { |
| 111 | + Builtin.destroyArray(Pointee.self, _rawValue, count._builtinWordValue) |
| 112 | + } |
| 113 | + @inlinable |
| 114 | + public func move() -> Pointee { |
| 115 | + return Builtin.take(_rawValue) |
| 116 | + } |
| 117 | +} |
0 commit comments