Skip to content

Commit e3eb9ae

Browse files
committed
[sil] Introduce FullApplySiteKind and ApplySiteKind to allow for exhaustive switching over FullApplySites and ApplySiteKind.
Currently there is a bug in the closure specializer that was caused by BeginApply not being handled correctly. Rather than just fixing that and leaving the badness, I am instead in this commit introducing enums for apply sites so we can avoid this problem in the future by using exhaustive switches to guide developers adding new types of apply sites in the future. rdar://44612356
1 parent 53a5d6a commit e3eb9ae

File tree

2 files changed

+282
-84
lines changed

2 files changed

+282
-84
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 140 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -7477,6 +7477,40 @@ class TryApplyInst final
74777477
const GenericSpecializationInformation *SpecializationInfo);
74787478
};
74797479

7480+
struct ApplySiteKind {
7481+
enum innerty : std::underlying_type<SILInstructionKind>::type {
7482+
#define APPLYSITE_INST(ID, PARENT) ID = unsigned(SILInstructionKind::ID),
7483+
#include "swift/SIL/SILNodes.def"
7484+
} value;
7485+
7486+
explicit ApplySiteKind(SILInstructionKind kind) {
7487+
auto newValue = ApplySiteKind::fromNodeKindHelper(kind);
7488+
assert(newValue && "Non apply site passed into ApplySiteKind");
7489+
value = newValue.getValue();
7490+
}
7491+
7492+
ApplySiteKind(innerty value) : value(value) {}
7493+
operator innerty() const { return value; }
7494+
7495+
static Optional<ApplySiteKind> fromNodeKind(SILInstructionKind kind) {
7496+
if (auto innerTyOpt = ApplySiteKind::fromNodeKindHelper(kind))
7497+
return ApplySiteKind(*innerTyOpt);
7498+
return None;
7499+
}
7500+
7501+
private:
7502+
static Optional<innerty> fromNodeKindHelper(SILInstructionKind kind) {
7503+
switch (kind) {
7504+
#define APPLYSITE_INST(ID, PARENT) \
7505+
case SILInstructionKind::ID: \
7506+
return ApplySiteKind::ID;
7507+
#include "swift/SIL/SILNodes.def"
7508+
default:
7509+
return None;
7510+
}
7511+
}
7512+
};
7513+
74807514
/// An apply instruction.
74817515
class ApplySite {
74827516
SILInstruction *Inst;
@@ -7500,17 +7534,23 @@ class ApplySite {
75007534
}
75017535

75027536
static ApplySite isa(SILNode *node) {
7503-
switch (node->getKind()) {
7504-
case SILNodeKind::ApplyInst:
7537+
auto *i = dyn_cast<SILInstruction>(node);
7538+
if (!i)
7539+
return ApplySite();
7540+
7541+
auto kind = ApplySiteKind::fromNodeKind(i->getKind());
7542+
if (!kind)
7543+
return ApplySite();
7544+
7545+
switch (kind.getValue()) {
7546+
case ApplySiteKind::ApplyInst:
75057547
return ApplySite(cast<ApplyInst>(node));
7506-
case SILNodeKind::BeginApplyInst:
7548+
case ApplySiteKind::BeginApplyInst:
75077549
return ApplySite(cast<BeginApplyInst>(node));
7508-
case SILNodeKind::TryApplyInst:
7550+
case ApplySiteKind::TryApplyInst:
75097551
return ApplySite(cast<TryApplyInst>(node));
7510-
case SILNodeKind::PartialApplyInst:
7552+
case ApplySiteKind::PartialApplyInst:
75117553
return ApplySite(cast<PartialApplyInst>(node));
7512-
default:
7513-
return ApplySite();
75147554
}
75157555
}
75167556

@@ -7524,19 +7564,18 @@ class ApplySite {
75247564
SILFunction *getFunction() const { return Inst->getFunction(); }
75257565
SILBasicBlock *getParent() const { return Inst->getParent(); }
75267566

7527-
#define FOREACH_IMPL_RETURN(OPERATION) do { \
7528-
switch (Inst->getKind()) { \
7529-
case SILInstructionKind::ApplyInst: \
7530-
return cast<ApplyInst>(Inst)->OPERATION; \
7531-
case SILInstructionKind::BeginApplyInst: \
7532-
return cast<BeginApplyInst>(Inst)->OPERATION; \
7533-
case SILInstructionKind::PartialApplyInst: \
7534-
return cast<PartialApplyInst>(Inst)->OPERATION; \
7535-
case SILInstructionKind::TryApplyInst: \
7536-
return cast<TryApplyInst>(Inst)->OPERATION; \
7537-
default: \
7538-
llvm_unreachable("not an apply instruction!"); \
7539-
} \
7567+
#define FOREACH_IMPL_RETURN(OPERATION) \
7568+
do { \
7569+
switch (ApplySiteKind(Inst->getKind())) { \
7570+
case ApplySiteKind::ApplyInst: \
7571+
return cast<ApplyInst>(Inst)->OPERATION; \
7572+
case ApplySiteKind::BeginApplyInst: \
7573+
return cast<BeginApplyInst>(Inst)->OPERATION; \
7574+
case ApplySiteKind::PartialApplyInst: \
7575+
return cast<PartialApplyInst>(Inst)->OPERATION; \
7576+
case ApplySiteKind::TryApplyInst: \
7577+
return cast<TryApplyInst>(Inst)->OPERATION; \
7578+
} \
75407579
} while (0)
75417580

75427581
/// Return the callee operand.
@@ -7670,12 +7709,12 @@ class ApplySite {
76707709
/// Return the callee's function argument index corresponding to the first
76717710
/// applied argument: 0 for full applies; >= 0 for partial applies.
76727711
unsigned getCalleeArgIndexOfFirstAppliedArg() const {
7673-
switch (Inst->getKind()) {
7674-
case SILInstructionKind::ApplyInst:
7675-
case SILInstructionKind::BeginApplyInst:
7676-
case SILInstructionKind::TryApplyInst:
7712+
switch (ApplySiteKind(Inst->getKind())) {
7713+
case ApplySiteKind::ApplyInst:
7714+
case ApplySiteKind::BeginApplyInst:
7715+
case ApplySiteKind::TryApplyInst:
76777716
return 0;
7678-
case SILInstructionKind::PartialApplyInst:
7717+
case ApplySiteKind::PartialApplyInst:
76797718
// The arguments to partial_apply are a suffix of the partial_apply's
76807719
// callee. Note that getSubstCalleeConv is function type of the callee
76817720
// argument passed to this apply, not necessarilly the function type of
@@ -7686,8 +7725,6 @@ class ApplySite {
76867725
// pa2 = partial_apply pa1(b) : $(a, b)
76877726
// apply pa2(a)
76887727
return getSubstCalleeConv().getNumSILArguments() - getNumArguments();
7689-
default:
7690-
llvm_unreachable("not implemented for this instruction!");
76917728
}
76927729
}
76937730

@@ -7711,72 +7748,72 @@ class ApplySite {
77117748

77127749
/// Return true if 'self' is an applied argument.
77137750
bool hasSelfArgument() const {
7714-
switch (Inst->getKind()) {
7715-
case SILInstructionKind::ApplyInst:
7751+
switch (ApplySiteKind(Inst->getKind())) {
7752+
case ApplySiteKind::ApplyInst:
77167753
return cast<ApplyInst>(Inst)->hasSelfArgument();
7717-
case SILInstructionKind::BeginApplyInst:
7754+
case ApplySiteKind::BeginApplyInst:
77187755
return cast<BeginApplyInst>(Inst)->hasSelfArgument();
7719-
case SILInstructionKind::TryApplyInst:
7756+
case ApplySiteKind::TryApplyInst:
77207757
return cast<TryApplyInst>(Inst)->hasSelfArgument();
7721-
default:
7722-
llvm_unreachable("not implemented for this instruction!");
7758+
case ApplySiteKind::PartialApplyInst:
7759+
llvm_unreachable("unhandled case");
77237760
}
77247761
}
77257762

77267763
/// Return the applied 'self' argument value.
77277764
SILValue getSelfArgument() const {
7728-
switch (Inst->getKind()) {
7729-
case SILInstructionKind::ApplyInst:
7765+
switch (ApplySiteKind(Inst->getKind())) {
7766+
case ApplySiteKind::ApplyInst:
77307767
return cast<ApplyInst>(Inst)->getSelfArgument();
7731-
case SILInstructionKind::BeginApplyInst:
7768+
case ApplySiteKind::BeginApplyInst:
77327769
return cast<BeginApplyInst>(Inst)->getSelfArgument();
7733-
case SILInstructionKind::TryApplyInst:
7770+
case ApplySiteKind::TryApplyInst:
77347771
return cast<TryApplyInst>(Inst)->getSelfArgument();
7735-
default:
7736-
llvm_unreachable("not implemented for this instruction!");
7772+
case ApplySiteKind::PartialApplyInst:
7773+
llvm_unreachable("unhandled case");
77377774
}
77387775
}
77397776

77407777
/// Return the 'self' apply operand.
77417778
Operand &getSelfArgumentOperand() {
7742-
switch (Inst->getKind()) {
7743-
case SILInstructionKind::ApplyInst:
7779+
switch (ApplySiteKind(Inst->getKind())) {
7780+
case ApplySiteKind::ApplyInst:
77447781
return cast<ApplyInst>(Inst)->getSelfArgumentOperand();
7745-
case SILInstructionKind::BeginApplyInst:
7782+
case ApplySiteKind::BeginApplyInst:
77467783
return cast<BeginApplyInst>(Inst)->getSelfArgumentOperand();
7747-
case SILInstructionKind::TryApplyInst:
7784+
case ApplySiteKind::TryApplyInst:
77487785
return cast<TryApplyInst>(Inst)->getSelfArgumentOperand();
7749-
default:
7750-
llvm_unreachable("not implemented for this instruction!");
7786+
case ApplySiteKind::PartialApplyInst:
7787+
llvm_unreachable("Unhandled cast");
77517788
}
77527789
}
77537790

77547791
/// Return a list of applied arguments without self.
77557792
OperandValueArrayRef getArgumentsWithoutSelf() const {
7756-
switch (Inst->getKind()) {
7757-
case SILInstructionKind::ApplyInst:
7793+
switch (ApplySiteKind(Inst->getKind())) {
7794+
case ApplySiteKind::ApplyInst:
77587795
return cast<ApplyInst>(Inst)->getArgumentsWithoutSelf();
7759-
case SILInstructionKind::BeginApplyInst:
7796+
case ApplySiteKind::BeginApplyInst:
77607797
return cast<BeginApplyInst>(Inst)->getArgumentsWithoutSelf();
7761-
case SILInstructionKind::TryApplyInst:
7798+
case ApplySiteKind::TryApplyInst:
77627799
return cast<TryApplyInst>(Inst)->getArgumentsWithoutSelf();
7763-
default:
7764-
llvm_unreachable("not implemented for this instruction!");
7800+
case ApplySiteKind::PartialApplyInst:
7801+
llvm_unreachable("Unhandled case");
77657802
}
77667803
}
77677804

77687805
/// Return whether the given apply is of a formally-throwing function
77697806
/// which is statically known not to throw.
77707807
bool isNonThrowing() const {
7771-
switch (getInstruction()->getKind()) {
7772-
case SILInstructionKind::ApplyInst:
7808+
switch (ApplySiteKind(getInstruction()->getKind())) {
7809+
case ApplySiteKind::ApplyInst:
77737810
return cast<ApplyInst>(Inst)->isNonThrowing();
7774-
case SILInstructionKind::BeginApplyInst:
7811+
case ApplySiteKind::BeginApplyInst:
77757812
return cast<BeginApplyInst>(Inst)->isNonThrowing();
7776-
case SILInstructionKind::TryApplyInst:
7813+
case ApplySiteKind::TryApplyInst:
77777814
return false;
7778-
default:
7779-
llvm_unreachable("not implemented for this instruction!");
7815+
case ApplySiteKind::PartialApplyInst:
7816+
llvm_unreachable("Unhandled case");
77807817
}
77817818
}
77827819

@@ -7792,10 +7829,41 @@ class ApplySite {
77927829
}
77937830

77947831
static bool classof(const SILInstruction *inst) {
7795-
return (inst->getKind() == SILInstructionKind::ApplyInst ||
7796-
inst->getKind() == SILInstructionKind::BeginApplyInst ||
7797-
inst->getKind() == SILInstructionKind::PartialApplyInst ||
7798-
inst->getKind() == SILInstructionKind::TryApplyInst);
7832+
return bool(ApplySiteKind::fromNodeKind(inst->getKind()));
7833+
}
7834+
};
7835+
7836+
struct FullApplySiteKind {
7837+
enum innerty : std::underlying_type<SILInstructionKind>::type {
7838+
#define FULLAPPLYSITE_INST(ID, PARENT) ID = unsigned(SILInstructionKind::ID),
7839+
#include "swift/SIL/SILNodes.def"
7840+
} value;
7841+
7842+
explicit FullApplySiteKind(SILInstructionKind kind) {
7843+
auto fullApplySiteKind = FullApplySiteKind::fromNodeKindHelper(kind);
7844+
assert(fullApplySiteKind && "SILNodeKind is not a FullApplySiteKind?!");
7845+
value = fullApplySiteKind.getValue();
7846+
}
7847+
7848+
FullApplySiteKind(innerty value) : value(value) {}
7849+
operator innerty() const { return value; }
7850+
7851+
static Optional<FullApplySiteKind> fromNodeKind(SILInstructionKind kind) {
7852+
if (auto innerOpt = FullApplySiteKind::fromNodeKindHelper(kind))
7853+
return FullApplySiteKind(*innerOpt);
7854+
return None;
7855+
}
7856+
7857+
private:
7858+
static Optional<innerty> fromNodeKindHelper(SILInstructionKind kind) {
7859+
switch (kind) {
7860+
#define FULLAPPLYSITE_INST(ID, PARENT) \
7861+
case SILInstructionKind::ID: \
7862+
return FullApplySiteKind::ID;
7863+
#include "swift/SIL/SILNodes.def"
7864+
default:
7865+
return None;
7866+
}
77997867
}
78007868
};
78017869

@@ -7813,15 +7881,19 @@ class FullApplySite : public ApplySite {
78137881
FullApplySite(TryApplyInst *inst) : ApplySite(inst) {}
78147882

78157883
static FullApplySite isa(SILNode *node) {
7816-
switch (node->getKind()) {
7817-
case SILNodeKind::ApplyInst:
7884+
auto *i = dyn_cast<SILInstruction>(node);
7885+
if (!i)
7886+
return FullApplySite();
7887+
auto kind = FullApplySiteKind::fromNodeKind(i->getKind());
7888+
if (!kind)
7889+
return FullApplySite();
7890+
switch (kind.getValue()) {
7891+
case FullApplySiteKind::ApplyInst:
78187892
return FullApplySite(cast<ApplyInst>(node));
7819-
case SILNodeKind::BeginApplyInst:
7893+
case FullApplySiteKind::BeginApplyInst:
78207894
return FullApplySite(cast<BeginApplyInst>(node));
7821-
case SILNodeKind::TryApplyInst:
7895+
case FullApplySiteKind::TryApplyInst:
78227896
return FullApplySite(cast<TryApplyInst>(node));
7823-
default:
7824-
return FullApplySite();
78257897
}
78267898
}
78277899

@@ -7846,9 +7918,7 @@ class FullApplySite : public ApplySite {
78467918
}
78477919

78487920
static bool classof(const SILInstruction *inst) {
7849-
return (inst->getKind() == SILInstructionKind::ApplyInst ||
7850-
inst->getKind() == SILInstructionKind::BeginApplyInst ||
7851-
inst->getKind() == SILInstructionKind::TryApplyInst);
7921+
return bool(FullApplySiteKind::fromNodeKind(inst->getKind()));
78527922
}
78537923
};
78547924

0 commit comments

Comments
 (0)