@@ -155,6 +155,12 @@ namespace {
155
155
if (operandValue.getType ().isAddress ()) {
156
156
operandValue = SGF.B .createLoadTake (Loc, operandValue);
157
157
}
158
+
159
+ // If we are not supposed to destroy this value on failure, then we need
160
+ // to borrow it.
161
+ if (!shouldDestroyOnFailure (consumption)) {
162
+ operandValue = operandValue.borrow (SGF, Loc);
163
+ }
158
164
SGF.B .createCheckedCastBranch (Loc, /* exact*/ false , operandValue,
159
165
origTargetTL.getLoweredType (), trueBB,
160
166
falseBB, TrueCount, FalseCount);
@@ -171,8 +177,16 @@ namespace {
171
177
result = finishFromResultBuffer (hasAbstraction, resultBuffer,
172
178
abstraction, origTargetTL, ctx);
173
179
} else {
174
- ManagedValue argument =
175
- SGF.B .createOwnedPhiArgument (origTargetTL.getLoweredType ());
180
+ // If we had copy_on_success, then we need to use a guaranteed
181
+ // argument.
182
+ ManagedValue argument;
183
+ if (!shouldTakeOnSuccess (consumption)) {
184
+ argument = SGF.B .createGuaranteedPhiArgument (
185
+ origTargetTL.getLoweredType ());
186
+ } else {
187
+ argument =
188
+ SGF.B .createOwnedPhiArgument (origTargetTL.getLoweredType ());
189
+ }
176
190
result = finishFromResultScalar (hasAbstraction, argument, consumption,
177
191
abstraction, origTargetTL, ctx);
178
192
}
@@ -215,7 +229,13 @@ namespace {
215
229
return ;
216
230
}
217
231
218
- handleFalse (SGF.B .createOwnedPhiArgument (operandValue.getType ()));
232
+ if (consumption == CastConsumptionKind::CopyOnSuccess) {
233
+ SGF.B .createGuaranteedPhiArgument (operandValue.getType ());
234
+ handleFalse (None);
235
+ } else {
236
+ handleFalse (SGF.B .createOwnedPhiArgument (operandValue.getType ()));
237
+ }
238
+
219
239
assert (!SGF.B .hasValidInsertionPoint () && " handler did not end block" );
220
240
}
221
241
}
@@ -306,225 +326,6 @@ void SILGenFunction::emitCheckedCastBranch(
306
326
ctx, handleTrue, handleFalse, TrueCount, FalseCount);
307
327
}
308
328
309
- namespace {
310
- class CheckedCastEmitterOld {
311
- SILGenFunction &SGF;
312
- SILLocation Loc;
313
- CanType SourceType;
314
- CanType TargetType;
315
-
316
- enum class CastStrategy : uint8_t {
317
- Address,
318
- Scalar,
319
- };
320
- CastStrategy Strategy;
321
-
322
- public:
323
- CheckedCastEmitterOld (SILGenFunction &SGF, SILLocation loc, Type sourceType,
324
- Type targetType)
325
- : SGF(SGF), Loc(loc), SourceType(sourceType->getCanonicalType ()),
326
- TargetType(targetType->getCanonicalType ()),
327
- Strategy(computeStrategy()) {}
328
-
329
- bool isOperandIndirect () const { return Strategy == CastStrategy::Address; }
330
-
331
- RValue emitUnconditionalCast (ManagedValue operand, SGFContext ctx) {
332
- // The cast functions don't know how to work with anything but
333
- // the most general possible abstraction level.
334
- AbstractionPattern abstraction =
335
- SGF.SGM .Types .getMostGeneralAbstraction ();
336
- auto &origTargetTL = SGF.getTypeLowering (abstraction, TargetType);
337
- auto &substTargetTL = SGF.getTypeLowering (TargetType);
338
- bool hasAbstraction =
339
- (origTargetTL.getLoweredType () != substTargetTL.getLoweredType ());
340
-
341
- // If we're using checked_cast_addr, take the operand (which
342
- // should be an address) and build into the destination buffer.
343
- if (Strategy == CastStrategy::Address &&
344
- SGF.silConv .useLoweredAddresses ()) {
345
- SILValue resultBuffer =
346
- createAbstractResultBuffer (hasAbstraction, origTargetTL, ctx);
347
- SGF.B .createUnconditionalCheckedCastAddr (
348
- Loc, operand.forward (SGF), SourceType, resultBuffer, TargetType);
349
- return RValue (SGF, Loc, TargetType,
350
- finishFromResultBuffer (hasAbstraction, resultBuffer,
351
- abstraction, origTargetTL, ctx));
352
- }
353
-
354
- SILValue resultScalar;
355
- if (Strategy == CastStrategy::Address) {
356
- resultScalar = SGF.B .createUnconditionalCheckedCastValue (
357
- Loc, operand.forward (SGF), origTargetTL.getLoweredType ());
358
- } else {
359
- resultScalar = SGF.B .createUnconditionalCheckedCast (
360
- Loc, operand.forward (SGF), origTargetTL.getLoweredType ());
361
- }
362
-
363
- return RValue (SGF, Loc, TargetType,
364
- finishFromResultScalar (hasAbstraction, resultScalar,
365
- CastConsumptionKind::TakeAlways,
366
- abstraction, origTargetTL, ctx));
367
- }
368
-
369
- // / Emit a conditional cast.
370
- void emitConditional (ManagedValue operand, CastConsumptionKind consumption,
371
- SGFContext ctx,
372
- llvm::function_ref<void (ManagedValue)> handleTrue,
373
- llvm::function_ref<void()> handleFalse,
374
- ProfileCounter TrueCount = ProfileCounter(),
375
- ProfileCounter FalseCount = ProfileCounter()) {
376
- // The cast instructions don't know how to work with anything
377
- // but the most general possible abstraction level.
378
- AbstractionPattern abstraction = SGF.SGM .Types .getMostGeneralAbstraction ();
379
- auto &origTargetTL = SGF.getTypeLowering (abstraction, TargetType);
380
- auto &substTargetTL = SGF.getTypeLowering (TargetType);
381
- bool hasAbstraction =
382
- (origTargetTL.getLoweredType () != substTargetTL.getLoweredType ());
383
-
384
- SILBasicBlock *falseBB = SGF.B .splitBlockForFallthrough ();
385
- SILBasicBlock *trueBB = SGF.B .splitBlockForFallthrough ();
386
-
387
- // Emit the branch.
388
- SILValue scalarOperandValue;
389
- SILValue resultBuffer;
390
- if (Strategy == CastStrategy::Address) {
391
- assert (operand.getType ().isAddress ());
392
- resultBuffer =
393
- createAbstractResultBuffer (hasAbstraction, origTargetTL, ctx);
394
- SGF.B .createCheckedCastAddrBranch (
395
- Loc, consumption, operand.forward (SGF), SourceType, resultBuffer,
396
- TargetType, trueBB, falseBB, TrueCount, FalseCount);
397
- } else {
398
- // Tolerate being passed an address here. It comes up during switch
399
- // emission.
400
- scalarOperandValue = operand.forward (SGF);
401
- if (scalarOperandValue->getType ().isAddress ()) {
402
- scalarOperandValue = SGF.B .emitLoadValueOperation (
403
- Loc, scalarOperandValue, LoadOwnershipQualifier::Take);
404
- }
405
- SGF.B .createCheckedCastBranch (Loc, /* exact*/ false , scalarOperandValue,
406
- origTargetTL.getLoweredType (), trueBB,
407
- falseBB, TrueCount, FalseCount);
408
- }
409
-
410
- // Emit the success block.
411
- SGF.B .setInsertionPoint (trueBB);
412
- {
413
- FullExpr scope (SGF.Cleanups , CleanupLocation::get (Loc));
414
-
415
- ManagedValue result;
416
- if (Strategy == CastStrategy::Address) {
417
- result = finishFromResultBuffer (hasAbstraction, resultBuffer,
418
- abstraction, origTargetTL, ctx);
419
- } else {
420
- SILValue argument = trueBB->createPhiArgument (
421
- origTargetTL.getLoweredType (), ValueOwnershipKind::Owned);
422
- result = finishFromResultScalar (hasAbstraction, argument, consumption,
423
- abstraction, origTargetTL, ctx);
424
- }
425
-
426
- handleTrue (result);
427
- assert (!SGF.B .hasValidInsertionPoint () && " handler did not end block" );
428
- }
429
-
430
- // Emit the failure block.
431
- SGF.B .setInsertionPoint (falseBB);
432
- {
433
- FullExpr scope (SGF.Cleanups , CleanupLocation::get (Loc));
434
-
435
- // If we're using the scalar strategy, handle the consumption rules.
436
- if (Strategy != CastStrategy::Address &&
437
- shouldDestroyOnFailure (consumption)) {
438
- SGF.B .emitDestroyValueOperation (Loc, scalarOperandValue);
439
- }
440
-
441
- handleFalse ();
442
- assert (!SGF.B .hasValidInsertionPoint () && " handler did not end block" );
443
- }
444
- }
445
-
446
- SILValue createAbstractResultBuffer (bool hasAbstraction,
447
- const TypeLowering &origTargetTL,
448
- SGFContext ctx) {
449
- // Note that the conditions here must exactly match the criteria in
450
- // finishFromResultBuffer.
451
- if (!hasAbstraction) {
452
- if (auto address = ctx.getAddressForInPlaceInitialization (SGF, Loc))
453
- return address;
454
- }
455
-
456
- return SGF.emitTemporaryAllocation (Loc, origTargetTL.getLoweredType ());
457
- }
458
-
459
- ManagedValue finishFromResultBuffer (bool hasAbstraction,
460
- SILValue buffer,
461
- AbstractionPattern abstraction,
462
- const TypeLowering &origTargetTL,
463
- SGFContext ctx) {
464
- // Note that the conditions here must exactly match the criteria in
465
- // createAbstractResultBuffer.
466
- if (!hasAbstraction) {
467
- if (ctx.finishInPlaceInitialization (SGF))
468
- return ManagedValue::forInContext ();
469
- }
470
-
471
- ManagedValue result;
472
- if (!origTargetTL.isAddressOnly ()) {
473
- result = SGF.emitLoad (Loc, buffer, origTargetTL, ctx, IsTake);
474
- } else {
475
- result = SGF.emitManagedBufferWithCleanup (buffer, origTargetTL);
476
- }
477
-
478
- if (hasAbstraction) {
479
- result = SGF.emitOrigToSubstValue (Loc, result, abstraction,
480
- TargetType, ctx);
481
- }
482
- return result;
483
- }
484
-
485
- // / Our cast succeeded and gave us this abstracted value.
486
- ManagedValue finishFromResultScalar (bool hasAbstraction, SILValue value,
487
- CastConsumptionKind consumption,
488
- AbstractionPattern abstraction,
489
- const TypeLowering &origTargetTL,
490
- SGFContext ctx) {
491
- // Retain the result if this is copy-on-success.
492
- if (!shouldTakeOnSuccess (consumption))
493
- value = origTargetTL.emitCopyValue (SGF.B , Loc, value);
494
-
495
- // Enter a cleanup for the +1 result.
496
- ManagedValue result
497
- = SGF.emitManagedRValueWithCleanup (value, origTargetTL);
498
-
499
- // Re-abstract if necessary.
500
- if (hasAbstraction) {
501
- result = SGF.emitOrigToSubstValue (Loc, result, abstraction,
502
- TargetType, ctx);
503
- }
504
- return result;
505
- }
506
-
507
- private:
508
- CastStrategy computeStrategy () const {
509
- if (canUseScalarCheckedCastInstructions (SGF.SGM .M ,
510
- SourceType, TargetType))
511
- return CastStrategy::Scalar;
512
- return CastStrategy::Address;
513
- }
514
- };
515
- } // end anonymous namespace
516
-
517
- void SILGenFunction::emitCheckedCastBranchOld (
518
- SILLocation loc, ConsumableManagedValue src, Type sourceType,
519
- CanType targetType, SGFContext ctx,
520
- llvm::function_ref<void (ManagedValue)> handleTrue,
521
- llvm::function_ref<void()> handleFalse, ProfileCounter TrueCount,
522
- ProfileCounter FalseCount) {
523
- CheckedCastEmitterOld emitter (*this , loc, sourceType, targetType);
524
- emitter.emitConditional (src.getFinalManagedValue (), src.getFinalConsumption (),
525
- ctx, handleTrue, handleFalse, TrueCount, FalseCount);
526
- }
527
-
528
329
// / Emit a collection downcast expression.
529
330
// /
530
331
// / \param conditional Whether to emit a conditional downcast; if
0 commit comments