Skip to content

Commit 60a09dd

Browse files
committed
[builtin] Change ConvertStrongToUnownedUnsafe and ConvertUnownedUnsafeToGuaranteed to take non-optional arguments.
1 parent a498004 commit 60a09dd

File tree

2 files changed

+44
-65
lines changed

2 files changed

+44
-65
lines changed

lib/SILGen/SILGenBuiltin.cpp

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,7 +1052,7 @@ emitBuiltinGlobalStringTablePointer(SILGenFunction &SGF, SILLocation loc,
10521052
/// guaranteed arguments, and hence doesn't require the arguments to
10531053
/// be at +1. Therefore, this builtin is emitted specially.
10541054
///
1055-
/// We assume our convention is (T, @inout @unmanaged Optional<T>) -> ()
1055+
/// We assume our convention is (T, @inout @unmanaged T) -> ()
10561056
static ManagedValue emitBuiltinConvertStrongToUnownedUnsafe(
10571057
SILGenFunction &SGF, SILLocation loc, SubstitutionMap subs,
10581058
PreparedArguments &&preparedArgs, SGFContext C) {
@@ -1085,25 +1085,19 @@ static ManagedValue emitBuiltinConvertStrongToUnownedUnsafe(
10851085

10861086
// Make sure our types match up as we expect.
10871087
if (objectSrcValue->getType() !=
1088-
destType.getReferenceStorageReferentType().getOptionalObjectType()) {
1088+
destType.getReferenceStorageReferentType().getObjectType()) {
10891089
llvm::errs()
10901090
<< "Invalid usage of Builtin.convertStrongToUnownedUnsafe. lhsType "
1091-
"must be T and rhsType must be inout unsafe(unowned) Optional<T>"
1091+
"must be T and rhsType must be inout unsafe(unowned) T"
10921092
<< "lhsType: " << objectSrcValue->getType() << "\n"
10931093
<< "rhsType: " << inoutDest->getType() << "\n";
10941094
llvm::report_fatal_error("standard fatal error msg");
10951095
}
10961096

1097-
// Ok. We have the right types. First convert objectSrcValue to its
1098-
// unowned representation.
1099-
SILType optionalType = SILType::getOptionalType(objectSrcValue->getType());
1100-
SILValue someVal =
1101-
SGF.B.createOptionalSome(loc, objectSrcValue, optionalType);
1102-
1103-
SILType unmanagedOptType = someVal->getType().getReferenceStorageType(
1097+
SILType unmanagedOptType = objectSrcValue->getType().getReferenceStorageType(
11041098
SGF.getASTContext(), ReferenceOwnership::Unmanaged);
11051099
SILValue unownedObjectSrcValue = SGF.B.createRefToUnmanaged(
1106-
loc, someVal, unmanagedOptType.getObjectType());
1100+
loc, objectSrcValue, unmanagedOptType.getObjectType());
11071101
SGF.B.emitStoreValueOperation(loc, unownedObjectSrcValue, inoutDest,
11081102
StoreOwnershipQualifier::Trivial);
11091103
return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
@@ -1113,7 +1107,7 @@ static ManagedValue emitBuiltinConvertStrongToUnownedUnsafe(
11131107
///
11141108
/// We assume our convention is:
11151109
///
1116-
/// <BaseT, T> (BaseT, @in_guaranteed @unmanaged Optional<T>) -> @guaranteed T
1110+
/// <BaseT, T> (BaseT, @inout @unowned(unsafe) T) -> @guaranteed T
11171111
///
11181112
static ManagedValue emitBuiltinConvertUnownedUnsafeToGuaranteed(
11191113
SILGenFunction &SGF, SILLocation loc, SubstitutionMap subs,
@@ -1152,14 +1146,8 @@ static ManagedValue emitBuiltinConvertUnownedUnsafeToGuaranteed(
11521146
loc, unownedNonTrivialRef, ValueOwnershipKind::Guaranteed);
11531147
auto guaranteedNonTrivialRefMV =
11541148
SGF.emitManagedBorrowedRValueWithCleanup(guaranteedNonTrivialRef);
1155-
auto someDecl = SGF.getASTContext().getOptionalSomeDecl();
1156-
1157-
// Then unsafely extract from the optional.
1158-
auto extMV =
1159-
SGF.B.createUncheckedEnumData(loc, guaranteedNonTrivialRefMV, someDecl);
1160-
11611149
// Now create a mark dependence on our base and return the result.
1162-
return SGF.B.createMarkDependence(loc, extMV, baseMV);
1150+
return SGF.B.createMarkDependence(loc, guaranteedNonTrivialRefMV, baseMV);
11631151
}
11641152

11651153
Optional<SpecializedEmitter>

test/SILGen/unsafevalue.swift

Lines changed: 37 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,7 @@ import Swift
99
@frozen
1010
public struct UnsafeValue<Element: AnyObject> {
1111
@usableFromInline
12-
internal unowned(unsafe) var _value: Element?
13-
14-
@_transparent
15-
@inlinable
16-
public init() {
17-
_value = nil
18-
}
12+
internal unowned(unsafe) var _value: Element
1913

2014
// Create a new unmanaged value that owns the underlying value. This unmanaged
2115
// value must after use be deinitialized by calling the function deinitialize()
@@ -24,7 +18,7 @@ public struct UnsafeValue<Element: AnyObject> {
2418
@_transparent
2519
@inlinable
2620
public init(copying newValue: __shared Element) {
27-
self.init()
21+
Builtin.retain(newValue)
2822
_value = newValue
2923
}
3024

@@ -34,15 +28,14 @@ public struct UnsafeValue<Element: AnyObject> {
3428
// CHECK-LABEL: sil [transparent] [serialized] [ossa] @$s11unsafevalue11UnsafeValueV14unsafelyAssignACyxGxh_tcfC : $@convention(method) <Element where Element : AnyObject> (@guaranteed Element, @thin UnsafeValue<Element>.Type) -> UnsafeValue<Element> {
3529
// CHECK: bb0([[INPUT_ELEMENT:%.*]] : @guaranteed $Element,
3630
// CHECK: [[BOX:%.*]] = alloc_box
37-
// CHECK: [[UNINIT_BOX:%.*]] = mark_uninitialized [delegatingself] [[BOX]]
31+
// CHECK: [[UNINIT_BOX:%.*]] = mark_uninitialized [rootself] [[BOX]]
3832
// CHECK: [[PROJECT_UNINIT_BOX:%.*]] = project_box [[UNINIT_BOX]]
39-
// CHECK: [[DELEGATING_INIT_RESULT:%.*]] = apply {{%.*}}<Element>(
40-
// CHECK: assign [[DELEGATING_INIT_RESULT]] to [[PROJECT_UNINIT_BOX]]
41-
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT_UNINIT_BOX]]
33+
// CHECK: [[COPY_INPUT_ELEMENT:%.*]] = copy_value [[INPUT_ELEMENT]]
34+
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT_UNINIT_BOX]]
4235
// CHECK: [[STRUCT_ACCESS:%.*]] = struct_element_addr [[ACCESS]]
43-
// CHECK: [[OPT_INPUT_ELEMENT:%.*]] = enum $Optional<Element>, #Optional.some!enumelt.1, [[INPUT_ELEMENT]]
44-
// CHECK: [[UNMANAGED_OPT_INPUT_ELEMENT:%.*]] = ref_to_unmanaged [[OPT_INPUT_ELEMENT]]
45-
// CHECK: store [[UNMANAGED_OPT_INPUT_ELEMENT]] to [trivial] [[STRUCT_ACCESS]]
36+
// CHECK: [[UNMANAGED_INPUT_ELEMENT:%.*]] = ref_to_unmanaged [[COPY_INPUT_ELEMENT]]
37+
// CHECK: assign [[UNMANAGED_INPUT_ELEMENT]] to [[STRUCT_ACCESS]]
38+
// CHECK: destroy_value [[COPY_INPUT_ELEMENT]]
4639
// CHECK: end_access [[ACCESS]]
4740
// CHECK: [[RESULT:%.*]] = load [trivial] [[PROJECT_UNINIT_BOX]]
4841
// CHECK: destroy_value [[UNINIT_BOX]]
@@ -52,89 +45,87 @@ public struct UnsafeValue<Element: AnyObject> {
5245
// CANONICAL-LABEL: sil [transparent] [serialized] @$s11unsafevalue11UnsafeValueV14unsafelyAssignACyxGxh_tcfC : $@convention(method) <Element where Element : AnyObject> (@guaranteed Element, @thin UnsafeValue<Element>.Type) -> UnsafeValue<Element> {
5346
// CANONICAL: bb0([[INPUT_ELEMENT:%.*]] : $Element,
5447
// CANONICAL-NEXT: debug_value
55-
// TODO(gottesmm): release_value on a .none shouldn't exist.
56-
// CANONICAL-NEXT: [[NONE:%.*]] = enum $Optional<Element>, #Optional.none!enumelt
57-
// CANONICAL-NEXT: release_value [[NONE]]
58-
// CANONICAL-NEXT: [[ENUM:%.*]] = enum $Optional<Element>, #Optional.some!enumelt.1, [[INPUT_ELEMENT]]
59-
// CANONICAL-NEXT: [[UNMANAGED_ENUM:%.*]] = ref_to_unmanaged [[ENUM]]
60-
// CANONICAL-NEXT: [[RESULT:%.*]] = struct $UnsafeValue<Element> ([[UNMANAGED_ENUM]] : $@sil_unmanaged Optional<Element>)
61-
// CANONICAL-NEXT: tuple
48+
// CANONICAL-NEXT: [[UNMANAGED_ELEMENT:%.*]] = ref_to_unmanaged [[INPUT_ELEMENT]]
49+
// CANONICAL-NEXT: [[RESULT:%.*]] = struct $UnsafeValue<Element> ([[UNMANAGED_ELEMENT]] : $@sil_unmanaged Element)
6250
// CANONICAL-NEXT: return [[RESULT]]
6351
// CANONICAL: } // end sil function '$s11unsafevalue11UnsafeValueV14unsafelyAssignACyxGxh_tcfC'
6452
//
6553
// OPT-LABEL: sil [transparent] @$s11unsafevalue11UnsafeValueV14unsafelyAssignACyxGxh_tcfC : $@convention(method) <Element where Element : AnyObject> (@guaranteed Element, @thin UnsafeValue<Element>.Type) -> UnsafeValue<Element> {
6654
// OPT: bb0([[INPUT_ELEMENT:%.*]] : $Element,
6755
// OPT-NEXT: debug_value
68-
// OPT-NEXT: [[ENUM:%.*]] = enum $Optional<Element>, #Optional.some!enumelt.1, [[INPUT_ELEMENT]]
69-
// OPT-NEXT: [[UNMANAGED_ENUM:%.*]] = ref_to_unmanaged [[ENUM]]
70-
// OPT-NEXT: [[RESULT:%.*]] = struct $UnsafeValue<Element> ([[UNMANAGED_ENUM]] : $@sil_unmanaged Optional<Element>)
56+
// OPT-NEXT: [[UNMANAGED_ELEMENT:%.*]] = ref_to_unmanaged [[INPUT_ELEMENT]]
57+
// OPT-NEXT: [[RESULT:%.*]] = struct $UnsafeValue<Element> ([[UNMANAGED_ELEMENT]] : $@sil_unmanaged Element)
7158
// OPT-NEXT: return [[RESULT]]
7259
// OPT: } // end sil function '$s11unsafevalue11UnsafeValueV14unsafelyAssignACyxGxh_tcfC'
7360
@_transparent
7461
@inlinable
7562
public init(unsafelyAssign newValue: __shared Element) {
76-
self.init()
77-
Builtin.convertStrongToUnownedUnsafe(newValue, &_value)
63+
_value = newValue
7864
}
7965

8066
// Access the underlying value at +0, guaranteeing its lifetime by base.
8167
//
82-
// CHECK-LABEL: sil [transparent] [serialized] [ossa] @$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base1fqd_0_qd___qd_0_xXEtr0_lF : $@convention(method) <Element where Element : AnyObject><Base, Result> (@in_guaranteed Base, @noescape @callee_guaranteed (@guaranteed Element) -> @out Result, UnsafeValue<Element>) -> @out Result {
68+
// CHECK-LABEL: sil [transparent] [serialized] [ossa] @$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base_qd_0_qd___qd_0_xXEtr0_lF : $@convention(method) <Element where Element : AnyObject><Base, Result> (@in_guaranteed Base, @noescape @callee_guaranteed (@guaranteed Element) -> @out Result, UnsafeValue<Element>) -> @out Result {
8369
// CHECK: bb0([[RESULT:%.*]] : $*Result, [[BASE:%.*]] : $*Base, [[CLOSURE:%.*]] : $@noescape @callee_guaranteed (@guaranteed Element) -> @out Result, [[UNSAFE_VALUE:%.*]] : $UnsafeValue<Element>):
8470
// CHECK: [[COPY_BOX:%.*]] = alloc_box
8571
// CHECK: [[COPY_PROJ:%.*]] = project_box [[COPY_BOX]]
8672
// CHECK: store [[UNSAFE_VALUE]] to [trivial] [[COPY_PROJ]]
8773
// CHECK: [[VALUE_ADDR:%.*]] = begin_access [read] [unknown] [[COPY_PROJ]]
8874
// CHECK: [[STR_VALUE_ADDR:%.*]] = struct_element_addr [[VALUE_ADDR]]
8975
// CHECK: [[UNMANAGED_VALUE:%.*]] = load [trivial] [[STR_VALUE_ADDR]]
90-
// CHECK: [[UNOWNED_REF_OPTIONAL:%.*]] = unmanaged_to_ref [[UNMANAGED_VALUE]]
91-
// CHECK: [[GUARANTEED_REF_OPTIONAL:%.*]] = unchecked_ownership_conversion [[UNOWNED_REF_OPTIONAL]]
92-
// CHECK: [[GUARANTEED_REF:%.*]] = unchecked_enum_data [[GUARANTEED_REF_OPTIONAL]]
76+
// CHECK: [[UNOWNED_REF:%.*]] = unmanaged_to_ref [[UNMANAGED_VALUE]]
77+
// CHECK: [[GUARANTEED_REF:%.*]] = unchecked_ownership_conversion [[UNOWNED_REF]]
9378
// CHECK: [[GUARANTEED_REF_DEP_ON_BASE:%.*]] = mark_dependence [[GUARANTEED_REF]] : $Element on [[BASE]]
9479
// CHECK: end_access [[VALUE_ADDR]]
9580
// CHECK: apply [[CLOSURE]]([[RESULT]], [[GUARANTEED_REF_DEP_ON_BASE]])
96-
// CHECK: end_borrow [[GUARANTEED_REF_OPTIONAL]]
81+
// CHECK: end_borrow [[GUARANTEED_REF]]
9782
// CHECK: destroy_value [[COPY_BOX]]
98-
// CHECK: } // end sil function '$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base1fqd_0_qd___qd_0_xXEtr0_lF'
83+
// CHECK: } // end sil function '$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base_qd_0_qd___qd_0_xXEtr0_lF'
9984
//
100-
// CANONICAL-LABEL: sil [transparent] [serialized] @$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base1fqd_0_qd___qd_0_xXEtr0_lF : $@convention(method) <Element where Element : AnyObject><Base, Result> (@in_guaranteed Base, @noescape @callee_guaranteed (@guaranteed Element) -> @out Result, UnsafeValue<Element>) -> @out Result {
85+
// CANONICAL-LABEL: sil [transparent] [serialized] @$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base_qd_0_qd___qd_0_xXEtr0_lF : $@convention(method) <Element where Element : AnyObject><Base, Result> (@in_guaranteed Base, @noescape @callee_guaranteed (@guaranteed Element) -> @out Result, UnsafeValue<Element>) -> @out Result {
10186
// CANONICAL: bb0([[RESULT:%.*]] : $*Result, [[BASE:%.*]] : $*Base, [[CLOSURE:%.*]] : $@noescape @callee_guaranteed (@guaranteed Element) -> @out Result, [[UNSAFE_VALUE:%.*]] : $UnsafeValue<Element>):
10287
// CANONICAL: [[UNMANAGED_VALUE:%.*]] = struct_extract [[UNSAFE_VALUE]]
103-
// CANONICAL: [[UNOWNED_REF_OPTIONAL:%.*]] = unmanaged_to_ref [[UNMANAGED_VALUE]]
104-
// CANONICAL: [[GUARANTEED_REF:%.*]] = unchecked_enum_data [[UNOWNED_REF_OPTIONAL]]
105-
// CANONICAL: [[GUARANTEED_REF_DEP_ON_BASE:%.*]] = mark_dependence [[GUARANTEED_REF]] : $Element on [[BASE]]
88+
// CANONICAL: [[UNOWNED_REF:%.*]] = unmanaged_to_ref [[UNMANAGED_VALUE]]
89+
// CANONICAL: [[GUARANTEED_REF_DEP_ON_BASE:%.*]] = mark_dependence [[UNOWNED_REF]] : $Element on [[BASE]]
10690
// CANONICAL: apply [[CLOSURE]]([[RESULT]], [[GUARANTEED_REF_DEP_ON_BASE]])
107-
// CANONICAL: } // end sil function '$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base1fqd_0_qd___qd_0_xXEtr0_lF'
91+
// CANONICAL: } // end sil function '$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base_qd_0_qd___qd_0_xXEtr0_lF'
10892
//
109-
// OPT-LABEL: sil [transparent] @$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base1fqd_0_qd___qd_0_xXEtr0_lF : $@convention(method) <Element where Element : AnyObject><Base, Result> (@in_guaranteed Base, @noescape @callee_guaranteed (@guaranteed Element) -> @out Result, UnsafeValue<Element>) -> @out Result {
93+
// OPT-LABEL: sil [transparent] @$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base_qd_0_qd___qd_0_xXEtr0_lF : $@convention(method) <Element where Element : AnyObject><Base, Result> (@in_guaranteed Base, @noescape @callee_guaranteed (@guaranteed Element) -> @out Result, UnsafeValue<Element>) -> @out Result {
11094
// OPT: bb0([[RESULT:%.*]] : $*Result, [[BASE:%.*]] : $*Base, [[CLOSURE:%.*]] : $@noescape @callee_guaranteed (@guaranteed Element) -> @out Result, [[UNSAFE_VALUE:%.*]] : $UnsafeValue<Element>):
11195
// OPT: [[UNMANAGED_VALUE:%.*]] = struct_extract [[UNSAFE_VALUE]]
112-
// OPT: [[UNOWNED_REF_OPTIONAL:%.*]] = unmanaged_to_ref [[UNMANAGED_VALUE]]
113-
// OPT: [[GUARANTEED_REF:%.*]] = unchecked_enum_data [[UNOWNED_REF_OPTIONAL]]
114-
// OPT: [[GUARANTEED_REF_DEP_ON_BASE:%.*]] = mark_dependence [[GUARANTEED_REF]] : $Element on [[BASE]]
96+
// OPT: [[UNOWNED_REF:%.*]] = unmanaged_to_ref [[UNMANAGED_VALUE]]
97+
// OPT: [[GUARANTEED_REF_DEP_ON_BASE:%.*]] = mark_dependence [[UNOWNED_REF]] : $Element on [[BASE]]
11598
// OPT: apply [[CLOSURE]]([[RESULT]], [[GUARANTEED_REF_DEP_ON_BASE]])
116-
// OPT: } // end sil function '$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base1fqd_0_qd___qd_0_xXEtr0_lF'
99+
// OPT: } // end sil function '$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base_qd_0_qd___qd_0_xXEtr0_lF'
117100
@_transparent
118101
@inlinable
119-
func withGuaranteeingBase<Base, Result>(base: Base, f: (Element) -> Result) -> Result {
102+
func withGuaranteeingBase<Base, Result>(base: Base, _ f: (Element) -> Result) -> Result {
120103
// Just so we can not mark self as mutating. This is just a bitwise copy.
121104
var tmp = self
122105
return f(Builtin.convertUnownedUnsafeToGuaranteed(base, &tmp._value))
123106
}
124107

108+
@_transparent
109+
@inlinable
110+
func assumingGuaranteeingBase<Result>(_ f: (Element) -> Result) -> Result {
111+
// Just so we can not mark self as mutating. This is just a bitwise copy.
112+
let fakeBase: Int? = nil
113+
return withGuaranteeingBase(base: fakeBase, f)
114+
}
115+
125116
// If the unmanaged value was initialized with a copy, release the underlying value.
126117
//
127118
// This will insert a release that can not be removed by the optimizer.
128119
@_transparent
129120
@inlinable
130121
mutating func deinitialize() {
131-
_value = nil
122+
Builtin.release(_value)
132123
}
133124

134125
// Return a new strong reference to the unmanaged value.
135126
//
136127
// This will insert a retain that can not be removed by the optimizer!
137128
@_transparent
138129
@inlinable
139-
public var strongRef: Element { _value.unsafelyUnwrapped }
130+
public var strongRef: Element { _value }
140131
}

0 commit comments

Comments
 (0)