-
Notifications
You must be signed in to change notification settings - Fork 702
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
try to avoid #[repr(packed)]
when align
is needed
#2734
Conversation
OK, based on the test failures from these types not compiling, I take it I should fix this |
d4fb6f5
to
5df4ef5
Compare
pushed v2:
|
The combination of bitfields and |
Since rustc accepts |
Bindgen should already be doing this. It works when
Hmm. Do you have any examples of cases where problems could arise here? I'll admit I am not familiar with all the rules for bitfields especially across different C compilers. I'll try to research it more myself too but if you can give an example of a problem case that would be helpful. If this patch exposes problem cases it'll need to be reworked, but if it doesn't I think it'd be nice to go ahead with it and handle more cases in bindgen. Ultimately, not handling this case in bindgen isn't the end of the world since users can construct the Rust bindings by hand, but it would be nice to have bindgen handle as many cases as possible. |
Ah, okay. I am "blessed" to work on a codebase that uses bindgen but the target C codebase only has one instance of using the combined ...they otherwise prefer to manually pack things, byte by byte, in code. Charming, really.
Even for the "same ABI", alignment for the "storage allocation" of the bitfield types can have different default alignments, and this deviates further when
Emphasis mine. It should be noted that AArch64 has one of the most well-defined ABIs in this case, and they still mumble something that leaves at least a few things up in the air and then just ban it in public interfaces. You cannot truly coherently reason about the allocation sizes of bitfields for most ABIs, because the C Standard is essentially mute on how they work, and then psABIs only constrain it just-enough. Then we inject |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this looks somewhat reasonable. I have a couple nits. I also wonder if this should just be inside the is_packed
logic, rather than as another walk through the fields, but maybe this way is simpler to reason about.
Currently rustc forbids compound types from having both a `packed` and `align` attribute. When a source type has both attributes, this may mean it cannot be represented with the current rustc. Often, though, one or both of these attributes is redundant and can be safely removed from the generated Rust code. Previously, bindgen avoided placing the `align` attribute when it is not needed. However, it would always place the `packed` attribute if the source type has it, even when it is redundant because the source type is "naturally packed". With this change, bindgen avoids placing `packed` on a type if the `packed` is redundant and the type needs an `align` attribute. If the type does not have an "align" attribute, then bindgen will still place `packed` so as to avoid changing existing working behavior. This commit also takes out an extraneous `is_packed()` call from `StructLayoutTracker::new()` since the value can be passed in from the caller; this avoids duplicating work in some cases.
5df4ef5
to
c45be66
Compare
This is a good point; but after looking into this some it's not actually obvious to me what the best way to handle this is. Doing this probably adds complexity and might not skip that much work in many cases. First, this patch shouldn't result in any extra work in the common cases since the new method will only be called for types that are both packed and need I realized In the revision I just uploaded, I take out one extra call to |
@workingjubilee -- thanks for posting the additional info about bitfields (and thanks for reviewing this patch)! That aarch64 ABI doc was helpful. I don't think this patch should change anything about how bindgen lays out structs with bitfields--in particular, any bindgen-created code that previously compiled under rustc should be unaffected (I intentionally tried to write this patch to not affect any existing working behavior). But I'll keep thinking about this in case there any problem scenarios I've missed... |
if packed && | ||
!is_opaque && | ||
!(explicit_align.is_some() && | ||
self.already_packed(ctx).map_or(false, |t| t)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unwrap_or(false)
This is for #2725
This patch handles the "type has both packed and align attrs" case, but it doesn't do anything for the "packed type transitively contains aligned type" case.
The test header intentionally generates types that won't compile. If this is a problem, and the test output rust source needs to compile, let me know and I'll remove those types...
I'm still pretty new to Rust, so a thorough review would be much appreciated!
Currently rustc forbids compound types from having both a
packed
andalign
attribute.When a source type has both attributes, this may mean it cannot be represented with the current rustc. Often, though, one or both of these attributes is redundant and can be safely removed from the generated Rust code.
Previously, bindgen avoided placing the
align
attribute when it is not needed. However, it would always place thepacked
attribute if the source type has it, even when it is redundant because the source type is "naturally packed".With this change, bindgen avoids placing
packed
on a type if thepacked
is redundant and the type needs analign
attribute. If the type does not have an "align" attribute, then bindgen will still placepacked
so as to avoid changing existing working behavior.