//===--- InvertibleProtocols.h - invertible protocol meta ---*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2024 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 // //===----------------------------------------------------------------------===// // // This header declares various types for invertible protocols, such as // Copyable. // //===----------------------------------------------------------------------===// #ifndef SWIFT_ABI_INVERTIBLEPROTOCOLS_H #define SWIFT_ABI_INVERTIBLEPROTOCOLS_H #include #include #include namespace swift { /// Describes an "invertible" protocol, such as Copyable, which is assumed to /// hold for all types unless explicitly indicated otherwise. enum class InvertibleProtocolKind : uint8_t { #define INVERTIBLE_PROTOCOL(Name, Bit) Name = Bit, #include "swift/ABI/InvertibleProtocols.def" }; /// A set of invertible protocols, whose bits correspond to the cases of /// InvertibleProtocolKind. class InvertibleProtocolSet { using StorageType = uint16_t; /// The stored bits. StorageType bits; /// Retrieve the mask for this bit. static StorageType getMask(InvertibleProtocolKind kind) { return 1 << static_cast(kind); } public: explicit constexpr InvertibleProtocolSet(StorageType bits) : bits(bits) {} constexpr InvertibleProtocolSet() : bits(0) {} InvertibleProtocolSet( std::initializer_list elements ) : bits(0) { for (auto element : elements) insert(element); } /// Retrieve the raw bits that describe this set. StorageType rawBits() const { return bits; } /// Whether the set contains no protocols. bool empty() const { return bits == 0; } /// Check whether the set contains the specific invertible protocol. bool contains(InvertibleProtocolKind kind) const { return bits & getMask(kind); } /// Insert the invertible protocol into the set. void insert(InvertibleProtocolKind kind) { bits = bits | getMask(kind); } /// Insert all of the invertible protocols from the other set into this /// one. void insertAll(InvertibleProtocolSet other) { bits |= other.bits; } /// Remove the given invertible protocol from the set. void remove(InvertibleProtocolKind kind) { uint16_t mask = getMask(kind); bits = bits & ~mask; } /// Clear out all of the protocols from the set. void clear() { bits = 0; } #define INVERTIBLE_PROTOCOL(Name, Bit) \ bool contains##Name() const { \ return contains(InvertibleProtocolKind::Name); \ } #include "swift/ABI/InvertibleProtocols.def" /// Produce a invertible protocol set containing all known invertible /// protocols. static InvertibleProtocolSet allKnown() { InvertibleProtocolSet result; #define INVERTIBLE_PROTOCOL(Name, Bit) \ result.insert(InvertibleProtocolKind::Name); #include "swift/ABI/InvertibleProtocols.def" return result; } /// Determine whether this protocol set contains any unknown protocols. /// /// This can occur when an older Swift runtime is working with metadata /// or mangled names generated by a newer compiler that has introduced /// another kind of invertible protocol. The Swift runtime will need to /// step lightly around protocol sets with unknown protocols. bool hasUnknownProtocols() const { return !(*this - allKnown()).empty(); } class iterator { /// The bits remaining in the set, which will be 0 when we have hit the /// end. unsigned bitsRemaining; /// The current bit index unsigned currentBitIndex; /// Advance to the next set bit. void advance() { // Already at the end. if (bitsRemaining == 0) return; do { ++currentBitIndex; unsigned mask = 1 << currentBitIndex; if ((bitsRemaining & mask) != 0) break; } while (true); } /// Clear out the current bit, then advance. void clearAndAdvance() { // Clear the current bit. unsigned mask = 1 << currentBitIndex; bitsRemaining = bitsRemaining & ~mask; // Advance to the next set bit, or stop if we're done. advance(); } public: using difference_type = int; using value_type = InvertibleProtocolKind; using pointer = void; using reference = value_type; using iterator_category = std::input_iterator_tag; iterator() : bitsRemaining(0), currentBitIndex(0) { } iterator(unsigned bitsRemaining) : bitsRemaining(bitsRemaining), currentBitIndex(0) { if ((bitsRemaining & 0x01) == 0) advance(); } iterator &operator++() { clearAndAdvance(); return *this; } iterator operator++(int) { iterator tmp = *this; ++(*this); return tmp; } InvertibleProtocolKind operator*() const { return static_cast(currentBitIndex); } friend bool operator ==(iterator lhs, iterator rhs) { if (lhs.bitsRemaining != rhs.bitsRemaining) return false; if (lhs.bitsRemaining == 0) return true; return lhs.currentBitIndex == rhs.currentBitIndex; } friend bool operator !=(iterator lhs, iterator rhs) { return !(lhs == rhs); } }; iterator begin() const { return iterator(rawBits()); } iterator end() const { return iterator(0); } friend bool operator==( InvertibleProtocolSet lhs, InvertibleProtocolSet rhs) { return lhs.bits == rhs.bits; } friend bool operator!=( InvertibleProtocolSet lhs, InvertibleProtocolSet rhs) { return lhs.bits != rhs.bits; } friend InvertibleProtocolSet operator-( InvertibleProtocolSet lhs, InvertibleProtocolSet rhs) { return InvertibleProtocolSet(lhs.bits & ~rhs.bits); } InvertibleProtocolSet &operator-=(InvertibleProtocolSet rhs) { bits = bits & ~rhs.bits; return *this; } friend InvertibleProtocolSet operator|( InvertibleProtocolSet lhs, InvertibleProtocolSet rhs) { return InvertibleProtocolSet(lhs.bits | rhs.bits); } InvertibleProtocolSet &operator|=(InvertibleProtocolSet rhs) { bits |= rhs.bits; return *this; } }; /// Retrieve the name for the given invertible protocol. static inline const char * getInvertibleProtocolKindName(InvertibleProtocolKind kind) { switch (kind) { #define INVERTIBLE_PROTOCOL(Name, Bit) \ case InvertibleProtocolKind::Name: return #Name; #include "swift/ABI/InvertibleProtocols.def" } return ""; } } // end namespace swift #endif // SWIFT_ABI_INVERTIBLEPROTOCOLS_H