Skip to content

Commit 26081ff

Browse files
committed
[silgen] Teach accessor projection to use store_borrow if it has a non-tuple.
This prevents another type of copy of noncopyable value error. I also as a small change, changed the tuple version to use a formal access temporary since we are projecting a component out implying that the lifetime of the temporary must end within the formal access. Otherwise, we cause the lifetime of the temporary to outlive the access. This can be seen in the change to read_accessor.swift where we used to extend the lifetime of the destroy_addr outside of the coroutine access we are performing.
1 parent 55892ef commit 26081ff

File tree

6 files changed

+28
-15
lines changed

6 files changed

+28
-15
lines changed

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2595,7 +2595,12 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
25952595
require(SI->getDest()->getType().isAddress(),
25962596
"Must store to an address dest");
25972597
// Note: This is the current implementation and the design is not final.
2598-
require(isa<AllocStackInst>(SI->getDest()),
2598+
auto isLegal = [](SILValue value) {
2599+
if (auto *mmci = dyn_cast<MarkMustCheckInst>(value))
2600+
value = mmci->getOperand();
2601+
return isa<AllocStackInst>(value);
2602+
};
2603+
require(isLegal(SI->getDest()),
25992604
"store_borrow destination can only be an alloc_stack");
26002605
requireSameType(SI->getDest()->getType().getObjectType(),
26012606
SI->getSrc()->getType(),

lib/SILGen/SILGenLValue.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2156,12 +2156,25 @@ namespace {
21562156
if (value.getType().isAddress() ||
21572157
!isReadAccessResultAddress(getAccessKind()))
21582158
return value;
2159+
2160+
// If we have a guaranteed object and our read access result requires an
2161+
// address, store it using a store_borrow.
2162+
if (value.getType().isObject() &&
2163+
value.getOwnershipKind() == OwnershipKind::Guaranteed) {
2164+
SILValue alloc = SGF.emitTemporaryAllocation(loc, getTypeOfRValue());
2165+
if (alloc->getType().isMoveOnly())
2166+
alloc = SGF.B.createMarkMustCheckInst(
2167+
loc, alloc, MarkMustCheckInst::CheckKind::NoConsumeOrAssign);
2168+
return SGF.B.createFormalAccessStoreBorrow(loc, value, alloc);
2169+
}
21592170
}
21602171

21612172
// Otherwise, we need to make a temporary.
2173+
// TODO: This needs to be changed to use actual store_borrows. Noncopyable
2174+
// types do not support tuples today, so we can avoid this for now.
21622175
// TODO: build a scalar tuple if possible.
2163-
auto temporary =
2164-
SGF.emitTemporary(loc, SGF.getTypeLowering(getTypeOfRValue()));
2176+
auto temporary = SGF.emitFormalAccessTemporary(
2177+
loc, SGF.getTypeLowering(getTypeOfRValue()));
21652178
auto yieldsAsArray = llvm::makeArrayRef(yields);
21662179
copyBorrowedYieldsIntoTemporary(SGF, loc, yieldsAsArray,
21672180
getOrigFormalType(), getSubstFormalType(),

test/SILGen/moveonly.swift

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,10 +1265,9 @@ public class LoadableSubscriptGetOnlyTesterClassParent {
12651265
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
12661266
// CHECK: ([[CORO_RESULT:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
12671267
// CHECK: [[TEMP:%.*]] = alloc_stack $LoadableSubscriptGetOnlyTester
1268-
// CHECK: [[TEMP_MARK:%.*]] = mark_must_check [consumable_and_assignable] [[TEMP]]
1269-
// CHECK: [[CORO_RESULT_COPY:%.*]] = copy_value [[CORO_RESULT]]
1270-
// CHECK: store [[CORO_RESULT_COPY]] to [init] [[TEMP_MARK]]
1271-
// CHECK: [[LOAD:%.*]] = load_borrow [[TEMP_MARK]]
1268+
// CHECK: [[TEMP_MARK:%.*]] = mark_must_check [no_consume_or_assign] [[TEMP]]
1269+
// CHECK: [[TEMP_MARK_BORROW:%.*]] = store_borrow [[CORO_RESULT]] to [[TEMP_MARK]]
1270+
// CHECK: [[LOAD:%.*]] = load_borrow [[TEMP_MARK_BORROW]]
12721271
// CHECK: [[TEMP2:%.*]] = alloc_stack $
12731272
// CHECK: [[TEMP2_MARK:%.*]] = mark_must_check [consumable_and_assignable] [[TEMP2]]
12741273
// CHECK: apply {{%.*}}([[TEMP2_MARK]], {{%.*}}, [[LOAD]])
@@ -1284,10 +1283,9 @@ public class LoadableSubscriptGetOnlyTesterClassParent {
12841283
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
12851284
// CHECK: ([[CORO_RESULT:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
12861285
// CHECK: [[TEMP:%.*]] = alloc_stack $LoadableSubscriptGetOnlyTester
1287-
// CHECK: [[TEMP_MARK:%.*]] = mark_must_check [consumable_and_assignable] [[TEMP]]
1288-
// CHECK: [[CORO_RESULT_COPY:%.*]] = copy_value [[CORO_RESULT]]
1289-
// CHECK: store [[CORO_RESULT_COPY]] to [init] [[TEMP_MARK]]
1290-
// CHECK: [[GEP:%.*]] = struct_element_addr [[TEMP_MARK]]
1286+
// CHECK: [[TEMP_MARK:%.*]] = mark_must_check [no_consume_or_assign] [[TEMP]]
1287+
// CHECK: [[TEMP_MARK_BORROW:%.*]] = store_borrow [[CORO_RESULT]] to [[TEMP_MARK]]
1288+
// CHECK: [[GEP:%.*]] = struct_element_addr [[TEMP_MARK_BORROW]]
12911289
// CHECK: [[LOAD:%.*]] = load_borrow [[GEP]]
12921290
// CHECK: [[TEMP2:%.*]] = alloc_stack $
12931291
// CHECK: [[TEMP2_MARK:%.*]] = mark_must_check [consumable_and_assignable] [[TEMP2]]

test/SILGen/read_accessor.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ struct TupleReader {
112112
// CHECK-NEXT: [[TUPLE:%.*]] = load [copy] [[TEMP]]
113113
// CHECK-NEXT: destructure_tuple
114114
// CHECK-NEXT: destructure_tuple
115+
// CHECK-NEXT: destroy_addr [[TEMP]]
115116
// CHECK-NEXT: end_apply
116117
// CHECK-LABEL: } // end sil function '$s13read_accessor11TupleReaderV11useReadableyyF'
117118
func useReadable() {

test/SILOptimizer/moveonly_addressonly_subscript_diagnostics.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,7 @@ public func testSubscriptGetOnlyThroughParentClass_BaseLoadable_ResultAddressOnl
8383
var m = LoadableSubscriptGetOnlyTesterClassParent()
8484
m = LoadableSubscriptGetOnlyTesterClassParent()
8585
m.tester[0].nonMutatingFunc()
86-
// expected-error @-1 {{copy of noncopyable typed value}}
8786
m.testerParent.tester[0].nonMutatingFunc()
88-
// expected-error @-1 {{copy of noncopyable typed value}}
8987
m.computedTester[0].nonMutatingFunc()
9088
}
9189

test/SILOptimizer/moveonly_loadable_subscript_diagnostics.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,7 @@ public func testSubscriptGetOnlyThroughParentClass_BaseLoadable_ResultLoadable_V
8080
var m = LoadableSubscriptGetOnlyTesterClassParent()
8181
m = LoadableSubscriptGetOnlyTesterClassParent()
8282
m.tester[0].nonMutatingFunc()
83-
// expected-error @-1 {{copy of noncopyable typed value}}
8483
m.testerParent.tester[0].nonMutatingFunc()
85-
// expected-error @-1 {{copy of noncopyable typed value}}
8684
m.computedTester[0].nonMutatingFunc()
8785
}
8886

0 commit comments

Comments
 (0)