Skip to content

Commit d782f46

Browse files
committed
[SILGen] Factor out the generation of blocks for switching on an enum
This code is shared between emitEnumElementDispatch and emitEnumElementDispatchWithOwnership. Eventually the former will go away, but for now there's no need to have both copies (which really are the same). No intended functionality change.
1 parent 535b12f commit d782f46

File tree

1 file changed

+106
-164
lines changed

1 file changed

+106
-164
lines changed

lib/SILGen/SILGenPattern.cpp

Lines changed: 106 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -1679,113 +1679,136 @@ void PatternMatchEmission::emitIsDispatch(ArrayRef<RowToSpecialize> rows,
16791679
[&] { (*innerFailure)(loc); }, rows[0].Count);
16801680
}
16811681

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 {
16931683
struct CaseInfo {
16941684
EnumElementDecl *FormalElement;
16951685
Pattern *FirstMatcher;
16961686
bool Irrefutable = false;
16971687
SmallVector<SpecializedRow, 2> SpecializedRows;
16981688
};
1689+
} // end anonymous namespace
16991690

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);
17091707

17101708
caseBBs.reserve(rows.size());
17111709
caseInfos.reserve(rows.size());
17121710

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();
17281712

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::DenseMap<EnumElementDecl*, unsigned> 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();
17581724
}
1725+
auto elt = SGF.SGM.getLoweredEnumElementDecl(formalElt);
1726+
assert(elt->getParentEnum() == enumDecl);
17591727

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);
17651742

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;
17691748

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);
17761757
}
1777-
1778-
if (!exhaustive)
1779-
defaultBB = SGF.createBasicBlock(curBB);
17801758
}
17811759

17821760
assert(caseBBs.size() == caseInfos.size());
17831761

1762+
// We always need a default block if the enum is resilient.
1763+
// If the enum is @_fixed_layout, we only need one if the
1764+
// switch is not exhaustive.
1765+
bool exhaustive = false;
1766+
1767+
if (!enumDecl->isResilient(SGF.SGM.M.getSwiftModule(),
1768+
SGF.F.getResilienceExpansion())) {
1769+
exhaustive = true;
1770+
for (auto elt : enumDecl->getAllElements()) {
1771+
if (!caseToIndex.count(elt)) {
1772+
exhaustive = false;
1773+
break;
1774+
}
1775+
}
1776+
}
1777+
1778+
if (!exhaustive)
1779+
defaultBB = SGF.createBasicBlock(curBB);
1780+
}
1781+
1782+
/// Perform specialized dispatch for a sequence of EnumElementPattern or an
1783+
/// OptionalSomePattern.
1784+
void PatternMatchEmission::emitEnumElementDispatchWithOwnership(
1785+
ArrayRef<RowToSpecialize> rows, ConsumableManagedValue src,
1786+
const SpecializationHandler &handleCase,
1787+
const FailureHandler &outerFailure) {
1788+
assert(src.getFinalConsumption() != CastConsumptionKind::TakeOnSuccess &&
1789+
"SIL ownership does not support TakeOnSuccess");
1790+
1791+
CanType sourceType = rows[0].Pattern->getType()->getCanonicalType();
1792+
1793+
// Collect the cases and specialized rows.
1794+
//
1795+
// These vectors are completely parallel, but the switch
1796+
// instructions want only the first information, so we split them up.
1797+
SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 4> caseBBs;
1798+
SmallVector<ProfileCounter, 4> caseCounts;
1799+
SmallVector<CaseInfo, 4> caseInfos;
1800+
SILBasicBlock *defaultBB = nullptr;
1801+
1802+
generateEnumCaseBlocks(SGF, rows, sourceType, SGF.B.getInsertionBB(),
1803+
caseBBs, caseCounts, caseInfos, defaultBB);
1804+
17841805
SILLocation loc = PatternMatchStmt;
17851806
loc.setDebugLoc(rows[0].Pattern);
17861807
// SEMANTIC SIL TODO: Once we have the representation of a switch_enum that
17871808
// can take a +0 value, this extra copy should be a borrow.
17881809
SILValue srcValue = src.getFinalManagedValue().copy(SGF, loc).forward(SGF);
1810+
// FIXME: Pass caseCounts in here as well, as it is in
1811+
// emitEnumElementDispatch.
17891812
SGF.B.createSwitchEnum(loc, srcValue, defaultBB, caseBBs);
17901813

17911814
// Okay, now emit all the cases.
@@ -1910,15 +1933,6 @@ void PatternMatchEmission::emitEnumElementDispatch(
19101933

19111934
CanType sourceType = rows[0].Pattern->getType()->getCanonicalType();
19121935

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-
19221936
// Collect the cases and specialized rows.
19231937
//
19241938
// These vectors are completely parallel, but the switch
@@ -1928,80 +1942,8 @@ void PatternMatchEmission::emitEnumElementDispatch(
19281942
SmallVector<ProfileCounter, 4> caseCounts;
19291943
SILBasicBlock *defaultBB = nullptr;
19301944

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());
1945+
generateEnumCaseBlocks(SGF, rows, sourceType, SGF.B.getInsertionBB(),
1946+
caseBBs, caseCounts, caseInfos, defaultBB);
20051947

20061948
// Emit the switch_enum{_addr} instruction.
20071949
bool addressOnlyEnum = src.getType().isAddress();

0 commit comments

Comments
 (0)