Odin
Odin copied to clipboard
Allow #align for #packed structs
blah:: struct #packed #align 2 {
...
}
This should work, as per discussion on Discord. Currently "Syntax Error: '#align' cannot be applied with '#packed'"
With regards to allowing #align on a #packed struct, what should be the size of this data structure?
blah :: struct #packed #align 2 {x: [3]u8}
size_of(blah) == ???
Should the answer be 4 or error?
Why not 3?
@JesseRMeyer Because there is a rule in most programming languages that size_of(T) % align_of(T) == 0 . Making it 3 would break this rule.
I think we can rightfully question the applicability of that rule (read: convention) given the combination of these features. Adding a byte to the size is equivalent to adding a tail padding field, violating at least one sense of #packed.
However, I think most people would find any implicit behavior here, however logically consistent, to be surprising given the prevalence of the rule. In the spirit of 'minimal implicitness', emit an error with guidance from the compiler for the user to do it right up front.
From what you re saying, it ought to be an error.
In this particular case, yes.
This is probably dead but, this would actually be quite a useful feature for kernel development. Most notable example I can think of is for implementing a GDT
GDT_Entry :: struct #packed
{
limit0: u16,
base0: u16,
base1: u8,
accessByte: u8,
limitFlags: u8,
base2: u8,
}
GDT :: struct #packed #align 0x1000
{
null: GDT_Entry,
kernelCode: GDT_Entry,
kernelData: GDT_Entry,
userNull: GDT_Entry,
userCode: GDT_Entry,
userData: GDT_Entry,
}
This problem has now been solved with #field_align(N).
#field_align(N) will set the minimum alignment for each field to N or its natural alignment, whichever is larger.
Foo :: struct #field_align(4) {
x: u8, // offset == 0
y: u8, // offset == 4
z: u16, // offset == 8
w: u64, // offset = 16
}
@Hachem-H I wonder if this solves this usecase
GDT_Entry :: struct #packed {
limit0: u16,
base0: u16,
base1: u8,
accessByte: u8,
limitFlags: u8,
base2: u8,
}
GDT :: struct #align 0x1000 {
using _: struct #packed {
null: GDT_Entry,
kernelCode: GDT_Entry,
kernelData: GDT_Entry,
userNull: GDT_Entry,
userCode: GDT_Entry,
userData: GDT_Entry,
},
}
Also aren't GDT entries sized according to the CPU mode, i.e. 32-bit in protected and compat mode, and 64 bits in long mode?
@flysand7 Yes actually though its rather finicky but it certainly works thank you! and also yes you're correct it depends on the CPU mode I just tried to write a GDT entry off the top of my head if i'm being completely honest.