Skip to content

Commit 6f5cbbc

Browse files
author
Joe Shajrawi
committed
Merge pull request #13336 from shajrawi/cast_opt_bug_fix
Cast Optimizer: bail out when we can't do the cast
1 parent e39bf89 commit 6f5cbbc

File tree

2 files changed

+82
-4
lines changed

2 files changed

+82
-4
lines changed

lib/SILOptimizer/Utils/Local.cpp

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,6 +1571,40 @@ optimizeBridgedObjCToSwiftCast(SILInstruction *Inst,
15711571
return (NewI) ? NewI : AI;
15721572
}
15731573

1574+
static bool canOptimizeCast(const swift::Type &BridgedTargetTy,
1575+
swift::SILModule &M,
1576+
swift::SILFunctionConventions &substConv) {
1577+
// DestTy is the type which we want to convert to
1578+
SILType DestTy =
1579+
SILType::getPrimitiveObjectType(BridgedTargetTy->getCanonicalType());
1580+
// ConvTy is the return type of the _bridgeToObjectiveCImpl()
1581+
auto ConvTy = substConv.getSILResultType().getObjectType();
1582+
if (ConvTy == DestTy) {
1583+
// Destination is the same type
1584+
return true;
1585+
}
1586+
// Check if a superclass/subclass of the source operand
1587+
if (DestTy.isExactSuperclassOf(ConvTy)) {
1588+
return true;
1589+
}
1590+
if (ConvTy.isExactSuperclassOf(DestTy)) {
1591+
return true;
1592+
}
1593+
// check if it is a bridgeable CF type
1594+
if (ConvTy.getSwiftRValueType() ==
1595+
getNSBridgedClassOfCFClass(M.getSwiftModule(),
1596+
DestTy.getSwiftRValueType())) {
1597+
return true;
1598+
}
1599+
if (DestTy.getSwiftRValueType() ==
1600+
getNSBridgedClassOfCFClass(M.getSwiftModule(),
1601+
ConvTy.getSwiftRValueType())) {
1602+
return true;
1603+
}
1604+
// All else failed - can't optimize this case
1605+
return false;
1606+
}
1607+
15741608
/// Create a call of _bridgeToObjectiveC which converts an _ObjectiveCBridgeable
15751609
/// instance into a bridged ObjC type.
15761610
SILInstruction *
@@ -1646,7 +1680,8 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
16461680
if (ResultsRef.size() != 1)
16471681
return nullptr;
16481682

1649-
auto MemberDeclRef = SILDeclRef(Results.front());
1683+
auto *resultDecl = Results.front();
1684+
auto MemberDeclRef = SILDeclRef(resultDecl);
16501685
auto *BridgedFunc = M.getOrCreateFunction(Loc, MemberDeclRef,
16511686
ForDefinition_t::NotForDefinition);
16521687

@@ -1677,6 +1712,11 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
16771712
SILType SubstFnTy = SILFnTy.substGenericArgs(M, SubMap);
16781713
SILFunctionConventions substConv(SubstFnTy.castTo<SILFunctionType>(), M);
16791714

1715+
// check that we can go through with the optimization
1716+
if (!canOptimizeCast(BridgedTargetTy, M, substConv)) {
1717+
return nullptr;
1718+
}
1719+
16801720
auto FnRef = Builder.createFunctionRef(Loc, BridgedFunc);
16811721
if (Src->getType().isAddress() && !substConv.isSILIndirect(ParamTypes[0])) {
16821722
// Create load
@@ -1811,6 +1851,9 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
18111851
// If it is addr cast then store the result.
18121852
auto ConvTy = NewAI->getType();
18131853
auto DestTy = Dest->getType().getObjectType();
1854+
assert(DestTy == SILType::getPrimitiveObjectType(
1855+
BridgedTargetTy->getCanonicalType()) &&
1856+
"Expected Dest Type to be the same as BridgedTargetTy");
18141857
SILValue CastedValue;
18151858
if (ConvTy == DestTy) {
18161859
CastedValue = NewAI;
@@ -1842,9 +1885,11 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
18421885
CastedValue =
18431886
SILValue(Builder.createUncheckedRefCast(Loc, NewAI, DestTy));
18441887
} else {
1845-
llvm_unreachable(
1846-
"Destination should have the same type, be bridgeable CF "
1847-
"type or be a superclass/subclass of the source operand");
1888+
llvm_unreachable("optimizeBridgedSwiftToObjCCast: should never reach "
1889+
"this condition: if the Destination does not have the "
1890+
"same type, is not a bridgeable CF type and isn't a "
1891+
"superclass/subclass of the source operand we should "
1892+
"have bailed earlier");
18481893
}
18491894
NewI = Builder.createStore(Loc, CastedValue, Dest,
18501895
StoreOwnershipQualifier::Unqualified);

test/SILOptimizer/bridged_casts_folding.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,3 +911,36 @@ var anyHashable: AnyHashable = 0
911911
public func testUncondCastSwiftToSubclass() -> NSObjectSubclass {
912912
return anyHashable as! NSObjectSubclass
913913
}
914+
915+
class MyThing: Hashable {
916+
let name: String
917+
918+
init(name: String) {
919+
self.name = name
920+
}
921+
922+
deinit {
923+
Swift.print("Deinit \(name)")
924+
}
925+
926+
var hashValue: Int {
927+
return 0
928+
}
929+
930+
static func ==(lhs: MyThing, rhs: MyThing) -> Bool {
931+
return false
932+
}
933+
}
934+
935+
// CHECK-LABEL: sil hidden [noinline] @_T021bridged_casts_folding26doSomethingWithAnyHashableys0gH0VF : $@convention(thin) (@in AnyHashable) -> ()
936+
// CHECK: checked_cast_addr_br take_always AnyHashable in %0 : $*AnyHashable to MyThing
937+
@inline(never)
938+
func doSomethingWithAnyHashable(_ item: AnyHashable) {
939+
_ = item as? MyThing
940+
}
941+
942+
@inline(never)
943+
public func testMyThing() {
944+
let x = MyThing(name: "B")
945+
doSomethingWithAnyHashable(x)
946+
}

0 commit comments

Comments
 (0)