Open bertschingert opened 9 months ago
I'd take a reasonable patch for this, sure :)
I'd take a reasonable patch for this, sure :)
Cool. I will get to work :)
The patch I've just uploaded (https://github.com/rust-lang/rust-bindgen/pull/2734) 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.
What do you think of a follow-up that handles the latter case? There is one example of a "packed" struct in bcachefs where the "packed" is redundant and it has an "aligned" member type: struct btree_node
(https://github.com/koverstreet/bcachefs/blob/e7152225f6b401edb0c4dc285ccc9ac5fdfbcd85/fs/bcachefs/bcachefs_format.h#L1968). So handling this case would allow us to use bindgen for this type and not have to code it manually outside of bindgen.
I think this is a little trickier because in bindgen's code generation step we don't have the information easily available of if any child types had the "align" attribute applied to them. The determination to apply that attribute is done in StructLayoutTracker::requires_explicit_align
but then it's not clear that it's easy to make that information available to any parent type that may contain the current type.
So I think to support this, it might make sense to try to move the logic to check if "align" is explicitly needed into an earlier stage, maybe somewhere under src/ir/analysis/
? Then a field could be added to struct Layout
which is accessible to any parent type that contains a type with this layout.
@@ -15,6 +15,8 @@ pub(crate) struct Layout {
pub(crate) align: usize,
/// Whether this layout's members are packed or not.
pub(crate) packed: bool,
+ /// Whether this layout needs an explicit "align(N)" attribute
+ pub(crate) explicit_align: bool,
}
What do you think of this -- does it make sense? Would you take a patch that does something like this?
So I think to support this, it might make sense to try to move the logic to check if "align" is explicitly needed into an earlier stage, maybe somewhere under src/ir/analysis/? Then a field could be added to struct Layout which is accessible to any parent type that contains a type with this layout.
Makes sense to me. Not sure if a full analysis/ pass would be necessary. It seems it would be feasible to handle it in CompInfo::layout
?
Makes sense to me. Not sure if a full analysis/ pass would be necessary. It seems it would be feasible to handle it in CompInfo::layout?
Thanks! - I may take a look at implementing this but I probably won't get to it in the immediate future since the other patch was higher priority.
Emilio -
I've submitted two patches that take different approaches to handling "packed type transitively contains aligned type".
The first patch (https://github.com/rust-lang/rust-bindgen/pull/2769) is simpler but doesn't cover as many cases (for example, types with bitfields).
The second patch (https://github.com/rust-lang/rust-bindgen/pull/2770) is a lot more complex but it covers more cases.
I'm sharing both in case you prefer one approach over the other.
Honestly both patches are somewhat ugly and working on this issue has really convinced me that trying to work around this rustc limitation in bindgen is not the way to go. However, I imagine getting rustc enhanced to allow this will take a long time and in the short term handling this in bindgen would be helpful for a handful of types that have this problem in bcachefs.
For what it's worth, the first, simpler patch should be good enough for all the bcachefs types with this problem, but since the second patch is more complete, I figured I would still share it for consideration.
When a C struct has both
packed
andaligned(N)
attributes, in some cases bindgen generates a Rust struct with apacked(N)
attribute only that has the correct ABI. (Note, I'm assuming GCC semantics for thepacked
andaligned(N)
attributes on the C side.)In other cases, though, bindgen generates code with both attributes, which doesn't compile under rustc. Many of these cases can be handled correctly by applying only an
align(N)
attribute; intuitively, this should work if the struct is "naturally packed".Here is a minimal example:
This comes up for a handful of structs used in bcachefs. I wrote about this in a message to the rust-for-linux email list: https://lore.kernel.org/rust-for-linux/20240122024711.GC151023@fedora-laptop/T/#m4439be01c0bcfdbaa781c379be3e227358cfab27
From that message:
It looks like bindgen already mostly handles case (1).
However, bindgen doesn't seem to handle case (2). What do you think of adding the logic to handle that case into bindgen? This would be really helpful for bcachefs with the structs mentioned in the above email.