Skip to content

Commit f3df836

Browse files
committed
[ownership] Treat open_existential_box as an interior pointer producting instruction.
This means that it can only have a guaranteed object as an operandand that we validate that all uses of the result address of open_existential_box occur only within the lifetime of said object's borrow scope.
1 parent b3606cd commit f3df836

File tree

10 files changed

+57
-24
lines changed

10 files changed

+57
-24
lines changed

include/swift/SIL/OwnershipUtils.h

+8-5
Original file line numberDiff line numberDiff line change
@@ -388,11 +388,10 @@ Optional<BorrowScopeIntroducingValue>
388388
getSingleBorrowIntroducingValue(SILValue inputValue);
389389

390390
struct InteriorPointerOperandKind {
391-
using UnderlyingKindTy = std::underlying_type<SILInstructionKind>::type;
392-
393-
enum Kind : UnderlyingKindTy {
394-
RefElementAddr = UnderlyingKindTy(SILInstructionKind::RefElementAddrInst),
395-
RefTailAddr = UnderlyingKindTy(SILInstructionKind::RefTailAddrInst),
391+
enum Kind : uint8_t {
392+
RefElementAddr,
393+
RefTailAddr,
394+
OpenExistentialBox,
396395
};
397396

398397
Kind value;
@@ -410,6 +409,8 @@ struct InteriorPointerOperandKind {
410409
return InteriorPointerOperandKind(RefElementAddr);
411410
case SILInstructionKind::RefTailAddrInst:
412411
return InteriorPointerOperandKind(RefTailAddr);
412+
case SILInstructionKind::OpenExistentialBoxInst:
413+
return InteriorPointerOperandKind(OpenExistentialBox);
413414
}
414415
}
415416

@@ -457,6 +458,8 @@ struct InteriorPointerOperand {
457458
return cast<RefElementAddrInst>(operand->getUser());
458459
case InteriorPointerOperandKind::RefTailAddr:
459460
return cast<RefTailAddrInst>(operand->getUser());
461+
case InteriorPointerOperandKind::OpenExistentialBox:
462+
return cast<OpenExistentialBoxInst>(operand->getUser());
460463
}
461464
llvm_unreachable("Covered switch isn't covered?!");
462465
}

lib/SIL/OperandOwnership.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ INTERIOR_POINTER_PROJECTION(RefTailAddr)
167167
}
168168
CONSTANT_OWNERSHIP_INST(Guaranteed, MustBeLive, OpenExistentialValue)
169169
CONSTANT_OWNERSHIP_INST(Guaranteed, MustBeLive, OpenExistentialBoxValue)
170+
CONSTANT_OWNERSHIP_INST(Guaranteed, MustBeLive, OpenExistentialBox)
170171
CONSTANT_OWNERSHIP_INST(Owned, MustBeInvalidated, AutoreleaseValue)
171172
CONSTANT_OWNERSHIP_INST(Owned, MustBeInvalidated, DeallocBox)
172173
CONSTANT_OWNERSHIP_INST(Owned, MustBeInvalidated, DeallocExistentialBox)
@@ -282,7 +283,6 @@ ACCEPTS_ANY_OWNERSHIP_INST(SuperMethod)
282283
ACCEPTS_ANY_OWNERSHIP_INST(BridgeObjectToWord)
283284
ACCEPTS_ANY_OWNERSHIP_INST(ClassifyBridgeObject)
284285
ACCEPTS_ANY_OWNERSHIP_INST(CopyBlock)
285-
ACCEPTS_ANY_OWNERSHIP_INST(OpenExistentialBox)
286286
ACCEPTS_ANY_OWNERSHIP_INST(RefToRawPointer)
287287
ACCEPTS_ANY_OWNERSHIP_INST(SetDeallocating)
288288
ACCEPTS_ANY_OWNERSHIP_INST(ProjectExistentialBox)

