Seems like my “hacky solution” is quite ok.
I tested my solution in godbolt to see the generated code.
Since zig doesn’t handle alignment over the minimum page size we can use std.mem.page_size
as the maximum alignment.
// The Zig Allocator interface is not intended to solve alignments beyond
// the minimum OS page size. For these use cases, the caller must use OS
// APIs directly.
code (godbolt test)
export fn alignedAlloc(alignment: u32) usize {
const Log2PageSizeType = std.math.IntFittingRange(0, std.math.log2(std.mem.page_size));
const aligned: Log2PageSizeType = @intCast(std.math.log2(alignment));
var b: usize = 0;
switch (aligned) {
inline else => |a| {
b = 1 << a;
},
}
return b;
}
generated assembly
alignedAlloc:
lzcnt eax, edi
and eax, 15
xor eax, 7
mov rax, qword ptr [8*rax + .Lswitch.table.alignedAlloc]
ret
.Lswitch.table.alignedAlloc:
.quad 256
.quad 512
.quad 1024
.quad 2048
.quad 4096
.quad 8192
.quad 16384
.quad 32768
.quad 1
.quad 2
.quad 4
.quad 8
.quad 16
.quad 32
.quad 64
.quad 128
So the solution could look something like this:
pub fn alignedFree(allocator: Allocator, alignment: u29, memory: []u8) void {
const Log2PageSizeType = std.math.IntFittingRange(0, std.math.log2(std.mem.page_size));
const aligned: Log2PageSizeType = @intCast(std.math.log2(alignment));
assert(std.mem.isValidAlign(alignment));
assert(alignment <= std.mem.page_size);
switch (aligned) {
inline else => |a| {
allocator.free(@as([]align(@as(usize, 1) << a) u8, @alignCast(memory)));
},
}
}
pub fn alignedAlloc(T: type, allocator: Allocator, alignment: u29, n: usize) ![]u8 {
const Log2PageSizeType = std.math.IntFittingRange(0, std.math.log2(std.mem.page_size));
const aligned: Log2PageSizeType = @intCast(std.math.log2(alignment));
assert(std.mem.isValidAlign(alignment));
switch (aligned) {
inline else => |a| {
if (builtin.mode == .Debug or builtin.mode == .ReleaseSafe) {
if ((1 << a) <= std.mem.page_size) {
return try allocator.alignedAlloc(T, 1 << a, n);
}
panic("Alignment to big, maximum alignment is: {}.", .{std.mem.page_size});
} else {
return try allocator.alignedAlloc(T, 1 << a, n);
}
},
}
}
Thanks for all the input, appriciate it!