================ @@ -14,6 +14,105 @@ namespace clang::CIRGen { +/// Record with information about how a bitfield should be accessed. This is +/// very similar to what LLVM codegen does, once CIR evolves it's possible we +/// can use a more higher level representation. +/// +/// Often we lay out a sequence of bitfields as a contiguous sequence of bits. +/// When the AST record layout does this, we represent it in CIR as a +/// `!cir.record` type, which directly reflects the structure's layout, +/// including bitfield packing and padding, using CIR types such as +/// `!cir.bool`, `!s8i`, `!u16i`. +/// +/// To access a particular bitfield in CIR, we use the operations +/// `cir.get_bitfield` (`GetBitfieldOp`) or `cir.set_bitfield` +/// (`SetBitfieldOp`). These operations rely on the `bitfield_info` +/// attribute, which provides detailed metadata required for access, +/// such as the size and offset of the bitfield, the type and size of +/// the underlying storage, and whether the value is signed. +/// The CIRGenRecordLayout also has a bitFields map which encodes which +/// byte-sequence this bitfield falls within. Let's assume the following C +/// struct: +/// +/// struct S { +/// char a, b, c; +/// unsigned bits : 3; +/// unsigned more_bits : 4; +/// unsigned still_more_bits : 7; +/// }; +/// +/// This will end up as the following cir.record. The first array is the +/// bitfield, and the second is the padding out to a 4-byte alignment. +/// +/// !rec_S = !cir.record<struct "S" padded {!s8i, !s8i, !s8i, !u8i, !u8i, +/// !cir.array<!u8i x 3>}> +/// +/// When generating code to access more_bits, we'll generate something +/// essentially like this: +/// +/// #bfi_more_bits = #cir.bitfield_info<name = "more_bits", storage_type = +/// !u16i, size = 4, offset = 3, is_signed = false> +/// +/// cir.func @store_field() { +/// %0 = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s"] {alignment = 4 : i64} +/// %1 = cir.const #cir.int<2> : !s32i +/// %2 = cir.cast(integral, %1 : !s32i), !u32i +/// %3 = cir.get_member %0[4] {name = "more_bits"} : !cir.ptr<!rec_S> -> +/// !cir.ptr<!u16i> +/// %4 = cir.set_bitfield(#bfi_more_bits, %3 : +/// !cir.ptr<!u16i>, %2 : !u32i) -> !u32i +/// cir.return +/// } +/// +struct CIRGenBitFieldInfo { + /// The offset within a contiguous run of bitfields that are represented as + /// a single "field" within the cir.record type. This offset is in bits. + unsigned offset : 16; + + /// The total size of the bit-field, in bits. + unsigned size : 15; + + /// Whether the bit-field is signed. + unsigned isSigned : 1; + + /// The storage size in bits which should be used when accessing this + /// bitfield. + unsigned storageSize; + + /// The offset of the bitfield storage from the start of the record. + clang::CharUnits storageOffset; + + /// The offset within a contiguous run of bitfields that are represented as a + /// single "field" within the cir.record type, taking into account the AAPCS + /// rules for volatile bitfields. This offset is in bits. + unsigned volatileOffset : 16; + + /// The storage size in bits which should be used when accessing this + /// bitfield. + unsigned volatileStorageSize; + + /// The offset of the bitfield storage from the start of the record. + clang::CharUnits volatileStorageOffset; + + /// The name of a bitfield + llvm::StringRef name; + + // The actual storage type for the bitfield + mlir::Type storageType; + + CIRGenBitFieldInfo() + : offset(), size(), isSigned(), storageSize(), volatileOffset(), + volatileStorageSize() {} + + CIRGenBitFieldInfo(unsigned offset, unsigned size, bool isSigned, + unsigned storageSize, clang::CharUnits storageOffset) + : offset(offset), size(size), isSigned(isSigned), + storageSize(storageSize), storageOffset(storageOffset) {} + + void print(llvm::raw_ostream &os) const; + void dump() const; ---------------- andykaylor wrote:
```suggestion LLVM_DUMP_METHOD void dump() const; ``` This tells the linker not to discard this even though it isn't called. https://github.com/llvm/llvm-project/pull/142041 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits