@@ -75,6 +75,72 @@ static SubstitutionMap lookupBridgeToObjCProtocolSubs(SILModule &mod,
75
75
target, conf);
76
76
}
77
77
78
+ // / Given that our insertion point is at the cast that we are trying to
79
+ // / optimize, convert our incoming value to something that can be passed to the
80
+ // / bridge call.
81
+ static std::pair<SILValue, SILInstruction *>
82
+ convertObjectToLoadableBridgeableType (SILBuilderWithScope &builder,
83
+ SILDynamicCastInst dynamicCast,
84
+ SILValue src) {
85
+ auto *f = dynamicCast.getFunction ();
86
+ auto loc = dynamicCast.getLocation ();
87
+ bool isConditional = dynamicCast.isConditional ();
88
+
89
+ SILValue load =
90
+ builder.createLoad (loc, src, LoadOwnershipQualifier::Unqualified);
91
+
92
+ SILType silBridgedTy = *dynamicCast.getLoweredBridgedTargetObjectType ();
93
+
94
+ // If we are not conditional...
95
+ if (!isConditional) {
96
+ // and our loaded type is our bridged type, just return the load as our
97
+ // SILValue and signal to our caller that we did not create a new cast
98
+ // instruction by returning nullptr as second.
99
+ if (load->getType () == silBridgedTy) {
100
+ return {load, nullptr };
101
+ }
102
+
103
+ // Otherwise, just perform an unconditional checked cast to the sil bridged
104
+ // ty. We return the cast as our value and as our new cast instruction.
105
+ auto *cast =
106
+ builder.createUnconditionalCheckedCast (loc, load, silBridgedTy);
107
+ return {cast, cast};
108
+ }
109
+
110
+ // If we /are/ conditional and we do not need to bridge the load to the sil,
111
+ // then we just create our cast success block and branch from the end of the
112
+ // cast instruction block to the cast success block. We leave our insertion
113
+ // point in the cast success block since when we return, we are going to
114
+ // insert the bridge call/switch there. We return the argument of the cast
115
+ // success block as the value to be passed to the bridging function.
116
+ if (load->getType () == silBridgedTy) {
117
+ SILBasicBlock *castSuccessBB = f->createBasicBlock ();
118
+ castSuccessBB->createPhiArgument (silBridgedTy, ValueOwnershipKind::Owned);
119
+ builder.createBranch (loc, castSuccessBB, load);
120
+ builder.setInsertionPoint (castSuccessBB);
121
+ return {castSuccessBB->getArgument (0 ), nullptr };
122
+ }
123
+
124
+ auto *castFailBB = ([&]() -> SILBasicBlock * {
125
+ auto *failureBB = dynamicCast.getFailureBlock ();
126
+ SILBuilderWithScope failureBBBuilder (&(*failureBB->begin ()), builder);
127
+ return splitBasicBlockAndBranch (failureBBBuilder, &(*failureBB->begin ()),
128
+ nullptr , nullptr );
129
+ }());
130
+
131
+ // Ok, we need to perform the full cast optimization. This means that we are
132
+ // going to replace the cast terminator in inst_block with a
133
+ // checked_cast_br. This in turn means
134
+ auto *castSuccessBB = f->createBasicBlock ();
135
+ castSuccessBB->createPhiArgument (silBridgedTy, ValueOwnershipKind::Owned);
136
+
137
+ auto *ccbi = builder.createCheckedCastBranch (loc, false , load, silBridgedTy,
138
+ castSuccessBB, castFailBB);
139
+ splitEdge (ccbi, /* EdgeIdx to CastFailBB */ 1 );
140
+ builder.setInsertionPoint (castSuccessBB);
141
+ return {castSuccessBB->getArgument (0 ), ccbi};
142
+ }
143
+
78
144
// / Create a call of _forceBridgeFromObjectiveC_bridgeable or
79
145
// / _conditionallyBridgeFromObjectiveC_bridgeable which converts an ObjC
80
146
// / instance into a corresponding Swift type, conforming to
@@ -187,62 +253,15 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
187
253
188
254
SILBuilderWithScope Builder (Inst, builderContext);
189
255
190
- // If this is a conditional cast:
191
- //
192
- // We need a new fail BB in order to add a dealloc_stack to it
193
- SILBasicBlock *CastFailBB = nullptr ;
194
- if (isConditional) {
195
- auto CurrInsPoint = Builder.getInsertionPoint ();
196
- CastFailBB = splitBasicBlockAndBranch (Builder, &(*FailureBB->begin ()),
197
- nullptr , nullptr );
198
- Builder.setInsertionPoint (CurrInsPoint);
199
- }
200
-
201
- // Check if we can simplify a cast into:
202
- // - ObjCTy to _ObjectiveCBridgeable._ObjectiveCType.
203
- // - then convert _ObjectiveCBridgeable._ObjectiveCType to
204
- // a Swift type using _forceBridgeFromObjectiveC.
205
-
206
- // Inline constructor.
256
+ // Generate a load for the source argument since as part of our optimization
257
+ // we are going to promote the cast to work with objects instead of
258
+ // addresses. Additionally, if we have an objc object that is not bridgeable,
259
+ // but that could be converted to something that is bridgeable, we try to
260
+ // convert to the bridgeable type.
207
261
SILValue srcOp;
208
262
SILInstruction *newI;
209
- std::tie (srcOp, newI) = [&]() -> std::pair<SILValue, SILInstruction *> {
210
- // Generate a load for the source argument.
211
- SILValue load =
212
- Builder.createLoad (Loc, src, LoadOwnershipQualifier::Unqualified);
213
-
214
- SILType silBridgedTy = *dynamicCast.getLoweredBridgedTargetObjectType ();
215
-
216
- // If type of the source and the expected ObjC type are equal, there is no
217
- // need to generate the conversion from ObjCTy to
218
- // _ObjectiveCBridgeable._ObjectiveCType.
219
- if (load->getType () == silBridgedTy) {
220
- if (isConditional) {
221
- SILBasicBlock *castSuccessBB = F->createBasicBlock ();
222
- castSuccessBB->createPhiArgument (silBridgedTy,
223
- ValueOwnershipKind::Owned);
224
- Builder.createBranch (Loc, castSuccessBB, load);
225
- Builder.setInsertionPoint (castSuccessBB);
226
- return {castSuccessBB->getArgument (0 ), nullptr };
227
- }
228
-
229
- return {load, nullptr };
230
- }
231
-
232
- if (isConditional) {
233
- SILBasicBlock *castSuccessBB = F->createBasicBlock ();
234
- castSuccessBB->createPhiArgument (silBridgedTy, ValueOwnershipKind::Owned);
235
- auto *ccbi = Builder.createCheckedCastBranch (
236
- Loc, false , load, silBridgedTy, castSuccessBB, CastFailBB);
237
- splitEdge (ccbi, /* EdgeIdx to CastFailBB */ 1 );
238
- Builder.setInsertionPoint (castSuccessBB);
239
- return {castSuccessBB->getArgument (0 ), ccbi};
240
- }
241
-
242
- auto *cast =
243
- Builder.createUnconditionalCheckedCast (Loc, load, silBridgedTy);
244
- return {cast, cast};
245
- }();
263
+ std::tie (srcOp, newI) =
264
+ convertObjectToLoadableBridgeableType (Builder, dynamicCast, src);
246
265
247
266
// Now emit the a cast from the casted ObjC object into a target type.
248
267
// This is done by means of calling _forceBridgeFromObjectiveC or
0 commit comments