@@ -822,6 +822,11 @@ static Operand *getReusedStorageOperand(SILValue value) {
822
822
if (auto *switchEnum = dyn_cast<SwitchEnumInst>(term)) {
823
823
return &switchEnum->getAllOperands ()[0 ];
824
824
}
825
+ if (auto *checkedCastBr = dyn_cast<CheckedCastBranchInst>(term)) {
826
+ if (value->getParentBlock () == checkedCastBr->getFailureBB ()) {
827
+ return &checkedCastBr->getAllOperands ()[0 ];
828
+ }
829
+ }
825
830
}
826
831
break ;
827
832
}
@@ -2561,36 +2566,10 @@ class UseRewriter : SILInstructionVisitor<UseRewriter> {
2561
2566
}
2562
2567
2563
2568
void visitUnconditionalCheckedCastInst (
2564
- UnconditionalCheckedCastInst *uncondCheckedCast) {
2565
- SILValue srcVal = uncondCheckedCast->getOperand ();
2566
- assert (srcVal->getType ().isAddressOnly (*pass.function ));
2567
- SILValue srcAddr = pass.valueStorageMap .getStorage (srcVal).storageAddress ;
2569
+ UnconditionalCheckedCastInst *uncondCheckedCast);
2570
+
2571
+ void visitCheckedCastBranchInst (CheckedCastBranchInst *checkedCastBranch);
2568
2572
2569
- if (uncondCheckedCast->getType ().isAddressOnly (*pass.function )) {
2570
- // When cast destination has address only type, use the storage address
2571
- SILValue destAddr = addrMat.materializeAddress (uncondCheckedCast);
2572
- markRewritten (uncondCheckedCast, destAddr);
2573
- builder.createUnconditionalCheckedCastAddr (
2574
- uncondCheckedCast->getLoc (), srcAddr, srcAddr->getType ().getASTType (),
2575
- destAddr, destAddr->getType ().getASTType ());
2576
- return ;
2577
- }
2578
- // For loadable cast destination type, create a stack temporary
2579
- SILValue destAddr = builder.createAllocStack (uncondCheckedCast->getLoc (),
2580
- uncondCheckedCast->getType ());
2581
- builder.createUnconditionalCheckedCastAddr (
2582
- uncondCheckedCast->getLoc (), srcAddr, srcAddr->getType ().getASTType (),
2583
- destAddr, destAddr->getType ().getASTType ());
2584
- auto nextBuilder =
2585
- pass.getBuilder (uncondCheckedCast->getNextInstruction ()->getIterator ());
2586
- auto dest = nextBuilder.createLoad (
2587
- uncondCheckedCast->getLoc (), destAddr,
2588
- destAddr->getType ().isTrivial (*uncondCheckedCast->getFunction ())
2589
- ? LoadOwnershipQualifier::Trivial
2590
- : LoadOwnershipQualifier::Copy);
2591
- nextBuilder.createDeallocStack (uncondCheckedCast->getLoc (), destAddr);
2592
- uncondCheckedCast->replaceAllUsesWith (dest);
2593
- }
2594
2573
void visitUncheckedEnumDataInst (UncheckedEnumDataInst *enumDataInst);
2595
2574
};
2596
2575
} // end anonymous namespace
@@ -2832,6 +2811,89 @@ void UseRewriter::visitSwitchEnumInst(SwitchEnumInst * switchEnum) {
2832
2811
defaultCounter);
2833
2812
}
2834
2813
2814
+ void UseRewriter::visitCheckedCastBranchInst (
2815
+ CheckedCastBranchInst *checkedCastBranch) {
2816
+ auto loc = checkedCastBranch->getLoc ();
2817
+ auto *func = checkedCastBranch->getFunction ();
2818
+ auto *successBB = checkedCastBranch->getSuccessBB ();
2819
+ auto *failureBB = checkedCastBranch->getFailureBB ();
2820
+ auto *oldSuccessVal = successBB->getArgument (0 );
2821
+ auto *oldFailureVal = failureBB->getArgument (0 );
2822
+ auto termBuilder = pass.getTermBuilder (checkedCastBranch);
2823
+ auto successBuilder = pass.getBuilder (successBB->begin ());
2824
+ auto failureBuilder = pass.getBuilder (failureBB->begin ());
2825
+ bool isAddressOnlyTarget = oldSuccessVal->getType ().isAddressOnly (*func);
2826
+
2827
+ auto srcAddr = pass.valueStorageMap .getStorage (use->get ()).storageAddress ;
2828
+
2829
+ if (isAddressOnlyTarget) {
2830
+ // If target is opaque, use the storage address mapped to success
2831
+ // block's argument as the destination for checked_cast_addr_br.
2832
+ SILValue destAddr =
2833
+ pass.valueStorageMap .getStorage (oldSuccessVal).storageAddress ;
2834
+
2835
+ termBuilder.createCheckedCastAddrBranch (
2836
+ loc, CastConsumptionKind::TakeOnSuccess, srcAddr,
2837
+ checkedCastBranch->getSourceFormalType (), destAddr,
2838
+ checkedCastBranch->getTargetFormalType (), successBB, failureBB,
2839
+ checkedCastBranch->getTrueBBCount (),
2840
+ checkedCastBranch->getFalseBBCount ());
2841
+
2842
+ // In this case, since both success and failure block's args are opaque,
2843
+ // create dummy loads from their storage addresses that will later be
2844
+ // rewritten to copy_addr in DefRewriter::visitLoadInst
2845
+ auto newSuccessVal = successBuilder.createTrivialLoadOr (
2846
+ loc, destAddr, LoadOwnershipQualifier::Take);
2847
+ oldSuccessVal->replaceAllUsesWith (newSuccessVal);
2848
+ successBB->eraseArgument (0 );
2849
+
2850
+ pass.valueStorageMap .replaceValue (oldSuccessVal, newSuccessVal);
2851
+
2852
+ auto newFailureVal = failureBuilder.createTrivialLoadOr (
2853
+ loc, srcAddr, LoadOwnershipQualifier::Take);
2854
+ oldFailureVal->replaceAllUsesWith (newFailureVal);
2855
+ failureBB->eraseArgument (0 );
2856
+
2857
+ pass.valueStorageMap .replaceValue (oldFailureVal, newFailureVal);
2858
+ markRewritten (newFailureVal, srcAddr);
2859
+ } else {
2860
+ // If the target is loadable, create a stack temporary to be used as the
2861
+ // destination for checked_cast_addr_br.
2862
+ SILValue destAddr = termBuilder.createAllocStack (
2863
+ loc, checkedCastBranch->getTargetLoweredType ());
2864
+
2865
+ termBuilder.createCheckedCastAddrBranch (
2866
+ loc, CastConsumptionKind::TakeOnSuccess, srcAddr,
2867
+ checkedCastBranch->getSourceFormalType (), destAddr,
2868
+ checkedCastBranch->getTargetFormalType (), successBB, failureBB,
2869
+ checkedCastBranch->getTrueBBCount (),
2870
+ checkedCastBranch->getFalseBBCount ());
2871
+
2872
+ // Replace the success block arg with loaded value from destAddr, and delete
2873
+ // the success block arg.
2874
+ auto newSuccessVal = successBuilder.createTrivialLoadOr (
2875
+ loc, destAddr, LoadOwnershipQualifier::Take);
2876
+ oldSuccessVal->replaceAllUsesWith (newSuccessVal);
2877
+ successBB->eraseArgument (0 );
2878
+
2879
+ successBuilder.createDeallocStack (loc, destAddr);
2880
+ failureBuilder.createDeallocStack (loc, destAddr);
2881
+
2882
+ // Since failure block arg is opaque, create dummy load from its storage
2883
+ // address. This will be replaced later with copy_addr in
2884
+ // DefRewriter::visitLoadInst.
2885
+ auto newFailureVal = failureBuilder.createTrivialLoadOr (
2886
+ loc, srcAddr, LoadOwnershipQualifier::Take);
2887
+ oldFailureVal->replaceAllUsesWith (newFailureVal);
2888
+ failureBB->eraseArgument (0 );
2889
+
2890
+ pass.valueStorageMap .replaceValue (oldFailureVal, newFailureVal);
2891
+ markRewritten (newFailureVal, srcAddr);
2892
+ }
2893
+
2894
+ pass.deleter .forceDelete (checkedCastBranch);
2895
+ }
2896
+
2835
2897
void UseRewriter::visitUncheckedEnumDataInst (
2836
2898
UncheckedEnumDataInst *enumDataInst) {
2837
2899
assert (use == getReusedStorageOperand (enumDataInst));
@@ -2852,6 +2914,38 @@ void UseRewriter::visitUncheckedEnumDataInst(
2852
2914
markRewritten (enumDataInst, enumAddrInst);
2853
2915
}
2854
2916
2917
+ void UseRewriter::visitUnconditionalCheckedCastInst (
2918
+ UnconditionalCheckedCastInst *uncondCheckedCast) {
2919
+ SILValue srcVal = uncondCheckedCast->getOperand ();
2920
+ assert (srcVal->getType ().isAddressOnly (*pass.function ));
2921
+ SILValue srcAddr = pass.valueStorageMap .getStorage (srcVal).storageAddress ;
2922
+
2923
+ if (uncondCheckedCast->getType ().isAddressOnly (*pass.function )) {
2924
+ // When cast destination has address only type, use the storage address
2925
+ SILValue destAddr = addrMat.materializeAddress (uncondCheckedCast);
2926
+ markRewritten (uncondCheckedCast, destAddr);
2927
+ builder.createUnconditionalCheckedCastAddr (
2928
+ uncondCheckedCast->getLoc (), srcAddr, srcAddr->getType ().getASTType (),
2929
+ destAddr, destAddr->getType ().getASTType ());
2930
+ return ;
2931
+ }
2932
+ // For loadable cast destination type, create a stack temporary
2933
+ SILValue destAddr = builder.createAllocStack (uncondCheckedCast->getLoc (),
2934
+ uncondCheckedCast->getType ());
2935
+ builder.createUnconditionalCheckedCastAddr (
2936
+ uncondCheckedCast->getLoc (), srcAddr, srcAddr->getType ().getASTType (),
2937
+ destAddr, destAddr->getType ().getASTType ());
2938
+ auto nextBuilder =
2939
+ pass.getBuilder (uncondCheckedCast->getNextInstruction ()->getIterator ());
2940
+ auto dest = nextBuilder.createLoad (
2941
+ uncondCheckedCast->getLoc (), destAddr,
2942
+ destAddr->getType ().isTrivial (*uncondCheckedCast->getFunction ())
2943
+ ? LoadOwnershipQualifier::Trivial
2944
+ : LoadOwnershipQualifier::Copy);
2945
+ nextBuilder.createDeallocStack (uncondCheckedCast->getLoc (), destAddr);
2946
+ uncondCheckedCast->replaceAllUsesWith (dest);
2947
+ }
2948
+
2855
2949
// ===----------------------------------------------------------------------===//
2856
2950
// DefRewriter
2857
2951
//
@@ -2881,7 +2975,6 @@ class DefRewriter : SILInstructionVisitor<DefRewriter> {
2881
2975
static void rewriteValue (SILValue value, AddressLoweringState &pass) {
2882
2976
if (auto *inst = value->getDefiningInstruction ()) {
2883
2977
DefRewriter (pass, value, inst->getIterator ()).visit (inst);
2884
-
2885
2978
} else {
2886
2979
// function args are already rewritten.
2887
2980
auto *blockArg = cast<SILPhiArgument>(value);
0 commit comments