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

Add support for bitfields #585

Closed
wants to merge 1 commit into from
Closed

Conversation

antoyo
Copy link
Member

@antoyo antoyo commented Apr 18, 2018

No description provided.

"u64"
}
else {
truncated = Some("Bit fields too large".to_string());
Copy link

Choose a reason for hiding this comment

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

The inconsistency between this case and IsIncomplete implementation will cause problems for any other struct that contains truncated one. But if such large bitfields don't happen in practice then LGTM.

@sdroege
Copy link
Member

sdroege commented Apr 18, 2018

I'm not sure this is correct with all C compilers, but I guess for the majority of cases it will work. We have the ABI tests for checking struct sizes at least.

You can remove the hack that is currently in gir for (IIRC) GClosure then. Or GHookList or something :)

@ghost
Copy link

ghost commented Apr 18, 2018

Yes, this definitely needs some ABI checks. Sadly, those run on AppVeyor don't have any bitfields, but I can later test this with x86_64-unknown-linux-gnu target.

@ghost
Copy link

ghost commented Apr 18, 2018

Using large integer types may increase alignment:

	Layout mismatch for GDate
Rust: Layout { size: 8, alignment: 8 }
C:    Layout { size: 8, alignment: 4 }
#[repr(C)]
#[derive(Copy, Clone)]
pub struct GDate {
    pub julian_days: u64,
}
struct _GDate
{
  guint julian_days : 32; /* julian days representation - we use a
                           *  bitfield hoping that 64 bit platforms
                           *  will pack this whole struct in one big
                           *  int
                           */

  guint julian : 1;    /* julian is valid */
  guint dmy    : 1;    /* dmy is valid */

  /* DMY representation */
  guint day    : 6;
  guint month  : 4;
  guint year   : 16;
};

}
else if bits <= 64 {
"u64"
}
Copy link
Member

Choose a reason for hiding this comment

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

Maybe better stop on 8, 16, 32 bit and create field?
Not sure how you plan decombining it actually.

@ghost
Copy link

ghost commented Apr 18, 2018

Further mismatches in Gtk+:

Layout mismatch for GtkTableRowCol
Rust: Layout { size: 8, alignment: 2 }
C:    Layout { size: 8, alignment: 4 }
Layout mismatch for GtkTextAppearance
Rust: Layout { size: 96, alignment: 8 }
C:    Layout { size: 48, alignment: 8 }
Layout mismatch for GtkTextAttributes
Rust: Layout { size: 216, alignment: 8 }
C:    Layout { size: 168, alignment: 8 }
#[repr(C)]
#[derive(Copy, Clone)]
pub struct GtkTableRowCol {
    pub requisition: u16,
    pub allocation: u16,
    pub spacing: u16,
    pub need_expand: u8,
}
struct _GtkTableRowCol
{
  guint16 requisition;
  guint16 allocation;
  guint16 spacing;
  guint need_expand : 1;
  guint need_shrink : 1;
  guint expand : 1;
  guint shrink : 1;
  guint empty : 1;
};

The case GtkTextAppearance and GtkTextAttributes is much more complicated.

@sdroege
Copy link
Member

sdroege commented Apr 19, 2018

I would expect the size/alignment to also differ between compilers, especially MSVC. What did you test @tmiasko?

I also don't understand why the alignment for GtkTableRowCol would be 4. There's a u16 at the beginning, so that would require 2. Even if the alignment is 4, the first bit of the bitfield would be only 2-aligned unless the compiler adds padding between spacing and the bitfields. I.e. if the compiler always falls back to a C int for the bitfield unless it is more than 32 bits for one component.

Someone please read what the C standard has to say about this in bitfields, but from my memory all this is implementation defined.

@ghost
Copy link

ghost commented Apr 19, 2018

I tested this with x86_64-unknown-linux-gnu. I could probably test further
revisions of this PR on i686 as well, but I don't have access to Windows
setup right now.

From System V Application Binary Interface AMD64 Architecture Processor Supplement:

Bit-fields obey the same size and alignment rules as other structure and union members. Also:

  • bit-fields are allocated from right to left
  • bit-fields must be contained in a storage unit appropriate for its declared type
  • bit-fields may share a storage unit with other struct / union members

Yes, all this is implementation defined, so in case there are differences
exercised by GLib, Gio, Gtk+, etc., this might be formidable challenge.

@sdroege
Copy link
Member

sdroege commented Apr 19, 2018

Probably have to wait for rust-lang/rfcs#314 before we can do something meaningful here

@antoyo
Copy link
Member Author

antoyo commented Apr 21, 2018

I started the work to compute the alignment.
The problem however, is that the structs are sometimes using the type without a pointer as a field.
For instance, this c type has pointers to GdkRGBA while in Rust it embed GdkRGBA directly (and it seems it is missing fields).
So, I could continue working on alignment, but this would also require works for the field size.

@ghost
Copy link

ghost commented Apr 21, 2018

I think you have linked to what will become Gtk+4. In Gtk+3 they are indeed
stored by value https://github.com/GNOME/gtk/blob/gtk-3-22/gtk/gtktextattributes.h#L89,
and there is no discrepancy between introspection data and C definitions.

This does pose some additional challenges as you say, but we can also make some
simplifying assumptions if hard cases doesn't actually happen in practice.
With ABI tests the risk of getting things wrong might be manageable.

For example, assuming that first bitfield is always placed in a new storage
unit (as opposed sharing it with members before), you wouldn't have to
calculate size and alignment of anything that comes before. I think that would
work in cases above.

@antoyo
Copy link
Member Author

antoyo commented May 10, 2019

I'll close this for now.

@antoyo antoyo closed this May 10, 2019
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.

3 participants