@@ -177,6 +177,85 @@ struct UseDefChainVisitor
177
177
178
178
} // namespace
179
179
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
+
180
259
static SILValue getUnderlyingTrackedObjectValue (SILValue value) {
181
260
auto *fn = value->getFunction ();
182
261
SILValue result = value;
@@ -189,47 +268,37 @@ static SILValue getUnderlyingTrackedObjectValue(SILValue value) {
189
268
temp = lookThroughOwnershipInsts (temp);
190
269
191
270
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)) {
197
272
temp = svi->getOperand (0 );
198
273
}
199
274
200
275
// If we have a cast and our operand and result are non-Sendable, treat it
201
276
// as a look through.
202
- if (isa<UncheckedTrivialBitCastInst, UncheckedBitwiseCastInst,
203
- UncheckedValueCastInst>(svi)) {
277
+ if (isLookThroughIfOperandAndResultSendable (svi)) {
204
278
if (isNonSendableType (svi->getType (), fn) &&
205
279
isNonSendableType (svi->getOperand (0 )->getType (), fn)) {
206
280
temp = svi->getOperand (0 );
207
281
}
208
282
}
209
- }
210
283
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
+ }
215
288
}
216
- }
217
289
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
+ }
223
295
}
224
296
}
225
297
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
+ }
233
302
}
234
303
235
304
if (temp != result) {
@@ -1787,6 +1856,11 @@ class PartitionOpTranslator {
1787
1856
1788
1857
case TranslationSemantics::LookThrough:
1789
1858
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!" );
1790
1864
return translateSILLookThrough (inst->getResults (), inst->getOperand (0 ));
1791
1865
1792
1866
case TranslationSemantics::Store:
@@ -1895,6 +1969,12 @@ void PartitionOpBuilder::print(llvm::raw_ostream &os) const {
1895
1969
1896
1970
#define CONSTANT_TRANSLATION (INST, Kind ) \
1897
1971
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?!" ); \
1898
1978
return TranslationSemantics::Kind; \
1899
1979
}
1900
1980
@@ -2008,6 +2088,11 @@ CONSTANT_TRANSLATION(MarkUninitializedInst, LookThrough)
2008
2088
CONSTANT_TRANSLATION(DestructureTupleInst, LookThrough)
2009
2089
CONSTANT_TRANSLATION(DestructureStructInst, LookThrough)
2010
2090
CONSTANT_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)
2011
2096
2012
2097
// ===---
2013
2098
// Store
@@ -2032,6 +2117,7 @@ CONSTANT_TRANSLATION(MarkUnresolvedMoveAddrInst, Store)
2032
2117
// value is within or because even though they are technically a use we would
2033
2118
// rather emit an error on a better instruction.
2034
2119
CONSTANT_TRANSLATION(AllocGlobalInst, Ignored)
2120
+ CONSTANT_TRANSLATION(AutoreleaseValueInst, Ignored)
2035
2121
CONSTANT_TRANSLATION(DeallocBoxInst, Ignored)
2036
2122
CONSTANT_TRANSLATION(DeallocStackInst, Ignored)
2037
2123
CONSTANT_TRANSLATION(DebugValueInst, Ignored)
@@ -2046,13 +2132,17 @@ CONSTANT_TRANSLATION(IsEscapingClosureInst, Ignored)
2046
2132
CONSTANT_TRANSLATION(MetatypeInst, Ignored)
2047
2133
CONSTANT_TRANSLATION(EndApplyInst, Ignored)
2048
2134
CONSTANT_TRANSLATION(AbortApplyInst, Ignored)
2135
+ CONSTANT_TRANSLATION(DebugStepInst, Ignored)
2049
2136
2050
2137
// ===---
2051
2138
// Require
2052
2139
//
2053
2140
2054
2141
// Instructions that only require that the region of the value be live:
2055
2142
CONSTANT_TRANSLATION(FixLifetimeInst, Require)
2143
+ CONSTANT_TRANSLATION(ClassifyBridgeObjectInst, Require)
2144
+ CONSTANT_TRANSLATION(BridgeObjectToWordInst, Require)
2145
+ CONSTANT_TRANSLATION(IsUniqueInst, Require)
2056
2146
2057
2147
// ===---
2058
2148
// Terminators
@@ -2094,20 +2184,12 @@ CONSTANT_TRANSLATION(DeallocExistentialBoxInst, Ignored)
2094
2184
// Unhandled Instructions
2095
2185
//
2096
2186
2097
- CONSTANT_TRANSLATION(RefToUnownedInst, Unhandled)
2098
- CONSTANT_TRANSLATION(UnownedToRefInst, Unhandled)
2099
- CONSTANT_TRANSLATION(BridgeObjectToWordInst, Unhandled)
2100
2187
CONSTANT_TRANSLATION(ObjCToThickMetatypeInst, Unhandled)
2101
2188
CONSTANT_TRANSLATION(ObjCMetatypeToObjectInst, Unhandled)
2102
2189
CONSTANT_TRANSLATION(ObjCExistentialMetatypeToObjectInst, Unhandled)
2103
- CONSTANT_TRANSLATION(ClassifyBridgeObjectInst, Unhandled)
2104
- CONSTANT_TRANSLATION(ValueToBridgeObjectInst, Unhandled)
2105
- CONSTANT_TRANSLATION(UnownedCopyValueInst, Unhandled)
2106
2190
CONSTANT_TRANSLATION(WeakCopyValueInst, Unhandled)
2107
2191
CONSTANT_TRANSLATION(StrongCopyWeakValueInst, Unhandled)
2108
2192
CONSTANT_TRANSLATION(StrongCopyUnmanagedValueInst, Unhandled)
2109
- CONSTANT_TRANSLATION(DropDeinitInst, Unhandled)
2110
- CONSTANT_TRANSLATION(IsUniqueInst, Unhandled)
2111
2193
CONSTANT_TRANSLATION(LoadUnownedInst, Unhandled)
2112
2194
CONSTANT_TRANSLATION(ValueMetatypeInst, Unhandled)
2113
2195
CONSTANT_TRANSLATION(ExistentialMetatypeInst, Unhandled)
@@ -2144,14 +2226,12 @@ CONSTANT_TRANSLATION(DeallocPartialRefInst, Unhandled)
2144
2226
CONSTANT_TRANSLATION(UnmanagedRetainValueInst, Unhandled)
2145
2227
CONSTANT_TRANSLATION(UnmanagedReleaseValueInst, Unhandled)
2146
2228
CONSTANT_TRANSLATION(UnmanagedAutoreleaseValueInst, Unhandled)
2147
- CONSTANT_TRANSLATION(AutoreleaseValueInst, Unhandled)
2148
2229
CONSTANT_TRANSLATION(BeginUnpairedAccessInst, Unhandled)
2149
2230
CONSTANT_TRANSLATION(EndUnpairedAccessInst, Unhandled)
2150
2231
CONSTANT_TRANSLATION(AssignInst, Unhandled)
2151
2232
CONSTANT_TRANSLATION(AssignByWrapperInst, Unhandled)
2152
2233
CONSTANT_TRANSLATION(AssignOrInitInst, Unhandled)
2153
2234
CONSTANT_TRANSLATION(MarkFunctionEscapeInst, Unhandled)
2154
- CONSTANT_TRANSLATION(DebugStepInst, Unhandled)
2155
2235
CONSTANT_TRANSLATION(TestSpecificationInst, Unhandled)
2156
2236
CONSTANT_TRANSLATION(StoreUnownedInst, Unhandled)
2157
2237
CONSTANT_TRANSLATION(DeinitExistentialAddrInst, Unhandled)
@@ -2211,6 +2291,7 @@ CONSTANT_TRANSLATION(DeallocPackMetadataInst, Asserting)
2211
2291
// of the Sendable addr. That would require adding more logic though.
2212
2292
#define LOOKTHROUGH_IF_NONSENDABLE_RESULT_REQUIRE_OTHERWISE (INST ) \
2213
2293
TranslationSemantics PartitionOpTranslator::visit##INST(INST *inst) { \
2294
+ assert (isLookThroughIfResultNonSendable (inst) && " Out of sync?!" ); \
2214
2295
if (isNonSendableType (inst->getType ())) { \
2215
2296
return TranslationSemantics::LookThrough; \
2216
2297
} \
@@ -2246,6 +2327,7 @@ IGNORE_IF_SENDABLE_RESULT_ASSIGN_OTHERWISE(StructExtractInst)
2246
2327
#define CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT (INST ) \
2247
2328
\
2248
2329
TranslationSemantics PartitionOpTranslator::visit##INST(INST *cast) { \
2330
+ assert (isLookThroughIfOperandAndResultSendable (cast) && " Out of sync" ); \
2249
2331
bool isOperandNonSendable = \
2250
2332
isNonSendableType (cast->getOperand ()->getType ()); \
2251
2333
bool isResultNonSendable = isNonSendableType (cast->getType ()); \
@@ -2276,6 +2358,7 @@ CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT(UncheckedValueCastInst)
2276
2358
2277
2359
TranslationSemantics
2278
2360
PartitionOpTranslator::visitRawPointerToRefInst (RawPointerToRefInst *r) {
2361
+ assert (isLookThroughIfResultNonSendable (r) && " Out of sync" );
2279
2362
// If our result is non sendable, perform a look through.
2280
2363
if (isNonSendableType (r->getType ()))
2281
2364
return TranslationSemantics::LookThrough;
@@ -2286,6 +2369,8 @@ PartitionOpTranslator::visitRawPointerToRefInst(RawPointerToRefInst *r) {
2286
2369
2287
2370
TranslationSemantics
2288
2371
PartitionOpTranslator::visitRefToRawPointerInst (RefToRawPointerInst *r) {
2372
+ assert (isLookThroughIfOperandNonSendable (r) && " Out of sync" );
2373
+
2289
2374
// If our source ref is non sendable, perform a look through.
2290
2375
if (isNonSendableType (r->getOperand ()->getType ()))
2291
2376
return TranslationSemantics::LookThrough;
@@ -2297,7 +2382,8 @@ PartitionOpTranslator::visitRefToRawPointerInst(RefToRawPointerInst *r) {
2297
2382
2298
2383
TranslationSemantics
2299
2384
PartitionOpTranslator::visitMarkDependenceInst (MarkDependenceInst *mdi) {
2300
- translateSILAssign (mdi, mdi->getValue ());
2385
+ assert (isStaticallyLookThroughInst (mdi) && " Out of sync" );
2386
+ translateSILLookThrough (mdi->getResults (), mdi->getValue ());
2301
2387
translateSILRequire (mdi->getBase ());
2302
2388
return TranslationSemantics::Special;
2303
2389
}
@@ -2312,8 +2398,12 @@ PartitionOpTranslator::visitPointerToAddressInst(PointerToAddressInst *ptai) {
2312
2398
2313
2399
TranslationSemantics PartitionOpTranslator::visitUnconditionalCheckedCastInst (
2314
2400
UnconditionalCheckedCastInst *ucci) {
2315
- if (SILDynamicCastInst (ucci).isRCIdentityPreserving ())
2401
+ if (SILDynamicCastInst (ucci).isRCIdentityPreserving ()) {
2402
+ assert (isStaticallyLookThroughInst (ucci) && " Out of sync" );
2316
2403
return TranslationSemantics::LookThrough;
2404
+ }
2405
+
2406
+ assert (!isStaticallyLookThroughInst (ucci) && " Out of sync" );
2317
2407
return TranslationSemantics::Assign;
2318
2408
}
2319
2409
0 commit comments