Skip to content

Commit 18004f8

Browse files
committed
[sil-opaque-values] Fix SILGen and ownership of open_existential_box_value.
1 parent 8455718 commit 18004f8

File tree

6 files changed

+58
-9
lines changed

6 files changed

+58
-9
lines changed

lib/SIL/SILOwnershipVerifier.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ static bool isGuaranteedForwardingValueKind(ValueKind K) {
221221
case ValueKind::TupleExtractInst:
222222
case ValueKind::StructExtractInst:
223223
case ValueKind::OpenExistentialValueInst:
224+
case ValueKind::OpenExistentialBoxValueInst:
224225
return true;
225226
default:
226227
return isOwnershipForwardingValueKind(K);
@@ -467,6 +468,7 @@ NO_OPERAND_INST(KeyPath)
467468
}
468469
CONSTANT_OWNERSHIP_INST(Guaranteed, MustBeLive, RefElementAddr)
469470
CONSTANT_OWNERSHIP_INST(Guaranteed, MustBeLive, OpenExistentialValue)
471+
CONSTANT_OWNERSHIP_INST(Guaranteed, MustBeLive, OpenExistentialBoxValue)
470472
CONSTANT_OWNERSHIP_INST(Owned, MustBeInvalidated, AutoreleaseValue)
471473
CONSTANT_OWNERSHIP_INST(Owned, MustBeInvalidated, DeallocBox)
472474
CONSTANT_OWNERSHIP_INST(Owned, MustBeInvalidated, DeallocExistentialBox)
@@ -613,7 +615,6 @@ ACCEPTS_ANY_NONTRIVIAL_OWNERSHIP(MustBeLive, BridgeObjectToWord)
613615
ACCEPTS_ANY_NONTRIVIAL_OWNERSHIP(MustBeLive, CopyBlock)
614616
ACCEPTS_ANY_NONTRIVIAL_OWNERSHIP(MustBeLive, DynamicMethod)
615617
ACCEPTS_ANY_NONTRIVIAL_OWNERSHIP(MustBeLive, OpenExistentialBox)
616-
ACCEPTS_ANY_NONTRIVIAL_OWNERSHIP(MustBeLive, OpenExistentialBoxValue)
617618
ACCEPTS_ANY_NONTRIVIAL_OWNERSHIP(MustBeLive, RefTailAddr)
618619
ACCEPTS_ANY_NONTRIVIAL_OWNERSHIP(MustBeLive, RefToRawPointer)
619620
ACCEPTS_ANY_NONTRIVIAL_OWNERSHIP(MustBeLive, RefToUnmanaged)

lib/SIL/ValueOwnershipKindClassifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Guaranteed, TupleExtract)
139139
// without additional work, in SIL we require opened archetypes to
140140
// be borrowed sub-objects of the parent CoW box.
141141
CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Guaranteed, OpenExistentialValue)
142+
CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Guaranteed, OpenExistentialBoxValue)
142143
CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Owned, UnconditionalCheckedCastValue)
143144

144145
// unchecked_bitwise_cast is a bitwise copy. It produces a trivial or unowned
@@ -287,7 +288,6 @@ FORWARDING_OWNERSHIP_INST(BridgeObjectToRef)
287288
FORWARDING_OWNERSHIP_INST(ConvertFunction)
288289
FORWARDING_OWNERSHIP_INST(InitExistentialRef)
289290
FORWARDING_OWNERSHIP_INST(OpenExistentialRef)
290-
FORWARDING_OWNERSHIP_INST(OpenExistentialBoxValue)
291291
FORWARDING_OWNERSHIP_INST(RefToBridgeObject)
292292
FORWARDING_OWNERSHIP_INST(SelectValue)
293293
FORWARDING_OWNERSHIP_INST(Object)

lib/SILGen/SILGenBuilder.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,15 @@ ManagedValue SILGenBuilder::createOpenExistentialValue(SILLocation loc,
665665
return ManagedValue::forUnmanaged(openedExistential);
666666
}
667667

