[clang] [CIR] Upstream new SetBitfieldOp for handling C and C++ struct bitfields (PR #147609)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 10 10:52:17 PDT 2025
================
@@ -1669,6 +1669,94 @@ def GetGlobalOp : CIR_Op<"get_global",
}];
}
+//===----------------------------------------------------------------------===//
+// SetBitfieldOp
+//===----------------------------------------------------------------------===//
+
+def SetBitfieldOp : CIR_Op<"set_bitfield"> {
+ let summary = "Set the value of a bitfield member";
+ let description = [{
+ The `cir.set_bitfield` operation provides a store-like access to
+ a bit field of a record.
+
+ It expects an address of a storage where to store, a type of the storage,
+ a value being stored, a name of a bit field, a pointer to the storage in the
+ base record, a size of the storage, a size the bit field, an offset
+ of the bit field and a sign. Returns a value being stored.
+
+ A unit attribute `volatile` can be used to indicate a volatile store of the
+ bitfield.
+ ```mlir
+ cir.set_bitfield(#bfi, %0 : !cir.ptr<!u32i>, %1 : !s32i) {is_volatile}
+ -> !s32i
+ ```
+
+ Example.
+ Suppose we have a struct with multiple bitfields stored in
+ different storages. The `cir.set_bitfield` operation sets the value
+ of the bitfield.
+ ```C++
+ typedef struct {
+ int a : 4;
+ int b : 27;
+ int c : 17;
+ int d : 2;
+ int e : 15;
+ } S;
+
+ void store_bitfield(S& s) {
+ s.e = 3;
+ }
+ ```
+
+ ```mlir
+ // 'e' is in the storage with the index 1
+ !record_type = !cir.record<struct "S" packed padded {!u64i, !u16i,
+ !cir.array<!u8i x 2>} #cir.record.decl.ast>
+ #bfi_e = #cir.bitfield_info<name = "e", storage_type = !u16i, size = 15,
+ offset = 0, is_signed = true>
+
+ %1 = cir.const #cir.int<3> : !s32i
+ %2 = cir.load %0 : !cir.ptr<!cir.ptr<!record_type>>, !cir.ptr<!record_type>
+ %3 = cir.get_member %2[1] {name = "e"} : !cir.ptr<!record_type>
+ -> !cir.ptr<!u16i>
+ %4 = cir.set_bitfield(#bfi_e, %3 : !cir.ptr<!u16i>, %1 : !s32i) -> !s32i
+ ```
+ }];
+
+ let arguments = (ins
+ Arg<CIR_PointerType, "the address to store the value", [MemWrite]>:$addr,
+ CIR_AnyType:$src,
+ BitfieldInfoAttr:$bitfield_info,
+ UnitAttr:$is_volatile
+ );
+
+ let results = (outs CIR_IntType:$result);
----------------
Andres-Salamanca wrote:
Ok, it would also be used in the case of a unary operation when it is upstream.
```cpp
void unOp(S* s) {
s->c++;
}
```
https://github.com/llvm/llvm-project/pull/147609
More information about the cfe-commits
mailing list