File: unsafevalue.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (137 lines) | stat: -rw-r--r-- 8,155 bytes parent folder | download
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 }
}