- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
codegen/llvm: fix wrong field offset in packed structs #16657
Conversation
TODO:
|
c1bc6fc
to
e444e49
Compare
https://ziglang.org/documentation/0.11.0/#packed-struct explains that a pointer to byte aligned field is always promoted to a simple "classic" pointer. var a:u4 = 0;
var b:packed struct { x:u4} = .{.x=0};
std.debug.print("{} {}\n", .{@TypeOf(&a), @TypeOf(&b.x)});
a -> *u4
b -> *align(1:0:1) u4 so I tried to reflect that in the code for pointer/offsets computations. note: the llvmir generated seem correct:
but the machine code that llvm generates from this doesn't apply a 0x0F mask, and the test fails: mov al, BYTE PTR [rip+0x92ef3]
sub al, 0x2
jne 0x2245b0 |
Out of curiosity (I don't have an actual use-case affecting me with that bug...) I investigated a bit further.
(* currently, when using non-byte sized int types, it works because the adjacent extra bits are stomped with zeros https://godbolt.org/z/rq1dWh65s - which should not be done in a packed struct) But then. at least the two last points seem problematic even outside of packed struct. maybe volatile/atomic access shouldn't be allowed with partial int types? and I don't known where are the rules about the padding bits? I guess there are at least two possibilities:
|
Fields smaller that the abisize, even when aligned to a byte boundary, are accessed via a packed_offset decorated ptr. This was not always considered by the code, and the offset was applied once to the pointer (as if it would be used as an undecorated ptr), and again when dereferencing it (by the packed_offset decoration) resolves ziglang#16615 and probaly ziglang#16621
f341ce3
to
b316d45
Compare
when a field was 'byte_aligned', the offset was applied once to the pointer
and again when dereferencing it (because it's a ptr with a 'packed_offset')
resolves #16615
and maybe #16621 ?