668+
ManagedValue SILGenBuilder::createOpenExistentialBoxValue(SILLocation loc,
669+
ManagedValue original,
670+
SILType type) {
671+
ManagedValue borrowedExistential = original.borrow(SGF, loc);
672+
SILValue openedExistential = SILBuilder::createOpenExistentialBoxValue(
673+
loc, borrowedExistential.getValue(), type);
674+
return ManagedValue::forUnmanaged(openedExistential);
675+
}
676+
668677
ManagedValue SILGenBuilder::createStore(SILLocation loc, ManagedValue value,
669678
SILValue address,
670679
StoreOwnershipQualifier qualifier) {

lib/SILGen/SILGenBuilder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,10 @@ class SILGenBuilder : public SILBuilder {
284284
ManagedValue createOpenExistentialValue(SILLocation loc,
285285
ManagedValue original, SILType type);
286286

287+
using SILBuilder::createOpenExistentialBoxValue;
288+
ManagedValue createOpenExistentialBoxValue(SILLocation loc,
289+
ManagedValue original, SILType type);
290+
287291
using SILBuilder::createOptionalSome;
288292
ManagedValue createOptionalSome(SILLocation Loc, ManagedValue Arg);
289293
ManagedValue createManagedOptionalNone(SILLocation Loc, SILType Type);

lib/SILGen/SILGenConvert.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -905,9 +905,8 @@ SILGenFunction::emitOpenExistential(
905905
loweredOpenedType));
906906
} else {
907907
assert(!silConv.useLoweredAddresses());
908-
archetypeMV = ManagedValue::forUnmanaged(
909-
B.createOpenExistentialBoxValue(loc, existentialValue.getValue(),
910-
loweredOpenedType));
908+
archetypeMV = getBuilder().createOpenExistentialBoxValue(
909+
loc, existentialValue, loweredOpenedType);
911910
}
912911
// NB: Don't forward the cleanup, because consuming a boxed value won't
913912
// consume the box reference.

test/SILGen/opaque_ownership.swift

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// RUN: %target-swift-frontend -enable-sil-opaque-values -enable-sil-ownership -emit-sorted-sil -Xllvm -sil-full-demangle -emit-silgen -parse-stdlib -parse-as-library -module-name Swift %s | %FileCheck %s
2+
// RUN: %target-swift-frontend -target x86_64-apple-macosx10.9 -enable-sil-opaque-values -enable-sil-ownership -emit-sorted-sil -Xllvm -sil-full-demangle -emit-silgen -parse-stdlib -parse-as-library -module-name Swift %s | %FileCheck --check-prefix=CHECK-OSX %s
23

34
public typealias AnyObject = Builtin.AnyObject
45

56
precedencegroup CastingPrecedence {}
7+
precedencegroup AssignmentPrecedence {}
68

79
public protocol _ObjectiveCBridgeable {}
810

