It is known that pointers have available bits, sometimes at both ends. Pointers to aligned storage have their least significant bits always zero (their number depends on alignment). Also, on some operating systems, it is guaranteed that some of the most significant bits are always zero.
Consequently std.bitmanip.bitfields should support pointers - an elegant way to keep client code high-level but also optimal in layout.
Since pointers have available bits at both ends, code with pointers should not do shifting; only masking. The client code chooses whether lower bits or upper bits are to be used.
Example 1: using two lower bits:
struct S {
mixin(bitfields!(
bool, "flag1", 1,
bool, "flag2", 1,
S*, "next", 62
));
}
In bitfields, layout is allocated from the LSB to MSB so flag1 and flag2 will occupy the two LSBs. The pointer will be masked when returned. When setting the pointer, an assert() verifies that the two LSBs are clear.
Example 2: using one lower bit and four upper bits:
struct S {
mixin(bitfields!(
bool, "flag1", 1,
S*, "next", 59,
uint, "color", 4
));
}
Documentation should specify that pointers manipulated that way may have impact on the GC. Because of that, it seems to me we can't @trust the respective functions.
Comment #1 by andrei — 2015-12-03T00:34:51Z
taggedPointer and taggedClassRef are separate implementations that should be integrated within bitfields and then undocummented.
Comment #2 by robert.schadek — 2024-12-01T16:25:31Z