Skip to content
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

Rework how bitfields are handled. #512

Merged
merged 2 commits into from
Feb 16, 2017
Merged

Conversation

emilio
Copy link
Contributor

@emilio emilio commented Feb 14, 2017

This fixes #111, and unblocks stylo.

The problem with this as of right now is that it drops the accessors (though before that this code was buggy so I'm not sure it's a loss).

I can probably try to re-implement those (though it'd be more complex). WDYT @fitzgen?

Also, note that I changed the max_align_nonce because it was incorrect (we shouldn't generate padding, because long double was 128 bits).

@highfive
Copy link

warning Warning warning

  • These commits modify unsafe code. Please review it carefully!

@emilio
Copy link
Contributor Author

emilio commented Feb 14, 2017

r? @fitzgen

@emilio
Copy link
Contributor Author

emilio commented Feb 14, 2017

Also @flier may want to take a look to ensure I didn't mess badly ;)

Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking this one on faith...

@@ -732,89 +732,96 @@ impl<'a> Bitfield<'a> {
fn codegen_fields(self,
ctx: &BindgenContext,
fields: &mut Vec<ast::StructField>,
methods: &mut Vec<ast::ImplItem>)
_methods: &mut Vec<ast::ImplItem>)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't a trait implementation, so we can change the set of parameters. Let's remove this if it isn't used anymore.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ this comment is still not addressed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was assuming that given #519 is assigned, it'll be used soon :)

@fitzgen
Copy link
Member

fitzgen commented Feb 14, 2017

I can probably try to re-implement those (though it'd be more complex).

I think we need the accessors to make this usable.

Copy link
Contributor

@flier flier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some compatibility issues

// bitfield, and whether we have to index in it. Thus, we don't know
// which integer type do we need.
//
// We could push them to a Vec or something, but given how buggy
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: We need some unit tests to verify accessor use the right offset same to LLVM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, this is why I didn't want to deep-dive into accessors ;)

fields.push(field);
}

Layout::new(bytes_from_bits(total_size_in_bits), max_align)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need padding some bits to the latest bitfield base on its type instead of size

consider the example

struct Date {  
   unsigned short nWeekDay  : 3;    // 0..7   (3 bits)  
   unsigned short nMonthDay : 6;    // 0..31  (6 bits)  
   unsigned short nMonth    : 5;    // 0..12  (5 bits)  
   unsigned short nYear     : 8;    // 0..100 (8 bits)  
};  

nYear should be aligned to offset 16bits with 16bits size, not a 8bit bit field
image

#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct Date {
    pub _bitfield_1: [u8; 2usize],
    pub _bitfield_2: u8,
    pub __bindgen_align: [u16; 0usize],
}

More detail

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrm, you're right about this, but this needs to only happen when this is the last field in the struct. Otherwise, we'd generate wrong code for this one (reusing your example here):

struct Date {
   unsigned short nWeekDay  : 3;    // 0..7   (3 bits)
   unsigned short nMonthDay : 6;    // 0..31  (6 bits)
   unsigned short nMonth    : 5;    // 0..12  (5 bits)
   unsigned short nYear     : 8;    // 0..100 (8 bits)
   unsigned char byte;
};

Where the size should still be 4 bytes.

I'll special-case this.

total_size_in_bits += width as usize;


let data_size = align_to(field_size_in_bits, field_align * 8);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: When we implement accessor, the data_size must limited by its type, C++ allow bitfields exceeds its type limites

If the specified size of the bit field is greater than the size of its type, the value is limited by the type: a std::uint8_t b : 1000; would still hold values between 0 and 255. the extra bits become unused padding.

struct foo
{
    unsigned char bar : 1000;
};

will generated data size, but only 8 bits should be accessible

#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct foo {
    pub _bitfield_1: [u8; 128usize],
    pub __bindgen_align: [u64; 0usize],
}

In the C programming language, the width of a bit field cannot exceed the width of the underlying type.

More detail

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I had already a note about packed and wide bitfields :)

@emilio
Copy link
Contributor Author

emilio commented Feb 15, 2017

