xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/CGRecordLayout.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- CGRecordLayout.h - LLVM Record Layout Information ------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_CODEGEN_CGRECORDLAYOUT_H
100b57cec5SDimitry Andric #define LLVM_CLANG_LIB_CODEGEN_CGRECORDLAYOUT_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "clang/AST/CharUnits.h"
130b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
140b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
150b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
160b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric namespace llvm {
190b57cec5SDimitry Andric   class StructType;
200b57cec5SDimitry Andric }
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric namespace clang {
230b57cec5SDimitry Andric namespace CodeGen {
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric /// Structure with information about how a bitfield should be accessed.
260b57cec5SDimitry Andric ///
270b57cec5SDimitry Andric /// Often we layout a sequence of bitfields as a contiguous sequence of bits.
280b57cec5SDimitry Andric /// When the AST record layout does this, we represent it in the LLVM IR's type
290b57cec5SDimitry Andric /// as either a sequence of i8 members or a byte array to reserve the number of
300b57cec5SDimitry Andric /// bytes touched without forcing any particular alignment beyond the basic
310b57cec5SDimitry Andric /// character alignment.
320b57cec5SDimitry Andric ///
330b57cec5SDimitry Andric /// Then accessing a particular bitfield involves converting this byte array
340b57cec5SDimitry Andric /// into a single integer of that size (i24 or i40 -- may not be power-of-two
350b57cec5SDimitry Andric /// size), loading it, and shifting and masking to extract the particular
360b57cec5SDimitry Andric /// subsequence of bits which make up that particular bitfield. This structure
370b57cec5SDimitry Andric /// encodes the information used to construct the extraction code sequences.
380b57cec5SDimitry Andric /// The CGRecordLayout also has a field index which encodes which byte-sequence
390b57cec5SDimitry Andric /// this bitfield falls within. Let's assume the following C struct:
400b57cec5SDimitry Andric ///
410b57cec5SDimitry Andric ///   struct S {
420b57cec5SDimitry Andric ///     char a, b, c;
430b57cec5SDimitry Andric ///     unsigned bits : 3;
440b57cec5SDimitry Andric ///     unsigned more_bits : 4;
450b57cec5SDimitry Andric ///     unsigned still_more_bits : 7;
460b57cec5SDimitry Andric ///   };
470b57cec5SDimitry Andric ///
480b57cec5SDimitry Andric /// This will end up as the following LLVM type. The first array is the
49e8d8bef9SDimitry Andric /// bitfield, and the second is the padding out to a 4-byte alignment.
500b57cec5SDimitry Andric ///
510b57cec5SDimitry Andric ///   %t = type { i8, i8, i8, i8, i8, [3 x i8] }
520b57cec5SDimitry Andric ///
530b57cec5SDimitry Andric /// When generating code to access more_bits, we'll generate something
540b57cec5SDimitry Andric /// essentially like this:
550b57cec5SDimitry Andric ///
560b57cec5SDimitry Andric ///   define i32 @foo(%t* %base) {
570b57cec5SDimitry Andric ///     %0 = gep %t* %base, i32 0, i32 3
580b57cec5SDimitry Andric ///     %2 = load i8* %1
590b57cec5SDimitry Andric ///     %3 = lshr i8 %2, 3
600b57cec5SDimitry Andric ///     %4 = and i8 %3, 15
610b57cec5SDimitry Andric ///     %5 = zext i8 %4 to i32
620b57cec5SDimitry Andric ///     ret i32 %i
630b57cec5SDimitry Andric ///   }
640b57cec5SDimitry Andric ///
650b57cec5SDimitry Andric struct CGBitFieldInfo {
660b57cec5SDimitry Andric   /// The offset within a contiguous run of bitfields that are represented as
670b57cec5SDimitry Andric   /// a single "field" within the LLVM struct type. This offset is in bits.
680b57cec5SDimitry Andric   unsigned Offset : 16;
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   /// The total size of the bit-field, in bits.
710b57cec5SDimitry Andric   unsigned Size : 15;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   /// Whether the bit-field is signed.
74*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
750b57cec5SDimitry Andric   unsigned IsSigned : 1;
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   /// The storage size in bits which should be used when accessing this
780b57cec5SDimitry Andric   /// bitfield.
790b57cec5SDimitry Andric   unsigned StorageSize;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   /// The offset of the bitfield storage from the start of the struct.
820b57cec5SDimitry Andric   CharUnits StorageOffset;
830b57cec5SDimitry Andric 
84e8d8bef9SDimitry Andric   /// The offset within a contiguous run of bitfields that are represented as a
85e8d8bef9SDimitry Andric   /// single "field" within the LLVM struct type, taking into account the AAPCS
86e8d8bef9SDimitry Andric   /// rules for volatile bitfields. This offset is in bits.
87e8d8bef9SDimitry Andric   unsigned VolatileOffset : 16;
88e8d8bef9SDimitry Andric 
89e8d8bef9SDimitry Andric   /// The storage size in bits which should be used when accessing this
90e8d8bef9SDimitry Andric   /// bitfield.
91e8d8bef9SDimitry Andric   unsigned VolatileStorageSize;
92e8d8bef9SDimitry Andric 
93e8d8bef9SDimitry Andric   /// The offset of the bitfield storage from the start of the struct.
94e8d8bef9SDimitry Andric   CharUnits VolatileStorageOffset;
95e8d8bef9SDimitry Andric 
CGBitFieldInfoCGBitFieldInfo960b57cec5SDimitry Andric   CGBitFieldInfo()
9704eeddc0SDimitry Andric       : Offset(), Size(), IsSigned(), StorageSize(), VolatileOffset(),
9804eeddc0SDimitry Andric         VolatileStorageSize() {}
990b57cec5SDimitry Andric 
CGBitFieldInfoCGBitFieldInfo1000b57cec5SDimitry Andric   CGBitFieldInfo(unsigned Offset, unsigned Size, bool IsSigned,
1010b57cec5SDimitry Andric                  unsigned StorageSize, CharUnits StorageOffset)
1020b57cec5SDimitry Andric       : Offset(Offset), Size(Size), IsSigned(IsSigned),
1030b57cec5SDimitry Andric         StorageSize(StorageSize), StorageOffset(StorageOffset) {}
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   void print(raw_ostream &OS) const;
1060b57cec5SDimitry Andric   void dump() const;
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   /// Given a bit-field decl, build an appropriate helper object for
1090b57cec5SDimitry Andric   /// accessing that field (which is expected to have the given offset and
1100b57cec5SDimitry Andric   /// size).
1110b57cec5SDimitry Andric   static CGBitFieldInfo MakeInfo(class CodeGenTypes &Types,
1120b57cec5SDimitry Andric                                  const FieldDecl *FD,
1130b57cec5SDimitry Andric                                  uint64_t Offset, uint64_t Size,
1140b57cec5SDimitry Andric                                  uint64_t StorageSize,
1150b57cec5SDimitry Andric                                  CharUnits StorageOffset);
1160b57cec5SDimitry Andric };
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric /// CGRecordLayout - This class handles struct and union layout info while
1190b57cec5SDimitry Andric /// lowering AST types to LLVM types.
1200b57cec5SDimitry Andric ///
1210b57cec5SDimitry Andric /// These layout objects are only created on demand as IR generation requires.
1220b57cec5SDimitry Andric class CGRecordLayout {
1230b57cec5SDimitry Andric   friend class CodeGenTypes;
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   CGRecordLayout(const CGRecordLayout &) = delete;
1260b57cec5SDimitry Andric   void operator=(const CGRecordLayout &) = delete;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric private:
1290b57cec5SDimitry Andric   /// The LLVM type corresponding to this record layout; used when
1300b57cec5SDimitry Andric   /// laying it out as a complete object.
1310b57cec5SDimitry Andric   llvm::StructType *CompleteObjectType;
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   /// The LLVM type for the non-virtual part of this record layout;
1340b57cec5SDimitry Andric   /// used when laying it out as a base subobject.
1350b57cec5SDimitry Andric   llvm::StructType *BaseSubobjectType;
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   /// Map from (non-bit-field) struct field to the corresponding llvm struct
1380b57cec5SDimitry Andric   /// type field no. This info is populated by record builder.
1390b57cec5SDimitry Andric   llvm::DenseMap<const FieldDecl *, unsigned> FieldInfo;
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   /// Map from (bit-field) struct field to the corresponding llvm struct type
1420b57cec5SDimitry Andric   /// field no. This info is populated by record builder.
1430b57cec5SDimitry Andric   llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields;
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   // FIXME: Maybe we could use a CXXBaseSpecifier as the key and use a single
1460b57cec5SDimitry Andric   // map for both virtual and non-virtual bases.
1470b57cec5SDimitry Andric   llvm::DenseMap<const CXXRecordDecl *, unsigned> NonVirtualBases;
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   /// Map from virtual bases to their field index in the complete object.
1500b57cec5SDimitry Andric   llvm::DenseMap<const CXXRecordDecl *, unsigned> CompleteObjectVirtualBases;
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   /// False if any direct or indirect subobject of this class, when
1530b57cec5SDimitry Andric   /// considered as a complete object, requires a non-zero bitpattern
1540b57cec5SDimitry Andric   /// when zero-initialized.
1550b57cec5SDimitry Andric   bool IsZeroInitializable : 1;
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric   /// False if any direct or indirect subobject of this class, when
1580b57cec5SDimitry Andric   /// considered as a base subobject, requires a non-zero bitpattern
1590b57cec5SDimitry Andric   /// when zero-initialized.
1600b57cec5SDimitry Andric   bool IsZeroInitializableAsBase : 1;
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric public:
CGRecordLayout(llvm::StructType * CompleteObjectType,llvm::StructType * BaseSubobjectType,bool IsZeroInitializable,bool IsZeroInitializableAsBase)1630b57cec5SDimitry Andric   CGRecordLayout(llvm::StructType *CompleteObjectType,
1640b57cec5SDimitry Andric                  llvm::StructType *BaseSubobjectType,
1650b57cec5SDimitry Andric                  bool IsZeroInitializable,
1660b57cec5SDimitry Andric                  bool IsZeroInitializableAsBase)
1670b57cec5SDimitry Andric     : CompleteObjectType(CompleteObjectType),
1680b57cec5SDimitry Andric       BaseSubobjectType(BaseSubobjectType),
1690b57cec5SDimitry Andric       IsZeroInitializable(IsZeroInitializable),
1700b57cec5SDimitry Andric       IsZeroInitializableAsBase(IsZeroInitializableAsBase) {}
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   /// Return the "complete object" LLVM type associated with
1730b57cec5SDimitry Andric   /// this record.
getLLVMType()1740b57cec5SDimitry Andric   llvm::StructType *getLLVMType() const {
1750b57cec5SDimitry Andric     return CompleteObjectType;
1760b57cec5SDimitry Andric   }
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   /// Return the "base subobject" LLVM type associated with
1790b57cec5SDimitry Andric   /// this record.
getBaseSubobjectLLVMType()1800b57cec5SDimitry Andric   llvm::StructType *getBaseSubobjectLLVMType() const {
1810b57cec5SDimitry Andric     return BaseSubobjectType;
1820b57cec5SDimitry Andric   }
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   /// Check whether this struct can be C++ zero-initialized
1850b57cec5SDimitry Andric   /// with a zeroinitializer.
isZeroInitializable()1860b57cec5SDimitry Andric   bool isZeroInitializable() const {
1870b57cec5SDimitry Andric     return IsZeroInitializable;
1880b57cec5SDimitry Andric   }
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   /// Check whether this struct can be C++ zero-initialized
1910b57cec5SDimitry Andric   /// with a zeroinitializer when considered as a base subobject.
isZeroInitializableAsBase()1920b57cec5SDimitry Andric   bool isZeroInitializableAsBase() const {
1930b57cec5SDimitry Andric     return IsZeroInitializableAsBase;
1940b57cec5SDimitry Andric   }
1950b57cec5SDimitry Andric 
containsFieldDecl(const FieldDecl * FD)196*0fca6ea1SDimitry Andric   bool containsFieldDecl(const FieldDecl *FD) const {
197*0fca6ea1SDimitry Andric     return FieldInfo.count(FD) != 0;
198*0fca6ea1SDimitry Andric   }
199*0fca6ea1SDimitry Andric 
2000b57cec5SDimitry Andric   /// Return llvm::StructType element number that corresponds to the
2010b57cec5SDimitry Andric   /// field FD.
getLLVMFieldNo(const FieldDecl * FD)2020b57cec5SDimitry Andric   unsigned getLLVMFieldNo(const FieldDecl *FD) const {
2030b57cec5SDimitry Andric     FD = FD->getCanonicalDecl();
2040b57cec5SDimitry Andric     assert(FieldInfo.count(FD) && "Invalid field for record!");
2050b57cec5SDimitry Andric     return FieldInfo.lookup(FD);
2060b57cec5SDimitry Andric   }
2070b57cec5SDimitry Andric 
20881ad6265SDimitry Andric   // Return whether the following non virtual base has a corresponding
20981ad6265SDimitry Andric   // entry in the LLVM struct.
hasNonVirtualBaseLLVMField(const CXXRecordDecl * RD)21081ad6265SDimitry Andric   bool hasNonVirtualBaseLLVMField(const CXXRecordDecl *RD) const {
21181ad6265SDimitry Andric     return NonVirtualBases.count(RD);
21281ad6265SDimitry Andric   }
21381ad6265SDimitry Andric 
getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl * RD)2140b57cec5SDimitry Andric   unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const {
2150b57cec5SDimitry Andric     assert(NonVirtualBases.count(RD) && "Invalid non-virtual base!");
2160b57cec5SDimitry Andric     return NonVirtualBases.lookup(RD);
2170b57cec5SDimitry Andric   }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   /// Return the LLVM field index corresponding to the given
2200b57cec5SDimitry Andric   /// virtual base.  Only valid when operating on the complete object.
getVirtualBaseIndex(const CXXRecordDecl * base)2210b57cec5SDimitry Andric   unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const {
2220b57cec5SDimitry Andric     assert(CompleteObjectVirtualBases.count(base) && "Invalid virtual base!");
2230b57cec5SDimitry Andric     return CompleteObjectVirtualBases.lookup(base);
2240b57cec5SDimitry Andric   }
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   /// Return the BitFieldInfo that corresponds to the field FD.
getBitFieldInfo(const FieldDecl * FD)2270b57cec5SDimitry Andric   const CGBitFieldInfo &getBitFieldInfo(const FieldDecl *FD) const {
2280b57cec5SDimitry Andric     FD = FD->getCanonicalDecl();
2290b57cec5SDimitry Andric     assert(FD->isBitField() && "Invalid call for non-bit-field decl!");
2300b57cec5SDimitry Andric     llvm::DenseMap<const FieldDecl *, CGBitFieldInfo>::const_iterator
2310b57cec5SDimitry Andric       it = BitFields.find(FD);
2320b57cec5SDimitry Andric     assert(it != BitFields.end() && "Unable to find bitfield info");
2330b57cec5SDimitry Andric     return it->second;
2340b57cec5SDimitry Andric   }
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   void print(raw_ostream &OS) const;
2370b57cec5SDimitry Andric   void dump() const;
2380b57cec5SDimitry Andric };
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric }  // end namespace CodeGen
2410b57cec5SDimitry Andric }  // end namespace clang
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric #endif
244