Skip to content

Commit 02a12d4

Browse files
committed
[move-only] Make sure to treat ref_element_addr mutable address accesses similar to inout.
I also slightly changed the codegen around where we insert the mark_must_check. Specifically, before we would emit the mark_must_check directly on the ref_element_addr and then insert the access. This had the unfortunate effect that we would hoist any destroy_addr that were actually needed out of the access scope. Rather than do that, I now insert the mark_must_check on the access itself. This results in the destroy_addr being within the scope (like the mark_must_check itself). rdar://105910066
1 parent 8f9772d commit 02a12d4

File tree

5 files changed

+65
-21
lines changed

5 files changed

+65
-21
lines changed

lib/SILGen/SILGenLValue.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -790,17 +790,6 @@ namespace {
790790
SGF.B.createRefElementAddr(loc, base.getUnmanagedValue(),
791791
Field, SubstFieldType);
792792

793-
// If we have a move only type...
794-
if (result->getType().isMoveOnly()) {
795-
auto checkKind =
796-
MarkMustCheckInst::CheckKind::AssignableButNotConsumable;
797-
if (isReadAccess(getAccessKind())) {
798-
// Add a mark_must_check [no_consume_or_assign].
799-
checkKind = MarkMustCheckInst::CheckKind::NoConsumeOrAssign;
800-
}
801-
result = SGF.B.createMarkMustCheckInst(loc, result, checkKind);
802-
}
803-
804793
// Avoid emitting access markers completely for non-accesses or immutable
805794
// declarations. Access marker verification is aware of these cases.
806795
if (!IsNonAccessing && !Field->isLet()) {
@@ -811,6 +800,20 @@ namespace {
811800
}
812801
}
813802

803+
// If we have a move only type, add a marker.
804+
//
805+
// NOTE: We purposely do this on the access itself to ensure that when we
806+
// hoist destroy_addr, they stay within the access scope.
807+
if (result->getType().isMoveOnly()) {
808+
auto checkKind =
809+
MarkMustCheckInst::CheckKind::AssignableButNotConsumable;
810+
if (isReadAccess(getAccessKind())) {
811+
// Add a mark_must_check [no_consume_or_assign].
812+
checkKind = MarkMustCheckInst::CheckKind::NoConsumeOrAssign;
813+
}
814+
result = SGF.B.createMarkMustCheckInst(loc, result, checkKind);
815+
}
816+
814817
return ManagedValue::forLValue(result);
815818
}
816819

lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,9 @@ static bool isInOutDefThatNeedsEndOfFunctionLiveness(MarkMustCheckInst *markedAd
383383
return true;
384384
}
385385
}
386+
387+
if (isa<RefElementAddrInst>(stripAccessMarkers(operand)))
388+
return true;
386389
}
387390

388391
return false;

test/SILGen/moveonly.swift

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -537,9 +537,9 @@ func moveOnlyStructCopyableStructCopyableStructCopyableKlassNonConsumingUse() {
537537
// CHECK: end_access [[ACCESS]]
538538
// CHECK: [[BORROWED_COPYABLE_KLASS:%.*]] = begin_borrow [[COPYABLE_KLASS]]
539539
// CHECK: [[FIELD:%.*]] = ref_element_addr [[BORROWED_COPYABLE_KLASS]]
540-
// CHECK: [[FIELD_MARK:%.*]] = mark_must_check [no_consume_or_assign] [[FIELD]]
541-
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[FIELD_MARK]]
542-
// CHECK: [[BORROWED_MOVEONLY_KLASS:%.*]] = load_borrow [[ACCESS]]
540+
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[FIELD]]
541+
// CHECK: [[ACCESS_MARK:%.*]] = mark_must_check [no_consume_or_assign] [[ACCESS]]
542+
// CHECK: [[BORROWED_MOVEONLY_KLASS:%.*]] = load_borrow [[ACCESS_MARK]]
543543
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly9borrowValyyAA2FDVhF :
544544
// CHECK: apply [[FN]]([[BORROWED_MOVEONLY_KLASS]])
545545
// CHECK: end_borrow [[BORROWED_MOVEONLY_KLASS]]
@@ -551,6 +551,22 @@ func moveOnlyStructCopyableStructCopyableStructCopyableKlassMoveOnlyKlassNonCons
551551
borrowVal(k.nonTrivialCopyableStruct.nonTrivialCopyableStruct2.copyableKlass.fd)
552552
}
553553

