Skip to content

Commit 3214474

Browse files
committed
---
yaml --- r: 347093 b: refs/heads/master c: cdf67f2 h: refs/heads/master i: 347091: 07be4e3
1 parent 9ca048c commit 3214474

File tree

2 files changed

+87
-90
lines changed

2 files changed

+87
-90
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 3cc8aba4a06d71d0ceb933f51661470940814cc4
2+
refs/heads/master: cdf67f26c74296dc2c92601fab2e34e47c253a7f
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/lib/SILOptimizer/Utils/CastOptimizer.cpp

Lines changed: 86 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -66,23 +66,52 @@ getObjCToSwiftBridgingFunction(SILOptFunctionBuilder &funcBuilder,
6666
ForDefinition_t::NotForDefinition);
6767
}
6868

69+
static SubstitutionMap lookupBridgeToObjCProtocolSubs(SILModule &mod,
70+
CanType target) {
71+
auto bridgedProto =
72+
mod.getASTContext().getProtocol(KnownProtocolKind::ObjectiveCBridgeable);
73+
auto conf = *mod.getSwiftModule()->lookupConformance(target, bridgedProto);
74+
return SubstitutionMap::getProtocolSubstitutions(conf.getRequirement(),
75+
target, conf);
76+
}
77+
6978
/// Create a call of _forceBridgeFromObjectiveC_bridgeable or
7079
/// _conditionallyBridgeFromObjectiveC_bridgeable which converts an ObjC
7180
/// instance into a corresponding Swift type, conforming to
7281
/// _ObjectiveCBridgeable.
7382
SILInstruction *
7483
CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
84+
auto kind = dynamicCast.getKind();
85+
(void)kind;
86+
assert(((kind == SILDynamicCastKind::CheckedCastAddrBranchInst) ||
87+
(kind == SILDynamicCastKind::UnconditionalCheckedCastAddrInst)) &&
88+
"Unsupported dynamic cast kind");
89+
90+
CanType target = dynamicCast.getTargetType();
91+
auto &mod = dynamicCast.getModule();
92+
93+
// AnyHashable is a special case that we do not handle since we only handle
94+
// objc targets in this function. Bailout early.
95+
if (auto dt = target.getNominalOrBoundGenericNominal()) {
96+
if (dt == mod.getASTContext().getAnyHashableDecl()) {
97+
return nullptr;
98+
}
99+
}
100+
101+
SILValue src = dynamicCast.getSource();
102+
// Check if we have a source type that is address only. We do not support that
103+
// today.
104+
if (src->getType().isAddressOnly(mod)) {
105+
return nullptr;
106+
}
75107

76108
SILInstruction *Inst = dynamicCast.getInstruction();
77109
bool isConditional = dynamicCast.isConditional();
78-
SILValue Src = dynamicCast.getSource();
79110
SILValue Dest = dynamicCast.getDest();
80-
CanType Target = dynamicCast.getTargetType();
81111
CanType BridgedTargetTy = dynamicCast.getBridgedTargetType();
82112
SILBasicBlock *SuccessBB = dynamicCast.getSuccessBlock();
83113
SILBasicBlock *FailureBB = dynamicCast.getFailureBlock();
84114
auto *F = Inst->getFunction();
85-
auto &M = Inst->getModule();
86115
auto Loc = Inst->getLoc();
87116

88117
// The conformance to _BridgedToObjectiveC is statically known.
@@ -93,23 +122,16 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
93122
if (!bridgingFunc)
94123
return nullptr;
95124

125+
auto paramTypes = bridgingFunc->getLoweredFunctionType()->getParameters();
126+
(void)paramTypes;
127+
assert(paramTypes[0].getConvention() ==
128+
ParameterConvention::Direct_Guaranteed &&
129+
"Parameter should be @guaranteed");
130+
96131
CanType CanBridgedTy = BridgedTargetTy->getCanonicalType();
97-
SILType SILBridgedTy = SILType::getPrimitiveObjectType(CanBridgedTy);
132+
SILType silBridgedTy = SILType::getPrimitiveObjectType(CanBridgedTy);
98133

99134
SILBuilderWithScope Builder(Inst, BuilderContext);
100-
SILValue SrcOp;
101-
SILInstruction *NewI = nullptr;
102-
103-
assert(Src->getType().isAddress() && "Source should have an address type");
104-
assert(Dest->getType().isAddress() && "Source should have an address type");
105-
106-
// AnyHashable is a special case - it does not conform to NSObject -
107-
// If AnyHashable - Bail out of the optimization
108-
if (auto DT = Target.getNominalOrBoundGenericNominal()) {
109-
if (DT == M.getASTContext().getAnyHashableDecl()) {
110-
return nullptr;
111-
}
112-
}
113135

114136
// If this is a conditional cast:
115137
// We need a new fail BB in order to add a dealloc_stack to it
@@ -121,81 +143,59 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
121143
Builder.setInsertionPoint(CurrInsPoint);
122144
}
123145

