xref: /freebsd/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenRecordLayout.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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"
13 #include "clang/CIR/Dialect/IR/CIRTypes.h"
14 
15 namespace 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 ///
68 struct CIRGenBitFieldInfo {
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.
84   clang::CharUnits storageOffset;
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.
93   unsigned volatileStorageSize;
94 
95   /// The offset of the bitfield storage from the start of the record.
96   clang::CharUnits volatileStorageOffset;
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 
CIRGenBitFieldInfoCIRGenBitFieldInfo104   CIRGenBitFieldInfo()
105       : offset(), size(), isSigned(), storageSize(), volatileOffset(),
106         volatileStorageSize() {}
107 
CIRGenBitFieldInfoCIRGenBitFieldInfo108   CIRGenBitFieldInfo(unsigned offset, unsigned size, bool isSigned,
109                      unsigned storageSize, clang::CharUnits storageOffset)
110       : offset(offset), size(size), isSigned(isSigned),
111         storageSize(storageSize), storageOffset(storageOffset) {}
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.
121 class CIRGenRecordLayout {
122   friend class CIRGenTypes;
123 
124   CIRGenRecordLayout(const CIRGenRecordLayout &) = delete;
125   void operator=(const CIRGenRecordLayout &) = delete;
126 
127 private:
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 (bit-field) record field to the corresponding CIR record type
145   /// field no. This info is populated by record builder.
146   llvm::DenseMap<const clang::FieldDecl *, CIRGenBitFieldInfo> bitFields;
147 
148   /// False if any direct or indirect subobject of this class, when considered
149   /// as a complete object, requires a non-zero bitpattern when
150   /// zero-initialized.
151   LLVM_PREFERRED_TYPE(bool)
152   unsigned zeroInitializable : 1;
153 
154   /// False if any direct or indirect subobject of this class, when considered
155   /// as a base subobject, requires a non-zero bitpattern when zero-initialized.
156   LLVM_PREFERRED_TYPE(bool)
157   unsigned zeroInitializableAsBase : 1;
158 
159 public:
CIRGenRecordLayout(cir::RecordType completeObjectType,cir::RecordType baseSubobjectType,bool zeroInitializable,bool zeroInitializableAsBase)160   CIRGenRecordLayout(cir::RecordType completeObjectType,
161                      cir::RecordType baseSubobjectType, bool zeroInitializable,
162                      bool zeroInitializableAsBase)
163       : completeObjectType(completeObjectType),
164         baseSubobjectType(baseSubobjectType),
165         zeroInitializable(zeroInitializable),
166         zeroInitializableAsBase(zeroInitializableAsBase) {}
167 
168   /// Return the "complete object" LLVM type associated with
169   /// this record.
getCIRType()170   cir::RecordType getCIRType() const { return completeObjectType; }
171 
172   /// Return the "base subobject" LLVM type associated with
173   /// this record.
getBaseSubobjectCIRType()174   cir::RecordType getBaseSubobjectCIRType() const { return baseSubobjectType; }
175 
176   /// Return cir::RecordType element number that corresponds to the field FD.
getCIRFieldNo(const clang::FieldDecl * fd)177   unsigned getCIRFieldNo(const clang::FieldDecl *fd) const {
178     fd = fd->getCanonicalDecl();
179     assert(fieldIdxMap.count(fd) && "Invalid field for record!");
180     return fieldIdxMap.lookup(fd);
181   }
182 
183   /// Check whether this struct can be C++ zero-initialized
184   /// with a zeroinitializer.
isZeroInitializable()185   bool isZeroInitializable() const { return zeroInitializable; }
186 
187   /// Check whether this struct can be C++ zero-initialized
188   /// with a zeroinitializer when considered as a base subobject.
isZeroInitializableAsBase()189   bool isZeroInitializableAsBase() const { return zeroInitializableAsBase; }
190 
191   /// Return the BitFieldInfo that corresponds to the field FD.
getBitFieldInfo(const clang::FieldDecl * fd)192   const CIRGenBitFieldInfo &getBitFieldInfo(const clang::FieldDecl *fd) const {
193     fd = fd->getCanonicalDecl();
194     assert(fd->isBitField() && "Invalid call for non-bit-field decl!");
195     llvm::DenseMap<const clang::FieldDecl *, CIRGenBitFieldInfo>::const_iterator
196         it = bitFields.find(fd);
197     assert(it != bitFields.end() && "Unable to find bitfield info");
198     return it->second;
199   }
200   void print(raw_ostream &os) const;
201   LLVM_DUMP_METHOD void dump() const;
202 };
203 
204 } // namespace clang::CIRGen
205 
206 #endif
207