blob: b41ae018d4edf6766d4bd4d6078ef190aee48074 [file] [log] [blame]
//===--- 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