From 7082dbb596e27b90e4fc44b3203b2860a86c3941 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Fri, 24 Jul 2020 17:13:10 -0700 Subject: [PATCH] [sil] Add an implementation of isIndirectResultOperand() onto ApplySite that returns false for partial_apply. Sometimes when working with the operands of an ApplySite, one needs to bail early if one has a full apply site and the operand is an indirect result argument. Sadly, there isn't any such API on ApplySite (it is only on FullApplySite), even though technically a partial_apply can be viewed as just not having any indirect result operands! That is what this patch implements. To implement this I added a simple useful method called: ``` Optional ApplySite::asFullApplySite() const ``` Seems like a useful thing to have for these sorts of cases. --- include/swift/SIL/ApplySite.h | 42 ++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/include/swift/SIL/ApplySite.h b/include/swift/SIL/ApplySite.h index de97fef3e9bf0..e11ca87b047b6 100644 --- a/include/swift/SIL/ApplySite.h +++ b/include/swift/SIL/ApplySite.h @@ -21,6 +21,7 @@ #ifndef SWIFT_SIL_APPLYSITE_H #define SWIFT_SIL_APPLYSITE_H +#include "swift/Basic/STLExtras.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBasicBlock.h" #include "swift/SIL/SILFunction.h" @@ -29,6 +30,8 @@ namespace swift { +class FullApplySite; + //===----------------------------------------------------------------------===// // ApplySite //===----------------------------------------------------------------------===// @@ -396,6 +399,10 @@ class ApplySite { llvm_unreachable("covered switch"); } + /// Returns true if \p op is an operand that passes an indirect + /// result argument to the apply site. + bool isIndirectResultOperand(const Operand &op) const; + /// Return whether the given apply is of a formally-throwing function /// which is statically known not to throw. bool isNonThrowing() const { @@ -425,6 +432,10 @@ class ApplySite { } void dump() const LLVM_ATTRIBUTE_USED { getInstruction()->dump(); } + + /// Attempt to cast this apply site to a full apply site, returning None on + /// failure. + Optional asFullApplySite() const; }; //===----------------------------------------------------------------------===// @@ -562,12 +573,6 @@ class FullApplySite : public ApplySite { return op.getOperandNumber() < getOperandIndexOfFirstArgument(); } - /// Returns true if \p op is an operand that passes an indirect - /// result argument to the apply site. - bool isIndirectResultOperand(const Operand &op) const { - return getCalleeArgIndex(op) < getNumIndirectSILResults(); - } - /// Is this an ApplySite that begins the evaluation of a coroutine. bool beginsCoroutineEvaluation() const { switch (getKind()) { @@ -637,6 +642,12 @@ class FullApplySite : public ApplySite { llvm_unreachable("covered switch isn't covered"); } + /// Returns true if \p op is an operand that passes an indirect + /// result argument to the apply site. + bool isIndirectResultOperand(const Operand &op) const { + return getCalleeArgIndex(op) < getNumIndirectSILResults(); + } + static FullApplySite getFromOpaqueValue(void *p) { return FullApplySite(p); } static bool classof(const SILInstruction *inst) { @@ -729,4 +740,23 @@ template <> struct DenseMapInfo<::swift::FullApplySite> { } // namespace llvm +//===----------------------------------------------------------------------===// +// Inline Definitions to work around Forward Declaration +//===----------------------------------------------------------------------===// + +namespace swift { + +inline Optional ApplySite::asFullApplySite() const { + return FullApplySite::isa(getInstruction()); +} + +inline bool ApplySite::isIndirectResultOperand(const Operand &op) const { + auto fas = asFullApplySite(); + if (!fas) + return false; + return fas->isIndirectResultOperand(op); +} + +} // namespace swift + #endif