Skip to content

Commit fbc8b53

Browse files
committed
[region-isolation] Add support for unchecked_bitwise_cast.
Just followed the model of unchecked_trivial_bit_cast.
1 parent 0b74399 commit fbc8b53

File tree

2 files changed

+109
-30
lines changed

2 files changed

+109
-30
lines changed

lib/SILOptimizer/Mandatory/TransferNonSendable.cpp

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ static SILValue getUnderlyingTrackedObjectValue(SILValue value) {
215215

216216
// If we have a cast and our operand and result are non-Sendable, treat it
217217
// as a look through.
218-
if (isa<UncheckedTrivialBitCastInst>(svi)) {
218+
if (isa<UncheckedTrivialBitCastInst, UncheckedBitwiseCastInst>(svi)) {
219219
if (isNonSendableType(svi->getType(), fn) &&
220220
isNonSendableType(svi->getOperand(0)->getType(), fn)) {
221221
temp = svi->getOperand(0);
@@ -2481,7 +2481,6 @@ CONSTANT_TRANSLATION(DeallocExistentialBoxInst, Ignored)
24812481
// Unhandled Instructions
24822482
//
24832483

2484-
CONSTANT_TRANSLATION(UncheckedBitwiseCastInst, Unhandled)
24852484
CONSTANT_TRANSLATION(UncheckedValueCastInst, Unhandled)
24862485
CONSTANT_TRANSLATION(RefToUnownedInst, Unhandled)
24872486
CONSTANT_TRANSLATION(UnownedToRefInst, Unhandled)
@@ -2628,6 +2627,36 @@ IGNORE_IF_SENDABLE_RESULT_ASSIGN_OTHERWISE(StructExtractInst)
26282627

26292628
#undef IGNORE_IF_SENDABLE_RESULT_ASSIGN_OTHERWISE
26302629

2630+
#ifdef CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT
2631+
#error "CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT already defined"
2632+
#endif
2633+
2634+
#define CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT(INST) \
2635+
\
2636+
TranslationSemantics PartitionOpTranslator::visit##INST(INST *cast) { \
2637+
bool isOperandNonSendable = \
2638+
isNonSendableType(cast->getOperand()->getType()); \
2639+
bool isResultNonSendable = isNonSendableType(cast->getType()); \
2640+
\
2641+
if (isOperandNonSendable) { \
2642+
if (isResultNonSendable) { \
2643+
return TranslationSemantics::LookThrough; \
2644+
} \
2645+
\
2646+
return TranslationSemantics::Require; \
2647+
} \
2648+
\
2649+
if (isResultNonSendable) \
2650+
return TranslationSemantics::AssignFresh; \
2651+
\
2652+
return TranslationSemantics::Ignored; \
2653+
}
2654+
2655+
CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT(UncheckedTrivialBitCastInst)
2656+
CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT(UncheckedBitwiseCastInst)
2657+
2658+
#undef CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT
2659+
26312660
//===---
26322661
// Custom Handling
26332662
//
@@ -2653,34 +2682,6 @@ PartitionOpTranslator::visitRefToRawPointerInst(RefToRawPointerInst *r) {
26532682
return TranslationSemantics::AssignFresh;
26542683
}
26552684

2656-
TranslationSemantics PartitionOpTranslator::visitUncheckedTrivialBitCastInst(
2657-
UncheckedTrivialBitCastInst *cast) {
2658-
bool isOperandNonSendable = isNonSendableType(cast->getOperand()->getType());
2659-
bool isResultNonSendable = isNonSendableType(cast->getType());
2660-
2661-
// If our operand is non sendable...
2662-
if (isOperandNonSendable) {
2663-
// ... and our result is non-Sendable, look through.
2664-
if (isResultNonSendable) {
2665-
return TranslationSemantics::LookThrough;
2666-
}
2667-
2668-
// Otherwise, if our result is Sendable, just treat this instruction as a
2669-
// require of the operand. It would be undefined behavior for the user to
2670-
// convert something from non-Sendable to Sendable if it was not actually
2671-
// Sendable behind the scenes.
2672-
return TranslationSemantics::Require;
2673-
}
2674-
2675-
// If our operand is sendable and our result is non-Sendable, treat this as
2676-
// assign fresh.
2677-
if (isResultNonSendable)
2678-
return TranslationSemantics::AssignFresh;
2679-
2680-
// Otherwise, both our operand and result are sendable, so just return ignore.
2681-
return TranslationSemantics::Ignored;
2682-
}
2683-
26842685
TranslationSemantics
26852686
PartitionOpTranslator::visitMarkDependenceInst(MarkDependenceInst *mdi) {
26862687
translateSILAssign(mdi, mdi->getValue());

test/Concurrency/transfernonsendable_instruction_matching.sil

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,84 @@ bb0:
652652

653653
%word = unchecked_trivial_bit_cast %value : $SendableKlass to $Builtin.Word
654654

655+
destroy_value %value : $SendableKlass
656+
%9999 = tuple ()
657+
return %9999 : $()
658+
}
659+
660+
////
661+
662+
sil [ossa] @unchecked_bitwise_cast_test_nonsendable_to_nonsendable : $@convention(thin) @async () -> () {
663+
bb0:
664+
%constructFn = function_ref @constructNonSendableKlass : $@convention(thin) () -> @owned NonSendableKlass
665+
%value = apply %constructFn() : $@convention(thin) () -> @owned NonSendableKlass
666+
667+
%rawPointer = unchecked_bitwise_cast %value : $NonSendableKlass to $Builtin.RawPointer
668+
669+
%transferRawPointer = function_ref @transferRawPointer : $@convention(thin) @async (Builtin.RawPointer) -> ()
670+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %transferRawPointer(%rawPointer) : $@convention(thin) @async (Builtin.RawPointer) -> ()
671+
// expected-warning @-1 {{passing argument of non-sendable type 'Builtin.RawPointer' from nonisolated context to global actor '<null>'-isolated context at this call site could yield a race with accesses later in this function}}
672+
673+
fix_lifetime %value : $NonSendableKlass
674+
// expected-note @-1 {{access here could race}}
675+
676+
destroy_value %value : $NonSendableKlass
677+
%9999 = tuple ()
678+
return %9999 : $()
679+
}
680+
681+
sil [ossa] @unchecked_bitwise_cast_test_sendable_to_nonsendable : $@convention(thin) @async () -> () {
682+
bb0:
683+
%constructFn = function_ref @constructSendableKlass : $@convention(thin) () -> @owned SendableKlass
684+
%value = apply %constructFn() : $@convention(thin) () -> @owned SendableKlass
685+
686+
%rawPointer = unchecked_bitwise_cast %value : $SendableKlass to $Builtin.RawPointer
687+
688+
%transferRawPointer = function_ref @transferRawPointer : $@convention(thin) @async (Builtin.RawPointer) -> ()
689+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %transferRawPointer(%rawPointer) : $@convention(thin) @async (Builtin.RawPointer) -> ()
690+
// expected-warning @-1 {{passing argument of non-sendable type 'Builtin.RawPointer' from nonisolated context to global actor '<null>'-isolated context at this call site could yield a race with accesses later in this function}}
691+
692+
fix_lifetime %value : $SendableKlass
693+
694+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %transferRawPointer(%rawPointer) : $@convention(thin) @async (Builtin.RawPointer) -> ()
695+
// expected-warning @-1 {{passing argument of non-sendable type 'Builtin.RawPointer' from nonisolated context to global actor '<null>'-isolated context at this call site could yield a race with accesses later in this function}}
696+
// expected-note @-2 {{access here could race}}
697+
698+
fix_lifetime %rawPointer : $Builtin.RawPointer
699+
// expected-note @-1 {{access here could race}}
700+
701+
destroy_value %value : $SendableKlass
702+
%9999 = tuple ()
703+
return %9999 : $()
704+
}
705+
706+
sil [ossa] @unchecked_bitwise_cast_test_nonsendable_to_sendable : $@convention(thin) @async () -> () {
707+
bb0:
708+
%constructFn = function_ref @constructNonSendableKlass : $@convention(thin) () -> @owned NonSendableKlass
709+
%value = apply %constructFn() : $@convention(thin) () -> @owned NonSendableKlass
710+
711+
%transferNonSendableKlass = function_ref @transferNonSendableKlass : $@convention(thin) @async (@guaranteed NonSendableKlass) -> ()
712+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %transferNonSendableKlass(%value) : $@convention(thin) @async (@guaranteed NonSendableKlass) -> ()
713+
// expected-warning @-1 {{passing argument of non-sendable type 'NonSendableKlass' from nonisolated context to global actor '<null>'-isolated context at this call site could yield a race with accesses later in this function}}
714+
715+
%word = unchecked_bitwise_cast %value : $NonSendableKlass to $Builtin.Word
716+
// expected-note @-1 {{access here could race}}
717+
718+
destroy_value %value : $NonSendableKlass
719+
%9999 = tuple ()
720+
return %9999 : $()
721+
}
722+
723+
sil [ossa] @unchecked_bitwise_cast_test_sendable_to_sendable : $@convention(thin) @async () -> () {
724+
bb0:
725+
%constructFn = function_ref @constructSendableKlass : $@convention(thin) () -> @owned SendableKlass
726+
%value = apply %constructFn() : $@convention(thin) () -> @owned SendableKlass
727+
728+
%transferSendableKlass = function_ref @transferSendableKlass : $@convention(thin) @async (@guaranteed SendableKlass) -> ()
729+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %transferSendableKlass(%value) : $@convention(thin) @async (@guaranteed SendableKlass) -> ()
730+
731+
%word = unchecked_bitwise_cast %value : $SendableKlass to $Builtin.Word
732+
655733
destroy_value %value : $SendableKlass
656734
%9999 = tuple ()
657735
return %9999 : $()

0 commit comments

Comments
 (0)