@@ -12,6 +12,7 @@ use ir::layout::Layout;
12
12
13
13
use std:: ops;
14
14
use std:: mem;
15
+ use std:: collections:: BTreeSet ;
15
16
use std:: collections:: hash_map:: { HashMap , Entry } ;
16
17
17
18
use syntax:: abi:: Abi ;
@@ -489,26 +490,6 @@ impl<'a> Bitfield<'a> {
489
490
}
490
491
}
491
492
492
- fn type_for_bitfield_width ( ctx : & BindgenContext , width : u32 , is_arg : bool ) -> P < ast:: Ty > {
493
- let input_type = if width > 16 {
494
- "u32"
495
- } else if width > 8 {
496
- "u16"
497
- } else if width > 1 {
498
- "u8"
499
- } else {
500
- if is_arg {
501
- "bool"
502
- } else {
503
- "u8"
504
- }
505
- } ;
506
-
507
- let ident = ctx. rust_ident_raw ( input_type) ;
508
- quote_ty ! ( ctx. ext_cx( ) , $ident)
509
- }
510
-
511
-
512
493
fn codegen_fields ( self ,
513
494
ctx : & BindgenContext ,
514
495
fields : & mut Vec < ast:: StructField > ,
@@ -1400,14 +1381,173 @@ impl CodeGenerator for Function {
1400
1381
}
1401
1382
}
1402
1383
1384
+ type ItemSet = BTreeSet < ItemId > ;
1385
+
1386
+ trait TypeCollector {
1387
+ type Extra ;
1388
+
1389
+ fn collect_types ( & self ,
1390
+ context : & BindgenContext ,
1391
+ types : & mut ItemSet ,
1392
+ extra : & Self :: Extra ) ;
1393
+ }
1394
+
1395
+ impl TypeCollector for ItemId {
1396
+ type Extra = ( ) ;
1397
+
1398
+ fn collect_types ( & self ,
1399
+ context : & BindgenContext ,
1400
+ types : & mut ItemSet ,
1401
+ extra : & ( ) ) {
1402
+ context. resolve_item ( * self ) . collect_types ( context, types, extra) ;
1403
+ }
1404
+ }
1405
+
1406
+ impl TypeCollector for Item {
1407
+ type Extra = ( ) ;
1408
+
1409
+ fn collect_types ( & self ,
1410
+ context : & BindgenContext ,
1411
+ types : & mut ItemSet ,
1412
+ _extra : & ( ) ) {
1413
+ if self . hidden ( context) || types. contains ( & self . id ( ) ) {
1414
+ return ;
1415
+ }
1416
+
1417
+ println ! ( "Collecting: {:?}" , self . id( ) ) ;
1418
+
1419
+ match * self . kind ( ) {
1420
+ ItemKind :: Type ( ref ty) => {
1421
+ types. insert ( self . id ( ) ) ;
1422
+ if !self . opaque ( context) {
1423
+ ty. collect_types ( context, types, self ) ;
1424
+ }
1425
+ }
1426
+ _ => { } , // FIXME.
1427
+ }
1428
+ }
1429
+ }
1430
+
1431
+ impl TypeCollector for Type {
1432
+ type Extra = Item ;
1433
+
1434
+ fn collect_types ( & self ,
1435
+ context : & BindgenContext ,
1436
+ types : & mut ItemSet ,
1437
+ item : & Item ) {
1438
+ match * self . kind ( ) {
1439
+ TypeKind :: Pointer ( inner) |
1440
+ TypeKind :: Reference ( inner) |
1441
+ TypeKind :: Array ( inner, _) |
1442
+ TypeKind :: Alias ( _, inner) |
1443
+ TypeKind :: Named ( _, Some ( inner) )
1444
+ => inner. collect_types ( context, types, & ( ) ) ,
1445
+
1446
+ TypeKind :: TemplateRef ( inner, ref template_args) => {
1447
+ inner. collect_types ( context, types, & ( ) ) ;
1448
+ for item in template_args {
1449
+ item. collect_types ( context, types, & ( ) ) ;
1450
+ }
1451
+ }
1452
+ TypeKind :: Comp ( ref ci) => ci. collect_types ( context, types, item) ,
1453
+ // FIXME: Pending types!
1454
+ ref other @ _ => {
1455
+ println ! ( "Ignoring: {:?}" , other) ;
1456
+ } ,
1457
+ }
1458
+ }
1459
+ }
1460
+
1461
+ impl TypeCollector for CompInfo {
1462
+ type Extra = Item ;
1463
+
1464
+ fn collect_types ( & self ,
1465
+ context : & BindgenContext ,
1466
+ types : & mut ItemSet ,
1467
+ item : & Item ) {
1468
+ if let Some ( template) = self . specialized_template ( ) {
1469
+ template. collect_types ( context, types, & ( ) ) ;
1470
+ }
1471
+
1472
+ let applicable_template_args = item. applicable_template_args ( context) ;
1473
+ for arg in applicable_template_args {
1474
+ arg. collect_types ( context, types, & ( ) ) ;
1475
+ }
1476
+
1477
+ for base in self . base_members ( ) {
1478
+ base. collect_types ( context, types, & ( ) ) ;
1479
+ }
1480
+
1481
+ for field in self . fields ( ) {
1482
+ field. ty ( ) . collect_types ( context, types, & ( ) ) ;
1483
+ }
1484
+
1485
+ for ty in self . inner_types ( ) {
1486
+ ty. collect_types ( context, types, & ( ) ) ;
1487
+ }
1488
+
1489
+ // FIXME(emilio): Methods, VTable?
1490
+ }
1491
+ }
1492
+
1403
1493
pub fn codegen ( context : & mut BindgenContext ) -> Vec < P < ast:: Item > > {
1404
1494
context. gen ( |context| {
1405
1495
let mut result = CodegenResult :: new ( ) ;
1406
- for ( _item_id, item) in context. items ( ) {
1407
- // Non-toplevel item parents are the responsible one for generating
1408
- // them.
1409
- if item. is_toplevel ( context) {
1410
- item. codegen ( context, & mut result, & ( ) ) ;
1496
+
1497
+ debug ! ( "codegen: {:?}" , context. options( ) ) ;
1498
+
1499
+ // If the whitelisted types set is empty, just generate everything.
1500
+ if context. options ( ) . whitelisted_types . is_empty ( ) {
1501
+ for ( _item_id, item) in context. items ( ) {
1502
+ // Non-toplevel item parents are the responsible one for generating
1503
+ // them.
1504
+ if item. is_toplevel ( context) {
1505
+ item. codegen ( context, & mut result, & ( ) ) ;
1506
+ }
1507
+ }
1508
+ } else {
1509
+ // Recursively collect all the types dependent on the whitelisted
1510
+ // types, then generate them.
1511
+ //
1512
+ // FIXME(emilio): This pass is probably slow, but it can't be faster
1513
+ // than docopt anyway :)
1514
+ let mut types = ItemSet :: new ( ) ;
1515
+ for ( _item_id, item) in context. items ( ) {
1516
+ // FIXME(emilio): This only works for types, but we need to
1517
+ // eventually come with a coherent history for functions...
1518
+ //
1519
+ // Whitelisting any type touched by a function seems overkill,
1520
+ // maybe another pass whitelisting functions that only contain
1521
+ // whitelisted types?
1522
+ if item. kind ( ) . is_type ( ) && item. is_toplevel ( context) {
1523
+ let name = item. canonical_name ( context) ;
1524
+ if context. options ( ) . whitelisted_types . contains ( & name) {
1525
+ item. collect_types ( context, & mut types, & ( ) ) ;
1526
+ }
1527
+ }
1528
+ }
1529
+
1530
+ fn contains_parent ( ctx : & BindgenContext , types : & ItemSet , id : ItemId ) -> bool {
1531
+ let item = ctx. resolve_item ( id) ;
1532
+ let mut last = id;
1533
+ let mut current = item. parent_id ( ) ;
1534
+
1535
+ while last != current {
1536
+ if types. contains ( & current) {
1537
+ return true ;
1538
+ }
1539
+ last = current;
1540
+ current = ctx. resolve_item ( current) . parent_id ( ) ;
1541
+ }
1542
+
1543
+ false
1544
+ }
1545
+
1546
+ for item_id in types. iter ( ) {
1547
+ let item = context. resolve_item ( * item_id) ;
1548
+ if item. is_toplevel ( context) || !contains_parent ( context, & types, * item_id) {
1549
+ item. codegen ( context, & mut result, & ( ) ) ;
1550
+ }
1411
1551
}
1412
1552
}
1413
1553
let saw_union = result. saw_union ;
0 commit comments