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

Support bitfield allocation units larger than 64 bits #1158

Merged
merged 1 commit into from
Nov 23, 2017
Merged

Support bitfield allocation units larger than 64 bits #1158

merged 1 commit into from
Nov 23, 2017

Conversation

glyn
Copy link
Contributor

@glyn glyn commented Nov 20, 2017

Individual bitfields are still limited to at most 64 bits, but this restriction can be weakened when Rust supports u128.

This implements issue #816.

Usage notes:

  • Since common code is added to each generated binding, a program which uses
    more than one binding may need to work around the duplication by including
    each binding in its own module.
  • The values created by bitfield allocation unit constructors can be assigned
    directly to the corresponding struct fields with no need for transmutation.

Implementation notes:

__BindgenBitfieldUnit represents a bitfield allocation unit using a Storage
type accessible as a slice of u8. The alignment of the unit is inherited from
an Align type by virtue of the field:

align: [Align; 0],

The position of this field in the struct is irrelevant.

It is assumed that the alignment of the Storage type is no larger than the
alignment of the Align type, which will be true if the Storage type is, for
example, an array of u8. This assumption is checked in a debug assertion.

Although the double underscore (__) prefix is reserved for implementations of
C++, there are precedents for this convention elsewhere in bindgen and so the
convention is adopted here too.

Acknowledgement:

Thanks to @fitzgen for an initial implementation of __BindgenBitfieldUnit and
code to integrate it into bindgen.

r? @emilio

@highfive
Copy link

warning Warning warning

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

@@ -0,0 +1,83 @@
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BindgenBitfieldUnit<Storage, Align>
Copy link
Contributor

Choose a reason for hiding this comment

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

This definitely needs to be repr(C).

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, I'd recommend maybe to put a double underscore as the prefix for the name, since that's technically reserved in C. Not sure what's @fitzgen's opinion on that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@emilio Nice catch! Thanks. Fixed.

@glyn
Copy link
Contributor Author

glyn commented Nov 21, 2017

@emilio Thanks for the feedback. I added repr(C) and the double underscore prefix. Since @fitgen doesn't seem to be around at the moment and you have begun a review, I've changed the reviewer to you. Let's hope @highfive notices...

@glyn
Copy link
Contributor Author

glyn commented Nov 21, 2017

r? @emilio

@highfive highfive assigned emilio and unassigned fitzgen Nov 21, 2017
Copy link
Contributor

@emilio emilio left a comment

Choose a reason for hiding this comment

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

looks pretty nice to me, but I think it can merge as-is. at least the use_core issue needs to be resolved. Maybe we can just get away fine without const fn...

{
#[inline]
pub fn new(storage: Storage) -> Self {
use std::mem::align_of;
Copy link
Contributor

Choose a reason for hiding this comment

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

This somehow needs to be core when --use-core is passed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@emilio The simplest solution is to remove the assertion (and its use of align_of) as it's not needed currently and it's very unlikely that anyone will trip over the assumption in the future.

#[inline]
pub fn new(storage: Storage) -> Self {
use std::mem::align_of;
debug_assert!(align_of::<Storage>() <= align_of::<Align>());
Copy link
Contributor

Choose a reason for hiding this comment

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

This can probably be a release assert!. It will go away anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@emilio The simplest solution is to remove the assertion as it's not needed currently and it's very unlikely that anyone will trip over the assumption in the future.

@@ -140,8 +140,6 @@ macro_rules! rust_feature_def {
rust_feature_def!(
/// Untagged unions ([RFC 1444](https://github.com/rust-lang/rfcs/blob/master/text/1444-union.md))
=> untagged_union;
/// Constant function ([RFC 911](https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md))
=> const_fn;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think const fn was also needed for SpiderMonkey, so not sure we can get away without it so easily...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@emilio I'll leave it out for now because it would be easy to add back in. Certainly the bitfield allocation unit constructors have no hope of being const fn.

this->nMonthDay == nMonthDay &&
this->nMonth == nMonth &&
this->byte == byte;
printf("\n");
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure how worth are the printfs? i'd usually just use gdb for this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@emilio Agreed. Better to delete this clutter. It's trivial to add back in for debugging if someone doesn't have gdb.

Individual bitfields are still limited to at most 64 bits, but this
restriction can be weakened when Rust supports u128.

This implements issue #816.

Usage notes:

* Since common code is added to each generated binding, a program which uses
  more than one binding may need to work around the duplication by including
  each binding in its own module.
* The values created by bitfield allocation unit constructors can be assigned
  directly to the corresponding struct fields with no need for transmutation.

Implementation notes:

__BindgenBitfieldUnit represents a bitfield allocation unit using a Storage
type accessible as a slice of u8. The alignment of the unit is inherited from
an Align type by virtue of the field:

align: [Align; 0],

The position of this field in the struct is irrelevant.

The alignment of the Storage type is intended to be no larger than the
alignment of the Align type, which will be true if the Storage type is, for
example, an array of u8.

Although the double underscore (__) prefix is reserved for implementations of
C++, there are precedents for this convention elsewhere in bindgen and so the
convention is adopted here too.

Acknowledgement:

Thanks to @fitzgen for an initial implementation of __BindgenBitfieldUnit and
code to integrate it into bindgen.
@emilio
Copy link
Contributor

emilio commented Nov 23, 2017

I took a closer look, and I can't think of why this shouldn't get merged. Thanks a lot @glyn!

@bors-servo r+

@bors-servo
Copy link

📌 Commit f0e0531 has been approved by emilio

@bors-servo
Copy link

⌛ Testing commit f0e0531 with merge 7c3584d...

bors-servo pushed a commit that referenced this pull request Nov 23, 2017
Support bitfield allocation units larger than 64 bits

Individual bitfields are still limited to at most 64 bits, but this restriction can be weakened when Rust supports `u128`.

This implements issue #816.

Usage notes:

* Since common code is added to each generated binding, a program which uses
  more than one binding may need to work around the duplication by including
  each binding in its own module.
* The values created by bitfield allocation unit constructors can be assigned
  directly to the corresponding struct fields with no need for transmutation.

Implementation notes:

`__BindgenBitfieldUnit` represents a bitfield allocation unit using a `Storage`
type accessible as a slice of `u8`. The alignment of the unit is inherited from
an `Align` type by virtue of the field:
```
align: [Align; 0],
```
The position of this field in the struct is irrelevant.

It is assumed that the alignment of the `Storage` type is no larger than the
alignment of the `Align` type, which will be true if the `Storage` type is, for
example, an array of `u8`. This assumption is checked in a debug assertion.

Although the double underscore (__) prefix is reserved for implementations of
C++, there are precedents for this convention elsewhere in bindgen and so the
convention is adopted here too.

Acknowledgement:

Thanks to @fitzgen for an initial implementation of `__BindgenBitfieldUnit` and
code to integrate it into bindgen.

r? @emilio
@bors-servo
Copy link

☀️ Test successful - status-travis
Approved by: emilio
Pushing 7c3584d to master...

@bors-servo bors-servo merged commit f0e0531 into rust-lang:master Nov 23, 2017
@fitzgen
Copy link
Member

fitzgen commented Nov 27, 2017

Thanks for taking this over the finishing line @glyn!

We should probably go back and re-test all of our bitfield bugs and see if we fixed any of them with this change.

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.

None yet

5 participants