@@ -419,6 +419,10 @@ struct AddressLoweringState {
419
419
// parameters are rewritten.
420
420
SmallBlotSetVector<FullApplySite, 16 > indirectApplies;
421
421
422
+ // unconditional_checked_cast instructions of loadable type which need to be
423
+ // rewritten.
424
+ SmallVector<UnconditionalCheckedCastInst *, 2 > nonopaqueResultUCCs;
425
+
422
426
// All function-exiting terminators (return or throw instructions).
423
427
SmallVector<TermInst *, 8 > exitingInsts;
424
428
@@ -639,8 +643,18 @@ void OpaqueValueVisitor::checkForIndirectApply(FullApplySite applySite) {
639
643
640
644
// / If `value` is address-only, add it to the `valueStorageMap`.
641
645
void OpaqueValueVisitor::visitValue (SILValue value) {
642
- if (!value->getType ().isObject ()
643
- || !value->getType ().isAddressOnly (*pass.function )) {
646
+ if (!value->getType ().isObject ())
647
+ return ;
648
+ if (!value->getType ().isAddressOnly (*pass.function )) {
649
+ if (auto *ucci = dyn_cast<UnconditionalCheckedCastInst>(value)) {
650
+ if (ucci->getSourceLoweredType ().isAddressOnly (*pass.function ))
651
+ return ;
652
+ if (!canIRGenUseScalarCheckedCastInstructions (
653
+ pass.function ->getModule (), ucci->getSourceFormalType (),
654
+ ucci->getTargetFormalType ())) {
655
+ pass.nonopaqueResultUCCs .push_back (ucci);
656
+ }
657
+ }
644
658
return ;
645
659
}
646
660
if (pass.valueStorageMap .contains (value)) {
@@ -3354,6 +3368,39 @@ static void rewriteIndirectApply(FullApplySite apply,
3354
3368
}
3355
3369
}
3356
3370
3371
+ static void rewriteNonopaqueUnconditionalCheckedCast (
3372
+ UnconditionalCheckedCastInst *uncondCheckedCast,
3373
+ AddressLoweringState &pass) {
3374
+ auto loc = uncondCheckedCast->getLoc ();
3375
+ SILValue srcVal = uncondCheckedCast->getOperand ();
3376
+ auto srcType = srcVal->getType ();
3377
+ auto destType = uncondCheckedCast->getType ();
3378
+ assert (srcType.isLoadable (*pass.function ));
3379
+ assert (!destType.isAddressOnly (*pass.function ));
3380
+
3381
+ // Create a stack temporary to store the source
3382
+ auto builder = pass.getBuilder (uncondCheckedCast->getIterator ());
3383
+ SILValue srcAddr = builder.createAllocStack (loc, srcType);
3384
+ builder.createStore (loc, srcVal, srcAddr,
3385
+ srcType.isTrivial (*pass.function )
3386
+ ? StoreOwnershipQualifier::Trivial
3387
+ : StoreOwnershipQualifier::Init);
3388
+ SILValue destAddr = builder.createAllocStack (loc, destType);
3389
+ builder.createUnconditionalCheckedCastAddr (loc, srcAddr, srcType.getASTType (),
3390
+ destAddr, destType.getASTType ());
3391
+
3392
+ auto afterBuilder =
3393
+ pass.getBuilder (uncondCheckedCast->getNextInstruction ()->getIterator ());
3394
+ auto *load = afterBuilder.createLoad (loc, destAddr,
3395
+ destType.isTrivial (*pass.function )
3396
+ ? LoadOwnershipQualifier::Trivial
3397
+ : LoadOwnershipQualifier::Take);
3398
+ uncondCheckedCast->replaceAllUsesWith (load);
3399
+ pass.deleter .forceDelete (uncondCheckedCast);
3400
+ afterBuilder.createDeallocStack (loc, destAddr);
3401
+ afterBuilder.createDeallocStack (loc, srcAddr);
3402
+ }
3403
+
3357
3404
static void rewriteFunction (AddressLoweringState &pass) {
3358
3405
// During rewriting, storage references are stable.
3359
3406
pass.valueStorageMap .setStable ();
@@ -3402,6 +3449,10 @@ static void rewriteFunction(AddressLoweringState &pass) {
3402
3449
}
3403
3450
}
3404
3451
3452
+ for (auto *ucci : pass.nonopaqueResultUCCs ) {
3453
+ rewriteNonopaqueUnconditionalCheckedCast (ucci, pass);
3454
+ }
3455
+
3405
3456
// Rewrite this function's return value now that all opaque values within the
3406
3457
// function are rewritten. This still depends on a valid ValueStorage
3407
3458
// projection operands.
0 commit comments