554+
//////////////////////
555+
// Assignment Tests //
556+
//////////////////////
557+
558+
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly19assignCopyableKlassyyAA0cD0CF : $@convention(thin) (@guaranteed CopyableKlass) -> () {
559+
// CHECK: bb0([[ARG:%.*]] : @guaranteed
560+
// CHECK: [[REF:%.*]] = ref_element_addr [[ARG]]
561+
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[REF]]
562+
// CHECK: [[MARKED_ACCESS:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]]
563+
// CHECK: assign {{%.*}} to [[MARKED_ACCESS]]
564+
// CHECK: end_access [[ACCESS]]
565+
// CHECK: } // end sil function '$s8moveonly19assignCopyableKlassyyAA0cD0CF'
566+
func assignCopyableKlass(_ x: CopyableKlass) {
567+
x.fd = FD()
568+
}
569+
554570
///////////////////////
555571
// Enum Switch Tests //
556572
///////////////////////

test/SILOptimizer/moveonly_addresschecker.sil

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,3 +467,29 @@ bb0(%0 : @closureCapture @guaranteed ${ var NonTrivialStruct }):
467467
%24 = tuple ()
468468
return %24 : $()
469469
}
470+
471+
// CHECK: sil hidden [ossa] @ref_element_addr_treated_like_inout : $@convention(method) (@guaranteed ClassContainingMoveOnly) -> () {
472+
// CHECK: bb0(
473+
// CHECK-NEXT: // function_ref
474+
// CHECK-NEXT: function_ref
475+
// CHECK-NEXT: apply
476+
// CHECK-NEXT: ref_element_addr
477+
// CHECK-NEXT: begin_access
478+
// CHECK-NEXT: destroy_addr
479+
// CHECK-NEXT: store
480+
// CHECK-NEXT: end_access
481+
// CHECK-NEXT: tuple ()
482+
// CHECK-NEXT: return
483+
// CHECK: } // end sil function 'ref_element_addr_treated_like_inout'
484+
sil hidden [ossa] @ref_element_addr_treated_like_inout : $@convention(method) (@guaranteed ClassContainingMoveOnly) -> () {
485+
bb0(%0 : @guaranteed $ClassContainingMoveOnly):
486+
%9 = function_ref @getNonTrivialStruct : $@convention(thin) () -> @owned NonTrivialStruct
487+
%10 = apply %9() : $@convention(thin) () -> @owned NonTrivialStruct
488+
%5 = ref_element_addr %0 : $ClassContainingMoveOnly, #ClassContainingMoveOnly.value
489+
%6 = begin_access [modify] [dynamic] %5 : $*NonTrivialStruct
490+
%7 = mark_must_check [assignable_but_not_consumable] %6 : $*NonTrivialStruct
491+
store %10 to [assign] %7 : $*NonTrivialStruct
492+
end_access %6 : $*NonTrivialStruct
493+
%11 = tuple ()
494+
return %11 : $()
495+
}

test/SILOptimizer/moveonly_coro_accessor.swift

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,10 @@ public class ListOfFiles {
4343
// CHECK: [[NEW_VAL_RELOADED:%.*]] = load [[NEW_VAL_STACK]] : $*File
4444
// >> destroy the element currently in the field
4545
// CHECK: [[FIELD:%.*]] = ref_element_addr [[SELF]] : $ListOfFiles, #ListOfFiles.file
46-
// CHECK: destroy_addr [[FIELD]] : $*File
4746
// >> write the new value in its place
4847
// CHECK: [[FIELD_ACCESS:%.*]] = begin_access [modify] [dynamic] [[FIELD]] : $*File
48+
// CHECK: destroy_addr [[FIELD_ACCESS]] : $*File
4949
// CHECK: store [[NEW_VAL_RELOADED]] to [[FIELD_ACCESS]] : $*File
50-
// >> FIXME: we should not be destroying the field here rdar://105910066
51-
// CHECK: destroy_addr [[FIELD]] : $*File
5250
//
5351
// CHECK: end_access [[FIELD_ACCESS]] : $*File
5452
// CHECK-NOT: begin_access
@@ -65,15 +63,13 @@ public class ListOfFiles {
6563
// CHECK: yield [[ACCESS]] : $*File, resume bb1, unwind bb2
6664
//
6765
// CHECK: bb1:
68-
// >> FIXME: we should not be destroying the field here rdar://105910066
69-
// CHECK: destroy_addr [[FIELD]] : $*File
7066
//
7167
// CHECK: end_access [[ACCESS]] : $*File
7268
// CHECK-NOT: begin_access
69+
// CHECK-NOT: destroy_addr [[FIELD]] : $*File
7370
//
7471
// CHECK: bb2:
75-
// >> FIXME: we should not be destroying the field here rdar://105910066
76-
// CHECK: destroy_addr [[FIELD]] : $*File
72+
// CHECK-NOT: destroy_addr [[FIELD]] : $*File
7773
//
7874
// CHECK: end_access [[ACCESS]] : $*File
7975
// CHECK-NOT: begin_access

0 commit comments

Comments
 (0)