Skip to content

Commit edf4543

Browse files
committed
[region-isolation] Add support for ref_tail_addr.
1 parent f5e5789 commit edf4543

File tree

2 files changed

+105
-3
lines changed

2 files changed

+105
-3
lines changed

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2410,7 +2410,6 @@ CONSTANT_TRANSLATION(VectorInst, Unhandled)
24102410
CONSTANT_TRANSLATION(TuplePackElementAddrInst, Unhandled)
24112411
CONSTANT_TRANSLATION(TuplePackExtractInst, Unhandled)
24122412
CONSTANT_TRANSLATION(PackElementGetInst, Unhandled)
2413-
CONSTANT_TRANSLATION(RefTailAddrInst, Unhandled)
24142413
CONSTANT_TRANSLATION(InitExistentialValueInst, Unhandled)
24152414
CONSTANT_TRANSLATION(InitExistentialMetatypeInst, Unhandled)
24162415
CONSTANT_TRANSLATION(OpenExistentialMetatypeInst, Unhandled)
@@ -2629,14 +2628,36 @@ TranslationSemantics PartitionOpTranslator::visitUnconditionalCheckedCastInst(
26292628
TranslationSemantics
26302629
PartitionOpTranslator::visitRefElementAddrInst(RefElementAddrInst *reai) {
26312630
// If we are accessing a let of a Sendable type, do not treat the
2632-
// ref_element_addr as a require use.
2631+
// ref_element_addr as an assign.
26332632
if (reai->getField()->isLet() && !isNonSendableType(reai->getType())) {
26342633
LLVM_DEBUG(llvm::dbgs() << " Found a let! Not tracking!\n");
26352634
return TranslationSemantics::Ignored;
26362635
}
26372636
return TranslationSemantics::Assign;
26382637
}
26392638

2639+
TranslationSemantics
2640+
PartitionOpTranslator::visitRefTailAddrInst(RefTailAddrInst *reai) {
2641+
// If our trailing type is Sendable...
2642+
if (!isNonSendableType(reai->getType())) {
2643+
// And our ref_tail_addr is immutable... we can ignore the access since we
2644+
// cannot race against a write to any of these fields.
2645+
if (reai->isImmutable()) {
2646+
LLVM_DEBUG(
2647+
llvm::dbgs()
2648+
<< " Found an immutable Sendable ref_tail_addr! Not tracking!\n");
2649+
return TranslationSemantics::Ignored;
2650+
}
2651+
2652+
// Otherwise, we need a require since the value maybe alive.
2653+
return TranslationSemantics::Require;
2654+
}
2655+
2656+
// If we have a NonSendable type, treat the address as a separate Element from
2657+
// our base value.
2658+
return TranslationSemantics::Assign;
2659+
}
2660+
26402661
/// Enum inst is handled specially since if it does not have an argument,
26412662
/// we must assign fresh. Otherwise, we must propagate.
26422663
TranslationSemantics PartitionOpTranslator::visitEnumInst(EnumInst *ei) {

test/Concurrency/transfernonsendable_instruction_matching.sil

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -transfer-non-sendable -enable-experimental-feature RegionBasedIsolation -strict-concurrency=complete %s -verify
1+
// RUN: %target-sil-opt -transfer-non-sendable -enable-experimental-feature RegionBasedIsolation -strict-concurrency=complete %s -verify -o /dev/null
22

33
// REQUIRES: concurrency
44
// REQUIRES: asserts
@@ -1011,3 +1011,84 @@ bb0:
10111011
%9999 = tuple ()
10121012
return %9999 : $()
10131013
}
1014+
1015+
// This is a require
1016+
sil [ossa] @ref_tail_addr_test_sendable_mutable : $@async @convention(thin) () -> () {
1017+
bb0:
1018+
%0 = function_ref @constructNonSendableKlass : $@convention(thin) () -> @owned NonSendableKlass
1019+
%1 = apply %0() : $@convention(thin) () -> @owned NonSendableKlass
1020+
%f = function_ref @transferNonSendableKlass : $@convention(thin) @async (@guaranteed NonSendableKlass) -> ()
1021+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f(%1) : $@convention(thin) @async (@guaranteed NonSendableKlass) -> () // expected-warning {{transferring value of non-Sendable type 'NonSendableKlass' from nonisolated context to global actor '<null>'-isolated context; later accesses could race}}
1022+
%2 = begin_borrow %1 : $NonSendableKlass
1023+
%3 = ref_tail_addr %2 : $NonSendableKlass, $*SendableKlass // expected-note {{access here could race}}
1024+
1025+
// Since our type is Sendable, we shouldn't see errors here.
1026+
%f2 = function_ref @transferIndirect : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1027+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f2<SendableKlass>(%3) : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1028+
1029+
%f3 = function_ref @useIndirect : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1030+
apply %f3<SendableKlass>(%3) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1031+
end_borrow %2 : $NonSendableKlass
1032+
destroy_value %1 : $NonSendableKlass
1033+
%9999 = tuple ()
1034+
return %9999 : $()
1035+
}
1036+
1037+
// This is ignored since we cannot race to write the Sendable field.
1038+
sil [ossa] @ref_tail_addr_test_sendable_immutable : $@async @convention(thin) () -> () {
1039+
bb0:
1040+
%0 = function_ref @constructNonSendableKlass : $@convention(thin) () -> @owned NonSendableKlass
1041+
%1 = apply %0() : $@convention(thin) () -> @owned NonSendableKlass
1042+
%f = function_ref @transferNonSendableKlass : $@convention(thin) @async (@guaranteed NonSendableKlass) -> ()
1043+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f(%1) : $@convention(thin) @async (@guaranteed NonSendableKlass) -> ()
1044+
%2 = begin_borrow %1 : $NonSendableKlass
1045+
%3 = ref_tail_addr [immutable] %2 : $NonSendableKlass, $*SendableKlass
1046+
end_borrow %2 : $NonSendableKlass
1047+
destroy_value %1 : $NonSendableKlass
1048+
%9999 = tuple ()
1049+
return %9999 : $()
1050+
}
1051+
1052+
sil [ossa] @ref_tail_addr_test_non_sendable_immutable : $@async @convention(thin) () -> () {
1053+
bb0:
1054+
%0 = function_ref @constructNonSendableKlass : $@convention(thin) () -> @owned NonSendableKlass
1055+
%1 = apply %0() : $@convention(thin) () -> @owned NonSendableKlass
1056+
%f = function_ref @transferNonSendableKlass : $@convention(thin) @async (@guaranteed NonSendableKlass) -> ()
1057+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f(%1) : $@convention(thin) @async (@guaranteed NonSendableKlass) -> () // expected-warning {{transferring value of non-Sendable type 'NonSendableKlass' from nonisolated context to global actor '<null>'-isolated context; later accesses could race}}
1058+
%2 = begin_borrow %1 : $NonSendableKlass
1059+
%3 = ref_tail_addr [immutable] %2 : $NonSendableKlass, $*NonSendableKlass // expected-note {{access here could race}}
1060+
1061+
// Since this is as assign, we should be able to get a separate error on the ref_tail_addr
1062+
%f2 = function_ref @transferIndirect : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1063+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f2<NonSendableKlass>(%3) : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> () // expected-warning {{transferring value of non-Sendable type 'NonSendableKlass' from nonisolated context to global actor '<null>'-isolated context; later accesses could race}}
1064+
1065+
%f3 = function_ref @useIndirect : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1066+
apply %f3<NonSendableKlass>(%3) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> () // expected-note {{access here could race}}
1067+
1068+
end_borrow %2 : $NonSendableKlass
1069+
destroy_value %1 : $NonSendableKlass
1070+
%9999 = tuple ()
1071+
return %9999 : $()
1072+
}
1073+
1074+
sil [ossa] @ref_tail_addr_test_non_sendable_mutable : $@async @convention(thin) () -> () {
1075+
bb0:
1076+
%0 = function_ref @constructNonSendableKlass : $@convention(thin) () -> @owned NonSendableKlass
1077+
%1 = apply %0() : $@convention(thin) () -> @owned NonSendableKlass
1078+
%f = function_ref @transferNonSendableKlass : $@convention(thin) @async (@guaranteed NonSendableKlass) -> ()
1079+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f(%1) : $@convention(thin) @async (@guaranteed NonSendableKlass) -> () // expected-warning {{transferring value of non-Sendable type 'NonSendableKlass' from nonisolated context to global actor '<null>'-isolated context; later accesses could race}}
1080+
%2 = begin_borrow %1 : $NonSendableKlass
1081+
%3 = ref_tail_addr %2 : $NonSendableKlass, $*NonSendableKlass // expected-note {{access here could race}}
1082+
1083+
// Since this is as assign, we should be able to get a separate error on the ref_tail_addr
1084+
%f2 = function_ref @transferIndirect : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1085+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f2<NonSendableKlass>(%3) : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> () // expected-warning {{transferring value of non-Sendable type 'NonSendableKlass' from nonisolated context to global actor '<null>'-isolated context; later accesses could race}}
1086+
1087+
%f3 = function_ref @useIndirect : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1088+
apply %f3<NonSendableKlass>(%3) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> () // expected-note {{access here could race}}
1089+
1090+
end_borrow %2 : $NonSendableKlass
1091+
destroy_value %1 : $NonSendableKlass
1092+
%9999 = tuple ()
1093+
return %9999 : $()
1094+
}

0 commit comments

Comments
 (0)