@@ -6,7 +6,7 @@ use aster;
6
6
use ir:: annotations:: FieldAccessorKind ;
7
7
use ir:: comp:: { CompInfo , CompKind , Field , Method } ;
8
8
use ir:: context:: BindgenContext ;
9
- use ir:: enum_ty:: Enum ;
9
+ use ir:: enum_ty:: { Enum , EnumVariant , EnumVariantValue } ;
10
10
use ir:: function:: { Function , FunctionSig } ;
11
11
use ir:: int:: IntKind ;
12
12
use ir:: item:: { Item , ItemCanonicalName , ItemCanonicalPath , ItemId } ;
@@ -1224,6 +1224,7 @@ impl MethodCodegen for Method {
1224
1224
}
1225
1225
}
1226
1226
1227
+ /// A helper type to construct enums, either bitfield ones or rust-style ones.
1227
1228
enum EnumBuilder < ' a > {
1228
1229
Rust ( aster:: item:: ItemEnumBuilder < aster:: invoke:: Identity > ) ,
1229
1230
Bitfield {
@@ -1233,6 +1234,8 @@ enum EnumBuilder<'a> {
1233
1234
}
1234
1235
1235
1236
impl < ' a > EnumBuilder < ' a > {
1237
+ /// Create a new enum given an item builder, a canonical name, a name for
1238
+ /// the representation, and whether it should be represented as a rust enum.
1236
1239
fn new ( aster : aster:: item:: ItemBuilder < aster:: invoke:: Identity > ,
1237
1240
name : & ' a str ,
1238
1241
repr_name : & str ,
@@ -1253,29 +1256,42 @@ impl<'a> EnumBuilder<'a> {
1253
1256
}
1254
1257
}
1255
1258
1256
- fn with_variant_ ( self ,
1257
- ctx : & BindgenContext ,
1258
- name : & str ,
1259
- expr : P < ast:: Expr > ,
1260
- rust_ty : P < ast:: Ty > ,
1261
- result : & mut CodegenResult )
1262
- -> Self {
1259
+ /// Add a variant to this enum.
1260
+ fn with_variant ( self ,
1261
+ ctx : & BindgenContext ,
1262
+ variant : & EnumVariant ,
1263
+ mangling_prefix : Option < & String > ,
1264
+ rust_ty : P < ast:: Ty > ,
1265
+ result : & mut CodegenResult )
1266
+ -> Self {
1267
+ let variant_name = ctx. rust_mangle ( variant. name ( ) ) ;
1268
+ let expr = aster:: AstBuilder :: new ( ) . expr ( ) ;
1269
+ let expr = match variant. val ( ) {
1270
+ EnumVariantValue :: Signed ( v) => expr. int ( v) ,
1271
+ EnumVariantValue :: Unsigned ( v) => expr. uint ( v) ,
1272
+ } ;
1273
+
1263
1274
match self {
1264
1275
EnumBuilder :: Rust ( b) => {
1265
1276
EnumBuilder :: Rust ( b. with_variant_ ( ast:: Variant_ {
1266
- name : ctx. rust_ident ( name ) ,
1277
+ name : ctx. rust_ident ( & * variant_name ) ,
1267
1278
attrs : vec ! [ ] ,
1268
1279
data : ast:: VariantData :: Unit ( ast:: DUMMY_NODE_ID ) ,
1269
1280
disr_expr : Some ( expr) ,
1270
1281
} ) )
1271
1282
}
1272
1283
EnumBuilder :: Bitfield { canonical_name, .. } => {
1273
- // FIXME: Probably if unnamed we should be smarter! Easy to
1274
- // improve.
1275
- let constant_name = format ! ( "{}_{}" , canonical_name, name) ;
1284
+ let constant_name = match mangling_prefix {
1285
+ Some ( prefix) => {
1286
+ Cow :: Owned ( format ! ( "{}_{}" , prefix, variant_name) )
1287
+ }
1288
+ None => variant_name,
1289
+ } ;
1290
+
1276
1291
let constant = aster:: AstBuilder :: new ( )
1277
1292
. item ( )
1278
- . const_ ( constant_name)
1293
+ . pub_ ( )
1294
+ . const_ ( & * constant_name)
1279
1295
. expr ( )
1280
1296
. call ( )
1281
1297
. id ( canonical_name)
@@ -1289,10 +1305,32 @@ impl<'a> EnumBuilder<'a> {
1289
1305
}
1290
1306
}
1291
1307
1292
- fn build ( self ) -> P < ast:: Item > {
1308
+ fn build ( self ,
1309
+ ctx : & BindgenContext ,
1310
+ rust_ty : P < ast:: Ty > ,
1311
+ result : & mut CodegenResult )
1312
+ -> P < ast:: Item > {
1293
1313
match self {
1294
1314
EnumBuilder :: Rust ( b) => b. build ( ) ,
1295
- EnumBuilder :: Bitfield { aster, .. } => aster,
1315
+ EnumBuilder :: Bitfield { canonical_name, aster } => {
1316
+ let rust_ty_name = ctx. rust_ident_raw ( canonical_name) ;
1317
+ let prefix = ctx. trait_prefix ( ) ;
1318
+
1319
+ let impl_ = quote_item ! ( ctx. ext_cx( ) ,
1320
+ impl :: $prefix:: ops:: BitOr <$rust_ty> for $rust_ty {
1321
+ type Output = Self ;
1322
+
1323
+ #[ inline]
1324
+ fn bitor( self , other: Self ) -> Self {
1325
+ $rust_ty_name( self . 0 | other. 0 )
1326
+ }
1327
+ }
1328
+ )
1329
+ . unwrap ( ) ;
1330
+
1331
+ result. push ( impl_) ;
1332
+ aster
1333
+ }
1296
1334
}
1297
1335
}
1298
1336
}
@@ -1304,8 +1342,6 @@ impl CodeGenerator for Enum {
1304
1342
ctx : & BindgenContext ,
1305
1343
result : & mut CodegenResult ,
1306
1344
item : & Item ) {
1307
- use ir:: enum_ty:: EnumVariantValue ;
1308
-
1309
1345
let name = item. canonical_name ( ctx) ;
1310
1346
let enum_ty = item. expect_type ( ) ;
1311
1347
let layout = enum_ty. layout ( ctx) ;
@@ -1404,15 +1440,27 @@ impl CodeGenerator for Enum {
1404
1440
result. push ( constant) ;
1405
1441
}
1406
1442
1407
- // Used to mangle the constants we generate in the unnamed-enum case.
1408
- let mut parent_canonical_name = None ;
1409
-
1410
1443
let mut builder =
1411
1444
EnumBuilder :: new ( builder, & name, repr_name, is_rust_enum) ;
1412
1445
1413
1446
// A map where we keep a value -> variant relation.
1414
1447
let mut seen_values = HashMap :: < _ , String > :: new ( ) ;
1415
1448
let enum_rust_ty = item. to_rust_ty ( ctx) ;
1449
+ let is_toplevel = item. is_toplevel ( ctx) ;
1450
+
1451
+ // Used to mangle the constants we generate in the unnamed-enum case.
1452
+ let parent_canonical_name = if is_toplevel {
1453
+ None
1454
+ } else {
1455
+ Some ( item. parent_id ( ) . canonical_name ( ctx) )
1456
+ } ;
1457
+
1458
+ let constant_mangling_prefix = if enum_ty. name ( ) . is_none ( ) {
1459
+ parent_canonical_name. as_ref ( ) . map ( |n| & * n)
1460
+ } else {
1461
+ Some ( & name)
1462
+ } ;
1463
+
1416
1464
for variant in self . variants ( ) . iter ( ) {
1417
1465
match seen_values. entry ( variant. val ( ) ) {
1418
1466
Entry :: Occupied ( ref entry) => {
@@ -1426,46 +1474,30 @@ impl CodeGenerator for Enum {
1426
1474
enum_rust_ty. clone ( ) ,
1427
1475
result) ;
1428
1476
} else {
1429
- // FIXME: Don't repeat this block below.
1430
- let expr = aster:: AstBuilder :: new ( ) . expr ( ) ;
1431
- let expr = match variant. val ( ) {
1432
- EnumVariantValue :: Signed ( val) => expr. int ( val) ,
1433
- EnumVariantValue :: Unsigned ( val) => expr. uint ( val) ,
1434
- } ;
1435
- let variant_name = ctx. rust_mangle ( variant. name ( ) ) ;
1436
- builder = builder. with_variant_ ( ctx,
1437
- & * variant_name,
1438
- expr,
1439
- enum_rust_ty. clone ( ) ,
1440
- result) ;
1477
+ builder = builder. with_variant ( ctx,
1478
+ variant,
1479
+ constant_mangling_prefix,
1480
+ enum_rust_ty. clone ( ) ,
1481
+ result) ;
1441
1482
}
1442
1483
}
1443
1484
Entry :: Vacant ( entry) => {
1444
- let expr = aster:: AstBuilder :: new ( ) . expr ( ) ;
1445
- let expr = match variant. val ( ) {
1446
- EnumVariantValue :: Signed ( val) => expr. int ( val) ,
1447
- EnumVariantValue :: Unsigned ( val) => expr. uint ( val) ,
1448
- } ;
1485
+ builder = builder. with_variant ( ctx,
1486
+ variant,
1487
+ constant_mangling_prefix,
1488
+ enum_rust_ty. clone ( ) ,
1489
+ result) ;
1490
+
1449
1491
let variant_name = ctx. rust_mangle ( variant. name ( ) ) ;
1450
- builder = builder. with_variant_ ( ctx,
1451
- & * variant_name,
1452
- expr,
1453
- enum_rust_ty. clone ( ) ,
1454
- result) ;
1455
1492
1456
1493
// If it's an unnamed enum, we also generate a constant so
1457
1494
// it can be properly accessed.
1458
1495
if is_rust_enum && enum_ty. name ( ) . is_none ( ) {
1459
1496
// NB: if we want to do this for other kind of nested
1460
1497
// enums we can probably mangle the name.
1461
- let mangled_name = if item . is_toplevel ( ctx ) {
1498
+ let mangled_name = if is_toplevel {
1462
1499
variant_name. clone ( )
1463
1500
} else {
1464
- if parent_canonical_name. is_none ( ) {
1465
- parent_canonical_name = Some ( item. parent_id ( )
1466
- . canonical_name ( ctx) ) ;
1467
- }
1468
-
1469
1501
let parent_name = parent_canonical_name. as_ref ( )
1470
1502
. unwrap ( ) ;
1471
1503
@@ -1486,7 +1518,8 @@ impl CodeGenerator for Enum {
1486
1518
}
1487
1519
}
1488
1520
1489
- result. push ( builder. build ( ) ) ;
1521
+ let enum_ = builder. build ( ctx, enum_rust_ty, result) ;
1522
+ result. push ( enum_) ;
1490
1523
}
1491
1524
}
1492
1525
0 commit comments