arocc icon indicating copy to clipboard operation
arocc copied to clipboard

Parser: Compute sizeof / alignof struct and union types

Open tomc1998 opened this issue 3 years ago • 6 comments

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:

  1. How can i report a compiler error? see line 1711. I poked around Compilation.zig but nothing jumped out.
  2. 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?

tomc1998 avatar Jun 03 '22 12:06 tomc1998

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.

ehaas avatar Jun 03 '22 17:06 ehaas

@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__)

ehaas avatar Jun 06 '22 15:06 ehaas

Hello, sorry i've been busy, i'll fix these up tonight or tomorrow night + maybe have a look at alignment :)

tomc1998 avatar Jun 07 '22 12:06 tomc1998

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.

TwoClocks avatar Jun 09 '22 12:06 TwoClocks

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.

Vexu avatar Jun 09 '22 18:06 Vexu

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!

tomc1998 avatar Jun 19 '22 13:06 tomc1998

Superseded by #364 - @tomc1998 can you see if netinet/in.h parses correctly for you now?

ehaas avatar Aug 04 '22 20:08 ehaas

With 7c179f6b9402b41e03bf60211bdecd183441d8f8 #include "netinet/in.h" now compiles without errors.

Vexu avatar Aug 05 '22 15:08 Vexu