Skip to content

[sil] Introduce FullApplySiteKind and ApplySiteKind to allow for exha… #19436

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
210 changes: 140 additions & 70 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -7477,6 +7477,40 @@ class TryApplyInst final
const GenericSpecializationInformation *SpecializationInfo);
};

struct ApplySiteKind {
enum innerty : std::underlying_type<SILInstructionKind>::type {
#define APPLYSITE_INST(ID, PARENT) ID = unsigned(SILInstructionKind::ID),
#include "swift/SIL/SILNodes.def"
} value;

explicit ApplySiteKind(SILInstructionKind kind) {
auto newValue = ApplySiteKind::fromNodeKindHelper(kind);
assert(newValue && "Non apply site passed into ApplySiteKind");
value = newValue.getValue();
}

ApplySiteKind(innerty value) : value(value) {}
operator innerty() const { return value; }

static Optional<ApplySiteKind> fromNodeKind(SILInstructionKind kind) {
if (auto innerTyOpt = ApplySiteKind::fromNodeKindHelper(kind))
return ApplySiteKind(*innerTyOpt);
return None;
}

private:
static Optional<innerty> fromNodeKindHelper(SILInstructionKind kind) {
switch (kind) {
#define APPLYSITE_INST(ID, PARENT) \
case SILInstructionKind::ID: \
return ApplySiteKind::ID;
#include "swift/SIL/SILNodes.def"
default:
return None;
}
}
};

