@@ -1595,6 +1595,7 @@ namespace {
1595
1595
SILBasicBlock *trueBB = SGF.B .splitBlockForFallthrough ();
1596
1596
1597
1597
// Emit the branch.
1598
+ SILValue scalarOperandValue;
1598
1599
SILValue resultBuffer;
1599
1600
if (Strategy == CastStrategy::Address) {
1600
1601
assert (operand.getType ().isAddress ());
@@ -1605,9 +1606,13 @@ namespace {
1605
1606
resultBuffer, TargetType,
1606
1607
trueBB, falseBB);
1607
1608
} else {
1608
- assert (!operand.getType ().isAddress ());
1609
- SGF.B .createCheckedCastBranch (Loc, /* exact*/ false ,
1610
- operand.forward (SGF),
1609
+ // Tolerate being passed an address here. It comes up during switch
1610
+ // emission.
1611
+ scalarOperandValue = operand.forward (SGF);
1612
+ if (scalarOperandValue.getType ().isAddress ()) {
1613
+ scalarOperandValue = SGF.B .createLoad (Loc, scalarOperandValue);
1614
+ }
1615
+ SGF.B .createCheckedCastBranch (Loc, /* exact*/ false , scalarOperandValue,
1611
1616
origTargetTL.getLoweredType (),
1612
1617
trueBB, falseBB);
1613
1618
}
@@ -1628,6 +1633,7 @@ namespace {
1628
1633
}
1629
1634
1630
1635
handleTrue (result);
1636
+ assert (!SGF.B .hasValidInsertionPoint () && " handler did not end block" );
1631
1637
}
1632
1638
1633
1639
// Emit the failure block.
@@ -1637,10 +1643,11 @@ namespace {
1637
1643
// If we're using the scalar strategy, handle the consumption rules.
1638
1644
if (Strategy != CastStrategy::Address &&
1639
1645
shouldDestroyOnFailure (consumption)) {
1640
- SGF.B .emitReleaseValueOperation (Loc, operand. getValue () );
1646
+ SGF.B .emitReleaseValueOperation (Loc, scalarOperandValue );
1641
1647
}
1642
1648
1643
1649
handleFalse ();
1650
+ assert (!SGF.B .hasValidInsertionPoint () && " handler did not end block" );
1644
1651
}
1645
1652
}
1646
1653
@@ -1742,38 +1749,33 @@ static RValue emitUnconditionalCheckedCast(SILGenFunction &SGF,
1742
1749
return emitter.emitUnconditionalCast (operandValue, C);
1743
1750
}
1744
1751
1745
- SILValue
1746
- SILGenFunction::emitCheckedCastAbstractionChange (SILLocation loc,
1747
- SILValue original,
1748
- const TypeLowering &origTL,
1749
- ArrayRef<const TypeLowering *> castTLs) {
1750
- // If we're casting a thin metatype, make it thick.
1751
- if (auto metatype = original.getType ().getAs <MetatypeType>()) {
1752
- if (metatype->getRepresentation () == MetatypeRepresentation::Thin) {
1753
- auto thickTy = CanMetatypeType::get (metatype.getInstanceType (),
1754
- MetatypeRepresentation::Thick);
1755
- return B.createMetatype (loc, SILType::getPrimitiveObjectType (thickTy));
1756
- }
1757
- return original;
1758
- }
1759
-
1760
- // If the original type is already address-only, we don't need to abstract
1761
- // further.
1762
- if (origTL.isAddressOnly ()) {
1763
- return SILValue ();
1764
- }
1765
-
1766
- // If any of the cast-to types are address-only, spill to a temporary.
1767
- if (std::find_if (castTLs.begin (), castTLs.end (),
1768
- [](const TypeLowering *tl){ return tl->isAddressOnly (); })
1769
- != castTLs.end ()) {
1770
- SILValue temp = emitTemporaryAllocation (loc, origTL.getLoweredType ());
1771
- B.createStore (loc, original, temp);
1772
- return temp;
1752
+ // / Treating this as a successful operation, turn a CMV into a +1 MV.
1753
+ ManagedValue SILGenFunction::getManagedValue (SILLocation loc,
1754
+ ConsumableManagedValue value) {
1755
+ // If the consumption rules say that this is already +1 given a
1756
+ // successful operation, just use the value.
1757
+ if (value.isOwned ())
1758
+ return value.getFinalManagedValue ();
1759
+
1760
+ SILType valueTy = value.getType ();
1761
+ auto &valueTL = getTypeLowering (valueTy);
1762
+
1763
+ // If the type is trivial, it's always +1.
1764
+ if (valueTL.isTrivial ())
1765
+ return ManagedValue::forUnmanaged (value.getValue ());
1766
+
1767
+ // If it's an object, retain and enter a release cleanup.
1768
+ if (valueTy.isObject ()) {
1769
+ valueTL.emitRetainValue (B, loc, value.getValue ());
1770
+ return emitManagedRValueWithCleanup (value.getValue (), valueTL);
1773
1771
}
1774
-
1775
- // Otherwise, no abstraction change is needed.
1776
- return SILValue ();
1772
+
1773
+ // Otherwise, produce a temporary and copy into that.
1774
+ auto temporary = emitTemporary (loc, valueTL);
1775
+ valueTL.emitCopyInto (B, loc, value.getValue (), temporary->getAddress (),
1776
+ IsNotTake, IsInitialization);
1777
+ temporary->finishInitialization (*this );
1778
+ return temporary->getManagedAddress ();
1777
1779
}
1778
1780
1779
1781
void SILGenFunction::emitCheckedCastBranch (SILLocation loc, Expr *source,
@@ -1787,6 +1789,18 @@ void SILGenFunction::emitCheckedCastBranch(SILLocation loc, Expr *source,
1787
1789
handleTrue, handleFalse);
1788
1790
}
1789
1791
1792
+ void SILGenFunction::emitCheckedCastBranch (SILLocation loc,
1793
+ ConsumableManagedValue src,
1794
+ CanType sourceType,
1795
+ CanType targetType,
1796
+ SGFContext ctx,
1797
+ std::function<void (ManagedValue)> handleTrue,
1798
+ std::function<void()> handleFalse) {
1799
+ CheckedCastEmitter emitter (*this , loc, sourceType, targetType);
1800
+ emitter.emitConditional (src.getFinalManagedValue (), src.getFinalConsumption (),
1801
+ ctx, handleTrue, handleFalse);
1802
+ }
1803
+
1790
1804
std::pair<SILBasicBlock*, SILBasicBlock*>
1791
1805
SILGenFunction::emitCheckedCastBranch (SILLocation loc,
1792
1806
SILValue original,
0 commit comments