1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
// RUN: %target-swift-emit-silgen -parse-stdlib %s -disable-access-control -disable-objc-attr-requires-foundation-module -enable-objc-interop | %FileCheck %s
// RUN: %target-swift-emit-sil -Onone -parse-stdlib %s -disable-access-control -disable-objc-attr-requires-foundation-module -enable-objc-interop | %FileCheck -check-prefix=CANONICAL %s
// RUN: %target-swift-emit-sil -O -parse-stdlib %s -disable-access-control -disable-objc-attr-requires-foundation-module -enable-objc-interop | %FileCheck -check-prefix=OPT %s
import Swift
// Eventually element will be unconstrained, but for testing this builtin, we
// should use it this way.
@frozen
public struct UnsafeValue<Element: AnyObject> {
@usableFromInline
internal unowned(unsafe) var _value: Element
// Create a new unmanaged value that owns the underlying value. This unmanaged
// value must after use be deinitialized by calling the function deinitialize()
//
// This will insert a retain that the optimizer can not remove!
@_transparent
@inlinable
public init(copying newValue: __shared Element) {
Builtin.retain(newValue)
_value = newValue
}
// Create a new unmanaged value that unsafely produces a new
// unmanaged value without introducing any rr traffic.
//
// CHECK-LABEL: sil [transparent] [serialized] [ossa] @$s11unsafevalue11UnsafeValueV14unsafelyAssignACyxGxh_tcfC : $@convention(method) <Element where Element : AnyObject> (@guaranteed Element, @thin UnsafeValue<Element>.Type) -> UnsafeValue<Element> {
// CHECK: bb0([[INPUT_ELEMENT:%.*]] : @guaranteed $Element,
// CHECK: [[BOX:%.*]] = alloc_box
// CHECK: [[UNINIT_BOX:%.*]] = mark_uninitialized [rootself] [[BOX]]
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [var_decl] [[UNINIT_BOX]]
// CHECK: [[PROJECT_UNINIT_BOX:%.*]] = project_box [[BOX_LIFETIME]]
// CHECK: [[COPY_INPUT_ELEMENT:%.*]] = copy_value [[INPUT_ELEMENT]]
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT_UNINIT_BOX]]
// CHECK: [[STRUCT_ACCESS:%.*]] = struct_element_addr [[ACCESS]]
// CHECK: [[UNMANAGED_INPUT_ELEMENT:%.*]] = ref_to_unmanaged [[COPY_INPUT_ELEMENT]]
// CHECK: assign [[UNMANAGED_INPUT_ELEMENT]] to [[STRUCT_ACCESS]]
// CHECK: destroy_value [[COPY_INPUT_ELEMENT]]
// CHECK: end_access [[ACCESS]]
// CHECK: [[RESULT:%.*]] = load [trivial] [[PROJECT_UNINIT_BOX]]
// CHECK: destroy_value [[UNINIT_BOX]]
// CHECK: return [[RESULT]]
// CHECK: } // end sil function '$s11unsafevalue11UnsafeValueV14unsafelyAssignACyxGxh_tcfC'
//
// CANONICAL-LABEL: sil [transparent] @$s11unsafevalue11UnsafeValueV14unsafelyAssignACyxGxh_tcfC : $@convention(method) <Element where Element : AnyObject> (@guaranteed Element, @thin UnsafeValue<Element>.Type) -> UnsafeValue<Element> {
// CANONICAL: bb0([[INPUT_ELEMENT:%.*]] : $Element,
// CANONICAL-NEXT: debug_value
// CANONICAL-NEXT: strong_retain [[INPUT_ELEMENT]]
// CANONICAL-NEXT: [[UNMANAGED_ELEMENT:%.*]] = ref_to_unmanaged [[INPUT_ELEMENT]]
// CANONICAL-NEXT: strong_release [[INPUT_ELEMENT]]
// CANONICAL-NEXT: [[RESULT:%.*]] = struct $UnsafeValue<Element> ([[UNMANAGED_ELEMENT]] : $@sil_unmanaged Element)
// CANONICAL-NEXT: return [[RESULT]]
// CANONICAL: } // end sil function '$s11unsafevalue11UnsafeValueV14unsafelyAssignACyxGxh_tcfC'
//
// OPT-LABEL: sil [transparent] @$s11unsafevalue11UnsafeValueV14unsafelyAssignACyxGxh_tcfC : $@convention(method) <Element where Element : AnyObject> (@guaranteed Element, @thin UnsafeValue<Element>.Type) -> UnsafeValue<Element> {
// OPT: bb0([[INPUT_ELEMENT:%.*]] : $Element,
// OPT-NEXT: debug_value
// OPT-NEXT: [[UNMANAGED_ELEMENT:%.*]] = ref_to_unmanaged [[INPUT_ELEMENT]]
// OPT-NEXT: [[RESULT:%.*]] = struct $UnsafeValue<Element> ([[UNMANAGED_ELEMENT]] : $@sil_unmanaged Element)
// OPT-NEXT: return [[RESULT]]
// OPT: } // end sil function '$s11unsafevalue11UnsafeValueV14unsafelyAssignACyxGxh_tcfC'
@_transparent
@inlinable
public init(unsafelyAssign newValue: __shared Element) {
_value = newValue
}
// Access the underlying value at +0, guaranteeing its lifetime by base.
//
// CHECK-LABEL: sil [transparent] [serialized] [ossa] @$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base_qd_0_qd___qd_0_xXEtr0_lF :
// CHECK: bb0([[RESULT:%.*]] : $*Result, [[BASE:%.*]] : $*Base, [[CLOSURE:%.*]] : @guaranteed $@noescape @callee_guaranteed {{.*}}, [[UNSAFE_VALUE:%.*]] : $UnsafeValue<Element>):
// CHECK: [[COPY_BOX:%.*]] = alloc_box
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [var_decl] [[COPY_BOX]]
// CHECK: [[COPY_PROJ:%.*]] = project_box [[BOX_LIFETIME]]
// CHECK: store [[UNSAFE_VALUE]] to [trivial] [[COPY_PROJ]]
// CHECK: [[CLOSUREC:%.*]] = copy_value [[CLOSURE]]
// CHECK: [[VALUE_ADDR:%.*]] = begin_access [read] [unknown] [[COPY_PROJ]]
// CHECK: [[STR_VALUE_ADDR:%.*]] = struct_element_addr [[VALUE_ADDR]]
// CHECK: [[UNMANAGED_VALUE:%.*]] = load [trivial] [[STR_VALUE_ADDR]]
// CHECK: [[UNOWNED_REF:%.*]] = unmanaged_to_ref [[UNMANAGED_VALUE]]
// CHECK: [[GUARANTEED_REF:%.*]] = unchecked_ownership_conversion [[UNOWNED_REF]]
// CHECK: [[GUARANTEED_REF_DEP_ON_BASE:%.*]] = mark_dependence [[GUARANTEED_REF]] : $Element on [[BASE]]
// CHECK: end_access [[VALUE_ADDR]]
// CHECK: [[CLOSUREB:%.*]] = begin_borrow [[CLOSUREC]]
// CHECK: apply [[CLOSUREB]]([[RESULT]], [[GUARANTEED_REF_DEP_ON_BASE]])
// CHECK: end_borrow [[GUARANTEED_REF]]
// CHECK: destroy_value [[COPY_BOX]]
// CHECK: } // end sil function '$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base_qd_0_qd___qd_0_xXEtr0_lF'
//
// CANONICAL-LABEL: sil [transparent] @$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base_qd_0_qd___qd_0_xXEtr0_lF :
// CANONICAL: bb0([[RESULT:%.*]] : $*Result, [[BASE:%.*]] : $*Base, [[CLOSURE:%.*]] : $@noescape @callee_guaranteed {{.*}}, [[UNSAFE_VALUE:%.*]] : $UnsafeValue<Element>):
// CANONICAL: [[UNMANAGED_VALUE:%.*]] = struct_extract [[UNSAFE_VALUE]]
// CANONICAL: [[UNOWNED_REF:%.*]] = unmanaged_to_ref [[UNMANAGED_VALUE]]
// CANONICAL: [[GUARANTEED_REF_DEP_ON_BASE:%.*]] = mark_dependence [[UNOWNED_REF]] : $Element on [[BASE]]
// CANONICAL: apply [[CLOSURE]]([[RESULT]], [[GUARANTEED_REF_DEP_ON_BASE]])
// CANONICAL: } // end sil function '$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base_qd_0_qd___qd_0_xXEtr0_lF'
//
// OPT-LABEL: sil [transparent] {{.*}}@$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base_qd_0_qd___qd_0_xXEtr0_lF :
// OPT: bb0([[RESULT:%.*]] : $*Result, [[BASE:%.*]] : $*Base, [[CLOSURE:%.*]] : $@noescape @callee_guaranteed {{.*}}, [[UNSAFE_VALUE:%.*]] : $UnsafeValue<Element>):
// OPT: [[UNMANAGED_VALUE:%.*]] = struct_extract [[UNSAFE_VALUE]]
// OPT: [[UNOWNED_REF:%.*]] = unmanaged_to_ref [[UNMANAGED_VALUE]]
// OPT: [[GUARANTEED_REF_DEP_ON_BASE:%.*]] = mark_dependence [[UNOWNED_REF]] : $Element on [[BASE]]
// OPT: apply [[CLOSURE]]([[RESULT]], [[GUARANTEED_REF_DEP_ON_BASE]])
// OPT: } // end sil function '$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base_qd_0_qd___qd_0_xXEtr0_lF'
@_transparent
@inlinable
func withGuaranteeingBase<Base, Result>(base: Base, _ f: (Element) -> Result) -> Result {
// Just so we can not mark self as mutating. This is just a bitwise copy.
var tmp = self
return f(Builtin.convertUnownedUnsafeToGuaranteed(base, &tmp._value))
}
@_transparent
@inlinable
func assumingGuaranteeingBase<Result>(_ f: (Element) -> Result) -> Result {
// Just so we can not mark self as mutating. This is just a bitwise copy.
let fakeBase: Int? = nil
return withGuaranteeingBase(base: fakeBase, f)
}
// If the unmanaged value was initialized with a copy, release the underlying value.
//
// This will insert a release that can not be removed by the optimizer.
@_transparent
@inlinable
mutating func deinitialize() {
Builtin.release(_value)
}
// Return a new strong reference to the unmanaged value.
//
// This will insert a retain that can not be removed by the optimizer!
@_transparent
@inlinable
public var strongRef: Element { _value }
}
|