clang 22.0.0git
CIRGenRecordLayout.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_CLANG_LIB_CIR_CIRGENRECORDLAYOUT_H
10#define LLVM_CLANG_LIB_CIR_CIRGENRECORDLAYOUT_H
11
12#include "clang/AST/Decl.h"
14
15namespace clang::CIRGen {
16
17/// Record with information about how a bitfield should be accessed. This is
18/// very similar to what LLVM codegen does, once CIR evolves it's possible we
19/// can use a more higher level representation.
20///
21/// Often we lay out a sequence of bitfields as a contiguous sequence of bits.
22/// When the AST record layout does this, we represent it in CIR as a
23/// `!cir.record` type, which directly reflects the structure's layout,
24/// including bitfield packing and padding, using CIR types such as
25/// `!cir.bool`, `!s8i`, `!u16i`.
26///
27/// To access a particular bitfield in CIR, we use the operations
28/// `cir.get_bitfield` (`GetBitfieldOp`) or `cir.set_bitfield`
29/// (`SetBitfieldOp`). These operations rely on the `bitfield_info`
30/// attribute, which provides detailed metadata required for access,
31/// such as the size and offset of the bitfield, the type and size of
32/// the underlying storage, and whether the value is signed.
33/// The CIRGenRecordLayout also has a bitFields map which encodes which
34/// byte-sequence this bitfield falls within. Let's assume the following C
35/// struct:
36///
37/// struct S {
38/// char a, b, c;
39/// unsigned bits : 3;
40/// unsigned more_bits : 4;
41/// unsigned still_more_bits : 7;
42/// };
43///
44/// This will end up as the following cir.record. The bitfield members are
45/// represented by one !u16i value, and the array provides padding to align the
46/// struct to a 4-byte alignment.
47///
48/// !rec_S = !cir.record<struct "S" padded {!s8i, !s8i, !s8i, !u16i,
49/// !cir.array<!u8i x 3>}>
50///
51/// When generating code to access more_bits, we'll generate something
52/// essentially like this:
53///
54/// #bfi_more_bits = #cir.bitfield_info<name = "more_bits", storage_type =
55/// !u16i, size = 4, offset = 3, is_signed = false>
56///
57/// cir.func @store_field() {
58/// %0 = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s"] {alignment = 4 : i64}
59/// %1 = cir.const #cir.int<2> : !s32i
60/// %2 = cir.cast(integral, %1 : !s32i), !u32i
61/// %3 = cir.get_member %0[3] {name = "more_bits"} : !cir.ptr<!rec_S> ->
62/// !cir.ptr<!u16i>
63/// %4 = cir.set_bitfield(#bfi_more_bits, %3 :
64/// !cir.ptr<!u16i>, %2 : !u32i) -> !u32i
65/// cir.return
66/// }
67///
69 /// The offset within a contiguous run of bitfields that are represented as
70 /// a single "field" within the cir.record type. This offset is in bits.
71 unsigned offset : 16;
72
73 /// The total size of the bit-field, in bits.
74 unsigned size : 15;
75
76 /// Whether the bit-field is signed.
77 unsigned isSigned : 1;
78
79 /// The storage size in bits which should be used when accessing this
80 /// bitfield.
81 unsigned storageSize;
82
83 /// The offset of the bitfield storage from the start of the record.
85
86 /// The offset within a contiguous run of bitfields that are represented as a
87 /// single "field" within the cir.record type, taking into account the AAPCS
88 /// rules for volatile bitfields. This offset is in bits.
89 unsigned volatileOffset : 16;
90
91 /// The storage size in bits which should be used when accessing this
92 /// bitfield.
94
95 /// The offset of the bitfield storage from the start of the record.
97
98 /// The name of a bitfield
99 llvm::StringRef name;
100
101 // The actual storage type for the bitfield
102 mlir::Type storageType;
103
107
108 CIRGenBitFieldInfo(unsigned offset, unsigned size, bool isSigned,
112
113 void print(llvm::raw_ostream &os) const;
114 LLVM_DUMP_METHOD void dump() const;
115};
116
117/// This class handles record and union layout info while lowering AST types
118/// to CIR types.
119///
120/// These layout objects are only created on demand as CIR generation requires.
122 friend class CIRGenTypes;
123
124 CIRGenRecordLayout(const CIRGenRecordLayout &) = delete;
125 void operator=(const CIRGenRecordLayout &) = delete;
126
127private:
128 /// The CIR type corresponding to this record layout; used when laying it out
129 /// as a complete object.
130 cir::RecordType completeObjectType;
131
132 /// The CIR type for the non-virtual part of this record layout; used when
133 /// laying it out as a base subobject.
134 cir::RecordType baseSubobjectType;
135
136 /// Map from (non-bit-field) record field to the corresponding cir record type
137 /// field no. This info is populated by the record builder.
138 llvm::DenseMap<const clang::FieldDecl *, unsigned> fieldIdxMap;
139
140 // FIXME: Maybe we could use CXXBaseSpecifier as the key and use a single map
141 // for both virtual and non-virtual bases.
142 llvm::DenseMap<const clang::CXXRecordDecl *, unsigned> nonVirtualBases;
143
144 /// Map from virtual bases to their field index in the complete object.
145 llvm::DenseMap<const clang::CXXRecordDecl *, unsigned>
146 completeObjectVirtualBases;
147
148 /// Map from (bit-field) record field to the corresponding CIR record type
149 /// field no. This info is populated by record builder.
150 llvm::DenseMap<const clang::FieldDecl *, CIRGenBitFieldInfo> bitFields;
151
152 /// False if any direct or indirect subobject of this class, when considered
153 /// as a complete object, requires a non-zero bitpattern when
154 /// zero-initialized.
155 LLVM_PREFERRED_TYPE(bool)
156 unsigned zeroInitializable : 1;
157
158 /// False if any direct or indirect subobject of this class, when considered
159 /// as a base subobject, requires a non-zero bitpattern when zero-initialized.
160 LLVM_PREFERRED_TYPE(bool)
161 unsigned zeroInitializableAsBase : 1;
162
163public:
164 CIRGenRecordLayout(cir::RecordType completeObjectType,
165 cir::RecordType baseSubobjectType, bool zeroInitializable,
166 bool zeroInitializableAsBase)
167 : completeObjectType(completeObjectType),
168 baseSubobjectType(baseSubobjectType),
169 zeroInitializable(zeroInitializable),
170 zeroInitializableAsBase(zeroInitializableAsBase) {}
171
172 /// Return the "complete object" LLVM type associated with
173 /// this record.
174 cir::RecordType getCIRType() const { return completeObjectType; }
175
176 /// Return the "base subobject" LLVM type associated with
177 /// this record.
178 cir::RecordType getBaseSubobjectCIRType() const { return baseSubobjectType; }
179
180 /// Return cir::RecordType element number that corresponds to the field FD.
181 unsigned getCIRFieldNo(const clang::FieldDecl *fd) const {
182 fd = fd->getCanonicalDecl();
183 assert(fieldIdxMap.count(fd) && "Invalid field for record!");
184 return fieldIdxMap.lookup(fd);
185 }
186
187 /// Check whether this struct can be C++ zero-initialized
188 /// with a zeroinitializer.
189 bool isZeroInitializable() const { return zeroInitializable; }
190
191 /// Check whether this struct can be C++ zero-initialized
192 /// with a zeroinitializer when considered as a base subobject.
193 bool isZeroInitializableAsBase() const { return zeroInitializableAsBase; }
194
195 /// Return the BitFieldInfo that corresponds to the field FD.
197 fd = fd->getCanonicalDecl();
198 assert(fd->isBitField() && "Invalid call for non-bit-field decl!");
199 llvm::DenseMap<const clang::FieldDecl *, CIRGenBitFieldInfo>::const_iterator
200 it = bitFields.find(fd);
201 assert(it != bitFields.end() && "Unable to find bitfield info");
202 return it->second;
203 }
204 void print(raw_ostream &os) const;
205 LLVM_DUMP_METHOD void dump() const;
206};
207
208} // namespace clang::CIRGen
209
210#endif
This class handles record and union layout info while lowering AST types to CIR types.
CIRGenRecordLayout(cir::RecordType completeObjectType, cir::RecordType baseSubobjectType, bool zeroInitializable, bool zeroInitializableAsBase)
cir::RecordType getCIRType() const
Return the "complete object" LLVM type associated with this record.
cir::RecordType getBaseSubobjectCIRType() const
Return the "base subobject" LLVM type associated with this record.
const CIRGenBitFieldInfo & getBitFieldInfo(const clang::FieldDecl *fd) const
Return the BitFieldInfo that corresponds to the field FD.
unsigned getCIRFieldNo(const clang::FieldDecl *fd) const
Return cir::RecordType element number that corresponds to the field FD.
bool isZeroInitializableAsBase() const
Check whether this struct can be C++ zero-initialized with a zeroinitializer when considered as a bas...
bool isZeroInitializable() const
Check whether this struct can be C++ zero-initialized with a zeroinitializer.
This class organizes the cross-module state that is used while lowering AST types to CIR types.
Definition: CIRGenTypes.h:48
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
Represents a member of a struct/union/class.
Definition: Decl.h:3153
bool isBitField() const
Determines whether this field is a bitfield.
Definition: Decl.h:3256
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition: Decl.h:3400
Record with information about how a bitfield should be accessed.
unsigned offset
The offset within a contiguous run of bitfields that are represented as a single "field" within the c...
void print(llvm::raw_ostream &os) const
CIRGenBitFieldInfo(unsigned offset, unsigned size, bool isSigned, unsigned storageSize, clang::CharUnits storageOffset)
unsigned storageSize
The storage size in bits which should be used when accessing this bitfield.
unsigned volatileStorageSize
The storage size in bits which should be used when accessing this bitfield.
clang::CharUnits storageOffset
The offset of the bitfield storage from the start of the record.
unsigned size
The total size of the bit-field, in bits.
unsigned isSigned
Whether the bit-field is signed.
clang::CharUnits volatileStorageOffset
The offset of the bitfield storage from the start of the record.
unsigned volatileOffset
The offset within a contiguous run of bitfields that are represented as a single "field" within the c...
llvm::StringRef name
The name of a bitfield.