lib/SILGen/SILGenBuilder.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,15 @@ ManagedValue SILGenBuilder::createOpenExistentialBoxValue(SILLocation loc,
664664
return ManagedValue::forUnmanaged(openedExistential);
665665
}
666666

667+
ManagedValue SILGenBuilder::createOpenExistentialBox(SILLocation loc,
668+
ManagedValue original,
669+
SILType type) {
670+
ManagedValue borrowedExistential = original.formalAccessBorrow(SGF, loc);
671+
SILValue openedExistentialAddr =
672+
createOpenExistentialBox(loc, borrowedExistential.getValue(), type);
673+
return ManagedValue::forUnmanaged(openedExistentialAddr);
674+
}
675+
667676
ManagedValue SILGenBuilder::createOpenExistentialMetatype(SILLocation loc,
668677
ManagedValue value,
669678
SILType openedType) {

lib/SILGen/SILGenBuilder.h

+4
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ class SILGenBuilder : public SILBuilder {
294294
ManagedValue createOpenExistentialBoxValue(SILLocation loc,
295295
ManagedValue original, SILType type);
296296

297+
using SILBuilder::createOpenExistentialBox;
298+
ManagedValue createOpenExistentialBox(SILLocation loc, ManagedValue original,
299+
SILType type);
300+
297301
using SILBuilder::createOpenExistentialMetatype;
298302
ManagedValue createOpenExistentialMetatype(SILLocation loc,
299303
ManagedValue value,

lib/SILGen/SILGenConvert.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -971,9 +971,8 @@ SILGenFunction::emitOpenExistential(
971971
existentialType = existentialValue.getType();
972972
assert(existentialType.isObject());
973973
if (loweredOpenedType.isAddress()) {
974-
return ManagedValue::forUnmanaged(
975-
B.createOpenExistentialBox(loc, existentialValue.getValue(),
976-
loweredOpenedType));
974+
return B.createOpenExistentialBox(loc, existentialValue,
975+
loweredOpenedType);
977976
} else {
978977
assert(!silConv.useLoweredAddresses());
979978
return B.createOpenExistentialBoxValue(

lib/SILGen/SILGenLValue.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -873,9 +873,14 @@ namespace {
873873
auto &TL = SGF.getTypeLowering(base.getType());
874874
error = SGF.emitLoad(loc, base.getValue(), TL,
875875
SGFContext(), IsNotTake);
876+
// Error comes back to us with a +1 cleanup that is not a formal
877+
// access cleanup. We need it to be that so that the load nests
878+
// properly with other lvalue scoped things like the borrow below.
879+
error = SGF.emitFormalAccessManagedRValueWithCleanup(
880+
loc, error.forward(SGF));
876881
}
877-
addr = SGF.B.createOpenExistentialBox(
878-
loc, error.getValue(), getTypeOfRValue().getAddressType());
882+
SILType addrType = getTypeOfRValue().getAddressType();
883+
addr = SGF.B.createOpenExistentialBox(loc, error, addrType).getValue();
879884
break;
880885
}
881886
default:

lib/SILGen/SILGenPoly.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -4141,6 +4141,7 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
41414141
break;
41424142
}
41434143

4144+
formalEvalScope.pop();
41444145
scope.pop();
41454146
B.createReturn(loc, reqtResultValue);
41464147
}

test/SIL/ownership-verifier/use_verifier.sil

+3-1
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,10 @@ bb0(%0 : @owned $SomeError):
238238
%1 = alloc_existential_box $Error, $SomeError
239239
%2 = project_existential_box $SomeError in %1 : $Error
240240
store %0 to [init] %2 : $*SomeError
241-
%4 = open_existential_box %1 : $Error to $*@opened("01234567-89AB-CDEF-0123-333333333333") Error
241+
%1a = begin_borrow %1 : $Error
242+
%4 = open_existential_box %1a : $Error to $*@opened("01234567-89AB-CDEF-0123-333333333333") Error
242243
destroy_addr %4 : $*@opened("01234567-89AB-CDEF-0123-333333333333") Error
244+
end_borrow %1a : $Error
243245
dealloc_existential_box %1 : $Error, $SomeError
244246
%9999 = tuple()
245247
return %9999 : $()

test/SILGen/boxed_existentials.swift

+17-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
// RUN: %target-swift-emit-silgen -module-name boxed_existentials -Xllvm -sil-full-demangle %s | %FileCheck %s
32
// RUN: %target-swift-emit-silgen -module-name boxed_existentials -Xllvm -sil-full-demangle %s | %FileCheck %s --check-prefix=GUARANTEED
43

@@ -88,16 +87,17 @@ func test_property_of_lvalue(_ x: Error) -> String {
8887
// CHECK: store [[ARG_COPY]] to [init] [[PVAR]]
8988
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PVAR]] : $*Error
9089
// CHECK: [[VALUE_BOX:%.*]] = load [copy] [[ACCESS]]
91-
// CHECK: [[VALUE:%.*]] = open_existential_box [[VALUE_BOX]] : $Error to $*[[VALUE_TYPE:@opened\(.*\) Error]]
90+
// CHECK: [[BORROWED_VALUE_BOX:%.*]] = begin_borrow [[VALUE_BOX]]
91+
// CHECK: [[VALUE:%.*]] = open_existential_box [[BORROWED_VALUE_BOX]] : $Error to $*[[VALUE_TYPE:@opened\(.*\) Error]]
9292
// CHECK: [[COPY:%.*]] = alloc_stack $[[VALUE_TYPE]]
9393
// CHECK: copy_addr [[VALUE]] to [initialization] [[COPY]]
94+
// CHECK: destroy_value [[VALUE_BOX]]
9495
// CHECK: [[BORROW:%.*]] = alloc_stack $[[VALUE_TYPE]]
9596
// CHECK: copy_addr [[COPY]] to [initialization] [[BORROW]]
9697
// CHECK: [[METHOD:%.*]] = witness_method $[[VALUE_TYPE]], #Error._domain!getter.1
9798
// CHECK: [[RESULT:%.*]] = apply [[METHOD]]<[[VALUE_TYPE]]>([[BORROW]])
9899
// CHECK: destroy_addr [[COPY]]
99100
// CHECK: dealloc_stack [[COPY]]
100-
// CHECK: destroy_value [[VALUE_BOX]]
101101
// CHECK: destroy_value [[VAR]]
102102
// CHECK-NOT: destroy_value [[ARG]]
103103
// CHECK: return [[RESULT]]
@@ -153,7 +153,8 @@ func test_open_existential_semantics(_ guaranteed: Error,
153153
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PB]] : $*Error
154154
// CHECK: [[IMMEDIATE:%.*]] = load [copy] [[ACCESS]]
155155
// -- need a copy_value to guarantee
156-
// CHECK: [[VALUE:%.*]] = open_existential_box [[IMMEDIATE]]
156+
// CHECK: [[IMMEDIATE_BORROW:%.*]] = begin_borrow [[IMMEDIATE]]
157+
// CHECK: [[VALUE:%.*]] = open_existential_box [[IMMEDIATE_BORROW]]
157158
// CHECK: [[METHOD:%.*]] = function_ref
158159
// CHECK-NOT: copy_addr
159160
// CHECK: apply [[METHOD]]<{{.*}}>([[VALUE]])
@@ -165,7 +166,8 @@ func test_open_existential_semantics(_ guaranteed: Error,
165166
// GUARANTEED: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PB]] : $*Error
166167
// GUARANTEED: [[IMMEDIATE:%.*]] = load [copy] [[ACCESS]]
167168
// -- need a copy_value to guarantee
168-
// GUARANTEED: [[VALUE:%.*]] = open_existential_box [[IMMEDIATE]]
169+
// GUARANTEED: [[BORROWED_IMMEDIATE:%.*]] = begin_borrow [[IMMEDIATE]]
170+
// GUARANTEED: [[VALUE:%.*]] = open_existential_box [[BORROWED_IMMEDIATE]]
169171
// GUARANTEED: [[METHOD:%.*]] = function_ref
170172
// GUARANTEED: apply [[METHOD]]<{{.*}}>([[VALUE]])
171173
// GUARANTEED-NOT: destroy_addr [[VALUE]]
@@ -175,15 +177,17 @@ func test_open_existential_semantics(_ guaranteed: Error,
175177

176178
// CHECK: [[F:%.*]] = function_ref {{.*}}plusOneError
177179
// CHECK: [[PLUS_ONE:%.*]] = apply [[F]]()
178-
// CHECK: [[VALUE:%.*]] = open_existential_box [[PLUS_ONE]]
180+
// CHECK: [[PLUS_ONE_BORROW:%.*]] = begin_borrow [[PLUS_ONE]]
181+
// CHECK: [[VALUE:%.*]] = open_existential_box [[PLUS_ONE_BORROW]]
179182
// CHECK: [[METHOD:%.*]] = function_ref
180183
// CHECK-NOT: copy_addr
181184
// CHECK: apply [[METHOD]]<{{.*}}>([[VALUE]])
182185
// CHECK: destroy_value [[PLUS_ONE]]
183186

184187
// GUARANTEED: [[F:%.*]] = function_ref {{.*}}plusOneError
185188
// GUARANTEED: [[PLUS_ONE:%.*]] = apply [[F]]()
186-
// GUARANTEED: [[VALUE:%.*]] = open_existential_box [[PLUS_ONE]]
189+
// GUARANTEED: [[BORROWED_PLUS_ONE:%.*]] = begin_borrow [[PLUS_ONE]]
190+
// GUARANTEED: [[VALUE:%.*]] = open_existential_box [[BORROWED_PLUS_ONE]]
187191
// GUARANTEED: [[METHOD:%.*]] = function_ref
188192
// GUARANTEED: apply [[METHOD]]<{{.*}}>([[VALUE]])
189193
// GUARANTEED-NOT: destroy_addr [[VALUE]]
@@ -207,15 +211,17 @@ func erasure_to_any(_ guaranteed: Error, _ immediate: Error) -> Any {
207211
} else if true {
208212
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PB]]
209213
// CHECK: [[IMMEDIATE:%.*]] = load [copy] [[ACCESS]]
210-
// CHECK: [[FROM_VALUE:%.*]] = open_existential_box [[IMMEDIATE]]
214+
// CHECK: [[BORROWED_IMMEDIATE:%.*]] = begin_borrow [[IMMEDIATE]]
215+
// CHECK: [[FROM_VALUE:%.*]] = open_existential_box [[BORROWED_IMMEDIATE]]
211216
// CHECK: [[TO_VALUE:%.*]] = init_existential_addr [[OUT]]
212217
// CHECK: copy_addr [[FROM_VALUE]] to [initialization] [[TO_VALUE]]
213218
// CHECK: destroy_value [[IMMEDIATE]]
214219
return immediate
215220
} else if true {
216221
// CHECK: function_ref boxed_existentials.plusOneError
217222
// CHECK: [[PLUS_ONE:%.*]] = apply
218-
// CHECK: [[FROM_VALUE:%.*]] = open_existential_box [[PLUS_ONE]]
223+
// CHECK: [[BORROWED_PLUS_ONE:%.*]] = begin_borrow [[PLUS_ONE]]
224+
// CHECK: [[FROM_VALUE:%.*]] = open_existential_box [[BORROWED_PLUS_ONE]]
219225
// CHECK: [[TO_VALUE:%.*]] = init_existential_addr [[OUT]]
220226
// CHECK: copy_addr [[FROM_VALUE]] to [initialization] [[TO_VALUE]]
221227
// CHECK: destroy_value [[PLUS_ONE]]
@@ -236,7 +242,8 @@ extension Error {
236242
// CHECK: [[ARRAY_GET:%.*]] = function_ref @$sSayxSicig
237243
// CHECK: apply [[ARRAY_GET]]<Error>([[ERROR_ADDR]]
238244
// CHECK: [[ERROR:%.*]] = load [take] [[ERROR_ADDR]] : $*Error
239-
// CHECK: open_existential_box [[ERROR]]
245+
// CHECK: [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]]
246+
// CHECK: open_existential_box [[BORROWED_ERROR]]
240247
func test() {
241248
var errors: [Error] = []
242249
test_property(errors[0].myError)

test/SILGen/objc_bridging_any.swift

+5-2
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ func passingToId<T: CP, U>(receiver: NSIdLover,
109109
receiver.takesId(existential)
110110

111111
// CHECK: [[ERROR_COPY:%.*]] = copy_value [[ERROR]] : $Error
112-
// CHECK: [[ERROR_BOX:%[0-9]+]] = open_existential_box [[ERROR_COPY]] : $Error to $*@opened([[ERROR_ARCHETYPE:"[^"]*"]]) Error
112+
// CHECK: [[BORROWED_ERROR_COPY:%.*]] = begin_borrow [[ERROR_COPY]]
113+
// CHECK: [[ERROR_BOX:%[0-9]+]] = open_existential_box [[BORROWED_ERROR_COPY]] : $Error to $*@opened([[ERROR_ARCHETYPE:"[^"]*"]]) Error
113114
// CHECK: [[ERROR_STACK:%[0-9]+]] = alloc_stack $@opened([[ERROR_ARCHETYPE]]) Error
114115
// CHECK: copy_addr [[ERROR_BOX]] to [initialization] [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]]) Error
115116
// CHECK: [[BRIDGE_FUNCTION:%[0-9]+]] = function_ref @$ss27_bridgeAnythingToObjectiveCyyXlxlF
@@ -320,9 +321,11 @@ func passingToNullableId<T: CP, U>(receiver: NSIdLover,
320321
receiver.takesNullableId(existential)
321322

322323
// CHECK-NEXT: [[ERROR_COPY:%.*]] = copy_value [[ERROR]] : $Error
323-
// CHECK-NEXT: [[ERROR_BOX:%[0-9]+]] = open_existential_box [[ERROR_COPY]] : $Error to $*@opened([[ERROR_ARCHETYPE:"[^"]*"]]) Error
324+
// CHECK-NEXT: [[BORROWED_ERROR_COPY:%.*]] = begin_borrow [[ERROR_COPY]]
325+
// CHECK-NEXT: [[ERROR_BOX:%[0-9]+]] = open_existential_box [[BORROWED_ERROR_COPY]] : $Error to $*@opened([[ERROR_ARCHETYPE:"[^"]*"]]) Error
324326
// CHECK-NEXT: [[ERROR_STACK:%[0-9]+]] = alloc_stack $@opened([[ERROR_ARCHETYPE]]) Error
325327
// CHECK-NEXT: copy_addr [[ERROR_BOX]] to [initialization] [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]]) Error
328+
// CHECK-NEXT: end_borrow [[BORROWED_ERROR_COPY]]
326329
// CHECK: [[BRIDGE_FUNCTION:%[0-9]+]] = function_ref @$ss27_bridgeAnythingToObjectiveCyyXlxlF
327330
// CHECK-NEXT: [[BRIDGED_ERROR:%[0-9]+]] = apply [[BRIDGE_FUNCTION]]<@opened([[ERROR_ARCHETYPE]]) Error>([[ERROR_STACK]])
328331
// CHECK-NEXT: [[BRIDGED_ERROR_OPT:%[0-9]+]] = enum $Optional<AnyObject>, #Optional.some!enumelt.1, [[BRIDGED_ERROR]] : $AnyObject

0 commit comments

Comments
 (0)