diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2020-01-29 00:40:39 +0100 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2020-01-29 02:27:24 +0100 |
commit | 0153dfe230c63a2ece4df5d1c4ed8231d58d3ea6 (patch) | |
tree | ca7d9c4f89da0ae333befab5b6da9c3d0dd55ec8 /src | |
parent | e0a0400e946a3786bfde0984386e9c235188043e (diff) |
ir: Account for packedness when computing bitfield sizes.
Fixes #1716
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/comp.rs | 84 |
1 files changed, 50 insertions, 34 deletions
diff --git a/src/ir/comp.rs b/src/ir/comp.rs index a82fd756..cc58e910 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -496,6 +496,7 @@ impl FieldMethods for RawField { fn raw_fields_to_fields_and_bitfield_units<I>( ctx: &BindgenContext, raw_fields: I, + packed: bool, ) -> Result<Vec<Field>, ()> where I: IntoIterator<Item = RawField>, @@ -533,6 +534,7 @@ where &mut bitfield_unit_count, &mut fields, bitfields, + packed, )?; } @@ -551,6 +553,7 @@ fn bitfields_to_allocation_units<E, I>( bitfield_unit_count: &mut usize, fields: &mut E, raw_bitfields: I, + packed: bool, ) -> Result<(), ()> where E: Extend<Field>, @@ -575,17 +578,22 @@ where unit_size_in_bits: usize, unit_align_in_bits: usize, bitfields: Vec<Bitfield>, + packed: bool, ) where E: Extend<Field>, { *bitfield_unit_count += 1; - let align = bytes_from_bits_pow2(unit_align_in_bits); + let align = if packed { + 1 + } else { + bytes_from_bits_pow2(unit_align_in_bits) + }; let size = align_to(unit_size_in_bits, align * 8) / 8; let layout = Layout::new(size, align); fields.extend(Some(Field::Bitfields(BitfieldUnit { nth: *bitfield_unit_count, - layout: layout, - bitfields: bitfields, + layout, + bitfields, }))); } @@ -607,34 +615,39 @@ where let bitfield_align = bitfield_layout.align; let mut offset = unit_size_in_bits; - if is_ms_struct { - if unit_size_in_bits != 0 && - (bitfield_width == 0 || - bitfield_width > unfilled_bits_in_unit) - { - // We've reached the end of this allocation unit, so flush it - // and its bitfields. - unit_size_in_bits = align_to(unit_size_in_bits, unit_align * 8); - flush_allocation_unit( - fields, - bitfield_unit_count, - unit_size_in_bits, - unit_align, - mem::replace(&mut bitfields_in_unit, vec![]), - ); + if !packed { + if is_ms_struct { + if unit_size_in_bits != 0 && + (bitfield_width == 0 || + bitfield_width > unfilled_bits_in_unit) + { + // We've reached the end of this allocation unit, so flush it + // and its bitfields. + unit_size_in_bits = + align_to(unit_size_in_bits, unit_align * 8); + flush_allocation_unit( + fields, + bitfield_unit_count, + unit_size_in_bits, + unit_align, + mem::replace(&mut bitfields_in_unit, vec![]), + packed, + ); - // Now we're working on a fresh bitfield allocation unit, so reset - // the current unit size and alignment. - offset = 0; - unit_align = 0; - } - } else { - if offset != 0 && - (bitfield_width == 0 || - (offset & (bitfield_align * 8 - 1)) + bitfield_width > - bitfield_size * 8) - { - offset = align_to(offset, bitfield_align * 8); + // Now we're working on a fresh bitfield allocation unit, so reset + // the current unit size and alignment. + offset = 0; + unit_align = 0; + } + } else { + if offset != 0 && + (bitfield_width == 0 || + (offset & (bitfield_align * 8 - 1)) + + bitfield_width > + bitfield_size * 8) + { + offset = align_to(offset, bitfield_align * 8); + } } } @@ -677,6 +690,7 @@ where unit_size_in_bits, unit_align, bitfields_in_unit, + packed, ); } @@ -717,7 +731,7 @@ impl CompFields { } } - fn compute_bitfield_units(&mut self, ctx: &BindgenContext) { + fn compute_bitfield_units(&mut self, ctx: &BindgenContext, packed: bool) { let raws = match *self { CompFields::BeforeComputingBitfieldUnits(ref mut raws) => { mem::replace(raws, vec![]) @@ -727,7 +741,7 @@ impl CompFields { } }; - let result = raw_fields_to_fields_and_bitfield_units(ctx, raws); + let result = raw_fields_to_fields_and_bitfield_units(ctx, raws, packed); match result { Ok(fields_and_units) => { @@ -1126,7 +1140,7 @@ impl CompInfo { /// Do we see a virtual function during parsing? /// Get the has_own_virtual_method boolean. pub fn has_own_virtual_method(&self) -> bool { - return self.has_own_virtual_method; + self.has_own_virtual_method } /// Did we see a destructor when parsing this type? @@ -1566,7 +1580,9 @@ impl CompInfo { /// Compute this compound structure's bitfield allocation units. pub fn compute_bitfield_units(&mut self, ctx: &BindgenContext) { - self.fields.compute_bitfield_units(ctx); + // TODO(emilio): If we could detect #pragma packed here we'd fix layout + // tests in divide-by-zero-in-struct-layout.rs + self.fields.compute_bitfield_units(ctx, self.packed_attr) } /// Assign for each anonymous field a generated name. |