@@ -2,7 +2,7 @@ mod helpers;
2
2
mod struct_layout;
3
3
4
4
use self :: helpers:: { BlobTyBuilder , attributes} ;
5
- use self :: struct_layout:: StructLayoutTracker ;
5
+ use self :: struct_layout:: { align_to , bytes_from_bits , StructLayoutTracker } ;
6
6
use aster;
7
7
8
8
use ir:: annotations:: FieldAccessorKind ;
@@ -717,12 +717,12 @@ impl<'a> ItemToRustTy for Vtable<'a> {
717
717
}
718
718
719
719
struct Bitfield < ' a > {
720
- index : usize ,
720
+ index : & ' a mut usize ,
721
721
fields : Vec < & ' a Field > ,
722
722
}
723
723
724
724
impl < ' a > Bitfield < ' a > {
725
- fn new ( index : usize , fields : Vec < & ' a Field > ) -> Self {
725
+ fn new ( index : & ' a mut usize , fields : Vec < & ' a Field > ) -> Self {
726
726
Bitfield {
727
727
index : index,
728
728
fields : fields,
@@ -732,89 +732,96 @@ impl<'a> Bitfield<'a> {
732
732
fn codegen_fields ( self ,
733
733
ctx : & BindgenContext ,
734
734
fields : & mut Vec < ast:: StructField > ,
735
- methods : & mut Vec < ast:: ImplItem > )
735
+ _methods : & mut Vec < ast:: ImplItem > )
736
736
-> Layout {
737
737
use aster:: struct_field:: StructFieldBuilder ;
738
- let mut total_width = self . fields
739
- . iter ( )
740
- . fold ( 0u32 , |acc, f| acc + f. bitfield ( ) . unwrap ( ) ) ;
741
-
742
- if !total_width. is_power_of_two ( ) || total_width < 8 {
743
- total_width = cmp:: max ( 8 , total_width. next_power_of_two ( ) ) ;
744
- }
745
- debug_assert_eq ! ( total_width % 8 , 0 ) ;
746
- let total_width_in_bytes = total_width as usize / 8 ;
747
-
748
- let bitfield_layout = Layout :: new ( total_width_in_bytes,
749
- total_width_in_bytes) ;
750
- let bitfield_type = BlobTyBuilder :: new ( bitfield_layout) . build ( ) ;
751
- let field_name = format ! ( "_bitfield_{}" , self . index) ;
752
- let field_ident = ctx. ext_cx ( ) . ident_of ( & field_name) ;
753
- let field = StructFieldBuilder :: named ( & field_name)
754
- . pub_ ( )
755
- . build_ty ( bitfield_type. clone ( ) ) ;
756
- fields. push ( field) ;
757
738
739
+ // NOTE: What follows is reverse-engineered from LLVM's
740
+ // lib/AST/RecordLayoutBuilder.cpp
741
+ //
742
+ // FIXME(emilio): There are some differences between Microsoft and the
743
+ // Itanium ABI, but we'll ignore those and stick to Itanium for now.
744
+ //
745
+ // Also, we need to handle packed bitfields and stuff.
746
+ // TODO(emilio): Take into account C++'s wide bitfields, and
747
+ // packing, sigh.
748
+ let mut total_size_in_bits = 0 ;
749
+ let mut max_align = 0 ;
750
+ let mut unfilled_bits_in_last_unit = 0 ;
751
+ let mut field_size_in_bits = 0 ;
752
+ * self . index += 1 ;
753
+ let mut last_field_name = format ! ( "_bitfield_{}" , self . index) ;
754
+ let mut last_field_align = 0 ;
758
755
759
- let mut offset = 0 ;
760
756
for field in self . fields {
761
757
let width = field. bitfield ( ) . unwrap ( ) ;
762
- let field_name = field. name ( )
763
- . map ( ToOwned :: to_owned)
764
- . unwrap_or_else ( || format ! ( "at_offset_{}" , offset) ) ;
765
-
766
758
let field_item = ctx. resolve_item ( field. ty ( ) ) ;
767
759
let field_ty_layout = field_item. kind ( )
768
760
. expect_type ( )
769
761
. layout ( ctx)
770
762
. expect ( "Bitfield without layout? Gah!" ) ;
771
763
772
- let field_type = field_item. to_rust_ty ( ctx) ;
773
- let int_type = BlobTyBuilder :: new ( field_ty_layout) . build ( ) ;
764
+ let field_align = field_ty_layout. align ;
774
765
775
- let getter_name = ctx. rust_ident ( & field_name) ;
776
- let setter_name = ctx. ext_cx ( )
777
- . ident_of ( & format ! ( "set_{}" , & field_name) ) ;
778
- let mask = ( ( 1usize << width) - 1 ) << offset;
779
- let prefix = ctx. trait_prefix ( ) ;
780
- // The transmute is unfortunate, but it's needed for enums in
781
- // bitfields.
782
- let item = quote_item ! ( ctx. ext_cx( ) ,
783
- impl X {
784
- #[ inline]
785
- pub fn $getter_name( & self ) -> $field_type {
786
- unsafe {
787
- :: $prefix:: mem:: transmute(
788
- (
789
- ( self . $field_ident &
790
- ( $mask as $bitfield_type) )
791
- >> $offset
792
- ) as $int_type
793
- )
794
- }
795
- }
766
+ if field_size_in_bits != 0 &&
767
+ ( width == 0 || width as usize > unfilled_bits_in_last_unit) {
768
+ field_size_in_bits = align_to ( field_size_in_bits, field_align) ;
769
+ // Push the new field.
770
+ let ty =
771
+ BlobTyBuilder :: new ( Layout :: new ( bytes_from_bits ( field_size_in_bits) ,
772
+ bytes_from_bits ( last_field_align) ) )
773
+ . build ( ) ;
796
774
797
- #[ inline]
798
- pub fn $setter_name( & mut self , val: $field_type) {
799
- self . $field_ident &= !( $mask as $bitfield_type) ;
800
- self . $field_ident |=
801
- ( val as $int_type as $bitfield_type << $offset) &
802
- ( $mask as $bitfield_type) ;
803
- }
804
- }
805
- )
806
- . unwrap ( ) ;
775
+ let field = StructFieldBuilder :: named ( & last_field_name)
776
+ . pub_ ( )
777
+ . build_ty ( ty) ;
778
+ fields. push ( field) ;
807
779
808
- let items = match item. unwrap ( ) . node {
809
- ast:: ItemKind :: Impl ( _, _, _, _, _, items) => items,
810
- _ => unreachable ! ( ) ,
811
- } ;
780
+ // TODO(emilio): dedup this.
781
+ * self . index += 1 ;
782
+ last_field_name = format ! ( "_bitfield_{}" , self . index) ;
812
783
813
- methods. extend ( items. into_iter ( ) ) ;
814
- offset += width;
784
+ // Now reset the size and the rest of stuff.
785
+ // unfilled_bits_in_last_unit = 0;
786
+ field_size_in_bits = 0 ;
787
+ last_field_align = 0 ;
788
+ }
789
+
790
+ // TODO(emilio): Create the accessors. Problem here is that we still
791
+ // don't know which one is going to be the final alignment of the
792
+ // bitfield, and whether we have to index in it. Thus, we don't know
793
+ // which integer type do we need.
794
+ //
795
+ // We could push them to a Vec or something, but given how buggy
796
+ // they where maybe it's not a great idea?
797
+ field_size_in_bits += width as usize ;
798
+ total_size_in_bits += width as usize ;
799
+
800
+
801
+ let data_size = align_to ( field_size_in_bits, field_align * 8 ) ;
802
+
803
+ max_align = cmp:: max ( max_align, field_align) ;
804
+
805
+ // NB: The width here is completely, absolutely intentional.
806
+ last_field_align = cmp:: max ( last_field_align, width as usize ) ;
807
+
808
+ unfilled_bits_in_last_unit = data_size - field_size_in_bits;
815
809
}
816
810
817
- bitfield_layout
811
+ if field_size_in_bits != 0 {
812
+ // Push the last field.
813
+ let ty =
814
+ BlobTyBuilder :: new ( Layout :: new ( bytes_from_bits ( field_size_in_bits) ,
815
+ bytes_from_bits ( last_field_align) ) )
816
+ . build ( ) ;
817
+
818
+ let field = StructFieldBuilder :: named ( & last_field_name)
819
+ . pub_ ( )
820
+ . build_ty ( ty) ;
821
+ fields. push ( field) ;
822
+ }
823
+
824
+ Layout :: new ( bytes_from_bits ( total_size_in_bits) , max_align)
818
825
}
819
826
}
820
827
@@ -1062,12 +1069,10 @@ impl CodeGenerator for CompInfo {
1062
1069
debug_assert ! ( !current_bitfield_fields. is_empty( ) ) ;
1063
1070
let bitfield_fields =
1064
1071
mem:: replace ( & mut current_bitfield_fields, vec ! [ ] ) ;
1065
- bitfield_count += 1 ;
1066
- let bitfield_layout = Bitfield :: new ( bitfield_count,
1072
+ let bitfield_layout = Bitfield :: new ( & mut bitfield_count,
1067
1073
bitfield_fields)
1068
1074
. codegen_fields ( ctx, & mut fields, & mut methods) ;
1069
-
1070
- struct_layout. saw_bitfield ( bitfield_layout) ;
1075
+ struct_layout. saw_bitfield_batch ( bitfield_layout) ;
1071
1076
1072
1077
current_bitfield_width = None ;
1073
1078
current_bitfield_layout = None ;
@@ -1099,8 +1104,7 @@ impl CodeGenerator for CompInfo {
1099
1104
} else {
1100
1105
quote_ty ! ( ctx. ext_cx( ) , __BindgenUnionField<$ty>)
1101
1106
}
1102
- } else if let Some ( item) =
1103
- field_ty. is_incomplete_array ( ctx) {
1107
+ } else if let Some ( item) = field_ty. is_incomplete_array ( ctx) {
1104
1108
result. saw_incomplete_array ( ) ;
1105
1109
1106
1110
let inner = item. to_rust_ty ( ctx) ;
@@ -1224,12 +1228,10 @@ impl CodeGenerator for CompInfo {
1224
1228
debug_assert ! ( !current_bitfield_fields. is_empty( ) ) ;
1225
1229
let bitfield_fields = mem:: replace ( & mut current_bitfield_fields,
1226
1230
vec ! [ ] ) ;
1227
- bitfield_count += 1 ;
1228
- let bitfield_layout = Bitfield :: new ( bitfield_count,
1231
+ let bitfield_layout = Bitfield :: new ( & mut bitfield_count,
1229
1232
bitfield_fields)
1230
1233
. codegen_fields ( ctx, & mut fields, & mut methods) ;
1231
-
1232
- struct_layout. saw_bitfield ( bitfield_layout) ;
1234
+ struct_layout. saw_bitfield_batch ( bitfield_layout) ;
1233
1235
}
1234
1236
debug_assert ! ( current_bitfield_fields. is_empty( ) ) ;
1235
1237
0 commit comments