@@ -448,20 +448,24 @@ impl<'a> ItemCanonicalName for Vtable<'a> {
448
448
}
449
449
}
450
450
451
+ impl < ' a > ItemToRustTy for Vtable < ' a > {
452
+ fn to_rust_ty ( & self , ctx : & BindgenContext ) -> P < ast:: Ty > {
453
+ aster:: ty:: TyBuilder :: new ( ) . id ( self . canonical_name ( ctx) )
454
+ }
455
+ }
456
+
451
457
struct Bitfield < ' a > {
452
458
item : & ' a Item ,
453
459
index : usize ,
454
460
fields : Vec < & ' a Field > ,
455
- layout : Layout ,
456
461
}
457
462
458
463
impl < ' a > Bitfield < ' a > {
459
- fn new ( item : & ' a Item , index : usize , fields : Vec < & ' a Field > , layout : Layout ) -> Self {
464
+ fn new ( item : & ' a Item , index : usize , fields : Vec < & ' a Field > ) -> Self {
460
465
Bitfield {
461
466
item : item,
462
467
index : index,
463
468
fields : fields,
464
- layout : layout,
465
469
}
466
470
}
467
471
@@ -490,15 +494,24 @@ impl<'a> Bitfield<'a> {
490
494
fields : & mut Vec < ast:: StructField > ,
491
495
methods : & mut Vec < ast:: ImplItem > ) {
492
496
use aster:: struct_field:: StructFieldBuilder ;
493
- let bitfield_type = BlobTyBuilder :: new ( self . layout ) . build ( ) ;
497
+ use std:: cmp;
498
+ let mut total_width = self . fields . iter ( )
499
+ . fold ( 0u32 , |acc, f| acc + f. bitfield ( ) . unwrap ( ) ) ;
500
+
501
+ if !total_width. is_power_of_two ( ) || total_width < 8 {
502
+ total_width = cmp:: max ( 8 , total_width. next_power_of_two ( ) ) ;
503
+ }
504
+ debug_assert_eq ! ( total_width % 8 , 0 ) ;
505
+ let total_width_in_bytes = total_width as usize / 8 ;
506
+
507
+ let bitfield_type =
508
+ BlobTyBuilder :: new ( Layout :: new ( total_width_in_bytes, total_width_in_bytes) ) . build ( ) ;
494
509
let field_name = format ! ( "_bitfield_{}" , self . index) ;
510
+ let field_ident = ctx. ext_cx ( ) . ident_of ( & field_name) ;
495
511
let field = StructFieldBuilder :: named ( & field_name) . pub_ ( )
496
512
. build_ty ( bitfield_type. clone ( ) ) ;
497
513
fields. push ( field) ;
498
514
499
- let field_ident = ctx. ext_cx ( ) . ident_of ( & field_name) ;
500
- let total_width = self . fields . iter ( )
501
- . fold ( 0u32 , |acc, f| acc + f. bitfield ( ) . unwrap ( ) ) ;
502
515
503
516
let mut offset = 0 ;
504
517
for field in self . fields {
@@ -571,7 +584,15 @@ impl CodeGenerator for CompInfo {
571
584
if let Some ( comment) = item. comment ( ) {
572
585
attributes. push ( doc ! ( comment) ) ;
573
586
}
574
- attributes. push ( repr ! ( "C" ) ) ;
587
+ if self . packed ( ) {
588
+ // TODO: reuse the repr! macro?
589
+ let c_packed =
590
+ aster:: AstBuilder :: new ( ) . attr ( ) . list ( "repr" )
591
+ . words ( & [ "C" , "packed" ] ) . build ( ) ;
592
+ attributes. push ( c_packed) ;
593
+ } else {
594
+ attributes. push ( repr ! ( "C" ) ) ;
595
+ }
575
596
576
597
let applicable_template_args = item. applicable_template_args ( ctx) ;
577
598
let mut template_args_used = vec ! [ false ; applicable_template_args. len( ) ] ;
@@ -584,21 +605,36 @@ impl CodeGenerator for CompInfo {
584
605
// TODO: I don't know how this could play with virtual methods that are
585
606
// not in the list of methods found by us, we'll see. Also, could the
586
607
// order of the vtable pointers vary?
608
+ //
609
+ // FIXME: Once we generate proper vtables, we need to codegen the
610
+ // vtable, but *not* generate a field for it in the case that
611
+ // needs_explicit_vtable is false but has_vtable is true.
612
+ //
613
+ // Also, we need to generate the vtable in such a way it "inherits" from
614
+ // the parent too.
587
615
let mut fields = vec ! [ ] ;
588
- if self . has_vtable ( ) {
616
+ if self . needs_explicit_vtable ( ctx ) {
589
617
let vtable = Vtable :: new ( item. id ( ) ,
590
618
self . methods ( ) ,
591
619
self . base_members ( ) ) ;
592
620
vtable. codegen ( ctx, result, item) ;
593
621
622
+ let vtable_type = vtable. to_rust_ty ( ctx) . to_ptr ( true , ctx. span ( ) ) ;
623
+
594
624
let vtable_field = StructFieldBuilder :: named ( "vtable_" ) . pub_ ( )
595
- . ty ( ) . id ( vtable . canonical_name ( ctx ) ) ;
625
+ . build_ty ( vtable_type ) ;
596
626
597
627
fields. push ( vtable_field) ;
598
628
}
599
629
600
630
for ( i, base) in self . base_members ( ) . iter ( ) . enumerate ( ) {
601
631
let base_ty = ctx. resolve_type ( * base) ;
632
+ // NB: We won't include unsized types in our base chain because they
633
+ // would contribute to our size given the dummy field we insert for
634
+ // unsized types.
635
+ if base_ty. expect_comp ( ) . is_unsized ( ctx) {
636
+ continue ;
637
+ }
602
638
for ( i, ty) in applicable_template_args. iter ( ) . enumerate ( ) {
603
639
if base_ty. signature_contains_named_type ( ctx, ctx. resolve_type ( * ty) ) {
604
640
template_args_used[ i] = true ;
@@ -619,12 +655,13 @@ impl CodeGenerator for CompInfo {
619
655
let layout = item. kind ( ) . expect_type ( ) . layout ( ctx) ;
620
656
621
657
let mut current_bitfield_width = None ;
622
- let mut current_bitfield_layout = None ;
658
+ let mut current_bitfield_layout: Option < Layout > = None ;
623
659
let mut current_bitfield_fields = vec ! [ ] ;
624
660
let mut bitfield_count = 0 ;
625
661
let struct_fields = self . fields ( ) ;
626
662
627
663
let mut methods = vec ! [ ] ;
664
+ let mut anonymous_field_count = 0 ;
628
665
for field in struct_fields {
629
666
debug_assert_eq ! ( current_bitfield_width. is_some( ) ,
630
667
current_bitfield_layout. is_some( ) ) ;
@@ -635,8 +672,9 @@ impl CodeGenerator for CompInfo {
635
672
636
673
// Try to catch a bitfield contination early.
637
674
if let ( Some ( ref mut bitfield_width) , Some ( width) ) = ( current_bitfield_width, field. bitfield ( ) ) {
638
- let layout = field_ty. layout ( ctx)
639
- . expect ( "How can a type in a bitfield have no layout?" ) ;
675
+ let layout = current_bitfield_layout. unwrap ( ) ;
676
+ debug ! ( "Testing bitfield continuation {} {} {:?}" ,
677
+ * bitfield_width, width, layout) ;
640
678
if * bitfield_width + width <= ( layout. size * 8 ) as u32 {
641
679
* bitfield_width += width;
642
680
current_bitfield_fields. push ( field) ;
@@ -650,8 +688,7 @@ impl CodeGenerator for CompInfo {
650
688
let bitfield_fields =
651
689
mem:: replace ( & mut current_bitfield_fields, vec ! [ ] ) ;
652
690
bitfield_count += 1 ;
653
- Bitfield :: new ( item, bitfield_count, bitfield_fields,
654
- current_bitfield_layout. unwrap ( ) )
691
+ Bitfield :: new ( item, bitfield_count, bitfield_fields)
655
692
. codegen_fields ( ctx, & mut fields, & mut methods) ;
656
693
current_bitfield_width = None ;
657
694
current_bitfield_layout = None ;
@@ -660,7 +697,7 @@ impl CodeGenerator for CompInfo {
660
697
661
698
if let Some ( width) = field. bitfield ( ) {
662
699
let layout = field_ty. layout ( ctx)
663
- . expect ( "How can a type in a bitfield have no layout?" ) ;
700
+ . expect ( "Bitfield type without layout?" ) ;
664
701
current_bitfield_width = Some ( width) ;
665
702
current_bitfield_layout = Some ( layout) ;
666
703
current_bitfield_fields. push ( field) ;
@@ -685,8 +722,14 @@ impl CodeGenerator for CompInfo {
685
722
if let Some ( comment) = field. comment ( ) {
686
723
attrs. push ( doc ! ( comment) ) ;
687
724
}
688
-
689
- let field = StructFieldBuilder :: named ( field. name ( ) . unwrap ( ) ) . pub_ ( )
725
+ let field_name = match field. name ( ) {
726
+ Some ( name) => name. to_owned ( ) ,
727
+ None => {
728
+ anonymous_field_count += 1 ;
729
+ format ! ( "__bindgen_anon_{}" , anonymous_field_count)
730
+ }
731
+ } ;
732
+ let field = StructFieldBuilder :: named ( field_name) . pub_ ( )
690
733
. with_attrs ( attrs)
691
734
. build_ty ( ty) ;
692
735
fields. push ( field) ;
@@ -695,12 +738,12 @@ impl CodeGenerator for CompInfo {
695
738
// Flush the last bitfield if any.
696
739
//
697
740
// FIXME: Reduce duplication with the loop above.
741
+ // FIXME: May need to pass current_bitfield_layout too.
698
742
if current_bitfield_width. is_some ( ) {
699
743
debug_assert ! ( !current_bitfield_fields. is_empty( ) ) ;
700
744
let bitfield_fields = mem:: replace ( & mut current_bitfield_fields, vec ! [ ] ) ;
701
745
bitfield_count += 1 ;
702
- Bitfield :: new ( item, bitfield_count, bitfield_fields,
703
- current_bitfield_layout. unwrap ( ) )
746
+ Bitfield :: new ( item, bitfield_count, bitfield_fields)
704
747
. codegen_fields ( ctx, & mut fields, & mut methods) ;
705
748
}
706
749
debug_assert ! ( current_bitfield_fields. is_empty( ) ) ;
@@ -716,6 +759,7 @@ impl CodeGenerator for CompInfo {
716
759
// Yeah, sorry about that.
717
760
if item. opaque ( ctx) {
718
761
fields. clear ( ) ;
762
+ methods. clear ( ) ;
719
763
for i in 0 ..template_args_used. len ( ) {
720
764
template_args_used[ i] = false ;
721
765
}
@@ -733,6 +777,18 @@ impl CodeGenerator for CompInfo {
733
777
}
734
778
}
735
779
780
+ // C requires every struct to be addressable, so what C compilers do is
781
+ // making the struct 1-byte sized.
782
+ //
783
+ // NOTE: This check is conveniently here to avoid the dummy fields we
784
+ // may add for unused template parameters.
785
+ if self . is_unsized ( ctx) {
786
+ let ty = BlobTyBuilder :: new ( Layout :: new ( 1 , 1 ) ) . build ( ) ;
787
+ let field = StructFieldBuilder :: named ( "_address" ) . pub_ ( )
788
+ . build_ty ( ty) ;
789
+ fields. push ( field) ;
790
+ }
791
+
736
792
// Append any extra template arguments that nobody has used so far.
737
793
for ( i, ty) in applicable_template_args. iter ( ) . enumerate ( ) {
738
794
if !template_args_used[ i] {
@@ -781,11 +837,36 @@ impl CodeGenerator for CompInfo {
781
837
ctx. resolve_item ( * ty) . codegen ( ctx, result, & ( ) ) ;
782
838
}
783
839
784
- if applicable_template_args. is_empty ( ) {
840
+ // NOTE: Some unexposed attributes (like alignment attributes) may
841
+ // affect layout, so we're bad and pray to the gods for avoid sending
842
+ // all the tests to shit when parsing things like max_align_t.
843
+ if self . found_unknown_attr ( ) {
844
+ warn ! ( "Type {} has an unkown attribute that may affect layout" , canonical_name) ;
845
+ }
846
+ if applicable_template_args. is_empty ( ) && !self . found_unknown_attr ( ) {
785
847
for var in self . inner_vars ( ) {
786
848
ctx. resolve_item ( * var) . codegen ( ctx, result, & ( ) ) ;
787
849
}
788
850
851
+ if let Some ( layout) = layout {
852
+ let fn_name =
853
+ ctx. rust_ident_raw ( format ! ( "bindgen_test_layout_{}" , canonical_name) ) ;
854
+ let ident = ctx. rust_ident_raw ( canonical_name) ;
855
+ let size_of_expr =
856
+ quote_expr ! ( ctx. ext_cx( ) , :: std:: mem:: size_of:: <$ident>( ) ) ;
857
+ let align_of_expr =
858
+ quote_expr ! ( ctx. ext_cx( ) , :: std:: mem:: align_of:: <$ident>( ) ) ;
859
+ let size = layout. size ;
860
+ let align = layout. align ;
861
+ let item = quote_item ! ( ctx. ext_cx( ) ,
862
+ #[ test]
863
+ fn $fn_name( ) {
864
+ assert_eq!( $size_of_expr, $size) ;
865
+ assert_eq!( $align_of_expr, $align) ;
866
+ } ) . unwrap ( ) ;
867
+ result. push ( item) ;
868
+ }
869
+
789
870
for method in self . methods ( ) {
790
871
if !method. is_virtual ( ) {
791
872
ctx. resolve_item ( method. signature ( ) ) . codegen ( ctx, result, & ( ) ) ;
0 commit comments