mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
190 lines
6.9 KiB
C++
190 lines
6.9 KiB
C++
//===--- 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 { NumberOf##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 : NumberOf##U##Bits, __VA_ARGS__; \
|
|
uint64_t : 64 - (NumberOf##U##Bits + (HC) + (C)); /* Better code gen */ \
|
|
} T; \
|
|
LLVM_PACKED_END \
|
|
enum { NumberOf##T##Bits = NumberOf##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 - (NumberOf##U##Bits + (C)) }; \
|
|
uint64_t : NumberOf##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 - (NumberOf##U##Bits + (C)) }; \
|
|
uint64_t : NumberOf##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 { NumberOf##T##Bits = NumberOf##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
|