@@ -194,18 +194,49 @@ struct UseDefChainVisitor
194
194
} // namespace
195
195
196
196
static SILValue getUnderlyingTrackedObjectValue (SILValue value) {
197
+ auto *fn = value->getFunction ();
197
198
SILValue result = value;
198
199
while (true ) {
199
200
SILValue temp = result;
200
201
201
- temp = getUnderlyingObject (temp);
202
+ temp = stripSinglePredecessorArgs (temp);
203
+ temp = stripAddressProjections (temp);
204
+ temp = stripIndexingInsts (temp);
205
+ temp = lookThroughOwnershipInsts (temp);
202
206
203
207
if (auto *svi = dyn_cast<SingleValueInstruction>(temp)) {
204
208
if (isa<ExplicitCopyValueInst, CopyableToMoveOnlyWrapperValueInst,
205
209
MoveOnlyWrapperToCopyableValueInst,
206
- MoveOnlyWrapperToCopyableBoxInst>(svi)) {
210
+ MoveOnlyWrapperToCopyableBoxInst, BeginAccessInst,
211
+ MarkDependenceInst>(svi) ||
212
+ isIdentityPreservingRefCast (svi)) {
207
213
temp = svi->getOperand (0 );
208
214
}
215
+
216
+ // If we have a cast and our operand and result are non-Sendable, treat it
217
+ // as a look through.
218
+ if (isa<UncheckedTrivialBitCastInst, UncheckedBitwiseCastInst,
219
+ UncheckedValueCastInst>(svi)) {
220
+ if (isNonSendableType (svi->getType (), fn) &&
221
+ isNonSendableType (svi->getOperand (0 )->getType (), fn)) {
222
+ temp = svi->getOperand (0 );
223
+ }
224
+ }
225
+ }
226
+
227
+ if (auto *r = dyn_cast<RefToRawPointerInst>(temp)) {
228
+ // If our operand is a non-Sendable type, look through this instruction.
229
+ if (isNonSendableType (r->getOperand ()->getType (), fn)) {
230
+ temp = r->getOperand ();
231
+ }
232
+ }
233
+
234
+ if (auto *r = dyn_cast<RawPointerToRefInst>(temp)) {
235
+ // If our result is a non-Sendable type, look through this
236
+ // instruction. Builtin.RawPointer is always non-Sendable.
237
+ if (isNonSendableType (r->getType (), fn)) {
238
+ temp = r->getOperand ();
239
+ }
209
240
}
210
241
211
242
if (auto *dsi = dyn_cast_or_null<DestructureStructInst>(
@@ -2321,6 +2352,7 @@ CONSTANT_TRANSLATION(UncheckedAddrCastInst, Assign)
2321
2352
CONSTANT_TRANSLATION(UncheckedEnumDataInst, Assign)
2322
2353
CONSTANT_TRANSLATION(UncheckedOwnershipConversionInst, Assign)
2323
2354
CONSTANT_TRANSLATION(UnmanagedToRefInst, Assign)
2355
+ CONSTANT_TRANSLATION(IndexRawPointerInst, Assign)
2324
2356
2325
2357
// These are used by SIL to aggregate values together in a gep like way. We
2326
2358
// want to look at uses of structs, not the struct uses itself. So just
@@ -2434,17 +2466,22 @@ CONSTANT_TRANSLATION(CondBranchInst, TerminatorPhi)
2434
2466
CONSTANT_TRANSLATION(CheckedCastBranchInst, TerminatorPhi)
2435
2467
CONSTANT_TRANSLATION(DynamicMethodBranchInst, TerminatorPhi)
2436
2468
2469
+ // ===---
2470
+ // Existential Box
2471
+ //
2472
+
2473
+ // NOTE: Today these can only be used with Errors. Since Error is a sub-protocol
2474
+ // of Sendable, we actually do not have any way to truly test them. These are
2475
+ // just hypothetical assignments so we are complete.
2476
+ CONSTANT_TRANSLATION(AllocExistentialBoxInst, AssignFresh)
2477
+ CONSTANT_TRANSLATION(ProjectExistentialBoxInst, Assign)
2478
+ CONSTANT_TRANSLATION(OpenExistentialBoxValueInst, Assign)
2479
+ CONSTANT_TRANSLATION(DeallocExistentialBoxInst, Ignored)
2480
+
2437
2481
// ===---
2438
2482
// Unhandled Instructions
2439
2483
//
2440
2484
2441
- CONSTANT_TRANSLATION(AllocExistentialBoxInst, Unhandled)
2442
- CONSTANT_TRANSLATION(IndexRawPointerInst, Unhandled)
2443
- CONSTANT_TRANSLATION(UncheckedTrivialBitCastInst, Unhandled)
2444
- CONSTANT_TRANSLATION(UncheckedBitwiseCastInst, Unhandled)
2445
- CONSTANT_TRANSLATION(UncheckedValueCastInst, Unhandled)
2446
- CONSTANT_TRANSLATION(RefToRawPointerInst, Unhandled)
2447
- CONSTANT_TRANSLATION(RawPointerToRefInst, Unhandled)
2448
2485
CONSTANT_TRANSLATION(RefToUnownedInst, Unhandled)
2449
2486
CONSTANT_TRANSLATION(UnownedToRefInst, Unhandled)
2450
2487
CONSTANT_TRANSLATION(BridgeObjectToWordInst, Unhandled)
@@ -2460,7 +2497,6 @@ CONSTANT_TRANSLATION(StrongCopyUnmanagedValueInst, Unhandled)
2460
2497
CONSTANT_TRANSLATION(DropDeinitInst, Unhandled)
2461
2498
CONSTANT_TRANSLATION(IsUniqueInst, Unhandled)
2462
2499
CONSTANT_TRANSLATION(LoadUnownedInst, Unhandled)
2463
- CONSTANT_TRANSLATION(ProjectExistentialBoxInst, Unhandled)
2464
2500
CONSTANT_TRANSLATION(ValueMetatypeInst, Unhandled)
2465
2501
CONSTANT_TRANSLATION(ExistentialMetatypeInst, Unhandled)
2466
2502
CONSTANT_TRANSLATION(VectorInst, Unhandled)
@@ -2472,7 +2508,6 @@ CONSTANT_TRANSLATION(InitExistentialValueInst, Unhandled)
2472
2508
CONSTANT_TRANSLATION(InitExistentialMetatypeInst, Unhandled)
2473
2509
CONSTANT_TRANSLATION(OpenExistentialMetatypeInst, Unhandled)
2474
2510
CONSTANT_TRANSLATION(OpenExistentialValueInst, Unhandled)
2475
- CONSTANT_TRANSLATION(OpenExistentialBoxValueInst, Unhandled)
2476
2511
CONSTANT_TRANSLATION(OpenPackElementInst, Unhandled)
2477
2512
CONSTANT_TRANSLATION(PackLengthInst, Unhandled)
2478
2513
CONSTANT_TRANSLATION(DynamicPackIndexInst, Unhandled)
@@ -2494,7 +2529,6 @@ CONSTANT_TRANSLATION(DeallocPackInst, Unhandled)
2494
2529
CONSTANT_TRANSLATION(DeallocStackRefInst, Unhandled)
2495
2530
CONSTANT_TRANSLATION(DeallocRefInst, Unhandled)
2496
2531
CONSTANT_TRANSLATION(DeallocPartialRefInst, Unhandled)
2497
- CONSTANT_TRANSLATION(DeallocExistentialBoxInst, Unhandled)
2498
2532
CONSTANT_TRANSLATION(UnmanagedRetainValueInst, Unhandled)
2499
2533
CONSTANT_TRANSLATION(UnmanagedReleaseValueInst, Unhandled)
2500
2534
CONSTANT_TRANSLATION(UnmanagedAutoreleaseValueInst, Unhandled)
@@ -2593,10 +2627,62 @@ IGNORE_IF_SENDABLE_RESULT_ASSIGN_OTHERWISE(StructExtractInst)
2593
2627
2594
2628
#undef IGNORE_IF_SENDABLE_RESULT_ASSIGN_OTHERWISE
2595
2629
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
+ CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT(UncheckedValueCastInst)
2658
+
2659
+ #undef CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT
2660
+
2596
2661
// ===---
2597
2662
// Custom Handling
2598
2663
//
2599
2664
2665
+ TranslationSemantics
2666
+ PartitionOpTranslator::visitRawPointerToRefInst (RawPointerToRefInst *r) {
2667
+ // If our result is non sendable, perform a look through.
2668
+ if (isNonSendableType (r->getType ()))
2669
+ return TranslationSemantics::LookThrough;
2670
+
2671
+ // Otherwise to be conservative, we need to treat this as a require.
2672
+ return TranslationSemantics::Require;
2673
+ }
2674
+
2675
+ TranslationSemantics
2676
+ PartitionOpTranslator::visitRefToRawPointerInst (RefToRawPointerInst *r) {
2677
+ // If our source ref is non sendable, perform a look through.
2678
+ if (isNonSendableType (r->getOperand ()->getType ()))
2679
+ return TranslationSemantics::LookThrough;
2680
+
2681
+ // Otherwise to be conservative, we need to treat the raw pointer as a fresh
2682
+ // sendable value.
2683
+ return TranslationSemantics::AssignFresh;
2684
+ }
2685
+
2600
2686
TranslationSemantics
2601
2687
PartitionOpTranslator::visitMarkDependenceInst (MarkDependenceInst *mdi) {
2602
2688
translateSILAssign (mdi, mdi->getValue ());
0 commit comments