clang 23.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
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.
121class CIRGenRecordLayout {
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:
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 bool hasCIRField(const clang::FieldDecl *fd) const {
188 fd = fd->getCanonicalDecl();
189 return fieldIdxMap.contains(fd);
190 }
191
192 unsigned getNonVirtualBaseCIRFieldNo(const CXXRecordDecl *rd) const {
193 assert(nonVirtualBases.count(rd) && "Invalid non-virtual base!");
194 return nonVirtualBases.lookup(rd);
195 }
196
198 return nonVirtualBases.contains(rd);
199 }
200
201 /// Check whether this struct can be C++ zero-initialized
202 /// with a zeroinitializer.
203 bool isZeroInitializable() const { return zeroInitializable; }
204
205 /// Check whether this struct can be C++ zero-initialized
206 /// with a zeroinitializer when considered as a base subobject.
207 bool isZeroInitializableAsBase() const { return zeroInitializableAsBase; }
208
209 /// Return the BitFieldInfo that corresponds to the field FD.
211 fd = fd->getCanonicalDecl();
212 assert(fd->isBitField() && "Invalid call for non-bit-field decl!");
213 llvm::DenseMap<const clang::FieldDecl *, CIRGenBitFieldInfo>::const_iterator
214 it = bitFields.find(fd);
215 assert(it != bitFields.end() && "Unable to find bitfield info");
216 return it->second;
217 }
218 void print(raw_ostream &os) const;
219 LLVM_DUMP_METHOD void dump() const;
220};
221
222} // namespace clang::CIRGen
223
224#endif
C++ view class that accepts both !cir.struct and !cir.union types.
Definition CIRTypes.h:93
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.
bool hasNonVirtualBaseCIRField(const CXXRecordDecl *rd) const
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 hasCIRField(const clang::FieldDecl *fd) const
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.
unsigned getNonVirtualBaseCIRFieldNo(const CXXRecordDecl *rd) const
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
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:3195
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3298
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition Decl.h:3442
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.