rust-bindgen icon indicating copy to clipboard operation
rust-bindgen copied to clipboard

fix some bitfield size calculate bug

Open qinghon opened this issue 6 months ago • 4 comments

Now, we can perceive non-starting bitfields and non-ending bitfields

Also, I modified the calculation method of align: only calculate alignment for bitfield from structure using bitfield_width The reason is that the code now no longer relies on #[repr(C)] to generate alignments, but always contains all bytes The problem that is currently known is that the test case bitfield-linux-32.hpp was dropped #[repr(packed(4))]. I don't know the reason, hope someone can help me

qinghon avatar May 31 '25 16:05 qinghon

Issue known to be repaired: #1377 #3105 #743 #981 #1314

qinghon avatar May 31 '25 17:05 qinghon

r? @emilio

qinghon avatar Jun 03 '25 02:06 qinghon

Error: The feature assign is not enabled in this repository. To enable it add its section in the triagebot.toml in the root of the repository.

Please file an issue on GitHub at triagebot if there's a problem with this bot, or reach out on #t-infra on Zulip.

rustbot avatar Jun 03 '25 02:06 rustbot

fix and add #3104 case

this change add depended clang report offset

qinghon avatar Jun 10 '25 15:06 qinghon

@emilio Can you take some time to review this PR ?

qinghon avatar Jun 20 '25 02:06 qinghon

Fixes #3238

wdouglass avatar Jun 25 '25 13:06 wdouglass

~~Looks like some cases are still broken.~~

struct appHand_supportedAppProtocolRes {
    appHand_responseCodeType ResponseCode; // enum with few variants, offset = 0x0
    uint8_t SchemaID; // offset = 0x1 (why?, isn't enum i32?)
    unsigned int SchemaID_isUsed:1; // offset = 0x2 ?, size of struct = 4
};

Generated with bindgen 0.72:

#[repr(C)]
pub struct appHand_supportedAppProtocolRes {
    pub ResponseCode: appHand_responseCodeType::Type,
    pub SchemaID: u8,
    pub _bitfield_align_1: [u8; 0], 
    pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, // offset = 0x5 ?
    pub __bindgen_padding_0: u16, // offset = 0x6, size of struct = 8
}

Generated with this PR:

#[repr(C)]
pub struct appHand_supportedAppProtocolRes {
    pub ResponseCode: appHand_responseCodeType::Type,
    pub SchemaID: u8,
    pub _bitfield_align_1: [u8; 0],
    pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>, // offset = 0x5, still
}

Bitfield storage alignment is invalid

EDIT: Wrong original offsets EDIT2: The actual problem is in size of enum, so this is a bit unrelated

nikvoid avatar Jul 03 '25 14:07 nikvoid

@nikvoid

Bitfield storage alignment is invalid

Yes

In the C compiler, SchemaID_isUsed and SchemaID will be packaged into an int and accessed in 4 byte alignment.

However, in bindgen, it is difficult to ensure this requirement under the current structure, which will cause some performance losses, but it is better than the wrong offset (the purpose of this PR is to fix the wrong offset/size, but at present, it does not destroy the alignment of the entire structure)

qinghon avatar Jul 03 '25 15:07 qinghon

This actually was a thing with different compilers used from bindgen and C sides... GCC fitted enum to 1 byte, but clang did not.

nikvoid avatar Jul 04 '25 14:07 nikvoid

Also could you squash before I hit the merge button? A lot of the commits don't have particularly descriptive commit messages (like cargo fmt)

emilio avatar Jul 11 '25 19:07 emilio

Ok so I dug into what's going on. The key difference between how bindgen tracks bitfields vs. LLVM is that we track the offset within the bitfield, but llvm tracks the global offset within the struct.

#3247 fixes that, which fixes all the regressions, and it is significantly simpler. @qinghon lmk if you have any feedback on that. I kept credit since the test-cases are yours and you spent a lot of effort on this.

Thanks!

emilio avatar Jul 11 '25 21:07 emilio

Superseded by https://github.com/rust-lang/rust-bindgen/pull/3247. But feel free to comment there or send more patches if something is not addressed. Thanks!

emilio avatar Jul 11 '25 22:07 emilio