@@ -66,23 +66,52 @@ getObjCToSwiftBridgingFunction(SILOptFunctionBuilder &funcBuilder,
66
66
ForDefinition_t::NotForDefinition);
67
67
}
68
68
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
+
69
78
// / Create a call of _forceBridgeFromObjectiveC_bridgeable or
70
79
// / _conditionallyBridgeFromObjectiveC_bridgeable which converts an ObjC
71
80
// / instance into a corresponding Swift type, conforming to
72
81
// / _ObjectiveCBridgeable.
73
82
SILInstruction *
74
83
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
+ }
75
107
76
108
SILInstruction *Inst = dynamicCast.getInstruction ();
77
109
bool isConditional = dynamicCast.isConditional ();
78
- SILValue Src = dynamicCast.getSource ();
79
110
SILValue Dest = dynamicCast.getDest ();
80
- CanType Target = dynamicCast.getTargetType ();
81
111
CanType BridgedTargetTy = dynamicCast.getBridgedTargetType ();
82
112
SILBasicBlock *SuccessBB = dynamicCast.getSuccessBlock ();
83
113
SILBasicBlock *FailureBB = dynamicCast.getFailureBlock ();
84
114
auto *F = Inst->getFunction ();
85
- auto &M = Inst->getModule ();
86
115
auto Loc = Inst->getLoc ();
87
116
88
117
// The conformance to _BridgedToObjectiveC is statically known.
@@ -93,23 +122,16 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
93
122
if (!bridgingFunc)
94
123
return nullptr ;
95
124
125
+ auto paramTypes = bridgingFunc->getLoweredFunctionType ()->getParameters ();
126
+ (void )paramTypes;
127
+ assert (paramTypes[0 ].getConvention () ==
128
+ ParameterConvention::Direct_Guaranteed &&
129
+ " Parameter should be @guaranteed" );
130
+
96
131
CanType CanBridgedTy = BridgedTargetTy->getCanonicalType ();
97
- SILType SILBridgedTy = SILType::getPrimitiveObjectType (CanBridgedTy);
132
+ SILType silBridgedTy = SILType::getPrimitiveObjectType (CanBridgedTy);
98
133
99
134
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
- }
113
135
114
136
// If this is a conditional cast:
115
137
// We need a new fail BB in order to add a dealloc_stack to it
@@ -121,81 +143,59 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
121
143
Builder.setInsertionPoint (CurrInsPoint);
122
144
}
123
145
124
- // We know this is always true since SILBridgedTy is an object and Src is an
125
- // address.
126
- assert (SILBridgedTy != Src->getType ());
127
-
128
146
// Check if we can simplify a cast into:
129
147
// - ObjCTy to _ObjectiveCBridgeable._ObjectiveCType.
130
148
// - then convert _ObjectiveCBridgeable._ObjectiveCType to
131
149
// a Swift type using _forceBridgeFromObjectiveC.
132
150
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
+ }
139
171
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
+ }
144
174
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.
149
175
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} ;
157
183
}
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
+ }();
172
189
173
190
// Now emit the a cast from the casted ObjC object into a target type.
174
191
// This is done by means of calling _forceBridgeFromObjectiveC or
175
192
// _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);
184
195
185
- auto *FuncRef = Builder.createFunctionRef (Loc, bridgingFunc);
186
-
187
- auto MetaTy = MetatypeType::get (Target, MetatypeRepresentation::Thick);
196
+ auto MetaTy = MetatypeType::get (target, MetatypeRepresentation::Thick);
188
197
auto SILMetaTy = F->getTypeLowering (MetaTy).getLoweredType ();
189
198
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);
199
199
200
200
// Temporary to hold the intermediate result.
201
201
AllocStackInst *Tmp = nullptr ;
@@ -213,38 +213,35 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
213
213
InOutOptionalParam = Dest;
214
214
}
215
215
216
- (void )ParamTypes;
217
- assert (ParamTypes[0 ].getConvention () == ParameterConvention::Direct_Guaranteed &&
218
- " Parameter should be @guaranteed" );
219
-
220
216
// Emit a retain.
221
- Builder.createRetainValue (Loc, SrcOp , Builder.getDefaultAtomicity ());
217
+ Builder.createRetainValue (Loc, srcOp , Builder.getDefaultAtomicity ());
222
218
219
+ SmallVector<SILValue, 1 > Args;
223
220
Args.push_back (InOutOptionalParam);
224
- Args.push_back (SrcOp );
221
+ Args.push_back (srcOp );
225
222
Args.push_back (MetaTyVal);
226
223
227
- auto *AI = Builder.createApply (Loc, FuncRef, SubMap , Args, false );
224
+ auto *AI = Builder.createApply (Loc, funcRef, subMap , Args, false );
228
225
229
226
// If we have guaranteed normal arguments, insert the destroy.
230
227
//
231
228
// TODO: Is it safe to just eliminate the initial retain?
232
- Builder.createReleaseValue (Loc, SrcOp , Builder.getDefaultAtomicity ());
229
+ Builder.createReleaseValue (Loc, srcOp , Builder.getDefaultAtomicity ());
233
230
234
231
// If the source of a cast should be destroyed, emit a release.
235
232
if (isa<UnconditionalCheckedCastAddrInst>(Inst)) {
236
- Builder.createReleaseValue (Loc, SrcOp , Builder.getDefaultAtomicity ());
233
+ Builder.createReleaseValue (Loc, srcOp , Builder.getDefaultAtomicity ());
237
234
}
238
235
239
236
if (auto *CCABI = dyn_cast<CheckedCastAddrBranchInst>(Inst)) {
240
237
switch (CCABI->getConsumptionKind ()) {
241
238
case CastConsumptionKind::TakeAlways:
242
- Builder.createReleaseValue (Loc, SrcOp , Builder.getDefaultAtomicity ());
239
+ Builder.createReleaseValue (Loc, srcOp , Builder.getDefaultAtomicity ());
243
240
break ;
244
241
case CastConsumptionKind::TakeOnSuccess:
245
242
// Insert a release in the success BB.
246
243
Builder.setInsertionPoint (SuccessBB->begin ());
247
- Builder.createReleaseValue (Loc, SrcOp , Builder.getDefaultAtomicity ());
244
+ Builder.createReleaseValue (Loc, srcOp , Builder.getDefaultAtomicity ());
248
245
break ;
249
246
case CastConsumptionKind::BorrowAlways:
250
247
llvm_unreachable (" checked_cast_addr_br never has BorrowAlways" );
@@ -263,7 +260,7 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
263
260
SILBasicBlock *ConvSuccessBB = Inst->getFunction ()->createBasicBlock ();
264
261
SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 1 > CaseBBs;
265
262
CaseBBs.push_back (
266
- std::make_pair (M .getASTContext ().getOptionalNoneDecl (), FailureBB));
263
+ std::make_pair (mod .getASTContext ().getOptionalNoneDecl (), FailureBB));
267
264
Builder.createSwitchEnumAddr (Loc, InOutOptionalParam, ConvSuccessBB,
268
265
CaseBBs);
269
266
@@ -282,7 +279,7 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
282
279
}
283
280
284
281
EraseInstAction (Inst);
285
- return (NewI ) ? NewI : AI;
282
+ return (newI ) ? newI : AI;
286
283
}
287
284
288
285
static bool canOptimizeCast (const swift::Type &BridgedTargetTy,
0 commit comments