Source: rust-bindgen Version: 0.66.1-7 Severity: normal Tags: patch upstream
bcachefs(-tools) upstream has been plagued by compilation issues resulting from a combination of packed/align. This has been discussed in its mailing list, as well as with both bindgen & Rust upstreams: https://github.com/rust-lang/rust/issues/59154 https://github.com/rust-lang/rust/issues/33158 https://github.com/rust-lang/rust-bindgen/issues/2240 https://github.com/rust-lang/rust-bindgen/issues/2725 (etc.) Thomas Bertschinger submitted a few workarounds in the bcachefs-tools upstream project, but eventually got a better fix in rust-bindgen, merged upstream and released with 0.69.4: https://github.com/rust-lang/rust-bindgen/commit/199bee441ad0fb81b4b054e0c1e2ffb51f4e4a6d src:bcachefs-tools ships a revert of one of those patches to a version that was kinda working with older bindgen, but this FTBFS on at least i386 (#1074797). I suppose updating bindgen to 0.69.4 to Debian is a larger endeavour. Fortunately though, the aforementioned commit applies cleanly on src:rust-bindgen 0.66.1-7. The cherry-pick is attached here for your convenience, ready to be dropped to debian/patches. With this patch, plus a rebuild of src:rust-bindgen-cli, I've managed to successfully build bcachefs-tools 1:1.9.4-1~exp1 for both amd64 and i386, with the "revert-bindgen-changes.patch" patch disabled. Would it be possible to include this patch in Debian? Thanks in advance! Regards, Faidon
>From 199bee441ad0fb81b4b054e0c1e2ffb51f4e4a6d Mon Sep 17 00:00:00 2001 From: Thomas Bertschinger <[email protected]> Date: Tue, 23 Jan 2024 21:41:14 -0700 Subject: [PATCH] try to avoid `#[repr(packed)]` when `align` is needed 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. diff --git a/codegen/mod.rs b/bindgen/codegen/mod.rs index 11425e02..c90dac9a 100644 --- a/codegen/mod.rs +++ b/codegen/mod.rs @@ -1970,6 +1970,7 @@ impl CodeGenerator for CompInfo { ty, &canonical_name, visibility, + packed, ); if !is_opaque { @@ -2189,7 +2190,14 @@ impl CodeGenerator for CompInfo { if let Some(comment) = item.comment(ctx) { attributes.push(attributes::doc(comment)); } - if packed && !is_opaque { + + // if a type has both a "packed" attribute and an "align(N)" attribute, then check if the + // "packed" attr is redundant, and do not include it if so. + if packed && + !is_opaque && + !(explicit_align.is_some() && + self.already_packed(ctx).map_or(false, |t| t)) + { let n = layout.map_or(1, |l| l.align); assert!(ctx.options().rust_features().repr_packed_n || n == 1); let packed_repr = if n == 1 { diff --git a/codegen/struct_layout.rs b/bindgen/codegen/struct_layout.rs index 56730603..b38479e4 100644 --- a/codegen/struct_layout.rs +++ b/codegen/struct_layout.rs @@ -91,9 +91,9 @@ impl<'a> StructLayoutTracker<'a> { ty: &'a Type, name: &'a str, visibility: FieldVisibilityKind, + is_packed: bool, ) -> Self { let known_type_layout = ty.layout(ctx); - let is_packed = comp.is_packed(ctx, known_type_layout.as_ref()); let (is_rust_union, can_copy_union_fields) = comp.is_rust_union(ctx, known_type_layout.as_ref(), name); StructLayoutTracker { diff --git a/ir/comp.rs b/bindgen/ir/comp.rs index 89e77e16..ae52dfb2 100644 --- a/ir/comp.rs +++ b/ir/comp.rs @@ -1641,6 +1641,26 @@ impl CompInfo { false } + /// Return true if a compound type is "naturally packed". This means we can exclude the + /// "packed" attribute without changing the layout. + /// This is useful for types that need an "align(N)" attribute since rustc won't compile + /// structs that have both of those attributes. + pub(crate) fn already_packed(&self, ctx: &BindgenContext) -> Option<bool> { + let mut total_size: usize = 0; + + for field in self.fields().iter() { + let layout = field.layout(ctx)?; + + if layout.align != 0 && total_size % layout.align != 0 { + return Some(false); + } + + total_size += layout.size; + } + + Some(true) + } + /// Returns true if compound type has been forward declared pub(crate) fn is_forward_declaration(&self) -> bool { self.is_forward_declaration -- 2.43.0

