@@ -205,6 +205,7 @@ pub fn insert_ffi_functions(asm: &mut Assembly, tcx: TyCtxt) {
205
205
swap_at_generic ( asm) ;
206
206
bounds_check ( asm) ;
207
207
atomic:: atomics ( asm) ;
208
+ bitreverse_u128 ( asm) ;
208
209
let c_void = crate :: r#type:: c_void ( tcx) ;
209
210
210
211
asm. add_typedef ( TypeDef :: new (
@@ -1328,3 +1329,198 @@ add_method_from_trees!(
1328
1329
) ] ,
1329
1330
vec![ Some ( "thread_handle" . into( ) ) , Some ( "result_ptr" . into( ) ) ]
1330
1331
) ;
1332
+
1333
+ fn shr_u128 ( value : CILNode , shift : CILNode ) -> CILNode {
1334
+ call ! (
1335
+ CallSite :: boxed(
1336
+ DotnetTypeRef :: uint_128( ) . into( ) ,
1337
+ "op_RightShift" . into( ) ,
1338
+ FnSig :: new( & [ Type :: U128 , Type :: I32 ] , Type :: U128 ) ,
1339
+ true ,
1340
+ ) ,
1341
+ [ value, shift]
1342
+ )
1343
+ }
1344
+ fn or_u128 ( lhs : CILNode , rhs : CILNode ) -> CILNode {
1345
+ call ! (
1346
+ CallSite :: boxed(
1347
+ DotnetTypeRef :: uint_128( ) . into( ) ,
1348
+ "op_BitwiseOr" . into( ) ,
1349
+ FnSig :: new( & [ Type :: U128 , Type :: U128 ] , Type :: U128 ) ,
1350
+ true ,
1351
+ ) ,
1352
+ [ lhs, rhs]
1353
+ )
1354
+ }
1355
+ fn and_u128 ( lhs : CILNode , rhs : CILNode ) -> CILNode {
1356
+ call ! (
1357
+ CallSite :: boxed(
1358
+ DotnetTypeRef :: uint_128( ) . into( ) ,
1359
+ "op_BitwiseAnd" . into( ) ,
1360
+ FnSig :: new( & [ Type :: U128 , Type :: U128 ] , Type :: U128 ) ,
1361
+ true ,
1362
+ ) ,
1363
+ [ lhs, rhs]
1364
+ )
1365
+ }
1366
+ fn shl_u128 ( value : CILNode , shift : CILNode ) -> CILNode {
1367
+ call ! (
1368
+ CallSite :: boxed(
1369
+ DotnetTypeRef :: uint_128( ) . into( ) ,
1370
+ "op_LeftShift" . into( ) ,
1371
+ FnSig :: new( & [ Type :: U128 , Type :: I32 ] , Type :: U128 ) ,
1372
+ true ,
1373
+ ) ,
1374
+ [ value, shift]
1375
+ )
1376
+ }
1377
+ fn const_u128 ( value : u128 ) -> CILNode {
1378
+ let low = u128_low_u64 ( value) ;
1379
+ let high = ( value >> 64 ) as u64 ;
1380
+ let ctor_sig = FnSig :: new (
1381
+ & [
1382
+ Type :: ManagedReference ( Type :: U128 . into ( ) ) ,
1383
+ Type :: U64 ,
1384
+ Type :: U64 ,
1385
+ ] ,
1386
+ Type :: Void ,
1387
+ ) ;
1388
+ CILNode :: NewObj ( Box :: new ( CallOpArgs {
1389
+ site : CallSite :: boxed (
1390
+ Some ( DotnetTypeRef :: uint_128 ( ) ) ,
1391
+ ".ctor" . into ( ) ,
1392
+ ctor_sig,
1393
+ false ,
1394
+ ) ,
1395
+ args : [ conv_u64 ! ( ldc_u64!( high) ) , conv_u64 ! ( ldc_u64!( low) ) ] . into ( ) ,
1396
+ } ) )
1397
+ }
1398
+ add_method_from_trees ! (
1399
+ bitreverse_u128,
1400
+ & [ Type :: U128 ] ,
1401
+ Type :: U128 ,
1402
+ vec![ BasicBlock :: new(
1403
+ vec![
1404
+ CILRoot :: STLoc {
1405
+ local: 0 ,
1406
+ tree: or_u128(
1407
+ and_u128(
1408
+ shr_u128( CILNode :: LDArg ( 0 ) , ldc_i32!( 1 ) ) ,
1409
+ const_u128( 0x5555_5555_5555_5555_5555_5555_5555_5555_u128 ) ,
1410
+ ) ,
1411
+ shl_u128(
1412
+ and_u128(
1413
+ CILNode :: LDArg ( 0 ) ,
1414
+ const_u128( 0x5555_5555_5555_5555_5555_5555_5555_5555_u128 ) ,
1415
+ ) ,
1416
+ ldc_i32!( 1 ) ,
1417
+ ) ,
1418
+ ) ,
1419
+ }
1420
+ . into( ) ,
1421
+ CILRoot :: STLoc {
1422
+ local: 0 ,
1423
+ tree: or_u128(
1424
+ and_u128(
1425
+ shr_u128( CILNode :: LDLoc ( 0 ) , ldc_i32!( 2 ) ) ,
1426
+ const_u128( 0x3333_3333_3333_3333_3333_3333_3333_3333_u128 ) ,
1427
+ ) ,
1428
+ shl_u128(
1429
+ and_u128(
1430
+ CILNode :: LDLoc ( 0 ) ,
1431
+ const_u128( 0x3333_3333_3333_3333_3333_3333_3333_3333_u128 ) ,
1432
+ ) ,
1433
+ ldc_i32!( 2 ) ,
1434
+ ) ,
1435
+ ) ,
1436
+ }
1437
+ . into( ) ,
1438
+ CILRoot :: STLoc {
1439
+ local: 0 ,
1440
+ tree: or_u128(
1441
+ and_u128(
1442
+ shr_u128( CILNode :: LDLoc ( 0 ) , ldc_i32!( 4 ) ) ,
1443
+ const_u128( 0x0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_u128 ) ,
1444
+ ) ,
1445
+ shl_u128(
1446
+ and_u128(
1447
+ CILNode :: LDLoc ( 0 ) ,
1448
+ const_u128( 0x0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_u128 ) ,
1449
+ ) ,
1450
+ ldc_i32!( 4 ) ,
1451
+ ) ,
1452
+ ) ,
1453
+ }
1454
+ . into( ) ,
1455
+ CILRoot :: STLoc {
1456
+ local: 0 ,
1457
+ tree: or_u128(
1458
+ and_u128(
1459
+ shr_u128( CILNode :: LDLoc ( 0 ) , ldc_i32!( 8 ) ) ,
1460
+ const_u128( 0x00FF_00FF_00FF_00FF_00FF_00FF_00FF_00FF_u128 ) ,
1461
+ ) ,
1462
+ shl_u128(
1463
+ and_u128(
1464
+ CILNode :: LDLoc ( 0 ) ,
1465
+ const_u128( 0x00FF_00FF_00FF_00FF_00FF_00FF_00FF_00FF_u128 ) ,
1466
+ ) ,
1467
+ ldc_i32!( 8 ) ,
1468
+ ) ,
1469
+ ) ,
1470
+ }
1471
+ . into( ) ,
1472
+ CILRoot :: STLoc {
1473
+ local: 0 ,
1474
+ tree: or_u128(
1475
+ and_u128(
1476
+ shr_u128( CILNode :: LDLoc ( 0 ) , ldc_i32!( 16 ) ) ,
1477
+ const_u128( 0x0000_FFFF_0000_FFFF_0000_FFFF_0000_FFFF_u128 ) ,
1478
+ ) ,
1479
+ shl_u128(
1480
+ and_u128(
1481
+ CILNode :: LDLoc ( 0 ) ,
1482
+ const_u128( 0x0000_FFFF_0000_FFFF_0000_FFFF_0000_FFFF_u128 ) ,
1483
+ ) ,
1484
+ ldc_i32!( 16 ) ,
1485
+ ) ,
1486
+ ) ,
1487
+ }
1488
+ . into( ) ,
1489
+ CILRoot :: STLoc {
1490
+ local: 0 ,
1491
+ tree: or_u128(
1492
+ and_u128(
1493
+ shr_u128( CILNode :: LDLoc ( 0 ) , ldc_i32!( 32 ) ) ,
1494
+ const_u128( 0x0000_0000_FFFF_FFFF_0000_0000_FFFF_FFFF_u128 ) ,
1495
+ ) ,
1496
+ shl_u128(
1497
+ and_u128(
1498
+ CILNode :: LDLoc ( 0 ) ,
1499
+ const_u128( 0x0000_0000_FFFF_FFFF_0000_0000_FFFF_FFFF_u128 ) ,
1500
+ ) ,
1501
+ ldc_i32!( 32 ) ,
1502
+ ) ,
1503
+ ) ,
1504
+ }
1505
+ . into( ) ,
1506
+ CILRoot :: Ret {
1507
+ tree: or_u128(
1508
+ shr_u128( CILNode :: LDLoc ( 0 ) , ldc_i32!( 64 ) ) ,
1509
+ shl_u128( CILNode :: LDLoc ( 0 ) , ldc_i32!( 64 ) ) ,
1510
+ ) ,
1511
+ }
1512
+ . into( ) ,
1513
+ ] ,
1514
+ 0 ,
1515
+ None
1516
+ ) ] ,
1517
+ vec![ ( Some ( "n" . into( ) ) , Type :: U128 ) ] ,
1518
+ vec![
1519
+ Some ( "buf1" . into( ) ) ,
1520
+ Some ( "buf2" . into( ) ) ,
1521
+ Some ( "size" . into( ) )
1522
+ ]
1523
+ ) ;
1524
+ fn u128_low_u64 ( value : u128 ) -> u64 {
1525
+ u64:: try_from ( value & u128:: from ( u64:: MAX ) ) . expect ( "trucating cast error" )
1526
+ }
0 commit comments