Needed because libc memory allocators don't provide old alignment and size which are required by Zig memory allocators.
const Header = packed struct(u64)
const Header = packed struct(u64) {
alignment: Alignment,
/// Does not include the extra alignment bytes added.
size: Size,
canary: Canary = magic,
comptime {
assert(@sizeOf(Header) <= alignment_bytes);
}
const safety = switch (builtin.mode) {
.debug, .safe => true,
.fast, .small => false,
};
const max_addr_bits = switch (safety) {
true => 48, // Ensures space for Canary bits.
false => 64,
};
const Size = @Int(.unsigned, @min(max_addr_bits, 64 - @bitSizeOf(Alignment), @bitSizeOf(usize)));
const Canary = @Int(.unsigned, 64 - @bitSizeOf(Alignment) - @bitSizeOf(Size));
const magic: Canary = switch (safety) {
true => @truncate(@as(u64, 0x76fa65bebb3d7a39)), // statically chosen entropy
false => 0,
};
fn get(base: [*]align(alignment_bytes) u8) Header {
const header: *Header = @ptrCast(base - @sizeOf(Header));
assert(header.canary == magic);
return header.*;
}
fn set(base: [*]align(alignment_bytes) u8, a: Alignment, size: Size) [*]align(alignment_bytes) u8 {
const header: *Header = @ptrCast(base - @sizeOf(Header));
header.* = .{ .alignment = a, .size = size };
return base;
}
}