4040#include " swift/Strings.h"
4141#include " llvm/ADT/APFloat.h"
4242#include " llvm/ADT/APInt.h"
43+ #include " llvm/ADT/SmallPtrSet.h"
4344#include " llvm/ADT/ilist.h"
4445#include " llvm/ADT/ilist_node.h"
4546#include " llvm/Support/TrailingObjects.h"
@@ -7318,6 +7319,20 @@ class TermInst : public NonValueInstruction {
73187319 }
73197320};
73207321
7322+ class OwnershipForwardingTermInst : public TermInst {
7323+ ValueOwnershipKind ownershipKind;
7324+
7325+ protected:
7326+ OwnershipForwardingTermInst (SILInstructionKind kind,
7327+ SILDebugLocation debugLoc,
7328+ ValueOwnershipKind ownershipKind)
7329+ : TermInst(kind, debugLoc), ownershipKind(ownershipKind) {}
7330+
7331+ public:
7332+ ValueOwnershipKind getOwnershipKind () const { return ownershipKind; }
7333+ void setOwnershipKind (ValueOwnershipKind newKind) { ownershipKind = newKind; }
7334+ };
7335+
73217336// / UnreachableInst - Position in the code which would be undefined to reach.
73227337// / These are always implicitly generated, e.g. when falling off the end of a
73237338// / function or after a no-return function call.
@@ -7806,9 +7821,9 @@ class SwitchValueInst final
78067821 }
78077822};
78087823
7809- // / Common implementation for the switch_enum and
7810- // / switch_enum_addr instructions.
7811- class SwitchEnumInstBase : public TermInst {
7824+ // / Common implementation for the switch_enum and switch_enum_addr instructions.
7825+ template < typename BaseTy>
7826+ class SwitchEnumInstBase : public BaseTy {
78127827 FixedOperandList<1 > Operands;
78137828
78147829 // Tail-allocated after the SwitchEnumInst record are:
@@ -7837,48 +7852,97 @@ class SwitchEnumInstBase : public TermInst {
78377852 }
78387853
78397854protected:
7855+ template <typename ... Rest>
78407856 SwitchEnumInstBase (
78417857 SILInstructionKind Kind, SILDebugLocation DebugLoc, SILValue Operand,
78427858 SILBasicBlock *DefaultBB,
78437859 ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
7844- Optional<ArrayRef<ProfileCounter>> Counts, ProfileCounter DefaultCount);
7860+ Optional<ArrayRef<ProfileCounter>> Counts, ProfileCounter DefaultCount,
7861+ Rest &&... rest)
7862+ : BaseTy(Kind, DebugLoc, std::forward<Rest>(rest)...),
7863+ Operands (this , Operand) {
7864+ SILInstruction::Bits.SEIBase .HasDefault = bool (DefaultBB);
7865+ SILInstruction::Bits.SEIBase .NumCases = CaseBBs.size ();
7866+ // Initialize the case and successor arrays.
7867+ auto *cases = getCaseBuf ();
7868+ auto *succs = getSuccessorBuf ();
7869+ for (unsigned i = 0 , size = CaseBBs.size (); i < size; ++i) {
7870+ cases[i] = CaseBBs[i].first ;
7871+ if (Counts) {
7872+ ::new (succs + i)
7873+ SILSuccessor (this , CaseBBs[i].second , Counts.getValue ()[i]);
7874+ } else {
7875+ ::new (succs + i) SILSuccessor (this , CaseBBs[i].second );
7876+ }
7877+ }
7878+
7879+ if (hasDefault ()) {
7880+ ::new (succs + getNumCases ()) SILSuccessor (this , DefaultBB, DefaultCount);
7881+ }
7882+ }
78457883
7846- template <typename SWITCH_ENUM_INST>
7884+ template <typename SWITCH_ENUM_INST, typename ... RestTys >
78477885 static SWITCH_ENUM_INST *createSwitchEnum (
78487886 SILDebugLocation DebugLoc, SILValue Operand, SILBasicBlock *DefaultBB,
78497887 ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
78507888 SILFunction &F, Optional<ArrayRef<ProfileCounter>> Counts,
7851- ProfileCounter DefaultCount);
7889+ ProfileCounter DefaultCount, RestTys &&... restArgs );
78527890
78537891public:
78547892 // / Clean up tail-allocated successor records for the switch cases.
7855- ~SwitchEnumInstBase ();
7893+ ~SwitchEnumInstBase () {
7894+ // Destroy the successor records to keep the CFG up to date.
7895+ auto *succs = getSuccessorBuf ();
7896+ for (unsigned i = 0 , end = getNumCases () + hasDefault (); i < end; ++i) {
7897+ succs[i].~SILSuccessor ();
7898+ }
7899+ }
78567900
78577901 SILValue getOperand () const { return Operands[0 ].get (); }
78587902
78597903 ArrayRef<Operand> getAllOperands () const { return Operands.asArray (); }
78607904 MutableArrayRef<Operand> getAllOperands () { return Operands.asArray (); }
78617905
7862- SuccessorListTy getSuccessors () {
7906+ TermInst:: SuccessorListTy getSuccessors () {
78637907 return MutableArrayRef<SILSuccessor>{getSuccessorBuf (),
78647908 static_cast <size_t >(getNumCases () + hasDefault ())};
78657909 }
78667910
7867- unsigned getNumCases () const {
7868- return SILInstruction::Bits.SwitchEnumInstBase .NumCases ;
7869- }
7911+ unsigned getNumCases () const { return SILInstruction::Bits.SEIBase .NumCases ; }
7912+
78707913 std::pair<EnumElementDecl*, SILBasicBlock*>
78717914 getCase (unsigned i) const {
78727915 assert (i < getNumCases () && " case out of bounds" );
78737916 return {getCaseBuf ()[i], getSuccessorBuf ()[i].getBB ()};
78747917 }
7918+
78757919 ProfileCounter getCaseCount (unsigned i) const {
78767920 assert (i < getNumCases () && " case out of bounds" );
78777921 return getSuccessorBuf ()[i].getCount ();
78787922 }
78797923
78807924 // Swap the cases at indices \p i and \p j.
7881- void swapCase (unsigned i, unsigned j);
7925+ void swapCase (unsigned i, unsigned j) {
7926+ assert (i < getNumCases () && " First index is out of bounds?!" );
7927+ assert (j < getNumCases () && " Second index is out of bounds?!" );
7928+
7929+ auto *succs = getSuccessorBuf ();
7930+
7931+ // First grab our destination blocks.
7932+ SILBasicBlock *iBlock = succs[i].getBB ();
7933+ SILBasicBlock *jBlock = succs[j].getBB ();
7934+
7935+ // Then destroy the sil successors and reinitialize them with the new things
7936+ // that they are pointing at.
7937+ succs[i].~SILSuccessor ();
7938+ ::new (succs + i) SILSuccessor (this , jBlock);
7939+ succs[j].~SILSuccessor ();
7940+ ::new (succs + j) SILSuccessor (this , iBlock);
7941+
7942+ // Now swap our cases.
7943+ auto *cases = getCaseBuf ();
7944+ std::swap (cases[i], cases[j]);
7945+ }
78827946
78837947 // / Return the block that will be branched to on the specified enum
78847948 // / case.
@@ -7893,22 +7957,69 @@ class SwitchEnumInstBase : public TermInst {
78937957 }
78947958
78957959 // / If the default refers to exactly one case decl, return it.
7896- NullablePtr<EnumElementDecl> getUniqueCaseForDefault ();
7960+ NullablePtr<EnumElementDecl> getUniqueCaseForDefault () {
7961+ auto enumValue = getOperand ();
7962+ SILType enumType = enumValue->getType ();
7963+
7964+ auto *f = SILInstruction::getFunction ();
7965+ if (!enumType.isEffectivelyExhaustiveEnumType (f))
7966+ return nullptr ;
7967+
7968+ EnumDecl *decl = enumType.getEnumOrBoundGenericEnum ();
7969+ assert (decl && " switch_enum operand is not an enum" );
7970+
7971+ SmallPtrSet<EnumElementDecl *, 4 > unswitchedElts;
7972+ for (auto elt : decl->getAllElements ())
7973+ unswitchedElts.insert (elt);
7974+
7975+ for (unsigned i = 0 , e = getNumCases (); i != e; ++i) {
7976+ auto Entry = getCase (i);
7977+ unswitchedElts.erase (Entry.first );
7978+ }
7979+
7980+ if (unswitchedElts.size () == 1 )
7981+ return *unswitchedElts.begin ();
7982+
7983+ return nullptr ;
7984+ }
78977985
78987986 // / If the given block only has one enum element decl matched to it,
78997987 // / return it.
7900- NullablePtr<EnumElementDecl> getUniqueCaseForDestination (SILBasicBlock *BB);
7901-
7902- bool hasDefault () const {
7903- return SILInstruction::Bits.SwitchEnumInstBase .HasDefault ;
7988+ NullablePtr<EnumElementDecl>
7989+ getUniqueCaseForDestination (SILBasicBlock *block) {
7990+ SILValue value = getOperand ();
7991+ SILType enumType = value->getType ();
7992+ EnumDecl *decl = enumType.getEnumOrBoundGenericEnum ();
7993+ assert (decl && " switch_enum operand is not an enum" );
7994+ (void )decl;
7995+
7996+ EnumElementDecl *eltDecl = nullptr ;
7997+ for (unsigned i : range (getNumCases ())) {
7998+ auto entry = getCase (i);
7999+ if (entry.second == block) {
8000+ if (eltDecl != nullptr )
8001+ return nullptr ;
8002+ eltDecl = entry.first ;
8003+ }
8004+ }
8005+ if (!eltDecl && hasDefault () && getDefaultBB () == block) {
8006+ return getUniqueCaseForDefault ();
8007+ }
8008+ return eltDecl;
79048009 }
79058010
8011+ bool hasDefault () const { return SILInstruction::Bits.SEIBase .HasDefault ; }
8012+
79068013 SILBasicBlock *getDefaultBB () const {
79078014 assert (hasDefault () && " doesn't have a default" );
79088015 return getSuccessorBuf ()[getNumCases ()];
79098016 }
79108017
7911- NullablePtr<SILBasicBlock> getDefaultBBOrNull () const ;
8018+ NullablePtr<SILBasicBlock> getDefaultBBOrNull () const {
8019+ if (!hasDefault ())
8020+ return nullptr ;
8021+ return getDefaultBB ();
8022+ }
79128023
79138024 ProfileCounter getDefaultCount () const {
79148025 assert (hasDefault () && " doesn't have a default" );
@@ -7925,7 +8036,7 @@ class SwitchEnumInstBase : public TermInst {
79258036// / passed into the corresponding destination block as an argument.
79268037class SwitchEnumInst
79278038 : public InstructionBase<SILInstructionKind::SwitchEnumInst,
7928- SwitchEnumInstBase> {
8039+ SwitchEnumInstBase<OwnershipForwardingTermInst> > {
79298040 friend SILBuilder;
79308041
79318042private:
@@ -7937,7 +8048,7 @@ class SwitchEnumInst
79378048 Optional<ArrayRef<ProfileCounter>> CaseCounts,
79388049 ProfileCounter DefaultCount)
79398050 : InstructionBase(DebugLoc, Operand, DefaultBB, CaseBBs, CaseCounts,
7940- DefaultCount) {}
8051+ DefaultCount, Operand.getOwnershipKind() ) {}
79418052 static SwitchEnumInst *
79428053 create (SILDebugLocation DebugLoc, SILValue Operand, SILBasicBlock *DefaultBB,
79438054 ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
@@ -7948,7 +8059,7 @@ class SwitchEnumInst
79488059// / A switch on an enum's discriminator in memory.
79498060class SwitchEnumAddrInst
79508061 : public InstructionBase<SILInstructionKind::SwitchEnumAddrInst,
7951- SwitchEnumInstBase> {
8062+ SwitchEnumInstBase<TermInst> > {
79528063 friend SILBuilder;
79538064
79548065private:
0 commit comments