| //===--- InlineBitfield.h - Inline bitfield macros --------------*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2017 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 file provides macros to simplify inline/intrusive bitfield logic. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_INLINE_BITFIELD_H |
| #define SWIFT_INLINE_BITFIELD_H |
| |
| #include "llvm/Support/Compiler.h" |
| #include <cstdint> |
| |
| // Boilerplate namespace in case we add non-macros. |
| namespace swift { |
| |
| /// NOTE: When passing the bit count to these macros, please do NOT precompute |
| /// the total. Instead, sum the bit counts in field order. This makes visually |
| /// verifying that all the fields are accounted for easier. For example: |
| /// SWIFT_INLINE_BITFIELD(Foo, Bar, 1+3+7+2, w:1, x:3, y:7, z:2); |
| |
| /// Define a base bitfield for type 'T' with 'C' bits used. |
| /// |
| /// Please note that the 'base' type does not need to be the root class in a |
| /// hierarchy. If a superclass bitfield is full, then a subclass can start a new |
| /// bitfield union for its subclasses to use. |
| #define SWIFT_INLINE_BITFIELD_BASE(T, C, ...) \ |
| LLVM_PACKED_START \ |
| class T##Bitfield { \ |
| friend class T; \ |
| uint64_t __VA_ARGS__; \ |
| uint64_t : 64 - (C); /* Better code gen */ \ |
| } T; \ |
| LLVM_PACKED_END \ |
| enum { Num##T##Bits = (C) }; \ |
| static_assert(sizeof(T##Bitfield) <= 8, "Bitfield overflow") |
| |
| /// Define an bitfield for type 'T' with parent class 'U' and 'C' bits used. |
| #define SWIFT_INLINE_BITFIELD_TEMPLATE(T, U, C, HC, ...) \ |
| LLVM_PACKED_START \ |
| class T##Bitfield { \ |
| friend class T; \ |
| uint64_t : Num##U##Bits, __VA_ARGS__; \ |
| uint64_t : 64 - (Num##U##Bits + (HC) + (C)); /* Better code gen */ \ |
| } T; \ |
| LLVM_PACKED_END \ |
| enum { Num##T##Bits = Num##U##Bits + (C) }; \ |
| static_assert(sizeof(T##Bitfield) <= 8, "Bitfield overflow") |
| |
| #define SWIFT_INLINE_BITFIELD(T, U, C, ...) \ |
| SWIFT_INLINE_BITFIELD_TEMPLATE(T, U, C, 0, __VA_ARGS__) |
| |
| /// Define a full bitfield for type 'T' that uses all of the remaining bits in |
| /// the inline bitfield. |
| /// |
| /// For optimal code gen, place naturally sized fields at the end, with the |
| /// largest naturally sized field at the very end. For example: |
| /// |
| /// SWIFT_INLINE_BITFIELD_FULL(Foo, Bar, 1+8+16, |
| /// flag : 1, |
| /// : NumPadBits, // pad the center, not the end |
| /// x : 8, |
| /// y : 16 |
| /// ); |
| #define SWIFT_INLINE_BITFIELD_FULL(T, U, C, ...) \ |
| LLVM_PACKED_START \ |
| class T##Bitfield { \ |
| friend class T; \ |
| enum { NumPadBits = 64 - (Num##U##Bits + (C)) }; \ |
| uint64_t : Num##U##Bits, __VA_ARGS__; \ |
| } T; \ |
| LLVM_PACKED_END \ |
| static_assert(sizeof(T##Bitfield) <= 8, "Bitfield overflow") |
| |
| /// Define a full bitfield for type 'T' that uses all of the remaining bits in |
| /// the inline bitfield. We allow for 'T' to have a single generic parameter. |
| /// |
| /// For optimal code gen, place naturally sized fields at the end, with the |
| /// largest naturally sized field at the very end. For example: |
| /// |
| /// SWIFT_INLINE_BITFIELD_FULL(Foo, Bar, 1+8+16, |
| /// flag : 1, |
| /// : NumPadBits, // pad the center, not the end |
| /// x : 8, |
| /// y : 16 |
| /// ); |
| /// |
| /// NOTE: All instances of Foo will access via the same bitfield entry even if |
| /// they differ in the templated value! |
| #define SWIFT_INLINE_BITFIELD_FULL_TEMPLATE(T, U, C, ...) \ |
| LLVM_PACKED_START \ |
| class T##Bitfield { \ |
| template <typename TTy> \ |
| friend class T; \ |
| enum { NumPadBits = 64 - (Num##U##Bits + (C)) }; \ |
| uint64_t : Num##U##Bits, __VA_ARGS__; \ |
| } T; \ |
| LLVM_PACKED_END \ |
| static_assert(sizeof(T##Bitfield) <= 8, "Bitfield overflow") |
| |
| /// Define an empty bitfield for type 'T'. |
| #define SWIFT_INLINE_BITFIELD_EMPTY(T, U) \ |
| enum { Num##T##Bits = Num##U##Bits } |
| |
| // XXX/HACK: templated max() doesn't seem to work in a bitfield size context. |
| constexpr unsigned bitmax(unsigned a, unsigned b) { |
| return a > b ? a : b; |
| } |
| |
| constexpr unsigned countBitsUsed(uint64_t arg) { |
| // Is there a C++ "std::countLeadingZeros()"? |
| return (arg & 1ull << 63 ? 63 : |
| arg & 1ull << 62 ? 62 : |
| arg & 1ull << 61 ? 61 : |
| arg & 1ull << 60 ? 60 : |
| arg & 1ull << 59 ? 59 : |
| arg & 1ull << 58 ? 58 : |
| arg & 1ull << 57 ? 57 : |
| arg & 1ull << 56 ? 56 : |
| arg & 1ull << 55 ? 55 : |
| arg & 1ull << 54 ? 54 : |
| arg & 1ull << 53 ? 53 : |
| arg & 1ull << 52 ? 52 : |
| arg & 1ull << 51 ? 51 : |
| arg & 1ull << 50 ? 50 : |
| arg & 1ull << 49 ? 49 : |
| arg & 1ull << 48 ? 48 : |
| arg & 1ull << 47 ? 47 : |
| arg & 1ull << 46 ? 46 : |
| arg & 1ull << 45 ? 45 : |
| arg & 1ull << 44 ? 44 : |
| arg & 1ull << 43 ? 43 : |
| arg & 1ull << 42 ? 42 : |
| arg & 1ull << 41 ? 41 : |
| arg & 1ull << 40 ? 40 : |
| arg & 1ull << 39 ? 39 : |
| arg & 1ull << 38 ? 38 : |
| arg & 1ull << 37 ? 37 : |
| arg & 1ull << 36 ? 36 : |
| arg & 1ull << 35 ? 35 : |
| arg & 1ull << 34 ? 34 : |
| arg & 1ull << 33 ? 33 : |
| arg & 1ull << 32 ? 32 : |
| arg & 1ull << 31 ? 31 : |
| arg & 1ull << 30 ? 30 : |
| arg & 1ull << 29 ? 29 : |
| arg & 1ull << 28 ? 28 : |
| arg & 1ull << 27 ? 27 : |
| arg & 1ull << 26 ? 26 : |
| arg & 1ull << 25 ? 25 : |
| arg & 1ull << 24 ? 24 : |
| arg & 1ull << 23 ? 23 : |
| arg & 1ull << 22 ? 22 : |
| arg & 1ull << 21 ? 21 : |
| arg & 1ull << 20 ? 20 : |
| arg & 1ull << 19 ? 19 : |
| arg & 1ull << 18 ? 18 : |
| arg & 1ull << 17 ? 17 : |
| arg & 1ull << 16 ? 16 : |
| arg & 1ull << 15 ? 15 : |
| arg & 1ull << 14 ? 14 : |
| arg & 1ull << 13 ? 13 : |
| arg & 1ull << 12 ? 12 : |
| arg & 1ull << 11 ? 11 : |
| arg & 1ull << 10 ? 10 : |
| arg & 1ull << 9 ? 9 : |
| arg & 1ull << 8 ? 8 : |
| arg & 1ull << 7 ? 7 : |
| arg & 1ull << 6 ? 6 : |
| arg & 1ull << 5 ? 5 : |
| arg & 1ull << 4 ? 4 : |
| arg & 1ull << 3 ? 3 : |
| arg & 1ull << 2 ? 2 : |
| arg & 1ull << 1 ? 1 : 0 |
| ) + 1; |
| } |
| |
| } // end namespace swift |
| |
| #endif // SWIFT_INLINE_BITFIELD_H |