================ @@ -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); ---------------- andykaylor wrote:
I see that you're right. Can you add a test case where the return value is used? This looks like it does that in C (though not in C++): ``` typedef struct { int a : 4; int b : 4; int c : 4; } S; void set_bitfield(volatile S* s) { s->a = s->b = 3; } ``` https://github.com/llvm/llvm-project/pull/147609 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits