1
1
mod helpers;
2
+ mod struct_layout;
2
3
3
4
use self :: helpers:: { BlobTyBuilder , attributes} ;
5
+ use self :: struct_layout:: StructLayoutTracker ;
4
6
use aster;
5
7
6
8
use ir:: annotations:: FieldAccessorKind ;
@@ -21,6 +23,7 @@ use ir::var::Var;
21
23
22
24
use std:: borrow:: Cow ;
23
25
use std:: cell:: Cell ;
26
+ use std:: cmp;
24
27
use std:: collections:: { HashSet , VecDeque } ;
25
28
use std:: collections:: hash_map:: { Entry , HashMap } ;
26
29
use std:: fmt:: Write ;
@@ -723,9 +726,9 @@ impl<'a> Bitfield<'a> {
723
726
fn codegen_fields ( self ,
724
727
ctx : & BindgenContext ,
725
728
fields : & mut Vec < ast:: StructField > ,
726
- methods : & mut Vec < ast:: ImplItem > ) {
729
+ methods : & mut Vec < ast:: ImplItem > )
730
+ -> Layout {
727
731
use aster:: struct_field:: StructFieldBuilder ;
728
- use std:: cmp;
729
732
let mut total_width = self . fields
730
733
. iter ( )
731
734
. fold ( 0u32 , |acc, f| acc + f. bitfield ( ) . unwrap ( ) ) ;
@@ -736,10 +739,9 @@ impl<'a> Bitfield<'a> {
736
739
debug_assert_eq ! ( total_width % 8 , 0 ) ;
737
740
let total_width_in_bytes = total_width as usize / 8 ;
738
741
739
- let bitfield_type =
740
- BlobTyBuilder :: new ( Layout :: new ( total_width_in_bytes,
741
- total_width_in_bytes) )
742
- . build ( ) ;
742
+ let bitfield_layout = Layout :: new ( total_width_in_bytes,
743
+ total_width_in_bytes) ;
744
+ let bitfield_type = BlobTyBuilder :: new ( bitfield_layout) . build ( ) ;
743
745
let field_name = format ! ( "_bitfield_{}" , self . index) ;
744
746
let field_ident = ctx. ext_cx ( ) . ident_of ( & field_name) ;
745
747
let field = StructFieldBuilder :: named ( & field_name)
@@ -805,6 +807,8 @@ impl<'a> Bitfield<'a> {
805
807
methods. extend ( items. into_iter ( ) ) ;
806
808
offset += width;
807
809
}
810
+
811
+ bitfield_layout
808
812
}
809
813
}
810
814
@@ -940,6 +944,7 @@ impl CodeGenerator for CompInfo {
940
944
// Also, we need to generate the vtable in such a way it "inherits" from
941
945
// the parent too.
942
946
let mut fields = vec ! [ ] ;
947
+ let mut struct_layout = StructLayoutTracker :: new ( ctx, self ) ;
943
948
if self . needs_explicit_vtable ( ctx) {
944
949
let vtable =
945
950
Vtable :: new ( item. id ( ) , self . methods ( ) , self . base_members ( ) ) ;
@@ -951,6 +956,8 @@ impl CodeGenerator for CompInfo {
951
956
. pub_ ( )
952
957
. build_ty ( vtable_type) ;
953
958
959
+ struct_layout. saw_vtable ( ) ;
960
+
954
961
fields. push ( vtable_field) ;
955
962
}
956
963
@@ -985,6 +992,8 @@ impl CodeGenerator for CompInfo {
985
992
format ! ( "_base_{}" , i)
986
993
} ;
987
994
995
+ struct_layout. saw_base ( base_ty) ;
996
+
988
997
let field = StructFieldBuilder :: named ( field_name)
989
998
. pub_ ( )
990
999
. build_ty ( inner) ;
@@ -1039,8 +1048,12 @@ impl CodeGenerator for CompInfo {
1039
1048
let bitfield_fields =
1040
1049
mem:: replace ( & mut current_bitfield_fields, vec ! [ ] ) ;
1041
1050
bitfield_count += 1 ;
1042
- Bitfield :: new ( bitfield_count, bitfield_fields)
1051
+ let bitfield_layout = Bitfield :: new ( bitfield_count,
1052
+ bitfield_fields)
1043
1053
. codegen_fields ( ctx, & mut fields, & mut methods) ;
1054
+
1055
+ struct_layout. saw_bitfield ( bitfield_layout) ;
1056
+
1044
1057
current_bitfield_width = None ;
1045
1058
current_bitfield_layout = None ;
1046
1059
}
@@ -1100,6 +1113,11 @@ impl CodeGenerator for CompInfo {
1100
1113
}
1101
1114
} ;
1102
1115
1116
+ if let Some ( padding_field) =
1117
+ struct_layout. pad_field ( & field_name, field_ty, field. offset ( ) ) {
1118
+ fields. push ( padding_field) ;
1119
+ }
1120
+
1103
1121
let is_private = field. annotations ( )
1104
1122
. private_fields ( )
1105
1123
. unwrap_or ( fields_should_be_private) ;
@@ -1192,8 +1210,11 @@ impl CodeGenerator for CompInfo {
1192
1210
let bitfield_fields = mem:: replace ( & mut current_bitfield_fields,
1193
1211
vec ! [ ] ) ;
1194
1212
bitfield_count += 1 ;
1195
- Bitfield :: new ( bitfield_count, bitfield_fields)
1213
+ let bitfield_layout = Bitfield :: new ( bitfield_count,
1214
+ bitfield_fields)
1196
1215
. codegen_fields ( ctx, & mut fields, & mut methods) ;
1216
+
1217
+ struct_layout. saw_bitfield ( bitfield_layout) ;
1197
1218
}
1198
1219
debug_assert ! ( current_bitfield_fields. is_empty( ) ) ;
1199
1220
@@ -1203,6 +1224,9 @@ impl CodeGenerator for CompInfo {
1203
1224
let field = StructFieldBuilder :: named ( "bindgen_union_field" )
1204
1225
. pub_ ( )
1205
1226
. build_ty ( ty) ;
1227
+
1228
+ struct_layout. saw_union ( layout) ;
1229
+
1206
1230
fields. push ( field) ;
1207
1231
}
1208
1232
@@ -1227,6 +1251,16 @@ impl CodeGenerator for CompInfo {
1227
1251
warn ! ( "Opaque type without layout! Expect dragons!" ) ;
1228
1252
}
1229
1253
}
1254
+ } else if !is_union && !self . is_unsized ( ctx) {
1255
+ if let Some ( padding_field) =
1256
+ layout. and_then ( |layout| struct_layout. pad_struct ( layout) ) {
1257
+ fields. push ( padding_field) ;
1258
+ }
1259
+
1260
+ if let Some ( align_field) =
1261
+ layout. and_then ( |layout| struct_layout. align_struct ( layout) ) {
1262
+ fields. push ( align_field) ;
1263
+ }
1230
1264
}
1231
1265
1232
1266
// C requires every struct to be addressable, so what C compilers do is
@@ -1296,7 +1330,7 @@ impl CodeGenerator for CompInfo {
1296
1330
canonical_name) ;
1297
1331
}
1298
1332
1299
- if applicable_template_args. is_empty ( ) && ! self . found_unknown_attr ( ) {
1333
+ if applicable_template_args. is_empty ( ) {
1300
1334
for var in self . inner_vars ( ) {
1301
1335
ctx. resolve_item ( * var)
1302
1336
. codegen ( ctx, result, whitelisted_items, & ( ) ) ;
@@ -1313,11 +1347,57 @@ impl CodeGenerator for CompInfo {
1313
1347
:: $prefix:: mem:: align_of:: <$ident>( ) ) ;
1314
1348
let size = layout. size ;
1315
1349
let align = layout. align ;
1350
+
1351
+ let check_struct_align = if align > mem:: size_of :: < * mut ( ) > ( ) {
1352
+ // FIXME when [RFC 1358](https://github.com/rust-lang/rust/issues/33626) ready
1353
+ None
1354
+ } else {
1355
+ quote_item ! ( ctx. ext_cx( ) ,
1356
+ assert_eq!( $align_of_expr, $align) ;
1357
+ )
1358
+ } ;
1359
+
1360
+ // FIXME when [issue #465](https://github.com/servo/rust-bindgen/issues/465) ready
1361
+ let too_many_base_vtables = self . base_members ( )
1362
+ . iter ( )
1363
+ . filter ( |base| ctx. resolve_type ( base. ty ) . has_vtable ( ctx) )
1364
+ . count ( ) >
1365
+ 1 ;
1366
+
1367
+ let should_skip_field_offset_checks = item. is_opaque ( ctx) ||
1368
+ too_many_base_vtables;
1369
+
1370
+ let check_field_offset = if should_skip_field_offset_checks {
1371
+ None
1372
+ } else {
1373
+ let type_name = ctx. rust_ident ( & canonical_name) ;
1374
+
1375
+ let asserts = self . fields ( )
1376
+ . iter ( )
1377
+ . filter ( |field| field. bitfield ( ) . is_none ( ) )
1378
+ . flat_map ( |field| {
1379
+ field. name ( ) . and_then ( |name| {
1380
+ field. offset ( ) . and_then ( |offset| {
1381
+ let field_offset = offset / 8 ;
1382
+ let field_name = ctx. rust_ident ( name) ;
1383
+
1384
+ quote_item ! ( ctx. ext_cx( ) ,
1385
+ assert_eq!( unsafe { & ( * ( 0 as * const $type_name) ) . $field_name as * const _ as usize } , $field_offset) ;
1386
+ )
1387
+ } )
1388
+ } )
1389
+ } ) . collect :: < Vec < P < ast:: Item > > > ( ) ;
1390
+
1391
+ Some ( asserts)
1392
+ } ;
1393
+
1316
1394
let item = quote_item ! ( ctx. ext_cx( ) ,
1317
1395
#[ test]
1318
1396
fn $fn_name( ) {
1319
1397
assert_eq!( $size_of_expr, $size) ;
1320
- assert_eq!( $align_of_expr, $align) ;
1398
+
1399
+ $check_struct_align
1400
+ $check_field_offset
1321
1401
} )
1322
1402
. unwrap ( ) ;
1323
1403
result. push ( item) ;
@@ -2278,22 +2358,20 @@ impl CodeGenerator for ObjCInterface {
2278
2358
2279
2359
// Collect the actual used argument names
2280
2360
let arg_names: Vec < _ > = fn_args. iter ( )
2281
- . map ( |ref arg| {
2282
- match arg. pat . node {
2283
- ast:: PatKind :: Ident ( _, ref spanning, _) => {
2284
- spanning. node . name . as_str ( ) . to_string ( )
2285
- }
2286
- _ => {
2287
- panic ! ( "odd argument!" ) ;
2288
- }
2361
+ . map ( |ref arg| match arg. pat . node {
2362
+ ast:: PatKind :: Ident ( _, ref spanning, _) => {
2363
+ spanning. node . name . as_str ( ) . to_string ( )
2364
+ }
2365
+ _ => {
2366
+ panic ! ( "odd argument!" ) ;
2289
2367
}
2290
2368
} )
2291
2369
. collect ( ) ;
2292
2370
2293
2371
let methods_and_args =
2294
2372
ctx. rust_ident ( & method. format_method_call ( & arg_names) ) ;
2295
- let body =
2296
- quote_stmt ! ( ctx . ext_cx ( ) , msg_send![ self , $methods_and_args] )
2373
+ let body = quote_stmt ! ( ctx . ext_cx ( ) ,
2374
+ msg_send![ self , $methods_and_args] )
2297
2375
. unwrap ( ) ;
2298
2376
let block = ast:: Block {
2299
2377
stmts : vec ! [ body] ,
@@ -2729,5 +2807,4 @@ mod utils {
2729
2807
}
2730
2808
} ) . collect :: < Vec < _ > > ( )
2731
2809
}
2732
-
2733
2810
}
0 commit comments