blob: b7efe5a4eea0010ba9a3f41de4e0a07568d7ab1d [file] [log] [blame]
Daniel Dunbar072d0bb2010-03-30 22:26:10 +00001//===--- CGRecordLayout.h - LLVM Record Layout Information ------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef CLANG_CODEGEN_CGRECORDLAYOUT_H
11#define CLANG_CODEGEN_CGRECORDLAYOUT_H
12
Daniel Dunbar034299e2010-03-31 01:09:11 +000013#include "llvm/ADT/DenseMap.h"
14#include "clang/AST/Decl.h"
Daniel Dunbar23ee4b72010-03-31 00:11:27 +000015namespace llvm {
Daniel Dunbarb97bff92010-04-12 18:14:18 +000016 class raw_ostream;
Anders Carlsson36e2fa82010-11-24 19:37:16 +000017 class StructType;
Daniel Dunbar23ee4b72010-03-31 00:11:27 +000018}
19
Daniel Dunbar072d0bb2010-03-30 22:26:10 +000020namespace clang {
21namespace CodeGen {
22
Daniel Dunbarb935b932010-04-13 20:58:55 +000023/// \brief Helper object for describing how to generate the code for access to a
Daniel Dunbarb97bff92010-04-12 18:14:18 +000024/// bit-field.
Daniel Dunbarb935b932010-04-13 20:58:55 +000025///
26/// This structure is intended to describe the "policy" of how the bit-field
27/// should be accessed, which may be target, language, or ABI dependent.
Daniel Dunbarcd3d5e72010-04-05 16:20:44 +000028class CGBitFieldInfo {
29public:
Daniel Dunbarb935b932010-04-13 20:58:55 +000030 /// Descriptor for a single component of a bit-field access. The entire
31 /// bit-field is constituted of a bitwise OR of all of the individual
32 /// components.
33 ///
34 /// Each component describes an accessed value, which is how the component
35 /// should be transferred to/from memory, and a target placement, which is how
36 /// that component fits into the constituted bit-field. The pseudo-IR for a
37 /// load is:
38 ///
39 /// %0 = gep %base, 0, FieldIndex
40 /// %1 = gep (i8*) %0, FieldByteOffset
41 /// %2 = (i(AccessWidth) *) %1
42 /// %3 = load %2, align AccessAlignment
43 /// %4 = shr %3, FieldBitStart
44 ///
45 /// and the composed bit-field is formed as the boolean OR of all accesses,
46 /// masked to TargetBitWidth bits and shifted to TargetBitOffset.
47 struct AccessInfo {
48 /// Offset of the field to load in the LLVM structure, if any.
49 unsigned FieldIndex;
50
51 /// Byte offset from the field address, if any. This should generally be
52 /// unused as the cleanest IR comes from having a well-constructed LLVM type
53 /// with proper GEP instructions, but sometimes its use is required, for
54 /// example if an access is intended to straddle an LLVM field boundary.
55 unsigned FieldByteOffset;
56
57 /// Bit offset in the accessed value to use. The width is implied by \see
58 /// TargetBitWidth.
59 unsigned FieldBitStart;
60
61 /// Bit width of the memory access to perform.
62 unsigned AccessWidth;
63
64 /// The alignment of the memory access, or 0 if the default alignment should
65 /// be used.
66 //
67 // FIXME: Remove use of 0 to encode default, instead have IRgen do the right
68 // thing when it generates the code, if avoiding align directives is
69 // desired.
70 unsigned AccessAlignment;
71
72 /// Offset for the target value.
73 unsigned TargetBitOffset;
74
75 /// Number of bits in the access that are destined for the bit-field.
76 unsigned TargetBitWidth;
77 };
78
79private:
Daniel Dunbarb935b932010-04-13 20:58:55 +000080 /// The components to use to access the bit-field. We may need up to three
81 /// separate components to support up to i64 bit-field access (4 + 2 + 1 byte
82 /// accesses).
83 //
84 // FIXME: De-hardcode this, just allocate following the struct.
85 AccessInfo Components[3];
86
Daniel Dunbarbb138452010-04-15 05:09:28 +000087 /// The total size of the bit-field, in bits.
Daniel Dunbarcd3d5e72010-04-05 16:20:44 +000088 unsigned Size;
Daniel Dunbarbb138452010-04-15 05:09:28 +000089
90 /// The number of access components to use.
91 unsigned NumComponents;
92
93 /// Whether the bit-field is signed.
Daniel Dunbar196ea442010-04-06 01:07:44 +000094 bool IsSigned : 1;
Daniel Dunbarb97bff92010-04-12 18:14:18 +000095
Daniel Dunbarb935b932010-04-13 20:58:55 +000096public:
Daniel Dunbar9c78d632010-04-15 05:09:32 +000097 CGBitFieldInfo(unsigned Size, unsigned NumComponents, AccessInfo *_Components,
98 bool IsSigned) : Size(Size), NumComponents(NumComponents),
99 IsSigned(IsSigned) {
100 assert(NumComponents <= 3 && "invalid number of components!");
101 for (unsigned i = 0; i != NumComponents; ++i)
102 Components[i] = _Components[i];
103
104 // Check some invariants.
105 unsigned AccessedSize = 0;
106 for (unsigned i = 0, e = getNumComponents(); i != e; ++i) {
107 const AccessInfo &AI = getComponent(i);
108 AccessedSize += AI.TargetBitWidth;
109
110 // We shouldn't try to load 0 bits.
111 assert(AI.TargetBitWidth > 0);
112
113 // We can't load more bits than we accessed.
114 assert(AI.FieldBitStart + AI.TargetBitWidth <= AI.AccessWidth);
115
116 // We shouldn't put any bits outside the result size.
117 assert(AI.TargetBitWidth + AI.TargetBitOffset <= Size);
118 }
119
120 // Check that the total number of target bits matches the total bit-field
121 // size.
122 assert(AccessedSize == Size && "Total size does not match accessed size!");
123 }
Daniel Dunbarbb138452010-04-15 05:09:28 +0000124
125public:
Daniel Dunbarb2b40a42010-04-14 04:07:59 +0000126 /// \brief Check whether this bit-field access is (i.e., should be sign
127 /// extended on loads).
Daniel Dunbarb935b932010-04-13 20:58:55 +0000128 bool isSigned() const { return IsSigned; }
129
Daniel Dunbarb2b40a42010-04-14 04:07:59 +0000130 /// \brief Get the size of the bit-field, in bits.
131 unsigned getSize() const { return Size; }
132
133 /// @name Component Access
134 /// @{
135
Daniel Dunbarb935b932010-04-13 20:58:55 +0000136 unsigned getNumComponents() const { return NumComponents; }
Daniel Dunbarb935b932010-04-13 20:58:55 +0000137
138 const AccessInfo &getComponent(unsigned Index) const {
139 assert(Index < getNumComponents() && "Invalid access!");
140 return Components[Index];
141 }
Daniel Dunbarb935b932010-04-13 20:58:55 +0000142
Daniel Dunbarb2b40a42010-04-14 04:07:59 +0000143 /// @}
144
Daniel Dunbarb97bff92010-04-12 18:14:18 +0000145 void print(llvm::raw_ostream &OS) const;
146 void dump() const;
Daniel Dunbarc7f9bba2010-09-02 23:53:28 +0000147
148 /// \brief Given a bit-field decl, build an appropriate helper object for
149 /// accessing that field (which is expected to have the given offset and
150 /// size).
151 static CGBitFieldInfo MakeInfo(class CodeGenTypes &Types, const FieldDecl *FD,
152 uint64_t FieldOffset, uint64_t FieldSize);
153
154 /// \brief Given a bit-field decl, build an appropriate helper object for
155 /// accessing that field (which is expected to have the given offset and
156 /// size). The field decl should be known to be contained within a type of at
157 /// least the given size and with the given alignment.
158 static CGBitFieldInfo MakeInfo(CodeGenTypes &Types, const FieldDecl *FD,
159 uint64_t FieldOffset, uint64_t FieldSize,
160 uint64_t ContainingTypeSizeInBits,
161 unsigned ContainingTypeAlign);
Daniel Dunbarcd3d5e72010-04-05 16:20:44 +0000162};
163
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000164/// CGRecordLayout - This class handles struct and union layout info while
165/// lowering AST types to LLVM types.
Daniel Dunbar034299e2010-03-31 01:09:11 +0000166///
167/// These layout objects are only created on demand as IR generation requires.
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000168class CGRecordLayout {
Daniel Dunbar034299e2010-03-31 01:09:11 +0000169 friend class CodeGenTypes;
170
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000171 CGRecordLayout(const CGRecordLayout&); // DO NOT IMPLEMENT
172 void operator=(const CGRecordLayout&); // DO NOT IMPLEMENT
173
Daniel Dunbar034299e2010-03-31 01:09:11 +0000174private:
Anders Carlssonc1351ca2010-11-09 05:25:47 +0000175 /// The LLVM type corresponding to this record layout.
Anders Carlsson36e2fa82010-11-24 19:37:16 +0000176 const llvm::StructType *LLVMType;
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000177
Anders Carlssonc1351ca2010-11-09 05:25:47 +0000178 /// The LLVM type for the non-virtual part of this record layout, used for
179 /// laying out the record as a base.
Anders Carlsson36e2fa82010-11-24 19:37:16 +0000180 const llvm::StructType *NonVirtualBaseLLVMType;
Anders Carlssonc1351ca2010-11-09 05:25:47 +0000181
Daniel Dunbar034299e2010-03-31 01:09:11 +0000182 /// Map from (non-bit-field) struct field to the corresponding llvm struct
183 /// type field no. This info is populated by record builder.
184 llvm::DenseMap<const FieldDecl *, unsigned> FieldInfo;
185
186 /// Map from (bit-field) struct field to the corresponding llvm struct type
187 /// field no. This info is populated by record builder.
Daniel Dunbarcd3d5e72010-04-05 16:20:44 +0000188 llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields;
Daniel Dunbar034299e2010-03-31 01:09:11 +0000189
Anders Carlsson061ca522010-05-18 05:22:06 +0000190 // FIXME: Maybe we could use a CXXBaseSpecifier as the key and use a single
191 // map for both virtual and non virtual bases.
192 llvm::DenseMap<const CXXRecordDecl *, unsigned> NonVirtualBaseFields;
193
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000194 /// Whether one of the fields in this record layout is a pointer to data
195 /// member, or a struct that contains pointer to data member.
John McCall614dbdc2010-08-22 21:01:12 +0000196 bool IsZeroInitializable : 1;
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000197
198public:
Anders Carlsson36e2fa82010-11-24 19:37:16 +0000199 CGRecordLayout(const llvm::StructType *LLVMType,
200 const llvm::StructType *NonVirtualBaseLLVMType,
Anders Carlssonc1351ca2010-11-09 05:25:47 +0000201 bool IsZeroInitializable)
Anders Carlssona7dd96c2010-11-21 23:59:45 +0000202 : LLVMType(LLVMType), NonVirtualBaseLLVMType(NonVirtualBaseLLVMType),
Anders Carlssonc1351ca2010-11-09 05:25:47 +0000203 IsZeroInitializable(IsZeroInitializable) {}
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000204
Daniel Dunbar034299e2010-03-31 01:09:11 +0000205 /// \brief Return the LLVM type associated with this record.
Anders Carlsson36e2fa82010-11-24 19:37:16 +0000206 const llvm::StructType *getLLVMType() const {
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000207 return LLVMType;
208 }
209
Anders Carlsson36e2fa82010-11-24 19:37:16 +0000210 const llvm::StructType *getNonVirtualBaseLLVMType() const {
Anders Carlssona7dd96c2010-11-21 23:59:45 +0000211 return NonVirtualBaseLLVMType;
Anders Carlssonc1351ca2010-11-09 05:25:47 +0000212 }
213
John McCall614dbdc2010-08-22 21:01:12 +0000214 /// \brief Check whether this struct can be C++ zero-initialized
215 /// with a zeroinitializer.
216 bool isZeroInitializable() const {
217 return IsZeroInitializable;
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000218 }
Daniel Dunbar034299e2010-03-31 01:09:11 +0000219
Daniel Dunbar19d63552010-04-27 14:51:07 +0000220 /// \brief Return llvm::StructType element number that corresponds to the
221 /// field FD.
Daniel Dunbar034299e2010-03-31 01:09:11 +0000222 unsigned getLLVMFieldNo(const FieldDecl *FD) const {
223 assert(!FD->isBitField() && "Invalid call for bit-field decl!");
224 assert(FieldInfo.count(FD) && "Invalid field for record!");
225 return FieldInfo.lookup(FD);
226 }
227
Anders Carlsson061ca522010-05-18 05:22:06 +0000228 unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const {
229 assert(NonVirtualBaseFields.count(RD) && "Invalid non-virtual base!");
230 return NonVirtualBaseFields.lookup(RD);
231 }
232
Daniel Dunbar19d63552010-04-27 14:51:07 +0000233 /// \brief Return the BitFieldInfo that corresponds to the field FD.
Daniel Dunbarcd3d5e72010-04-05 16:20:44 +0000234 const CGBitFieldInfo &getBitFieldInfo(const FieldDecl *FD) const {
Daniel Dunbar034299e2010-03-31 01:09:11 +0000235 assert(FD->isBitField() && "Invalid call for non bit-field decl!");
Daniel Dunbarcd3d5e72010-04-05 16:20:44 +0000236 llvm::DenseMap<const FieldDecl *, CGBitFieldInfo>::const_iterator
Daniel Dunbar034299e2010-03-31 01:09:11 +0000237 it = BitFields.find(FD);
238 assert(it != BitFields.end() && "Unable to find bitfield info");
239 return it->second;
240 }
Daniel Dunbarb97bff92010-04-12 18:14:18 +0000241
242 void print(llvm::raw_ostream &OS) const;
243 void dump() const;
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000244};
245
246} // end namespace CodeGen
247} // end namespace clang
248
249#endif