[cast-optimizer] Properly handle conditional bridged casts in optimizeBridgedSwiftToObjCCast

If there is a conditional bridged cast from a swift type to an objc type and this cast happens in two stages, where:
-  in the firs stage the Swift type is casted to its bridged ObjC class (e.g. String to NSString) and
-  in the second stage there is a downcast to a subclass of a bridged ObjC class (e.g. NSString to MyString)

then the second stage should use a conditional cast.

rdar://32319580
This commit is contained in:
Roman Levenstein
2017-05-22 00:18:52 -07:00
parent 664948eb3c
commit 4ef29e57af
2 changed files with 23 additions and 14 deletions

View File

@@ -1461,13 +1461,6 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
auto &M = Inst->getModule();
auto Loc = Inst->getLoc();
// FIXME (rdar://problem/32319580): The code below handles a cast from a Swift
// value type to a subclass of its bridged type by emitting an unconditional
// cast, even if the cast is supposed to be conditional.
if (isConditional && !BridgedSourceTy->isEqual(BridgedTargetTy) &&
BridgedSourceTy->isBindableToSuperclassOf(BridgedTargetTy))
return nullptr;
bool AddressOnlyType = false;
if (!Src->getType().isLoadable(M) || !Dest->getType().isLoadable(M)) {
AddressOnlyType = true;
@@ -1663,8 +1656,21 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
CastedValue = SILValue(
(ConvTy == DestTy) ? NewI : Builder.createUpcast(Loc, NewAI, DestTy));
} else if (ConvTy.isExactSuperclassOf(DestTy)) {
CastedValue = SILValue(
Builder.createUnconditionalCheckedCast(Loc, NewAI, DestTy));
// The downcast from a base class to derived class may fail.
if (isConditional) {
// In case of a conditional cast, we should handle it gracefully.
auto CondBrSuccessBB =
NewAI->getFunction()->createBasicBlock(NewAI->getParentBlock());
CondBrSuccessBB->createPHIArgument(DestTy, ValueOwnershipKind::Owned,
nullptr);
Builder.createCheckedCastBranch(Loc, /* isExact*/ false, NewAI, DestTy,
CondBrSuccessBB, FailureBB);
Builder.setInsertionPoint(CondBrSuccessBB, CondBrSuccessBB->begin());
CastedValue = CondBrSuccessBB->getArgument(0);
} else {
CastedValue = SILValue(
Builder.createUnconditionalCheckedCast(Loc, NewAI, DestTy));
}
} else if (ConvTy.getSwiftRValueType() ==
getNSBridgedClassOfCFClass(M.getSwiftModule(),
DestTy.getSwiftRValueType()) ||
@@ -1681,6 +1687,9 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
}
NewI = Builder.createStore(Loc, CastedValue, Dest,
StoreOwnershipQualifier::Unqualified);
if (isConditional && NewI->getParentBlock() != NewAI->getParentBlock()) {
Builder.createBranch(Loc, SuccessBB);
}
}
if (Dest) {