Parser: Compute sizeof / alignof struct and union types
Compute sizeof/alignof records.
This isn't a perfect solution - I'm unsure if it works identically to other compilers in all cases & it definitely doesn't factor in packed attributes. But it's good enough - I wanted to load netinet/in.h, which fails with the following error otherwise:
Compiler error:
/usr/include/netinet/in.h:244:53: warning: overflow in expression; result is '18446744073709551615' [-Winteger-overflow]
unsigned char sin_zero[sizeof (struct sockaddr) -
^
/usr/include/netinet/in.h:244:27: error: array is too large
unsigned char sin_zero[sizeof (struct sockaddr) -
// Because of this expression:
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) -
sizeof (struct in_addr)];
Two questions:
- How can i report a compiler error? see line 1711. I poked around Compilation.zig but nothing jumped out.
- The test is obviously flawed, I just matched whatever GCC produced on my system. I can either remove the test, or maybe there's a way to skip it on non-x64-linux systems?
How can i report a compiler error? see line 1711. I poked around Compilation.zig but nothing jumped out.
For this particular error - the for loop that this else belongs to verifies that every field in the record has a non-null size. So I think it's safe to use .? here.
@tomc1998 if you rebase this against latest master I fixed a couple bugs with attributes. If you move the entire for loop that computes the size/alignment to right before the node creation (https://github.com/Vexu/arocc/blob/master/src/Parser.zig#L1717=) you should also be able to grab the value of the aligned attribute of the record with ty.requestedAlignment(p.pp.comp) and update the values if necessary (keep in mind the aligned attribute can only increase alignment, not decrease it: https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Type-Attributes.html).
Another wrinkle is that aligned attributes on record fields themselves, unlike on variables, follow the "may not decrease alignment" rule. field.ty.alignof will return the requested alignment, even if it's lower than the natural alignment of the type. So we probably need a fieldAlignment function on Type that returns the max of the natural alignment and the requested alignment.
struct S1 {
__attribute__((aligned(64))) int x;
};
_Static_assert(_Alignof(struct S1) == 64, "bad alignment");
struct S2 {
__attribute__((aligned(1))) int y;
};
_Static_assert(_Alignof(struct S2) == _Alignof(int), "bad alignment");
int __attribute__((aligned(1))) z;
_Static_assert(_Alignof(z) == 1, "bad alignment");
Finally, for platform specific testing you can wrap your test in #if defined(__linux__) && defined(__x86_64__)
Hello, sorry i've been busy, i'll fix these up tonight or tomorrow night + maybe have a look at alignment :)
I have a port of mankoh's rust repr-c (https://github.com/mahkoh/repr-c) going on this branch here (https://github.com/TwoClocks/arocc/blob/records/src/RecordLayout.zig). Something I said I'd work on 6 months ago, but just came back to a few weeks ago.
I'm happy to abandon this work, or integrate it w/ this PR, or whatever is best.
This PR is a naive solution and not enough for replacing but it can unblock progress on other things while waiting for a complete solution.
Hello, i didn't abandon this - promise :)
I've rebased with master & made the changes @ehaas suggested - so now we take into account struct field attribute alignment!
Superseded by #364 - @tomc1998 can you see if netinet/in.h parses correctly for you now?
With 7c179f6b9402b41e03bf60211bdecd183441d8f8 #include "netinet/in.h" now compiles without errors.