Context: There are places in LLVM where we need to pack typed fields into opaque values.
For instance, the XXXInst classes in llvm/include/llvm/IR/Instructions.h that extract informations from Value::SubclassData via getSubclassDataFromInstruction().
The bit twiddling is done manually: this impairs readability and prevent consistent handling of out of range values (e.g. Instructions.h)
More importantly, the bit pattern is scattered throughout the implementation making it hard to pack additionnal fields or check for overlapping bits.
Design: The Bitfield structs are to be declared together so it is clear which bits are used or not.
The code is designed with simplicity in mind, hence a few limitations:
- Storage is limited to a single integer that cannot be bigger than uint64_t,
- Values and storage have to be unsigned or enum (enum class works), (edit: the new design allows signed integer but not signed enums)
- Is is not possible to store a full uint64_t at once i.e. Bitfield<uint64_t, 0, 64> will fail, (edit: the new design allows this)
- There are no automatic detection of overlapping fields (packed bitfield declaration should help though),
- The interface is C like so storage needs to be passed in every time (code is simpler and lifetime considerations more obvious)
Feedback welcome
Maybe it is worth to use std::numeric_limits<T>::digits here?
Like this:
then it will be possible to remove #include <climits> // CHAR_BIT