//===--- TerminatorUtils.h ------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// /// /// \file /// /// ADTs for working with various forms of terminators. /// //===----------------------------------------------------------------------===// #ifndef SWIFT_SIL_TERMINATORUTILS_H #define SWIFT_SIL_TERMINATORUTILS_H #include "swift/Basic/LLVM.h" #include "swift/SIL/SILInstruction.h" #include "llvm/ADT/PointerUnion.h" namespace swift { /// An ADT for writing generic code against SwitchEnumAddrInst and /// SwitchEnumInst. /// /// We use this instead of SwitchEnumInstBase for this purpose in order to avoid /// the need for templating SwitchEnumInstBase from causing this ADT type of /// usage to require templates. class SwitchEnumTermInst { PointerUnion value; public: SwitchEnumTermInst(SwitchEnumAddrInst *seai) : value(seai) {} SwitchEnumTermInst(SwitchEnumInst *seai) : value(seai) {} SwitchEnumTermInst(SILInstruction *i) : value(nullptr) { if (auto *seai = dyn_cast(i)) { value = seai; return; } if (auto *sei = dyn_cast(i)) { value = sei; return; } } SwitchEnumTermInst(const SILInstruction *i) : SwitchEnumTermInst(const_cast(i)) {} operator TermInst *() const { if (auto *seai = value.dyn_cast()) return seai; return cast(value); } TermInst *operator*() const { if (auto *seai = value.dyn_cast()) return seai; return cast(value); } TermInst *operator->() const { if (auto *seai = value.dyn_cast()) return seai; return cast(value); } operator bool() const { return bool(value); } SILValue getOperand() { if (auto *sei = value.dyn_cast()) return sei->getOperand(); return cast(value)->getOperand(); } unsigned getNumCases() { if (auto *sei = value.dyn_cast()) return sei->getNumCases(); return cast(value)->getNumCases(); } std::pair getCase(unsigned i) const { if (auto *sei = value.dyn_cast()) return sei->getCase(i); return cast(value)->getCase(i); } SILBasicBlock *getCaseDestination(EnumElementDecl *decl) const { if (auto *sei = value.dyn_cast()) return sei->getCaseDestination(decl); return cast(value)->getCaseDestination(decl); } ProfileCounter getCaseCount(unsigned i) const { if (auto *sei = value.dyn_cast()) return sei->getCaseCount(i); return cast(value)->getCaseCount(i); } ProfileCounter getDefaultCount() const { if (auto *sei = value.dyn_cast()) return sei->getDefaultCount(); return cast(value)->getDefaultCount(); } bool hasDefault() const { if (auto *sei = value.dyn_cast()) return sei->hasDefault(); return cast(value)->hasDefault(); } SILBasicBlock *getDefaultBB() const { if (auto *sei = value.dyn_cast()) return sei->getDefaultBB(); return cast(value)->getDefaultBB(); } NullablePtr getDefaultBBOrNull() const { if (auto *sei = value.dyn_cast()) return sei->getDefaultBBOrNull(); return cast(value)->getDefaultBBOrNull(); } /// If the default refers to exactly one case decl, return it. NullablePtr getUniqueCaseForDefault() const { if (auto *sei = value.dyn_cast()) return sei->getUniqueCaseForDefault(); return cast(value)->getUniqueCaseForDefault(); } /// If the given block only has one enum element decl matched to it, /// return it. NullablePtr getUniqueCaseForDestination(SILBasicBlock *BB) const { if (auto *sei = value.dyn_cast()) return sei->getUniqueCaseForDestination(BB); return cast(value)->getUniqueCaseForDestination(BB); } }; } // namespace swift #endif