@@ -16,12 +18,12 @@ public protocol Decoder {
1618

1719
// Test open_existential_value ownership
1820
// ---
19-
// CHECK-LABEL: sil @_T0s11takeDecoderBi1_s0B0_p4from_tKF : $@convention(thin) (@in Decoder) -> (Builtin.Int1, @error Builtin.NativeObject) {
21+
// CHECK-LABEL: sil @_T0s11takeDecoderBi1_s0B0_p4from_tKF : $@convention(thin) (@in Decoder) -> (Builtin.Int1, @error Error) {
2022
// CHECK: bb0(%0 : @owned $Decoder):
2123
// CHECK: [[BORROW1:%.*]] = begin_borrow %0 : $Decoder
2224
// CHECK: [[OPENED:%.*]] = open_existential_value [[BORROW1]] : $Decoder to $@opened("{{.*}}") Decoder
23-
// CHECK: [[WT:%.*]] = witness_method $@opened("{{.*}}") Decoder, #Decoder.unkeyedContainer!1 : <Self where Self : Decoder> (Self) -> () throws -> UnkeyedDecodingContainer, %4 : $@opened("{{.*}}") Decoder : $@convention(witness_method) <τ_0_0 where τ_0_0 : Decoder> (@in_guaranteed τ_0_0) -> (@out UnkeyedDecodingContainer, @error Builtin.NativeObject)
24-
// CHECK: try_apply [[WT]]<@opened("{{.*}}") Decoder>([[OPENED]]) : $@convention(witness_method) <τ_0_0 where τ_0_0 : Decoder> (@in_guaranteed τ_0_0) -> (@out UnkeyedDecodingContainer, @error Builtin.NativeObject), normal bb2, error bb1
25+
// CHECK: [[WT:%.*]] = witness_method $@opened("{{.*}}") Decoder, #Decoder.unkeyedContainer!1 : <Self where Self : Decoder> (Self) -> () throws -> UnkeyedDecodingContainer, %4 : $@opened("{{.*}}") Decoder : $@convention(witness_method) <τ_0_0 where τ_0_0 : Decoder> (@in_guaranteed τ_0_0) -> (@out UnkeyedDecodingContainer, @error Error)
26+
// CHECK: try_apply [[WT]]<@opened("{{.*}}") Decoder>([[OPENED]]) : $@convention(witness_method) <τ_0_0 where τ_0_0 : Decoder> (@in_guaranteed τ_0_0) -> (@out UnkeyedDecodingContainer, @error Error), normal bb2, error bb1
2527
//
2628
// CHECK:bb{{.*}}([[RET1:%.*]] : @owned $UnkeyedDecodingContainer):
2729
// CHECK: end_borrow [[BORROW1]] from %0 : $Decoder, $Decoder
@@ -58,13 +60,47 @@ public func unsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {
5860

5961
#if os(OSX)
6062
// Test open_existential_value used in a conversion context.
63+
// (the actual bridging call is dropped because we don't import Swift).
6164
// ---
62-
//
65+
// CHECK-OSX-LABEL: sil @_T0s26_unsafeDowncastToAnyObjectyXlyp04fromD0_tF : $@convention(thin) (@in Any) -> @owned AnyObject {
66+
// CHECK-OSX: bb0(%0 : @owned $Any):
67+
// CHECK-OSX: [[BORROW:%.*]] = begin_borrow %0 : $Any
68+
// CHECK-OSX: [[COPY:%.*]] = copy_value [[BORROW]] : $Any
69+
// CHECK-OSX: [[BORROW2:%.*]] = begin_borrow [[COPY]] : $Any
70+
// CHECK-OSX: [[VAL:%.*]] = open_existential_value [[BORROW2]] : $Any to $@opened
71+
// CHECK-OSX: [[COPY2:%.*]] = copy_value [[VAL]] : $@opened
72+
// CHECK-OSX: destroy_value [[COPY2]] : $@opened
73+
// CHECK-OSX: end_borrow [[BORROW2]] from [[COPY]] : $Any, $Any
74+
// CHECK-OSX: destroy_value [[COPY]] : $Any
75+
// CHECK-OSX: end_borrow [[BORROW]] from %0 : $Any, $Any
76+
// CHECK-OSX: destroy_value %0 : $Any
77+
// CHECK-OSX: return undef : $AnyObject
78+
// CHECK-OSX-LABEL: } // end sil function '_T0s26_unsafeDowncastToAnyObjectyXlyp04fromD0_tF'
6379
public func _unsafeDowncastToAnyObject(fromAny any: Any) -> AnyObject {
6480
return any as AnyObject
6581
}
6682
#endif
6783

84+
public protocol Error {}
85+
86+
#if os(OSX)
87+
// Test open_existential_box_value in a conversion context.
88+
// ---
89+
// CHECK-OSX-LABEL: sil @_T0s3fooys5Error_pSg1e_tF : $@convention(thin) (@owned Optional<Error>) -> () {
90+
// CHECK-OSX: [[BORROW:%.*]] = begin_borrow %{{.*}} : $Error
91+
// CHECK-OSX: [[VAL:%.*]] = open_existential_box_value [[BORROW]] : $Error to $@opened
92+
// CHECK-OSX: [[COPY:%.*]] = copy_value [[VAL]] : $@opened
93+
// CHECK-OSX: [[ANY:%.*]] = init_existential_value [[COPY]] : $@opened
94+
// CHECK-OSX: end_borrow [[BORROW]] from %{{.*}} : $Error, $Error
95+
// CHECK-OSX-LABEL: } // end sil function '_T0s3fooys5Error_pSg1e_tF'
96+
public func foo(e: Error?) {
97+
if let u = e {
98+
let a: Any = u
99+
_ = a
100+
}
101+
}
102+
#endif
103+
68104
public enum Optional<Wrapped> {
69105
case none
70106
case some(Wrapped)

0 commit comments

Comments
 (0)