@@ -1679,113 +1679,141 @@ void PatternMatchEmission::emitIsDispatch(ArrayRef<RowToSpecialize> rows,
1679
1679
[&] { (*innerFailure)(loc); }, rows[0 ].Count );
1680
1680
}
1681
1681
1682
- // / Perform specialized dispatch for a sequence of EnumElementPattern or an
1683
- // / OptionalSomePattern.
1684
- void PatternMatchEmission::emitEnumElementDispatchWithOwnership (
1685
- ArrayRef<RowToSpecialize> rows, ConsumableManagedValue src,
1686
- const SpecializationHandler &handleCase,
1687
- const FailureHandler &outerFailure) {
1688
- assert (src.getFinalConsumption () != CastConsumptionKind::TakeOnSuccess &&
1689
- " SIL ownership does not support TakeOnSuccess" );
1690
-
1691
- CanType sourceType = rows[0 ].Pattern ->getType ()->getCanonicalType ();
1692
-
1682
+ namespace {
1693
1683
struct CaseInfo {
1694
1684
EnumElementDecl *FormalElement;
1695
1685
Pattern *FirstMatcher;
1696
1686
bool Irrefutable = false ;
1697
1687
SmallVector<SpecializedRow, 2 > SpecializedRows;
1698
1688
};
1689
+ } // end anonymous namespace
1699
1690
1700
- SILBasicBlock *curBB = SGF.B .getInsertionBB ();
1701
-
1702
- // Collect the cases and specialized rows.
1703
- //
1704
- // These vectors are completely parallel, but the switch
1705
- // instructions want only the first information, so we split them up.
1706
- SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 4 > caseBBs;
1707
- SmallVector<CaseInfo, 4 > caseInfos;
1708
- SILBasicBlock *defaultBB = nullptr ;
1691
+ // / Create destination blocks for switching over the cases in an enum defined
1692
+ // / by \p rows.
1693
+ static void generateEnumCaseBlocks (
1694
+ SILGenFunction &SGF,
1695
+ ArrayRef<RowToSpecialize> rows,
1696
+ CanType sourceType,
1697
+ SILBasicBlock *curBB,
1698
+ SmallVectorImpl<std::pair<EnumElementDecl *, SILBasicBlock *>> &caseBBs,
1699
+ SmallVectorImpl<ProfileCounter> &caseCounts,
1700
+ SmallVectorImpl<CaseInfo> &caseInfos,
1701
+ SILBasicBlock *&defaultBB) {
1702
+
1703
+ assert (caseBBs.empty ());
1704
+ assert (caseCounts.empty ());
1705
+ assert (caseInfos.empty ());
1706
+ assert (defaultBB == nullptr );
1709
1707
1710
1708
caseBBs.reserve (rows.size ());
1711
1709
caseInfos.reserve (rows.size ());
1712
1710
1713
- {
1714
- // Create destination blocks for all the cases.
1715
- llvm::DenseMap<EnumElementDecl *, unsigned > caseToIndex;
1716
- for (auto &row : rows) {
1717
- EnumElementDecl *formalElt;
1718
- Pattern *subPattern = nullptr ;
1719
- if (auto eep = dyn_cast<EnumElementPattern>(row.Pattern )) {
1720
- formalElt = eep->getElementDecl ();
1721
- subPattern = eep->getSubPattern ();
1722
- } else {
1723
- auto *osp = cast<OptionalSomePattern>(row.Pattern );
1724
- formalElt = osp->getElementDecl ();
1725
- subPattern = osp->getSubPattern ();
1726
- }
1727
- auto elt = SGF.SGM .getLoweredEnumElementDecl (formalElt);
1711
+ auto enumDecl = sourceType.getEnumOrBoundGenericEnum ();
1728
1712
1729
- unsigned index = caseInfos.size ();
1730
- auto insertionResult = caseToIndex.insert ({elt, index});
1731
- if (!insertionResult.second ) {
1732
- index = insertionResult.first ->second ;
1733
- } else {
1734
- curBB = SGF.createBasicBlock (curBB);
1735
- caseBBs.push_back ({elt, curBB});
1736
- caseInfos.resize (caseInfos.size () + 1 );
1737
- caseInfos.back ().FormalElement = formalElt;
1738
- caseInfos.back ().FirstMatcher = row.Pattern ;
1739
- }
1740
- assert (caseToIndex[elt] == index);
1741
- assert (caseBBs[index].first == elt);
1742
-
1743
- auto &info = caseInfos[index];
1744
- info.Irrefutable = (info.Irrefutable || row.Irrefutable );
1745
- info.SpecializedRows .resize (info.SpecializedRows .size () + 1 );
1746
- auto &specRow = info.SpecializedRows .back ();
1747
- specRow.RowIndex = row.RowIndex ;
1748
-
1749
- // Use the row pattern, if it has one.
1750
- if (subPattern) {
1751
- specRow.Patterns .push_back (subPattern);
1752
- // It's also legal to write:
1753
- // case .Some { ... }
1754
- // which is an implicit wildcard.
1755
- } else {
1756
- specRow.Patterns .push_back (nullptr );
1757
- }
1713
+ llvm::SmallDenseMap<EnumElementDecl *, unsigned , 16 > caseToIndex;
1714
+ for (auto &row : rows) {
1715
+ EnumElementDecl *formalElt;
1716
+ Pattern *subPattern = nullptr ;
1717
+ if (auto eep = dyn_cast<EnumElementPattern>(row.Pattern )) {
1718
+ formalElt = eep->getElementDecl ();
1719
+ subPattern = eep->getSubPattern ();
1720
+ } else {
1721
+ auto *osp = cast<OptionalSomePattern>(row.Pattern );
1722
+ formalElt = osp->getElementDecl ();
1723
+ subPattern = osp->getSubPattern ();
1758
1724
}
1725
+ auto elt = SGF.SGM .getLoweredEnumElementDecl (formalElt);
1726
+ assert (elt->getParentEnum () == enumDecl);
1759
1727
1760
- // We always need a default block if the enum is resilient.
1761
- // If the enum is @_fixed_layout, we only need one if the
1762
- // switch is not exhaustive.
1763
- bool exhaustive = false ;
1764
- auto enumDecl = sourceType.getEnumOrBoundGenericEnum ();
1728
+ unsigned index = caseInfos.size ();
1729
+ auto insertionResult = caseToIndex.insert ({elt, index});
1730
+ if (!insertionResult.second ) {
1731
+ index = insertionResult.first ->second ;
1732
+ } else {
1733
+ curBB = SGF.createBasicBlock (curBB);
1734
+ caseBBs.push_back ({elt, curBB});
1735
+ caseInfos.push_back (CaseInfo ());
1736
+ caseInfos.back ().FormalElement = formalElt;
1737
+ caseInfos.back ().FirstMatcher = row.Pattern ;
1738
+ caseCounts.push_back (row.Count );
1739
+ }
1740
+ assert (caseToIndex[elt] == index);
1741
+ assert (caseBBs[index].first == elt);
1765
1742
1766
- if (!enumDecl->isResilient (SGF.SGM .M .getSwiftModule (),
1767
- SGF.F .getResilienceExpansion ())) {
1768
- exhaustive = true ;
1743
+ auto &info = caseInfos[index];
1744
+ info.Irrefutable = (info.Irrefutable || row.Irrefutable );
1745
+ info.SpecializedRows .push_back (SpecializedRow ());
1746
+ auto &specRow = info.SpecializedRows .back ();
1747
+ specRow.RowIndex = row.RowIndex ;
1769
1748
1770
- for (auto elt : enumDecl->getAllElements ()) {
1771
- if (!caseToIndex.count (elt)) {
1772
- exhaustive = false ;
1773
- break ;
1774
- }
1775
- }
1749
+ // Use the row pattern, if it has one.
1750
+ if (subPattern) {
1751
+ specRow.Patterns .push_back (subPattern);
1752
+ // It's also legal to write:
1753
+ // case .Some { ... }
1754
+ // which is an implicit wildcard.
1755
+ } else {
1756
+ specRow.Patterns .push_back (nullptr );
1776
1757
}
1777
-
1778
- if (!exhaustive)
1779
- defaultBB = SGF.createBasicBlock (curBB);
1780
1758
}
1781
1759
1782
1760
assert (caseBBs.size () == caseInfos.size ());
1783
1761
1762
+ // Check to see if the enum may have values beyond the cases we can see
1763
+ // at compile-time. This includes future cases (for resilient enums) and
1764
+ // random values crammed into C enums.
1765
+ //
1766
+ // Note: This relies on the fact that there are no "non-resilient" enums that
1767
+ // are still non-exhaustive, except for @objc enums.
1768
+ bool canAssumeExhaustive = !enumDecl->isObjC ();
1769
+ if (canAssumeExhaustive) {
1770
+ canAssumeExhaustive =
1771
+ !enumDecl->isResilient (SGF.SGM .SwiftModule ,
1772
+ SGF.F .getResilienceExpansion ());
1773
+ }
1774
+ if (canAssumeExhaustive) {
1775
+ // Check that Sema didn't let any cases slip through. (This can happen
1776
+ // with @_downgrade_exhaustivity_check.)
1777
+ canAssumeExhaustive = llvm::all_of (enumDecl->getAllElements (),
1778
+ [&](const EnumElementDecl *elt) {
1779
+ return caseToIndex.count (elt);
1780
+ });
1781
+ }
1782
+
1783
+ if (!canAssumeExhaustive)
1784
+ defaultBB = SGF.createBasicBlock (curBB);
1785
+ }
1786
+
1787
+ // / Perform specialized dispatch for a sequence of EnumElementPattern or an
1788
+ // / OptionalSomePattern.
1789
+ void PatternMatchEmission::emitEnumElementDispatchWithOwnership (
1790
+ ArrayRef<RowToSpecialize> rows, ConsumableManagedValue src,
1791
+ const SpecializationHandler &handleCase,
1792
+ const FailureHandler &outerFailure) {
1793
+ assert (src.getFinalConsumption () != CastConsumptionKind::TakeOnSuccess &&
1794
+ " SIL ownership does not support TakeOnSuccess" );
1795
+
1796
+ CanType sourceType = rows[0 ].Pattern ->getType ()->getCanonicalType ();
1797
+
1798
+ // Collect the cases and specialized rows.
1799
+ //
1800
+ // These vectors are completely parallel, but the switch
1801
+ // instructions want only the first information, so we split them up.
1802
+ SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 4 > caseBBs;
1803
+ SmallVector<ProfileCounter, 4 > caseCounts;
1804
+ SmallVector<CaseInfo, 4 > caseInfos;
1805
+ SILBasicBlock *defaultBB = nullptr ;
1806
+
1807
+ generateEnumCaseBlocks (SGF, rows, sourceType, SGF.B .getInsertionBB (),
1808
+ caseBBs, caseCounts, caseInfos, defaultBB);
1809
+
1784
1810
SILLocation loc = PatternMatchStmt;
1785
1811
loc.setDebugLoc (rows[0 ].Pattern );
1786
1812
// SEMANTIC SIL TODO: Once we have the representation of a switch_enum that
1787
1813
// can take a +0 value, this extra copy should be a borrow.
1788
1814
SILValue srcValue = src.getFinalManagedValue ().copy (SGF, loc).forward (SGF);
1815
+ // FIXME: Pass caseCounts in here as well, as it is in
1816
+ // emitEnumElementDispatch.
1789
1817
SGF.B .createSwitchEnum (loc, srcValue, defaultBB, caseBBs);
1790
1818
1791
1819
// Okay, now emit all the cases.
@@ -1910,15 +1938,6 @@ void PatternMatchEmission::emitEnumElementDispatch(
1910
1938
1911
1939
CanType sourceType = rows[0 ].Pattern ->getType ()->getCanonicalType ();
1912
1940
1913
- struct CaseInfo {
1914
- EnumElementDecl *FormalElement;
1915
- Pattern *FirstMatcher;
1916
- bool Irrefutable = false ;
1917
- SmallVector<SpecializedRow, 2 > SpecializedRows;
1918
- };
1919
-
1920
- SILBasicBlock *curBB = SGF.B .getInsertionBB ();
1921
-
1922
1941
// Collect the cases and specialized rows.
1923
1942
//
1924
1943
// These vectors are completely parallel, but the switch
@@ -1928,80 +1947,8 @@ void PatternMatchEmission::emitEnumElementDispatch(
1928
1947
SmallVector<ProfileCounter, 4 > caseCounts;
1929
1948
SILBasicBlock *defaultBB = nullptr ;
1930
1949
1931
- caseBBs.reserve (rows.size ());
1932
- caseInfos.reserve (rows.size ());
1933
-
1934
- {
1935
- // Create destination blocks for all the cases.
1936
- llvm::DenseMap<EnumElementDecl*, unsigned > caseToIndex;
1937
- for (auto &row : rows) {
1938
- EnumElementDecl *formalElt;
1939
- Pattern *subPattern = nullptr ;
1940
- if (auto eep = dyn_cast<EnumElementPattern>(row.Pattern )) {
1941
- formalElt = eep->getElementDecl ();
1942
- subPattern = eep->getSubPattern ();
1943
- } else {
1944
- auto *osp = cast<OptionalSomePattern>(row.Pattern );
1945
- formalElt = osp->getElementDecl ();
1946
- subPattern = osp->getSubPattern ();
1947
- }
1948
- auto elt = SGF.SGM .getLoweredEnumElementDecl (formalElt);
1949
-
1950
- unsigned index = caseInfos.size ();
1951
- auto insertionResult = caseToIndex.insert ({elt, index});
1952
- if (!insertionResult.second ) {
1953
- index = insertionResult.first ->second ;
1954
- } else {
1955
- curBB = SGF.createBasicBlock (curBB);
1956
- caseBBs.push_back ({elt, curBB});
1957
- caseInfos.resize (caseInfos.size () + 1 );
1958
- caseInfos.back ().FormalElement = formalElt;
1959
- caseInfos.back ().FirstMatcher = row.Pattern ;
1960
- caseCounts.push_back (row.Count );
1961
- }
1962
- assert (caseToIndex[elt] == index);
1963
- assert (caseBBs[index].first == elt);
1964
-
1965
- auto &info = caseInfos[index];
1966
- info.Irrefutable = (info.Irrefutable || row.Irrefutable );
1967
- info.SpecializedRows .resize (info.SpecializedRows .size () + 1 );
1968
- auto &specRow = info.SpecializedRows .back ();
1969
- specRow.RowIndex = row.RowIndex ;
1970
-
1971
- // Use the row pattern, if it has one.
1972
- if (subPattern) {
1973
- specRow.Patterns .push_back (subPattern);
1974
- // It's also legal to write:
1975
- // case .Some { ... }
1976
- // which is an implicit wildcard.
1977
- } else {
1978
- specRow.Patterns .push_back (nullptr );
1979
- }
1980
- }
1981
-
1982
- // We always need a default block if the enum is resilient.
1983
- // If the enum is @_fixed_layout, we only need one if the
1984
- // switch is not exhaustive.
1985
- bool exhaustive = false ;
1986
- auto enumDecl = sourceType.getEnumOrBoundGenericEnum ();
1987
-
1988
- if (!enumDecl->isResilient (SGF.SGM .M .getSwiftModule (),
1989
- SGF.F .getResilienceExpansion ())) {
1990
- exhaustive = true ;
1991
-
1992
- for (auto elt : enumDecl->getAllElements ()) {
1993
- if (!caseToIndex.count (elt)) {
1994
- exhaustive = false ;
1995
- break ;
1996
- }
1997
- }
1998
- }
1999
-
2000
- if (!exhaustive)
2001
- defaultBB = SGF.createBasicBlock (curBB);
2002
- }
2003
-
2004
- assert (caseBBs.size () == caseInfos.size ());
1950
+ generateEnumCaseBlocks (SGF, rows, sourceType, SGF.B .getInsertionBB (),
1951
+ caseBBs, caseCounts, caseInfos, defaultBB);
2005
1952
2006
1953
// Emit the switch_enum{_addr} instruction.
2007
1954
bool addressOnlyEnum = src.getType ().isAddress ();
@@ -2600,17 +2547,21 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
2600
2547
DEBUG (llvm::dbgs () << " emitting switch stmt\n " ;
2601
2548
S->print (llvm::dbgs ());
2602
2549
llvm::dbgs () << ' \n ' );
2603
- auto failure = [&](SILLocation location) {
2604
- // If we fail to match anything, we can just emit unreachable.
2605
- // This will be a dataflow error if we can reach here.
2606
- B.createUnreachable (S);
2550
+ auto failure = [this ](SILLocation location) {
2551
+ // If we fail to match anything, we trap. This can happen with a switch
2552
+ // over an @objc enum, which may contain any value of its underlying type.
2553
+ // FIXME: Even if we can't say what the invalid value was, we should at
2554
+ // least mention that this was because of a non-exhaustive enum.
2555
+ B.createBuiltinTrap (location);
2556
+ B.createUnreachable (location);
2607
2557
};
2608
2558
2609
2559
// If the subject expression is uninhabited, we're already dead.
2610
2560
// Emit an unreachable in place of the switch statement.
2611
2561
if (S->getSubjectExpr ()->getType ()->isStructurallyUninhabited ()) {
2612
2562
emitIgnoredExpr (S->getSubjectExpr ());
2613
- return failure (SILLocation (S));
2563
+ B.createUnreachable (S);
2564
+ return ;
2614
2565
}
2615
2566
2616
2567
auto completionHandler = [&](PatternMatchEmission &emission,
0 commit comments