124-
// We know this is always true since SILBridgedTy is an object and Src is an
125-
// address.
126-
assert(SILBridgedTy != Src->getType());
127-
128146
// Check if we can simplify a cast into:
129147
// - ObjCTy to _ObjectiveCBridgeable._ObjectiveCType.
130148
// - then convert _ObjectiveCBridgeable._ObjectiveCType to
131149
// a Swift type using _forceBridgeFromObjectiveC.
132150

133-
if (!Src->getType().isLoadable(M)) {
134-
// This code path is never reached in current test cases
135-
// If reached, we'd have to convert from an ObjC Any* to a loadable type
136-
// Should use check_addr / make a source we can actually load
137-
return nullptr;
138-
}
151+
// Inline constructor.
152+
SILValue srcOp;
153+
SILInstruction *newI;
154+
std::tie(srcOp, newI) = [&]() -> std::pair<SILValue, SILInstruction *> {
155+
// Generate a load for the source argument.
156+
SILValue load =
157+
Builder.createLoad(Loc, src, LoadOwnershipQualifier::Unqualified);
158+
159+
// If type of the source and the expected ObjC type are equal, there is no
160+
// need to generate the conversion from ObjCTy to
161+
// _ObjectiveCBridgeable._ObjectiveCType.
162+
if (load->getType() == silBridgedTy) {
163+
if (isConditional) {
164+
SILBasicBlock *castSuccessBB = F->createBasicBlock();
165+
castSuccessBB->createPhiArgument(silBridgedTy,
166+
ValueOwnershipKind::Owned);
167+
Builder.createBranch(Loc, castSuccessBB, load);
168+
Builder.setInsertionPoint(castSuccessBB);
169+
return {castSuccessBB->getArgument(0), nullptr};
170+
}
139171

140-
// Generate a load for the source argument.
141-
auto *Load =
142-
Builder.createLoad(Loc, Src, LoadOwnershipQualifier::Unqualified);
143-
// Try to convert the source into the expected ObjC type first.
172+
return {load, nullptr};
173+
}
144174

145-
if (Load->getType() == SILBridgedTy) {
146-
// If type of the source and the expected ObjC type are
147-
// equal, there is no need to generate the conversion
148-
// from ObjCTy to _ObjectiveCBridgeable._ObjectiveCType.
149175
if (isConditional) {
150-
SILBasicBlock *CastSuccessBB = F->createBasicBlock();
151-
CastSuccessBB->createPhiArgument(SILBridgedTy, ValueOwnershipKind::Owned);
152-
Builder.createBranch(Loc, CastSuccessBB, SILValue(Load));
153-
Builder.setInsertionPoint(CastSuccessBB);
154-
SrcOp = CastSuccessBB->getArgument(0);
155-
} else {
156-
SrcOp = Load;
176+
SILBasicBlock *castSuccessBB = F->createBasicBlock();
177+
castSuccessBB->createPhiArgument(silBridgedTy, ValueOwnershipKind::Owned);
178+
auto *ccbi = Builder.createCheckedCastBranch(
179+
Loc, false, load, silBridgedTy, castSuccessBB, ConvFailBB);
180+
splitEdge(ccbi, /* EdgeIdx to ConvFailBB */ 1);
181+
Builder.setInsertionPoint(castSuccessBB);
182+
return {castSuccessBB->getArgument(0), ccbi};
157183
}
158-
} else if (isConditional) {
159-
SILBasicBlock *CastSuccessBB = F->createBasicBlock();
160-
CastSuccessBB->createPhiArgument(SILBridgedTy, ValueOwnershipKind::Owned);
161-
auto *CCBI = Builder.createCheckedCastBranch(Loc, false, Load, SILBridgedTy,
162-
CastSuccessBB, ConvFailBB);
163-
NewI = CCBI;
164-
splitEdge(CCBI, /* EdgeIdx to ConvFailBB */ 1);
165-
Builder.setInsertionPoint(CastSuccessBB);
166-
SrcOp = CastSuccessBB->getArgument(0);
167-
} else {
168-
auto cast = Builder.createUnconditionalCheckedCast(Loc, Load, SILBridgedTy);
169-
NewI = cast;
170-
SrcOp = cast;
171-
}
184+
185+
auto *cast =
186+
Builder.createUnconditionalCheckedCast(Loc, load, silBridgedTy);
187+
return {cast, cast};
188+
}();
172189

173190
// Now emit the a cast from the casted ObjC object into a target type.
174191
// This is done by means of calling _forceBridgeFromObjectiveC or
175192
// _conditionallyBridgeFromObjectiveC_bridgeable from the Target type.
176-
// Lookup the required function in the Target type.
177-
178-
// Lookup the _ObjectiveCBridgeable protocol.
179-
auto BridgedProto =
180-
M.getASTContext().getProtocol(KnownProtocolKind::ObjectiveCBridgeable);
181-
auto Conf = *M.getSwiftModule()->lookupConformance(Target, BridgedProto);
182-
183-
auto ParamTypes = bridgingFunc->getLoweredFunctionType()->getParameters();
193+
auto *funcRef = Builder.createFunctionRef(Loc, bridgingFunc);
194+
SubstitutionMap subMap = lookupBridgeToObjCProtocolSubs(mod, target);
184195

