@@ -1415,6 +1415,154 @@ def VTableAddrPointOp : CIR_Op<"vtable.address_point",
1415
1415
let hasVerifier = 1;
1416
1416
}
1417
1417
1418
+ //===----------------------------------------------------------------------===//
1419
+ // SetBitfieldOp
1420
+ //===----------------------------------------------------------------------===//
1421
+
1422
+ def SetBitfieldOp : CIR_Op<"set_bitfield"> {
1423
+ let summary = "Set a bitfield";
1424
+ let description = [{
1425
+ The `cir.set_bitfield` operation provides a store-like access to
1426
+ a bit field of a record.
1427
+
1428
+ It expects an address of a storage where to store, a type of the storage,
1429
+ a value being stored, a name of a bit field, a pointer to the storage in the
1430
+ base record, a size of the storage, a size the bit field, an offset
1431
+ of the bit field and a sign. Returns a value being stored.
1432
+
1433
+ Example.
1434
+ Suppose we have a struct with multiple bitfields stored in
1435
+ different storages. The `cir.set_bitfield` operation sets the value
1436
+ of the bitfield.
1437
+ ```C++
1438
+ typedef struct {
1439
+ int a : 4;
1440
+ int b : 27;
1441
+ int c : 17;
1442
+ int d : 2;
1443
+ int e : 15;
1444
+ } S;
1445
+
1446
+ void store_bitfield(S& s) {
1447
+ s.d = 3;
1448
+ }
1449
+ ```
1450
+
1451
+ ```mlir
1452
+ // 'd' is in the storage with the index 1
1453
+ !struct_type = !cir.struct<struct "S" {!cir.int<u, 32>, !cir.int<u, 32>, !cir.int<u, 16>} #cir.record.decl.ast>
1454
+ #bfi_d = #cir.bitfield_info<name = "d", storage_type = !u32i, size = 2, offset = 17, is_signed = true>
1455
+
1456
+ %1 = cir.const(#cir.int<3> : !s32i) : !s32i
1457
+ %2 = cir.load %0 : cir.ptr <!cir.ptr<!struct_type>>, !cir.ptr<!struct_type>
1458
+ %3 = cir.get_member %2[1] {name = "d"} : !cir.ptr<!struct_type> -> !cir.ptr<!u32i>
1459
+ %4 = cir.set_bitfield(#bfi_d, %3 : !cir.ptr<!u32i>, %1 : !s32i) -> !s32i
1460
+ ```
1461
+ }];
1462
+
1463
+ let arguments = (ins
1464
+ AnyType:$dst,
1465
+ AnyType:$src,
1466
+ BitfieldInfoAttr:$bitfield_info
1467
+ );
1468
+
1469
+ let results = (outs CIR_IntType:$result);
1470
+
1471
+ let assemblyFormat = [{ `(`$bitfield_info`,` $dst`:`type($dst)`,`
1472
+ $src`:`type($src) `)` attr-dict `->` type($result) }];
1473
+
1474
+ let builders = [
1475
+ OpBuilder<(ins "Type":$type,
1476
+ "Value":$dst,
1477
+ "Type":$storage_type,
1478
+ "Value":$src,
1479
+ "StringRef":$name,
1480
+ "unsigned":$size,
1481
+ "unsigned":$offset,
1482
+ "bool":$is_signed
1483
+ ),
1484
+ [{
1485
+ BitfieldInfoAttr info =
1486
+ BitfieldInfoAttr::get($_builder.getContext(),
1487
+ name, storage_type,
1488
+ size, offset, is_signed);
1489
+ build($_builder, $_state, type, dst, src, info);
1490
+ }]>
1491
+ ];
1492
+ }
1493
+
1494
+ //===----------------------------------------------------------------------===//
1495
+ // GetBitfieldOp
1496
+ //===----------------------------------------------------------------------===//
1497
+
1498
+ def GetBitfieldOp : CIR_Op<"get_bitfield"> {
1499
+ let summary = "Get a bitfield";
1500
+ let description = [{
1501
+ The `cir.get_bitfield` operation provides a load-like access to
1502
+ a bit field of a record.
1503
+
1504
+ It expects a name if a bit field, a pointer to a storage in the
1505
+ base record, a type of the storage, a name of the bitfield,
1506
+ a size the bit field, an offset of the bit field and a sign.
1507
+
1508
+ Example:
1509
+ Suppose we have a struct with multiple bitfields stored in
1510
+ different storages. The `cir.get_bitfield` operation gets the value
1511
+ of the bitfield
1512
+ ```C++
1513
+ typedef struct {
1514
+ int a : 4;
1515
+ int b : 27;
1516
+ int c : 17;
1517
+ int d : 2;
1518
+ int e : 15;
1519
+ } S;
1520
+
1521
+ int load_bitfield(S& s) {
1522
+ return s.d;
1523
+ }
1524
+ ```
1525
+
1526
+ ```mlir
1527
+ // 'd' is in the storage with the index 1
1528
+ !struct_type = !cir.struct<struct "S" {!cir.int<u, 32>, !cir.int<u, 32>, !cir.int<u, 16>} #cir.record.decl.ast>
1529
+ #bfi_d = #cir.bitfield_info<name = "d", storage_type = !u32i, size = 2, offset = 17, is_signed = true>
1530
+
1531
+ %2 = cir.load %0 : cir.ptr <!cir.ptr<!struct_type>>, !cir.ptr<!struct_type>
1532
+ %3 = cir.get_member %2[1] {name = "d"} : !cir.ptr<!struct_type> -> !cir.ptr<!u32i>
1533
+ %4 = cir.get_bitfield(#bfi_d, %3 : !cir.ptr<!u32i>) -> !s32i
1534
+ ```
1535
+ }];
1536
+
1537
+ let arguments = (ins
1538
+ AnyType:$addr,
1539
+ BitfieldInfoAttr:$bitfield_info
1540
+ );
1541
+
1542
+ let results = (outs CIR_IntType:$result);
1543
+
1544
+ let assemblyFormat = [{ `(`$bitfield_info `,` $addr attr-dict `:`
1545
+ type($addr) `)` `->` type($result) }];
1546
+
1547
+ let builders = [
1548
+ OpBuilder<(ins "Type":$type,
1549
+ "Value":$addr,
1550
+ "Type":$storage_type,
1551
+ "StringRef":$name,
1552
+ "unsigned":$size,
1553
+ "unsigned":$offset,
1554
+ "bool":$is_signed
1555
+ ),
1556
+ [{
1557
+ BitfieldInfoAttr info =
1558
+ BitfieldInfoAttr::get($_builder.getContext(),
1559
+ name, storage_type,
1560
+ size, offset, is_signed);
1561
+ build($_builder, $_state, type, addr, info);
1562
+ }]>
1563
+ ];
1564
+ }
1565
+
1418
1566
//===----------------------------------------------------------------------===//
1419
1567
// GetMemberOp
1420
1568
//===----------------------------------------------------------------------===//
0 commit comments