Skip to content

Commit 85be8a9

Browse files
author
Joe Shajrawi
authored
Merge pull request #5028 from shajrawi/bridge-address-only
Support bridging cast optimization for address-only types
2 parents 1c90753 + e4fdecf commit 85be8a9

File tree

1 file changed

+52
-21
lines changed

1 file changed

+52
-21
lines changed

lib/SILOptimizer/Utils/Local.cpp

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,8 @@ bool swift::isIntermediateRelease(SILInstruction *I,
136136

137137
// This is a release on an owned parameter and its not the epilogue release.
138138
// Its not the final release.
139-
auto Rel
140-
= EAFI->computeEpilogueARCInstructions(
141-
EpilogueARCContext::EpilogueARCKind::Release, Arg);
139+
auto Rel = EAFI->computeEpilogueARCInstructions(
140+
EpilogueARCContext::EpilogueARCKind::Release, Arg);
142141
if (Rel.size() && !Rel.count(I))
143142
return true;
144143

@@ -1424,9 +1423,22 @@ optimizeBridgedObjCToSwiftCast(SILInstruction *Inst,
14241423
assert(Src->getType().isAddress() && "Source should have an address type");
14251424
assert(Dest->getType().isAddress() && "Source should have an address type");
14261425

1427-
if (!Src->getType().isLoadable(M) || !Dest->getType().isLoadable(M)) {
1428-
// TODO: Handle address only types.
1429-
return nullptr;
1426+
// AnyHashable is a special case - it does not conform to NSObject -
1427+
// If AnyHashable - Bail out of the optimization
1428+
if (auto DT = Target.getNominalOrBoundGenericNominal()) {
1429+
if (DT == M.getASTContext().getAnyHashableDecl()) {
1430+
return nullptr;
1431+
}
1432+
}
1433+
1434+
// If this is a conditional cast:
1435+
// We need a new fail BB in order to add a dealloc_stack to it
1436+
SILBasicBlock *ConvFailBB = nullptr;
1437+
if (isConditional) {
1438+
auto CurrInsPoint = Builder.getInsertionPoint();
1439+
ConvFailBB = splitBasicBlockAndBranch(Builder, &(*FailureBB->begin()),
1440+
nullptr, nullptr);
1441+
Builder.setInsertionPoint(CurrInsPoint);
14301442
}
14311443

14321444
if (SILBridgedTy != Src->getType()) {
@@ -1435,6 +1447,13 @@ optimizeBridgedObjCToSwiftCast(SILInstruction *Inst,
14351447
// - then convert _ObjectiveCBridgeable._ObjectiveCType to
14361448
// a Swift type using _forceBridgeFromObjectiveC.
14371449

1450+
if (!Src->getType().isLoadable(M)) {
1451+
// This code path is never reached in current test cases
1452+
// If reached, we'd have to convert from an ObjC Any* to a loadable type
1453+
// Should use check_addr / make a source we can actually load
1454+
return nullptr;
1455+
}
1456+
14381457
// Generate a load for the source argument.
14391458
auto *Load = Builder.createLoad(Loc, Src);
14401459
// Try to convert the source into the expected ObjC type first.
@@ -1456,9 +1475,8 @@ optimizeBridgedObjCToSwiftCast(SILInstruction *Inst,
14561475
} else if (isConditional) {
14571476
SILBasicBlock *CastSuccessBB = Inst->getFunction()->createBasicBlock();
14581477
CastSuccessBB->createBBArg(SILBridgedTy);
1459-
NewI = Builder.createCheckedCastBranch(Loc, false, Load,
1460-
SILBridgedTy, CastSuccessBB,
1461-
FailureBB);
1478+
NewI = Builder.createCheckedCastBranch(Loc, false, Load, SILBridgedTy,
1479+
CastSuccessBB, ConvFailBB);
14621480
Builder.setInsertionPoint(CastSuccessBB);
14631481
SrcOp = CastSuccessBB->getBBArg(0);
14641482
} else {
@@ -1575,10 +1593,8 @@ optimizeBridgedObjCToSwiftCast(SILInstruction *Inst,
15751593
Builder.setInsertionPoint(ConvSuccessBB);
15761594
auto Addr = Builder.createUncheckedTakeEnumDataAddr(Loc, InOutOptionalParam,
15771595
SomeDecl);
1578-
auto LoadFromOptional = Builder.createLoad(Loc, Addr);
15791596

1580-
// Store into Dest
1581-
Builder.createStore(Loc, LoadFromOptional, Dest);
1597+
Builder.createCopyAddr(Loc, Addr, Dest, IsTake, IsInitialization);
15821598

15831599
Builder.createDeallocStack(Loc, Tmp);
15841600
SmallVector<SILValue, 1> SuccessBBArgs;
@@ -1607,10 +1623,10 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
16071623

16081624
auto &M = Inst->getModule();
16091625
auto Loc = Inst->getLoc();
1610-
1626+
1627+
bool AddressOnlyType = false;
16111628
if (!Src->getType().isLoadable(M) || !Dest->getType().isLoadable(M)) {
1612-
// TODO: Handle address-only types.
1613-
return nullptr;
1629+
AddressOnlyType = true;
16141630
}
16151631

16161632
// Find the _BridgedToObjectiveC protocol.
@@ -1662,10 +1678,9 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
16621678

16631679
auto SILFnTy = SILType::getPrimitiveObjectType(
16641680
M.Types.getConstantFunctionType(BridgeFuncDeclRef));
1665-
1666-
// TODO: Handle indirect argument to or return from witness function.
1667-
if (ParamTypes[0].isIndirect()
1668-
|| BridgedFunc->getLoweredFunctionType()->getSingleResult().isIndirect())
1681+
1682+
// TODO: Handle return from witness function.
1683+
if (BridgedFunc->getLoweredFunctionType()->getSingleResult().isIndirect())
16691684
return nullptr;
16701685

16711686
// Get substitutions, if source is a bound generic type.
@@ -1677,7 +1692,7 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
16771692
SILType ResultTy = SubstFnTy.castTo<SILFunctionType>()->getSILResult();
16781693

16791694
auto FnRef = Builder.createFunctionRef(Loc, BridgedFunc);
1680-
if (Src->getType().isAddress()) {
1695+
if (Src->getType().isAddress() && !ParamTypes[0].isIndirect()) {
16811696
// Create load
16821697
Src = Builder.createLoad(Loc, Src);
16831698
}
@@ -1689,6 +1704,8 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
16891704
bool needReleaseInSucc = false;
16901705
switch (ParamTypes[0].getConvention()) {
16911706
case ParameterConvention::Direct_Guaranteed:
1707+
assert(!AddressOnlyType &&
1708+
"AddressOnlyType with Direct_Guaranteed is not supported");
16921709
switch (ConsumptionKind) {
16931710
case CastConsumptionKind::TakeAlways:
16941711
needReleaseAfterCall = true;
@@ -1718,6 +1735,8 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
17181735
// The Direct_Owned case is only handled for completeness. Currently this
17191736
// cannot appear, because the _bridgeToObjectiveC protocol witness method
17201737
// always receives the this pointer (= the source) as guaranteed.
1738+
assert(!AddressOnlyType &&
1739+
"AddressOnlyType with Direct_Owned is not supported");
17211740
switch (ConsumptionKind) {
17221741
case CastConsumptionKind::TakeAlways:
17231742
break;
@@ -1731,11 +1750,23 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
17311750
}
17321751
break;
17331752
case ParameterConvention::Direct_Unowned:
1753+
assert(!AddressOnlyType &&
1754+
"AddressOnlyType with Direct_Unowned is not supported");
17341755
break;
1735-
case ParameterConvention::Indirect_In:
17361756
case ParameterConvention::Indirect_In_Guaranteed:
1757+
// Source as-is, we don't need to copy it due to guarantee
1758+
break;
1759+
case ParameterConvention::Indirect_In: {
1760+
// Need to make a copy of the source, can be changed in ObjC
1761+
auto BridgeStack = Builder.createAllocStack(Loc, Src->getType());
1762+
Src = Builder.createCopyAddr(Loc, Src, BridgeStack, IsNotTake,
1763+
IsInitialization);
1764+
break;
1765+
}
17371766
case ParameterConvention::Indirect_Inout:
17381767
case ParameterConvention::Indirect_InoutAliasable:
1768+
// TODO handle remaining indirect argument types
1769+
return nullptr;
17391770
case ParameterConvention::Direct_Deallocating:
17401771
llvm_unreachable("unsupported convention for bridging conversion");
17411772
}

0 commit comments

Comments
 (0)