blob: 234f8591182bebebc2874c18eb398121b319ad97 [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;
Daniel Dunbar23ee4b72010-03-31 00:11:27 +000017 class Type;
18}
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:
80 /// The number of access components to use.
81 unsigned NumComponents;
82
83 /// The components to use to access the bit-field. We may need up to three
84 /// separate components to support up to i64 bit-field access (4 + 2 + 1 byte
85 /// accesses).
86 //
87 // FIXME: De-hardcode this, just allocate following the struct.
88 AccessInfo Components[3];
89
90public:
Daniel Dunbarc75c8bd2010-04-08 02:59:45 +000091 CGBitFieldInfo(const llvm::Type *FieldTy, unsigned FieldNo,
92 unsigned Start, unsigned Size, bool IsSigned)
93 : FieldTy(FieldTy), FieldNo(FieldNo),
94 Start(Start), Size(Size), IsSigned(IsSigned) {}
Daniel Dunbarcd3d5e72010-04-05 16:20:44 +000095
Daniel Dunbarc75c8bd2010-04-08 02:59:45 +000096 const llvm::Type *FieldTy;
Daniel Dunbarcd3d5e72010-04-05 16:20:44 +000097 unsigned FieldNo;
Daniel Dunbarc75c8bd2010-04-08 02:59:45 +000098
Daniel Dunbarcd3d5e72010-04-05 16:20:44 +000099 unsigned Start;
100 unsigned Size;
Daniel Dunbar196ea442010-04-06 01:07:44 +0000101 bool IsSigned : 1;
Daniel Dunbarb97bff92010-04-12 18:14:18 +0000102
Daniel Dunbarb935b932010-04-13 20:58:55 +0000103public:
104 bool isSigned() const { return IsSigned; }
105
106 unsigned getNumComponents() const { return NumComponents; }
107 void setNumComponents(unsigned Value) {
108 assert(Value < 4 && "Invalid number of components!");
109 NumComponents = Value;
110 }
111
112 const AccessInfo &getComponent(unsigned Index) const {
113 assert(Index < getNumComponents() && "Invalid access!");
114 return Components[Index];
115 }
116 AccessInfo &getComponent(unsigned Index) {
117 assert(Index < getNumComponents() && "Invalid access!");
118 return Components[Index];
119 }
120
Daniel Dunbarb97bff92010-04-12 18:14:18 +0000121 void print(llvm::raw_ostream &OS) const;
122 void dump() const;
Daniel Dunbarcd3d5e72010-04-05 16:20:44 +0000123};
124
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000125/// CGRecordLayout - This class handles struct and union layout info while
126/// lowering AST types to LLVM types.
Daniel Dunbar034299e2010-03-31 01:09:11 +0000127///
128/// These layout objects are only created on demand as IR generation requires.
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000129class CGRecordLayout {
Daniel Dunbar034299e2010-03-31 01:09:11 +0000130 friend class CodeGenTypes;
131
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000132 CGRecordLayout(const CGRecordLayout&); // DO NOT IMPLEMENT
133 void operator=(const CGRecordLayout&); // DO NOT IMPLEMENT
134
Daniel Dunbar034299e2010-03-31 01:09:11 +0000135private:
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000136 /// The LLVMType corresponding to this record layout.
137 const llvm::Type *LLVMType;
138
Daniel Dunbar034299e2010-03-31 01:09:11 +0000139 /// Map from (non-bit-field) struct field to the corresponding llvm struct
140 /// type field no. This info is populated by record builder.
141 llvm::DenseMap<const FieldDecl *, unsigned> FieldInfo;
142
143 /// Map from (bit-field) struct field to the corresponding llvm struct type
144 /// field no. This info is populated by record builder.
Daniel Dunbarcd3d5e72010-04-05 16:20:44 +0000145 llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields;
Daniel Dunbar034299e2010-03-31 01:09:11 +0000146
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000147 /// Whether one of the fields in this record layout is a pointer to data
148 /// member, or a struct that contains pointer to data member.
Daniel Dunbar034299e2010-03-31 01:09:11 +0000149 bool ContainsPointerToDataMember : 1;
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000150
151public:
152 CGRecordLayout(const llvm::Type *T, bool ContainsPointerToDataMember)
153 : LLVMType(T), ContainsPointerToDataMember(ContainsPointerToDataMember) {}
154
Daniel Dunbar034299e2010-03-31 01:09:11 +0000155 /// \brief Return the LLVM type associated with this record.
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000156 const llvm::Type *getLLVMType() const {
157 return LLVMType;
158 }
159
Daniel Dunbar034299e2010-03-31 01:09:11 +0000160 /// \brief Check whether this struct contains pointers to data members.
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000161 bool containsPointerToDataMember() const {
162 return ContainsPointerToDataMember;
163 }
Daniel Dunbar034299e2010-03-31 01:09:11 +0000164
165 /// \brief Return the BitFieldInfo that corresponds to the field FD.
166 unsigned getLLVMFieldNo(const FieldDecl *FD) const {
167 assert(!FD->isBitField() && "Invalid call for bit-field decl!");
168 assert(FieldInfo.count(FD) && "Invalid field for record!");
169 return FieldInfo.lookup(FD);
170 }
171
172 /// \brief Return llvm::StructType element number that corresponds to the
173 /// field FD.
Daniel Dunbarcd3d5e72010-04-05 16:20:44 +0000174 const CGBitFieldInfo &getBitFieldInfo(const FieldDecl *FD) const {
Daniel Dunbar034299e2010-03-31 01:09:11 +0000175 assert(FD->isBitField() && "Invalid call for non bit-field decl!");
Daniel Dunbarcd3d5e72010-04-05 16:20:44 +0000176 llvm::DenseMap<const FieldDecl *, CGBitFieldInfo>::const_iterator
Daniel Dunbar034299e2010-03-31 01:09:11 +0000177 it = BitFields.find(FD);
178 assert(it != BitFields.end() && "Unable to find bitfield info");
179 return it->second;
180 }
Daniel Dunbarb97bff92010-04-12 18:14:18 +0000181
182 void print(llvm::raw_ostream &OS) const;
183 void dump() const;
Daniel Dunbar072d0bb2010-03-30 22:26:10 +0000184};
185
186} // end namespace CodeGen
187} // end namespace clang
188
189#endif