@@ -177,6 +177,85 @@ struct UseDefChainVisitor
177177
178178} // namespace
179179
180+ // / Classify an instructions as look through when we are looking through
181+ // / values. We assert that all instructions that are CONSTANT_TRANSLATION
182+ // / LookThrough to make sure they stay in sync.
183+ static bool isStaticallyLookThroughInst (SILInstruction *inst) {
184+ if (auto cast = SILDynamicCastInst::getAs (inst))
185+ if (cast.isRCIdentityPreserving ())
186+ return true ;
187+
188+ switch (inst->getKind ()) {
189+ default :
190+ return false ;
191+ case SILInstructionKind::BeginAccessInst:
192+ case SILInstructionKind::BeginBorrowInst:
193+ case SILInstructionKind::BeginDeallocRefInst:
194+ case SILInstructionKind::BridgeObjectToRefInst:
195+ case SILInstructionKind::CopyValueInst:
196+ case SILInstructionKind::CopyableToMoveOnlyWrapperAddrInst:
197+ case SILInstructionKind::CopyableToMoveOnlyWrapperValueInst:
198+ case SILInstructionKind::DestructureStructInst:
199+ case SILInstructionKind::DestructureTupleInst:
200+ case SILInstructionKind::DropDeinitInst:
201+ case SILInstructionKind::EndCOWMutationInst:
202+ case SILInstructionKind::EndInitLetRefInst:
203+ case SILInstructionKind::ExplicitCopyValueInst:
204+ case SILInstructionKind::InitEnumDataAddrInst:
205+ case SILInstructionKind::MarkDependenceInst:
206+ case SILInstructionKind::MarkUninitializedInst:
207+ case SILInstructionKind::MarkUnresolvedNonCopyableValueInst:
208+ case SILInstructionKind::MarkUnresolvedReferenceBindingInst:
209+ case SILInstructionKind::MoveOnlyWrapperToCopyableAddrInst:
210+ case SILInstructionKind::MoveOnlyWrapperToCopyableBoxInst:
211+ case SILInstructionKind::MoveOnlyWrapperToCopyableValueInst:
212+ case SILInstructionKind::MoveValueInst:
213+ case SILInstructionKind::OpenExistentialAddrInst:
214+ case SILInstructionKind::ProjectBlockStorageInst:
215+ case SILInstructionKind::ProjectBoxInst:
216+ case SILInstructionKind::RefToBridgeObjectInst:
217+ case SILInstructionKind::RefToUnownedInst:
218+ case SILInstructionKind::UncheckedRefCastInst:
219+ case SILInstructionKind::UncheckedTakeEnumDataAddrInst:
220+ case SILInstructionKind::UnownedCopyValueInst:
221+ case SILInstructionKind::UnownedToRefInst:
222+ case SILInstructionKind::UpcastInst:
223+ case SILInstructionKind::ValueToBridgeObjectInst:
224+ return true ;
225+ }
226+ }
227+
228+ static bool isLookThroughIfResultNonSendable (SILInstruction *inst) {
229+ switch (inst->getKind ()) {
230+ default :
231+ return false ;
232+ case SILInstructionKind::TupleElementAddrInst:
233+ case SILInstructionKind::StructElementAddrInst:
234+ case SILInstructionKind::RawPointerToRefInst:
235+ return true ;
236+ }
237+ }
238+
239+ static bool isLookThroughIfOperandNonSendable (SILInstruction *inst) {
240+ switch (inst->getKind ()) {
241+ default :
242+ return false ;
243+ case SILInstructionKind::RefToRawPointerInst:
244+ return true ;
245+ }
246+ }
247+
248+ static bool isLookThroughIfOperandAndResultSendable (SILInstruction *inst) {
249+ switch (inst->getKind ()) {
250+ default :
251+ return false ;
252+ case SILInstructionKind::UncheckedTrivialBitCastInst:
253+ case SILInstructionKind::UncheckedBitwiseCastInst:
254+ case SILInstructionKind::UncheckedValueCastInst:
255+ return true ;
256+ }
257+ }
258+
180259static SILValue getUnderlyingTrackedObjectValue (SILValue value) {
181260 auto *fn = value->getFunction ();
182261 SILValue result = value;
@@ -189,47 +268,37 @@ static SILValue getUnderlyingTrackedObjectValue(SILValue value) {
189268 temp = lookThroughOwnershipInsts (temp);
190269
191270 if (auto *svi = dyn_cast<SingleValueInstruction>(temp)) {
192- if (isa<ExplicitCopyValueInst, CopyableToMoveOnlyWrapperValueInst,
193- MoveOnlyWrapperToCopyableValueInst,
194- MoveOnlyWrapperToCopyableBoxInst, BeginAccessInst,
195- MarkDependenceInst>(svi) ||
196- isIdentityPreservingRefCast (svi)) {
271+ if (isStaticallyLookThroughInst (svi)) {
197272 temp = svi->getOperand (0 );
198273 }
199274
200275 // If we have a cast and our operand and result are non-Sendable, treat it
201276 // as a look through.
202- if (isa<UncheckedTrivialBitCastInst, UncheckedBitwiseCastInst,
203- UncheckedValueCastInst>(svi)) {
277+ if (isLookThroughIfOperandAndResultSendable (svi)) {
204278 if (isNonSendableType (svi->getType (), fn) &&
205279 isNonSendableType (svi->getOperand (0 )->getType (), fn)) {
206280 temp = svi->getOperand (0 );
207281 }
208282 }
209- }
210283
211- if ( auto *r = dyn_cast<RefToRawPointerInst>(temp )) {
212- // If our operand is a non-Sendable type, look through this instruction.
213- if ( isNonSendableType (r ->getOperand ()-> getType (), fn)) {
214- temp = r-> getOperand ();
284+ if ( isLookThroughIfResultNonSendable (svi )) {
285+ if ( isNonSendableType (svi-> getType (), fn)) {
286+ temp = svi ->getOperand (0 );
287+ }
215288 }
216- }
217289
218- if ( auto *r = dyn_cast<RawPointerToRefInst>(temp )) {
219- // If our result is a non-Sendable type, look through this
220- // instruction. Builtin.RawPointer is always non-Sendable.
221- if ( isNonSendableType (r-> getType (), fn)) {
222- temp = r-> getOperand ();
290+ if ( isLookThroughIfOperandNonSendable (svi )) {
291+ // If our operand is a non-Sendable type, look through this instruction.
292+ if ( isNonSendableType (svi-> getOperand ( 0 )-> getType (), fn)) {
293+ temp = svi-> getOperand ( 0 );
294+ }
223295 }
224296 }
225297
226- if (auto *dsi = dyn_cast_or_null<DestructureStructInst>(
227- temp->getDefiningInstruction ())) {
228- temp = dsi->getOperand ();
229- }
230- if (auto *dti = dyn_cast_or_null<DestructureTupleInst>(
231- temp->getDefiningInstruction ())) {
232- temp = dti->getOperand ();
298+ if (auto *inst = temp->getDefiningInstruction ()) {
299+ if (isStaticallyLookThroughInst (inst)) {
300+ temp = inst->getOperand (0 );
301+ }
233302 }
234303
235304 if (temp != result) {
@@ -1787,6 +1856,11 @@ class PartitionOpTranslator {
17871856
17881857 case TranslationSemantics::LookThrough:
17891858 assert (inst->getNumOperands () == 1 );
1859+ assert ((isStaticallyLookThroughInst (inst) ||
1860+ isLookThroughIfResultNonSendable (inst) ||
1861+ isLookThroughIfOperandNonSendable (inst) ||
1862+ isLookThroughIfOperandAndResultSendable (inst)) &&
1863+ " Out of sync... should return true for one of these categories!" );
17901864 return translateSILLookThrough (inst->getResults (), inst->getOperand (0 ));
17911865
17921866 case TranslationSemantics::Store:
@@ -1895,6 +1969,12 @@ void PartitionOpBuilder::print(llvm::raw_ostream &os) const {
18951969
18961970#define CONSTANT_TRANSLATION (INST, Kind ) \
18971971 TranslationSemantics PartitionOpTranslator::visit##INST(INST *inst) { \
1972+ assert ((TranslationSemantics::Kind != TranslationSemantics::LookThrough || \
1973+ isStaticallyLookThroughInst (inst)) && \
1974+ " Out of sync?!" ); \
1975+ assert ((TranslationSemantics::Kind == TranslationSemantics::LookThrough || \
1976+ !isStaticallyLookThroughInst (inst)) && \
1977+ " Out of sync?!" ); \
18981978 return TranslationSemantics::Kind; \
18991979 }
19001980
@@ -2008,6 +2088,11 @@ CONSTANT_TRANSLATION(MarkUninitializedInst, LookThrough)
20082088CONSTANT_TRANSLATION(DestructureTupleInst, LookThrough)
20092089CONSTANT_TRANSLATION(DestructureStructInst, LookThrough)
20102090CONSTANT_TRANSLATION(ProjectBlockStorageInst, LookThrough)
2091+ CONSTANT_TRANSLATION(RefToUnownedInst, LookThrough)
2092+ CONSTANT_TRANSLATION(UnownedToRefInst, LookThrough)
2093+ CONSTANT_TRANSLATION(UnownedCopyValueInst, LookThrough)
2094+ CONSTANT_TRANSLATION(DropDeinitInst, LookThrough)
2095+ CONSTANT_TRANSLATION(ValueToBridgeObjectInst, LookThrough)
20112096
20122097// ===---
20132098// Store
@@ -2032,6 +2117,7 @@ CONSTANT_TRANSLATION(MarkUnresolvedMoveAddrInst, Store)
20322117// value is within or because even though they are technically a use we would
20332118// rather emit an error on a better instruction.
20342119CONSTANT_TRANSLATION(AllocGlobalInst, Ignored)
2120+ CONSTANT_TRANSLATION(AutoreleaseValueInst, Ignored)
20352121CONSTANT_TRANSLATION(DeallocBoxInst, Ignored)
20362122CONSTANT_TRANSLATION(DeallocStackInst, Ignored)
20372123CONSTANT_TRANSLATION(DebugValueInst, Ignored)
@@ -2046,13 +2132,17 @@ CONSTANT_TRANSLATION(IsEscapingClosureInst, Ignored)
20462132CONSTANT_TRANSLATION(MetatypeInst, Ignored)
20472133CONSTANT_TRANSLATION(EndApplyInst, Ignored)
20482134CONSTANT_TRANSLATION(AbortApplyInst, Ignored)
2135+ CONSTANT_TRANSLATION(DebugStepInst, Ignored)
20492136
20502137// ===---
20512138// Require
20522139//
20532140
20542141// Instructions that only require that the region of the value be live:
20552142CONSTANT_TRANSLATION(FixLifetimeInst, Require)
2143+ CONSTANT_TRANSLATION(ClassifyBridgeObjectInst, Require)
2144+ CONSTANT_TRANSLATION(BridgeObjectToWordInst, Require)
2145+ CONSTANT_TRANSLATION(IsUniqueInst, Require)
20562146
20572147// ===---
20582148// Terminators
@@ -2094,20 +2184,12 @@ CONSTANT_TRANSLATION(DeallocExistentialBoxInst, Ignored)
20942184// Unhandled Instructions
20952185//
20962186
2097- CONSTANT_TRANSLATION(RefToUnownedInst, Unhandled)
2098- CONSTANT_TRANSLATION(UnownedToRefInst, Unhandled)
2099- CONSTANT_TRANSLATION(BridgeObjectToWordInst, Unhandled)
21002187CONSTANT_TRANSLATION(ObjCToThickMetatypeInst, Unhandled)
21012188CONSTANT_TRANSLATION(ObjCMetatypeToObjectInst, Unhandled)
21022189CONSTANT_TRANSLATION(ObjCExistentialMetatypeToObjectInst, Unhandled)
2103- CONSTANT_TRANSLATION(ClassifyBridgeObjectInst, Unhandled)
2104- CONSTANT_TRANSLATION(ValueToBridgeObjectInst, Unhandled)
2105- CONSTANT_TRANSLATION(UnownedCopyValueInst, Unhandled)
21062190CONSTANT_TRANSLATION(WeakCopyValueInst, Unhandled)
21072191CONSTANT_TRANSLATION(StrongCopyWeakValueInst, Unhandled)
21082192CONSTANT_TRANSLATION(StrongCopyUnmanagedValueInst, Unhandled)
2109- CONSTANT_TRANSLATION(DropDeinitInst, Unhandled)
2110- CONSTANT_TRANSLATION(IsUniqueInst, Unhandled)
21112193CONSTANT_TRANSLATION(LoadUnownedInst, Unhandled)
21122194CONSTANT_TRANSLATION(ValueMetatypeInst, Unhandled)
21132195CONSTANT_TRANSLATION(ExistentialMetatypeInst, Unhandled)
@@ -2144,14 +2226,12 @@ CONSTANT_TRANSLATION(DeallocPartialRefInst, Unhandled)
21442226CONSTANT_TRANSLATION(UnmanagedRetainValueInst, Unhandled)
21452227CONSTANT_TRANSLATION(UnmanagedReleaseValueInst, Unhandled)
21462228CONSTANT_TRANSLATION(UnmanagedAutoreleaseValueInst, Unhandled)
2147- CONSTANT_TRANSLATION(AutoreleaseValueInst, Unhandled)
21482229CONSTANT_TRANSLATION(BeginUnpairedAccessInst, Unhandled)
21492230CONSTANT_TRANSLATION(EndUnpairedAccessInst, Unhandled)
21502231CONSTANT_TRANSLATION(AssignInst, Unhandled)
21512232CONSTANT_TRANSLATION(AssignByWrapperInst, Unhandled)
21522233CONSTANT_TRANSLATION(AssignOrInitInst, Unhandled)
21532234CONSTANT_TRANSLATION(MarkFunctionEscapeInst, Unhandled)
2154- CONSTANT_TRANSLATION(DebugStepInst, Unhandled)
21552235CONSTANT_TRANSLATION(TestSpecificationInst, Unhandled)
21562236CONSTANT_TRANSLATION(StoreUnownedInst, Unhandled)
21572237CONSTANT_TRANSLATION(DeinitExistentialAddrInst, Unhandled)
@@ -2211,6 +2291,7 @@ CONSTANT_TRANSLATION(DeallocPackMetadataInst, Asserting)
22112291// of the Sendable addr. That would require adding more logic though.
22122292#define LOOKTHROUGH_IF_NONSENDABLE_RESULT_REQUIRE_OTHERWISE (INST ) \
22132293 TranslationSemantics PartitionOpTranslator::visit##INST(INST *inst) { \
2294+ assert (isLookThroughIfResultNonSendable (inst) && " Out of sync?!" ); \
22142295 if (isNonSendableType (inst->getType ())) { \
22152296 return TranslationSemantics::LookThrough; \
22162297 } \
@@ -2246,6 +2327,7 @@ IGNORE_IF_SENDABLE_RESULT_ASSIGN_OTHERWISE(StructExtractInst)
22462327#define CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT (INST ) \
22472328 \
22482329 TranslationSemantics PartitionOpTranslator::visit##INST(INST *cast) { \
2330+ assert (isLookThroughIfOperandAndResultSendable (cast) && " Out of sync" ); \
22492331 bool isOperandNonSendable = \
22502332 isNonSendableType (cast->getOperand ()->getType ()); \
22512333 bool isResultNonSendable = isNonSendableType (cast->getType ()); \
@@ -2276,6 +2358,7 @@ CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT(UncheckedValueCastInst)
22762358
22772359TranslationSemantics
22782360PartitionOpTranslator::visitRawPointerToRefInst (RawPointerToRefInst *r) {
2361+ assert (isLookThroughIfResultNonSendable (r) && " Out of sync" );
22792362 // If our result is non sendable, perform a look through.
22802363 if (isNonSendableType (r->getType ()))
22812364 return TranslationSemantics::LookThrough;
@@ -2286,6 +2369,8 @@ PartitionOpTranslator::visitRawPointerToRefInst(RawPointerToRefInst *r) {
22862369
22872370TranslationSemantics
22882371PartitionOpTranslator::visitRefToRawPointerInst (RefToRawPointerInst *r) {
2372+ assert (isLookThroughIfOperandNonSendable (r) && " Out of sync" );
2373+
22892374 // If our source ref is non sendable, perform a look through.
22902375 if (isNonSendableType (r->getOperand ()->getType ()))
22912376 return TranslationSemantics::LookThrough;
@@ -2297,7 +2382,8 @@ PartitionOpTranslator::visitRefToRawPointerInst(RefToRawPointerInst *r) {
22972382
22982383TranslationSemantics
22992384PartitionOpTranslator::visitMarkDependenceInst (MarkDependenceInst *mdi) {
2300- translateSILAssign (mdi, mdi->getValue ());
2385+ assert (isStaticallyLookThroughInst (mdi) && " Out of sync" );
2386+ translateSILLookThrough (mdi->getResults (), mdi->getValue ());
23012387 translateSILRequire (mdi->getBase ());
23022388 return TranslationSemantics::Special;
23032389}
@@ -2312,8 +2398,12 @@ PartitionOpTranslator::visitPointerToAddressInst(PointerToAddressInst *ptai) {
23122398
23132399TranslationSemantics PartitionOpTranslator::visitUnconditionalCheckedCastInst (
23142400 UnconditionalCheckedCastInst *ucci) {
2315- if (SILDynamicCastInst (ucci).isRCIdentityPreserving ())
2401+ if (SILDynamicCastInst (ucci).isRCIdentityPreserving ()) {
2402+ assert (isStaticallyLookThroughInst (ucci) && " Out of sync" );
23162403 return TranslationSemantics::LookThrough;
2404+ }
2405+
2406+ assert (!isStaticallyLookThroughInst (ucci) && " Out of sync" );
23172407 return TranslationSemantics::Assign;
23182408}
23192409
0 commit comments