@@ -75,6 +75,72 @@ static SubstitutionMap lookupBridgeToObjCProtocolSubs(SILModule &mod,
7575 target, conf);
7676}
7777
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+
78144// / Create a call of _forceBridgeFromObjectiveC_bridgeable or
79145// / _conditionallyBridgeFromObjectiveC_bridgeable which converts an ObjC
80146// / instance into a corresponding Swift type, conforming to
@@ -187,62 +253,15 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
187253
188254 SILBuilderWithScope Builder (Inst, builderContext);
189255
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.
207261 SILValue srcOp;
208262 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);
246265
247266 // Now emit the a cast from the casted ObjC object into a target type.
248267 // This is done by means of calling _forceBridgeFromObjectiveC or
0 commit comments