185-
auto *FuncRef = Builder.createFunctionRef(Loc, bridgingFunc);
186-
187-
auto MetaTy = MetatypeType::get(Target, MetatypeRepresentation::Thick);
196+
auto MetaTy = MetatypeType::get(target, MetatypeRepresentation::Thick);
188197
auto SILMetaTy = F->getTypeLowering(MetaTy).getLoweredType();
189198
auto *MetaTyVal = Builder.createMetatype(Loc, SILMetaTy);
190-
SmallVector<SILValue, 1> Args;
191-
192-
// Add substitutions
193-
auto SubMap = SubstitutionMap::getProtocolSubstitutions(Conf.getRequirement(),
194-
Target, Conf);
195-
196-
auto SILFnTy = FuncRef->getType();
197-
SILType SubstFnTy = SILFnTy.substGenericArgs(M, SubMap);
198-
SILFunctionConventions substConv(SubstFnTy.castTo<SILFunctionType>(), M);
199199

200200
// Temporary to hold the intermediate result.
201201
AllocStackInst *Tmp = nullptr;
@@ -213,38 +213,35 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
213213
InOutOptionalParam = Dest;
214214
}
215215

216-
(void)ParamTypes;
217-
assert(ParamTypes[0].getConvention() == ParameterConvention::Direct_Guaranteed &&
218-
"Parameter should be @guaranteed");
219-
220216
// Emit a retain.
221-
Builder.createRetainValue(Loc, SrcOp, Builder.getDefaultAtomicity());
217+
Builder.createRetainValue(Loc, srcOp, Builder.getDefaultAtomicity());
222218

219+
SmallVector<SILValue, 1> Args;
223220
Args.push_back(InOutOptionalParam);
224-
Args.push_back(SrcOp);
221+
Args.push_back(srcOp);
225222
Args.push_back(MetaTyVal);
226223

227-
auto *AI = Builder.createApply(Loc, FuncRef, SubMap, Args, false);
224+
auto *AI = Builder.createApply(Loc, funcRef, subMap, Args, false);
228225

229226
// If we have guaranteed normal arguments, insert the destroy.
230227
//
231228
// TODO: Is it safe to just eliminate the initial retain?
232-
Builder.createReleaseValue(Loc, SrcOp, Builder.getDefaultAtomicity());
229+
Builder.createReleaseValue(Loc, srcOp, Builder.getDefaultAtomicity());
233230

234231
// If the source of a cast should be destroyed, emit a release.
235232
if (isa<UnconditionalCheckedCastAddrInst>(Inst)) {
236-
Builder.createReleaseValue(Loc, SrcOp, Builder.getDefaultAtomicity());
233+
Builder.createReleaseValue(Loc, srcOp, Builder.getDefaultAtomicity());
237234
}
238235

239236
if (auto *CCABI = dyn_cast<CheckedCastAddrBranchInst>(Inst)) {
240237
switch (CCABI->getConsumptionKind()) {
241238
case CastConsumptionKind::TakeAlways:
242-
Builder.createReleaseValue(Loc, SrcOp, Builder.getDefaultAtomicity());
239+
Builder.createReleaseValue(Loc, srcOp, Builder.getDefaultAtomicity());
243240
break;
244241
case CastConsumptionKind::TakeOnSuccess:
245242
// Insert a release in the success BB.
246243
Builder.setInsertionPoint(SuccessBB->begin());
247-
Builder.createReleaseValue(Loc, SrcOp, Builder.getDefaultAtomicity());
244+
Builder.createReleaseValue(Loc, srcOp, Builder.getDefaultAtomicity());
248245
break;
249246
case CastConsumptionKind::BorrowAlways:
250247
llvm_unreachable("checked_cast_addr_br never has BorrowAlways");
@@ -263,7 +260,7 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
263260
SILBasicBlock *ConvSuccessBB = Inst->getFunction()->createBasicBlock();
264261
SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 1> CaseBBs;
265262
CaseBBs.push_back(
266-
std::make_pair(M.getASTContext().getOptionalNoneDecl(), FailureBB));
263+
std::make_pair(mod.getASTContext().getOptionalNoneDecl(), FailureBB));
267264
Builder.createSwitchEnumAddr(Loc, InOutOptionalParam, ConvSuccessBB,
268265
CaseBBs);
269266

@@ -282,7 +279,7 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
282279
}
283280

284281
EraseInstAction(Inst);
285-
return (NewI) ? NewI : AI;
282+
return (newI) ? newI : AI;
286283
}
287284

288285
static bool canOptimizeCast(const swift::Type &BridgedTargetTy,

0 commit comments

Comments
 (0)