/// An apply instruction.
class ApplySite {
SILInstruction *Inst;
Expand All @@ -7500,17 +7534,23 @@ class ApplySite {
}

static ApplySite isa(SILNode *node) {
switch (node->getKind()) {
case SILNodeKind::ApplyInst:
auto *i = dyn_cast<SILInstruction>(node);
if (!i)
return ApplySite();

auto kind = ApplySiteKind::fromNodeKind(i->getKind());
if (!kind)
return ApplySite();

switch (kind.getValue()) {
case ApplySiteKind::ApplyInst:
return ApplySite(cast<ApplyInst>(node));
case SILNodeKind::BeginApplyInst:
case ApplySiteKind::BeginApplyInst:
return ApplySite(cast<BeginApplyInst>(node));
case SILNodeKind::TryApplyInst:
case ApplySiteKind::TryApplyInst:
return ApplySite(cast<TryApplyInst>(node));
case SILNodeKind::PartialApplyInst:
case ApplySiteKind::PartialApplyInst:
return ApplySite(cast<PartialApplyInst>(node));
default:
return ApplySite();
}
}

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

#define FOREACH_IMPL_RETURN(OPERATION) do { \
switch (Inst->getKind()) { \
case SILInstructionKind::ApplyInst: \
return cast<ApplyInst>(Inst)->OPERATION; \
case SILInstructionKind::BeginApplyInst: \
return cast<BeginApplyInst>(Inst)->OPERATION; \
case SILInstructionKind::PartialApplyInst: \
return cast<PartialApplyInst>(Inst)->OPERATION; \
case SILInstructionKind::TryApplyInst: \
return cast<TryApplyInst>(Inst)->OPERATION; \
default: \
llvm_unreachable("not an apply instruction!"); \
} \
#define FOREACH_IMPL_RETURN(OPERATION) \
do { \
switch (ApplySiteKind(Inst->getKind())) { \
case ApplySiteKind::ApplyInst: \
return cast<ApplyInst>(Inst)->OPERATION; \
case ApplySiteKind::BeginApplyInst: \
return cast<BeginApplyInst>(Inst)->OPERATION; \
case ApplySiteKind::PartialApplyInst: \
return cast<PartialApplyInst>(Inst)->OPERATION; \
case ApplySiteKind::TryApplyInst: \
return cast<TryApplyInst>(Inst)->OPERATION; \
} \
} while (0)

/// Return the callee operand.
Expand Down Expand Up @@ -7670,12 +7709,12 @@ class ApplySite {
/// Return the callee's function argument index corresponding to the first
/// applied argument: 0 for full applies; >= 0 for partial applies.
unsigned getCalleeArgIndexOfFirstAppliedArg() const {
switch (Inst->getKind()) {
case SILInstructionKind::ApplyInst:
case SILInstructionKind::BeginApplyInst:
case SILInstructionKind::TryApplyInst:
switch (ApplySiteKind(Inst->getKind())) {
case ApplySiteKind::ApplyInst:
case ApplySiteKind::BeginApplyInst:
case ApplySiteKind::TryApplyInst:
return 0;
case SILInstructionKind::PartialApplyInst:
case ApplySiteKind::PartialApplyInst:
// The arguments to partial_apply are a suffix of the partial_apply's
// callee. Note that getSubstCalleeConv is function type of the callee
// argument passed to this apply, not necessarilly the function type of
Expand All @@ -7686,8 +7725,6 @@ class ApplySite {
// pa2 = partial_apply pa1(b) : $(a, b)
// apply pa2(a)
return getSubstCalleeConv().getNumSILArguments() - getNumArguments();
default:
llvm_unreachable("not implemented for this instruction!");
}
}

Expand All @@ -7711,72 +7748,72 @@ class ApplySite {

/// Return true if 'self' is an applied argument.
bool hasSelfArgument() const {
switch (Inst->getKind()) {
case SILInstructionKind::ApplyInst:
switch (ApplySiteKind(Inst->getKind())) {
case ApplySiteKind::ApplyInst:
return cast<ApplyInst>(Inst)->hasSelfArgument();
case SILInstructionKind::BeginApplyInst:
case ApplySiteKind::BeginApplyInst:
return cast<BeginApplyInst>(Inst)->hasSelfArgument();
case SILInstructionKind::TryApplyInst:
case ApplySiteKind::TryApplyInst:
return cast<TryApplyInst>(Inst)->hasSelfArgument();
default:
llvm_unreachable("not implemented for this instruction!");
case ApplySiteKind::PartialApplyInst:
llvm_unreachable("unhandled case");
}
}

/// Return the applied 'self' argument value.
SILValue getSelfArgument() const {
switch (Inst->getKind()) {
case SILInstructionKind::ApplyInst:
switch (ApplySiteKind(Inst->getKind())) {
case ApplySiteKind::ApplyInst:
return cast<ApplyInst>(Inst)->getSelfArgument();
case SILInstructionKind::BeginApplyInst:
case ApplySiteKind::BeginApplyInst:
return cast<BeginApplyInst>(Inst)->getSelfArgument();
case SILInstructionKind::TryApplyInst:
case ApplySiteKind::TryApplyInst:
return cast<TryApplyInst>(Inst)->getSelfArgument();
default:
llvm_unreachable("not implemented for this instruction!");
case ApplySiteKind::PartialApplyInst:
llvm_unreachable("unhandled case");
}
}

/// Return the 'self' apply operand.
Operand &getSelfArgumentOperand() {
switch (Inst->getKind()) {
case SILInstructionKind::ApplyInst:
switch (ApplySiteKind(Inst->getKind())) {
case ApplySiteKind::ApplyInst:
return cast<ApplyInst>(Inst)->getSelfArgumentOperand();
case SILInstructionKind::BeginApplyInst:
case ApplySiteKind::BeginApplyInst:
return cast<BeginApplyInst>(Inst)->getSelfArgumentOperand();
case SILInstructionKind::TryApplyInst:
case ApplySiteKind::TryApplyInst:
return cast<TryApplyInst>(Inst)->getSelfArgumentOperand();
default:
llvm_unreachable("not implemented for this instruction!");
case ApplySiteKind::PartialApplyInst:
llvm_unreachable("Unhandled cast");
}
}

/// Return a list of applied arguments without self.
OperandValueArrayRef getArgumentsWithoutSelf() const {
switch (Inst->getKind()) {
case SILInstructionKind::ApplyInst:
switch (ApplySiteKind(Inst->getKind())) {
case ApplySiteKind::ApplyInst:
return cast<ApplyInst>(Inst)->getArgumentsWithoutSelf();
case SILInstructionKind::BeginApplyInst:
case ApplySiteKind::BeginApplyInst:
return cast<BeginApplyInst>(Inst)->getArgumentsWithoutSelf();
case SILInstructionKind::TryApplyInst:
case ApplySiteKind::TryApplyInst:
return cast<TryApplyInst>(Inst)->getArgumentsWithoutSelf();
default:
llvm_unreachable("not implemented for this instruction!");
case ApplySiteKind::PartialApplyInst:
llvm_unreachable("Unhandled case");
}
}

/// Return whether the given apply is of a formally-throwing function
/// which is statically known not to throw.
bool isNonThrowing() const {
switch (getInstruction()->getKind()) {
case SILInstructionKind::ApplyInst:
switch (ApplySiteKind(getInstruction()->getKind())) {
case ApplySiteKind::ApplyInst:
return cast<ApplyInst>(Inst)->isNonThrowing();
case SILInstructionKind::BeginApplyInst:
case ApplySiteKind::BeginApplyInst:
return cast<BeginApplyInst>(Inst)->isNonThrowing();
case SILInstructionKind::TryApplyInst:
case ApplySiteKind::TryApplyInst:
return false;
default:
llvm_unreachable("not implemented for this instruction!");
case ApplySiteKind::PartialApplyInst:
llvm_unreachable("Unhandled case");
}
}

Expand All @@ -7792,10 +7829,41 @@ class ApplySite {
}

static bool classof(const SILInstruction *inst) {
return (inst->getKind() == SILInstructionKind::ApplyInst ||
inst->getKind() == SILInstructionKind::BeginApplyInst ||
inst->getKind() == SILInstructionKind::PartialApplyInst ||
inst->getKind() == SILInstructionKind::TryApplyInst);
return bool(ApplySiteKind::fromNodeKind(inst->getKind()));
}
};

struct FullApplySiteKind {
enum innerty : std::underlying_type<SILInstructionKind>::type {
#define FULLAPPLYSITE_INST(ID, PARENT) ID = unsigned(SILInstructionKind::ID),
#include "swift/SIL/SILNodes.def"
} value;

explicit FullApplySiteKind(SILInstructionKind kind) {
auto fullApplySiteKind = FullApplySiteKind::fromNodeKindHelper(kind);
assert(fullApplySiteKind && "SILNodeKind is not a FullApplySiteKind?!");
value = fullApplySiteKind.getValue();
}

FullApplySiteKind(innerty value) : value(value) {}
operator innerty() const { return value; }

static Optional<FullApplySiteKind> fromNodeKind(SILInstructionKind kind) {
if (auto innerOpt = FullApplySiteKind::fromNodeKindHelper(kind))
return FullApplySiteKind(*innerOpt);
return None;
}

private:
static Optional<innerty> fromNodeKindHelper(SILInstructionKind kind) {
switch (kind) {
#define FULLAPPLYSITE_INST(ID, PARENT) \
case SILInstructionKind::ID: \
return FullApplySiteKind::ID;
#include "swift/SIL/SILNodes.def"
default:
return None;
}
}
};

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

static FullApplySite isa(SILNode *node) {
switch (node->getKind()) {
case SILNodeKind::ApplyInst:
auto *i = dyn_cast<SILInstruction>(node);
if (!i)
return FullApplySite();
auto kind = FullApplySiteKind::fromNodeKind(i->getKind());
if (!kind)
return FullApplySite();
switch (kind.getValue()) {
case FullApplySiteKind::ApplyInst:
return FullApplySite(cast<ApplyInst>(node));
case SILNodeKind::BeginApplyInst:
case FullApplySiteKind::BeginApplyInst:
return FullApplySite(cast<BeginApplyInst>(node));
case SILNodeKind::TryApplyInst:
case FullApplySiteKind::TryApplyInst:
return FullApplySite(cast<TryApplyInst>(node));
default:
return FullApplySite();
}
}

Expand All @@ -7846,9 +7918,7 @@ class FullApplySite : public ApplySite {
}

static bool classof(const SILInstruction *inst) {
return (inst->getKind() == SILInstructionKind::ApplyInst ||
inst->getKind() == SILInstructionKind::BeginApplyInst ||
inst->getKind() == SILInstructionKind::TryApplyInst);
return bool(FullApplySiteKind::fromNodeKind(inst->getKind()));
}
};

Expand Down
Loading