@@ -1415,6 +1415,154 @@ def VTableAddrPointOp : CIR_Op<"vtable.address_point",
14151415  let hasVerifier = 1;
14161416}
14171417
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+ 
14181566//===----------------------------------------------------------------------===//
14191567// GetMemberOp
14201568//===----------------------------------------------------------------------===//
0 commit comments