@@ -111,15 +111,18 @@ convertObjectToLoadableBridgeableType(SILBuilderWithScope &builder,
111
111
return {cast, cast};
112
112
}
113
113
114
+ SILBasicBlock *castSuccessBB =
115
+ f->createBasicBlockAfter (dynamicCast.getInstruction ()->getParent ());
116
+ castSuccessBB->createPhiArgument (silBridgedTy, ValueOwnershipKind::Owned);
117
+
114
118
// If we /are/ conditional and we do not need to bridge the load to the sil,
115
119
// then we just create our cast success block and branch from the end of the
116
120
// cast instruction block to the cast success block. We leave our insertion
117
121
// point in the cast success block since when we return, we are going to
118
122
// insert the bridge call/switch there. We return the argument of the cast
119
123
// success block as the value to be passed to the bridging function.
120
124
if (load->getType () == silBridgedTy) {
121
- SILBasicBlock *castSuccessBB = f->createBasicBlock ();
122
- castSuccessBB->createPhiArgument (silBridgedTy, ValueOwnershipKind::Owned);
125
+ castSuccessBB->moveAfter (dynamicCast.getInstruction ()->getParent ());
123
126
builder.createBranch (loc, castSuccessBB, load);
124
127
builder.setInsertionPoint (castSuccessBB);
125
128
return {castSuccessBB->getArgument (0 ), nullptr };
@@ -132,15 +135,51 @@ convertObjectToLoadableBridgeableType(SILBuilderWithScope &builder,
132
135
nullptr , nullptr );
133
136
}());
134
137
135
- // Ok, we need to perform the full cast optimization. This means that we are
136
- // going to replace the cast terminator in inst_block with a
137
- // checked_cast_br. This in turn means
138
- auto *castSuccessBB = f->createBasicBlock ();
139
- castSuccessBB->createPhiArgument (silBridgedTy, ValueOwnershipKind::Owned);
138
+ // Now that we have created the failure bb, move our cast success block right
139
+ // after the checked_cast_br bb.
140
+ castSuccessBB->moveAfter (dynamicCast.getInstruction ()->getParent ());
140
141
142
+ // Ok, we need to perform the full cast optimization. This means that we are
143
+ // going to replace the cast terminator in inst_block with a checked_cast_br.
141
144
auto *ccbi = builder.createCheckedCastBranch (loc, false , load, silBridgedTy,
142
145
castSuccessBB, castFailBB);
143
146
splitEdge (ccbi, /* EdgeIdx to CastFailBB */ 1 );
147
+
148
+ // Now that we have split the edge to cast fail bb, add the default argument
149
+ // for the checked_cast_br. Then we need to handle our error conditions,
150
+ // namely we destroy on take_always and otherwise store the value back into
151
+ // the memory location that we took it out of.
152
+ {
153
+ auto *newFailureBlock = ccbi->getFailureBB ();
154
+ SILValue defaultArg;
155
+ if (builder.hasOwnership ()) {
156
+ defaultArg = newFailureBlock->createPhiArgument (
157
+ load->getType (), ValueOwnershipKind::Owned);
158
+ } else {
159
+ defaultArg = ccbi->getOperand ();
160
+ }
161
+
162
+ // This block should be properly terminated already due to our method of
163
+ // splitting the failure block, so we can use begin() safely.
164
+ SILBuilderWithScope failureBuilder (newFailureBlock->begin ());
165
+
166
+ switch (dynamicCast.getBridgedConsumptionKind ()) {
167
+ case CastConsumptionKind::TakeAlways:
168
+ failureBuilder.emitDestroyValueOperation (loc, defaultArg);
169
+ break ;
170
+ case CastConsumptionKind::TakeOnSuccess:
171
+ case CastConsumptionKind::CopyOnSuccess:
172
+ // Without ownership, we do not need to consume the taken value.
173
+ if (failureBuilder.hasOwnership ()) {
174
+ failureBuilder.emitStoreValueOperation (loc, defaultArg, src,
175
+ StoreOwnershipQualifier::Init);
176
+ }
177
+ break ;
178
+ case CastConsumptionKind::BorrowAlways:
179
+ llvm_unreachable (" this should never occur here" );
180
+ }
181
+ }
182
+
144
183
builder.setInsertionPoint (castSuccessBB);
145
184
return {castSuccessBB->getArgument (0 ), ccbi};
146
185
}
@@ -370,12 +409,13 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
370
409
// Load from the optional.
371
410
auto *SomeDecl = Builder.getASTContext ().getOptionalSomeDecl ();
372
411
373
- SILBasicBlock *BridgeSuccessBB = Inst->getFunction ()->createBasicBlock ();
412
+ auto *BridgeSuccessBB =
413
+ Inst->getFunction ()->createBasicBlockAfter (Builder.getInsertionBB ());
374
414
SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 2 > CaseBBs;
415
+ CaseBBs.emplace_back (SomeDecl, BridgeSuccessBB);
375
416
CaseBBs.emplace_back (mod.getASTContext ().getOptionalNoneDecl (), FailureBB);
376
417
377
- Builder.createSwitchEnumAddr (Loc, InOutOptionalParam, BridgeSuccessBB,
378
- CaseBBs);
418
+ Builder.createSwitchEnumAddr (Loc, InOutOptionalParam, nullptr , CaseBBs);
379
419
380
420
Builder.setInsertionPoint (FailureBB->begin ());
381
421
Builder.createDeallocStack (Loc, Tmp);
0 commit comments