@@ -468,6 +468,61 @@ findBridgeToObjCFunc(SILOptFunctionBuilder &functionBuilder,
468
468
return std::make_pair (bridgedFunc, subMap);
469
469
}
470
470
471
+ static SILValue computeFinalCastedValue (SILBuilderWithScope &builder,
472
+ SILDynamicCastInst dynamicCast,
473
+ ApplyInst *newAI) {
474
+ SILValue dest = dynamicCast.getDest ();
475
+ SILBasicBlock *failureBB = dynamicCast.getFailureBlock ();
476
+ auto loc = dynamicCast.getLocation ();
477
+ auto convTy = newAI->getType ();
478
+ bool isConditional = dynamicCast.isConditional ();
479
+ auto destTy = dest->getType ().getObjectType ();
480
+ assert (destTy == dynamicCast.getLoweredBridgedTargetObjectType () &&
481
+ " Expected Dest Type to be the same as BridgedTargetTy" );
482
+
483
+ auto &m = dynamicCast.getModule ();
484
+ if (convTy == destTy) {
485
+ return newAI;
486
+ }
487
+
488
+ if (destTy.isExactSuperclassOf (convTy)) {
489
+ return builder.createUpcast (loc, newAI, destTy);
490
+ }
491
+
492
+ if (convTy.isExactSuperclassOf (destTy)) {
493
+ // If we are not conditional, we are ok with the downcast via checked cast
494
+ // fails since we will trap.
495
+ if (!isConditional) {
496
+ return builder.createUnconditionalCheckedCast (loc, newAI, destTy);
497
+ }
498
+
499
+ // Otherwise if we /are/ emitting a conditional cast, make sure that we
500
+ // handle the failure gracefully.
501
+ auto *condBrSuccessBB =
502
+ newAI->getFunction ()->createBasicBlockAfter (newAI->getParent ());
503
+ condBrSuccessBB->createPhiArgument (destTy, ValueOwnershipKind::Owned,
504
+ nullptr );
505
+ builder.createCheckedCastBranch (loc, /* isExact*/ false , newAI, destTy,
506
+ condBrSuccessBB, failureBB);
507
+ builder.setInsertionPoint (condBrSuccessBB, condBrSuccessBB->begin ());
508
+ return condBrSuccessBB->getArgument (0 );
509
+ }
510
+
511
+ if (convTy.getASTType () ==
512
+ getNSBridgedClassOfCFClass (m.getSwiftModule (), destTy.getASTType ()) ||
513
+ destTy.getASTType () ==
514
+ getNSBridgedClassOfCFClass (m.getSwiftModule (), convTy.getASTType ())) {
515
+ // Handle NS <-> CF toll-free bridging here.
516
+ return SILValue (builder.createUncheckedRefCast (loc, newAI, destTy));
517
+ }
518
+
519
+ llvm_unreachable (
520
+ " optimizeBridgedSwiftToObjCCast: should never reach this condition: if "
521
+ " the Destination does not have the same type, is not a bridgeable CF "
522
+ " type and isn't a superclass/subclass of the source operand we should "
523
+ " have bailed earlier." );
524
+ }
525
+
471
526
// / Create a call of _bridgeToObjectiveC which converts an _ObjectiveCBridgeable
472
527
// / instance into a bridged ObjC type.
473
528
SILInstruction *
@@ -632,63 +687,18 @@ CastOptimizer::optimizeBridgedSwiftToObjCCast(SILDynamicCastInst dynamicCast) {
632
687
}
633
688
}
634
689
635
- SILInstruction *NewI = NewAI;
636
-
637
- if (Dest) {
638
- // If it is addr cast then store the result.
639
- auto ConvTy = NewAI->getType ();
640
- auto DestTy = Dest->getType ().getObjectType ();
641
- assert (DestTy == SILType::getPrimitiveObjectType (
642
- BridgedTargetTy->getCanonicalType ()) &&
643
- " Expected Dest Type to be the same as BridgedTargetTy" );
644
- SILValue CastedValue;
645
- if (ConvTy == DestTy) {
646
- CastedValue = NewAI;
647
- } else if (DestTy.isExactSuperclassOf (ConvTy)) {
648
- CastedValue = Builder.createUpcast (Loc, NewAI, DestTy);
649
- } else if (ConvTy.isExactSuperclassOf (DestTy)) {
650
- // The downcast from a base class to derived class may fail.
651
- if (isConditional) {
652
- // In case of a conditional cast, we should handle it gracefully.
653
- auto CondBrSuccessBB =
654
- NewAI->getFunction ()->createBasicBlockAfter (NewAI->getParent ());
655
- CondBrSuccessBB->createPhiArgument (DestTy, ValueOwnershipKind::Owned,
656
- nullptr );
657
- Builder.createCheckedCastBranch (Loc, /* isExact*/ false , NewAI, DestTy,
658
- CondBrSuccessBB, FailureBB);
659
- Builder.setInsertionPoint (CondBrSuccessBB, CondBrSuccessBB->begin ());
660
- CastedValue = CondBrSuccessBB->getArgument (0 );
661
- } else {
662
- CastedValue = SILValue (
663
- Builder.createUnconditionalCheckedCast (Loc, NewAI, DestTy));
664
- }
665
- } else if (ConvTy.getASTType () ==
666
- getNSBridgedClassOfCFClass (M.getSwiftModule (),
667
- DestTy.getASTType ()) ||
668
- DestTy.getASTType () ==
669
- getNSBridgedClassOfCFClass (M.getSwiftModule (),
670
- ConvTy.getASTType ())) {
671
- // Handle NS <-> CF toll-free bridging here.
672
- CastedValue =
673
- SILValue (Builder.createUncheckedRefCast (Loc, NewAI, DestTy));
674
- } else {
675
- llvm_unreachable (" optimizeBridgedSwiftToObjCCast: should never reach "
676
- " this condition: if the Destination does not have the "
677
- " same type, is not a bridgeable CF type and isn't a "
678
- " superclass/subclass of the source operand we should "
679
- " have bailed earlier" );
680
- }
681
- NewI = Builder.createStore (Loc, CastedValue, Dest,
682
- StoreOwnershipQualifier::Unqualified);
683
- if (isConditional && NewI->getParent () != NewAI->getParent ()) {
684
- Builder.createBranch (Loc, SuccessBB);
685
- }
686
- }
690
+ if (!Dest)
691
+ return NewAI;
687
692
688
- if (Dest) {
689
- eraseInstAction (Inst);
693
+ // If it is addr cast then store the result.
694
+ SILValue castedValue = computeFinalCastedValue (Builder, dynamicCast, NewAI);
695
+ SILInstruction *NewI = Builder.createStore (
696
+ Loc, castedValue, Dest, StoreOwnershipQualifier::Unqualified);
697
+ if (isConditional && NewI->getParent () != NewAI->getParent ()) {
698
+ Builder.createBranch (Loc, SuccessBB);
690
699
}
691
700
701
+ eraseInstAction (Inst);
692
702
return NewI;
693
703
}
694
704
0 commit comments