So I pushed another wip that manages to get rid of the calc layout code, at the expense of failing the layout_array test.

That test generates an array of unaligned structs and previous to this commit, padded it. I'd argue that's pretty wrong, and it's wrong to not fail that test, since it's pretty unsafe (the structs in the array don't start where it should).

@flier, wdyt?

@emilio
Copy link
Contributor Author

emilio commented Feb 15, 2017

I fixed that test (if in a much hacky way).

@emilio
Copy link
Contributor Author

emilio commented Feb 15, 2017

Ok, so current commit passess all the layout and field offset tests here and gecko.

As I said, adding the getters and setters again is probably not too hard, but this has already went out of scope of what I initially intended.

@fitzgen mind taking a look again since a few things have changed?

@emilio emilio changed the title [wip] Rework how bitfields are handled. Rework how bitfields are handled. Feb 15, 2017
@@ -13,7 +13,7 @@ name = "bindgen"
readme = "README.md"
repository = "https://github.com/servo/rust-bindgen"
documentation = "https://docs.rs/bindgen"
version = "0.21.3"
version = "0.22.0"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've almost caught up with emacs!

@@ -11,6 +11,7 @@ mod codegen {
quasi_codegen::expand(&src, &dst).unwrap();
println!("cargo:rerun-if-changed=src/codegen/mod.rs");
println!("cargo:rerun-if-changed=src/codegen/helpers.rs");
println!("cargo:rerun-if-changed=src/codegen/struct_layout.rs");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these things support wildcards? If so, is there a reason we shouldn't do this

println!("cargo:rerun-if-changed=src/codegen/*");

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, it's not supported I think, we'd need to walkdir or something.

@@ -732,89 +732,96 @@ impl<'a> Bitfield<'a> {
fn codegen_fields(self,
ctx: &BindgenContext,
fields: &mut Vec<ast::StructField>,
methods: &mut Vec<ast::ImplItem>)
_methods: &mut Vec<ast::ImplItem>)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ this comment is still not addressed

@emilio
Copy link
Contributor Author

emilio commented Feb 15, 2017

@bors-servo r=fitzgen

@bors-servo
Copy link

📌 Commit b14adc3 has been approved by fitzgen

@bors-servo
Copy link

⌛ Testing commit b14adc3 with merge 852db65...

bors-servo pushed a commit that referenced this pull request Feb 16, 2017
Rework how bitfields are handled.

This fixes #111, and unblocks stylo.

The problem with this as of right now is that it drops the accessors (though before that this code was buggy so I'm not sure it's a loss).

I can probably try to re-implement those (though it'd be more complex). WDYT @fitzgen?

Also, note that I changed the max_align_nonce because it was incorrect (we shouldn't generate padding, because `long double` was `128` bits).
@emilio
Copy link
Contributor Author

emilio commented Feb 16, 2017

@bors-servo r=fitzgen

  • Cargo.lock

@bors-servo
Copy link

📌 Commit 08d4b8e has been approved by fitzgen

@bors-servo
Copy link

☔ The latest upstream changes (presumably #518) made this pull request unmergeable. Please resolve the merge conflicts.

@bors-servo
Copy link

🔒 Merge conflict

@emilio
Copy link
Contributor Author

emilio commented Feb 16, 2017

@bors-servo r=fitzgen

  • Grrr

@bors-servo
Copy link

📌 Commit 98f43d0 has been approved by fitzgen

@bors-servo
Copy link

⌛ Testing commit 98f43d0 with merge e57b2cb...

bors-servo pushed a commit that referenced this pull request Feb 16, 2017
Rework how bitfields are handled.

This fixes #111, and unblocks stylo.

The problem with this as of right now is that it drops the accessors (though before that this code was buggy so I'm not sure it's a loss).

I can probably try to re-implement those (though it'd be more complex). WDYT @fitzgen?

Also, note that I changed the max_align_nonce because it was incorrect (we shouldn't generate padding, because `long double` was `128` bits).
@bors-servo
Copy link

☀️ Test successful - status-travis
Approved by: fitzgen
Pushing e57b2cb to master...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

alignment of integer field holding bitfield values is not correct
5 participants