blob: a659003465ca57b936f8a946ba1c2bfb80fc0ef4 [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- CodeGenTypes.cpp - Type translation for LLVM CodeGen -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner0bc735f2007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Reid Spencer5f016e22007-07-11 17:01:13 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This is the code that handles AST -> LLVM type lowering.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CodeGenTypes.h"
15#include "clang/Basic/TargetInfo.h"
16#include "clang/AST/AST.h"
17#include "llvm/DerivedTypes.h"
Anders Carlsson4e533282007-08-17 22:00:32 +000018#include "llvm/Module.h"
Devang Pateld9e9ede2007-10-31 20:08:22 +000019#include "llvm/Target/TargetData.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000020
21using namespace clang;
22using namespace CodeGen;
23
Devang Patel057afdd2007-10-24 20:38:06 +000024namespace {
Devang Patel88a981b2007-11-01 19:11:01 +000025 /// RecordOrganizer - This helper class, used by CGRecordLayout, layouts
Devang Patel057afdd2007-10-24 20:38:06 +000026 /// structs and unions. It manages transient information used during layout.
Devang Patel4c4635c2008-02-05 03:17:42 +000027 /// FIXME : Handle field aligments. Handle packed structs.
Devang Patel057afdd2007-10-24 20:38:06 +000028 class RecordOrganizer {
29 public:
Devang Patelf9fef922007-11-01 00:07:12 +000030 explicit RecordOrganizer(CodeGenTypes &Types) :
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +000031 CGT(Types), STy(NULL), llvmFieldNo(0), Cursor(0),
32 llvmSize(0) {}
Devang Patel057afdd2007-10-24 20:38:06 +000033
34 /// addField - Add new field.
35 void addField(const FieldDecl *FD);
36
Devang Patel159e3302007-11-07 01:57:13 +000037 /// addLLVMField - Add llvm struct field that corresponds to llvm type Ty.
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +000038 /// Increment field count.
Devang Patel5bfc1a72008-02-05 01:40:48 +000039 void addLLVMField(const llvm::Type *Ty, bool isPaddingField = false);
Devang Patel0bd41f22007-10-31 23:17:19 +000040
Devang Patelb70a88e2007-11-07 21:04:59 +000041 /// addPaddingFields - Current cursor is not suitable place to add next
42 /// field. Add required padding fields.
Devang Pateldd6ecdb2007-12-21 18:43:53 +000043 void addPaddingFields(unsigned WaterMark);
Devang Patel0bd41f22007-10-31 23:17:19 +000044
Devang Patel86522b92007-10-29 20:50:19 +000045 /// layoutStructFields - Do the actual work and lay out all fields. Create
Devang Patel057afdd2007-10-24 20:38:06 +000046 /// corresponding llvm struct type. This should be invoked only after
47 /// all fields are added.
Devang Patel88a981b2007-11-01 19:11:01 +000048 void layoutStructFields(const ASTRecordLayout &RL);
Devang Patel86522b92007-10-29 20:50:19 +000049
50 /// layoutUnionFields - Do the actual work and lay out all fields. Create
51 /// corresponding llvm struct type. This should be invoked only after
52 /// all fields are added.
Devang Patelf9fef922007-11-01 00:07:12 +000053 void layoutUnionFields();
Devang Patel057afdd2007-10-24 20:38:06 +000054
55 /// getLLVMType - Return associated llvm struct type. This may be NULL
56 /// if fields are not laid out.
57 llvm::Type *getLLVMType() const {
58 return STy;
59 }
60
Devang Patel382c6432007-12-11 19:51:39 +000061 /// placeBitField - Find a place for FD, which is a bit-field.
62 void placeBitField(const FieldDecl *FD);
63
Devang Pateleae15602008-02-05 02:39:50 +000064 llvm::SmallSet<unsigned, 8> &getPaddingFields() {
Devang Patel5bfc1a72008-02-05 01:40:48 +000065 return PaddingFields;
66 }
67
Devang Patel057afdd2007-10-24 20:38:06 +000068 private:
Devang Patelf9fef922007-11-01 00:07:12 +000069 CodeGenTypes &CGT;
Devang Patel057afdd2007-10-24 20:38:06 +000070 llvm::Type *STy;
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +000071 unsigned llvmFieldNo;
72 uint64_t Cursor;
Devang Pateldd6ecdb2007-12-21 18:43:53 +000073 uint64_t llvmSize;
Devang Patel057afdd2007-10-24 20:38:06 +000074 llvm::SmallVector<const FieldDecl *, 8> FieldDecls;
Devang Patel0bd41f22007-10-31 23:17:19 +000075 std::vector<const llvm::Type*> LLVMFields;
Devang Patel6e8df732007-12-11 00:49:18 +000076 llvm::SmallVector<uint64_t, 8> Offsets;
Devang Pateleae15602008-02-05 02:39:50 +000077 llvm::SmallSet<unsigned, 8> PaddingFields;
Devang Patel057afdd2007-10-24 20:38:06 +000078 };
79}
80
Devang Patel7a4718e2007-10-31 20:01:01 +000081CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M,
82 const llvm::TargetData &TD)
83 : Context(Ctx), Target(Ctx.Target), TheModule(M), TheTargetData(TD) {
Chris Lattnerd2d2a112007-07-14 01:29:45 +000084}
Reid Spencer5f016e22007-07-11 17:01:13 +000085
Devang Patelb84a06e2007-10-23 02:10:49 +000086CodeGenTypes::~CodeGenTypes() {
Chris Lattneraf319132008-02-05 06:55:31 +000087 for(llvm::DenseMap<const TagDecl *, CGRecordLayout *>::iterator
Devang Patel88a981b2007-11-01 19:11:01 +000088 I = CGRecordLayouts.begin(), E = CGRecordLayouts.end();
Devang Patelb84a06e2007-10-23 02:10:49 +000089 I != E; ++I)
90 delete I->second;
Devang Patel88a981b2007-11-01 19:11:01 +000091 CGRecordLayouts.clear();
Devang Patelb84a06e2007-10-23 02:10:49 +000092}
93
Reid Spencer5f016e22007-07-11 17:01:13 +000094/// ConvertType - Convert the specified type to its LLVM form.
95const llvm::Type *CodeGenTypes::ConvertType(QualType T) {
Devang Patel30ec9972007-10-25 18:32:36 +000096 // See if type is already cached.
Devang Patel0ffe89a2007-10-30 20:46:47 +000097 llvm::DenseMap<Type *, llvm::PATypeHolder>::iterator
Chris Lattner4581fff2008-02-06 05:21:55 +000098 I = TypeCache.find(T.getTypePtr());
Devang Patel3c400852007-12-21 19:35:28 +000099 // If type is found in map and this is not a definition for a opaque
Chris Lattnerfae6e292008-02-06 05:29:46 +0000100 // place holder type then use it. Otherwise, convert type T.
Chris Lattner4581fff2008-02-06 05:21:55 +0000101 if (I != TypeCache.end())
Devang Patel47c87b42007-10-30 23:22:14 +0000102 return I->second.get();
Devang Patel30ec9972007-10-25 18:32:36 +0000103
104 const llvm::Type *ResultType = ConvertNewType(T);
Chris Lattner4581fff2008-02-06 05:21:55 +0000105 TypeCache.insert(std::make_pair(T.getTypePtr(),
106 llvm::PATypeHolder(ResultType)));
Devang Patel30ec9972007-10-25 18:32:36 +0000107 return ResultType;
108}
109
Chris Lattner4581fff2008-02-06 05:21:55 +0000110/// ConvertTypeForMem - Convert type T into a llvm::Type. This differs from
111/// ConvertType in that it is used to convert to the memory representation for
112/// a type. For example, the scalar representation for _Bool is i1, but the
113/// memory representation is usually i8 or i32, depending on the target.
Chris Lattner19009e62008-01-09 18:47:25 +0000114const llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T) {
115 const llvm::Type *R = ConvertType(T);
116
117 // If this is a non-bool type, don't map it.
118 if (R != llvm::Type::Int1Ty)
119 return R;
120
121 // Otherwise, return an integer of the target-specified size.
122 unsigned BoolWidth = (unsigned)Context.getTypeSize(T, SourceLocation());
123 return llvm::IntegerType::get(BoolWidth);
124
125}
126
Chris Lattnerc5b88062008-02-06 05:08:19 +0000127/// UpdateCompletedType - When we find the full definition for a TagDecl,
128/// replace the 'opaque' type we previously made for it if applicable.
129void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) {
Chris Lattnerd86e6bc2008-02-05 08:06:13 +0000130 llvm::DenseMap<const TagDecl*, llvm::PATypeHolder>::iterator TDTI =
Chris Lattner6ef58e32008-02-06 05:12:09 +0000131 TagDeclTypes.find(TD);
132 if (TDTI == TagDeclTypes.end()) return;
133
134 // Remember the opaque LLVM type for this tagdecl.
Chris Lattnerd86e6bc2008-02-05 08:06:13 +0000135 llvm::PATypeHolder OpaqueHolder = TDTI->second;
136 assert(isa<llvm::OpaqueType>(OpaqueHolder.get()) &&
Chris Lattner6ef58e32008-02-06 05:12:09 +0000137 "Updating compilation of an already non-opaque type?");
Chris Lattnerd86e6bc2008-02-05 08:06:13 +0000138
139 // Remove it from TagDeclTypes so that it will be regenerated.
140 TagDeclTypes.erase(TDTI);
141
Chris Lattner6ef58e32008-02-06 05:12:09 +0000142 QualType NewTy = Context.getTagDeclType(const_cast<TagDecl*>(TD));
Chris Lattnerc5b88062008-02-06 05:08:19 +0000143 const llvm::Type *NT = ConvertNewType(NewTy);
Chris Lattnerd86e6bc2008-02-05 08:06:13 +0000144
145 // If getting the type didn't itself refine it, refine it to its actual type
146 // now.
147 if (llvm::OpaqueType *OT = dyn_cast<llvm::OpaqueType>(OpaqueHolder.get()))
148 OT->refineAbstractTypeTo(NT);
149}
150
151
Chris Lattner19009e62008-01-09 18:47:25 +0000152
Devang Patel30ec9972007-10-25 18:32:36 +0000153const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000154 const clang::Type &Ty = *T.getCanonicalType();
155
156 switch (Ty.getTypeClass()) {
Chris Lattnerd14faaa2007-08-02 21:50:34 +0000157 case Type::TypeName: // typedef isn't canonical.
158 case Type::TypeOfExp: // typeof isn't canonical.
159 case Type::TypeOfTyp: // typeof isn't canonical.
160 assert(0 && "Non-canonical type, shouldn't happen");
Reid Spencer5f016e22007-07-11 17:01:13 +0000161 case Type::Builtin: {
162 switch (cast<BuiltinType>(Ty).getKind()) {
163 case BuiltinType::Void:
164 // LLVM void type can only be used as the result of a function call. Just
165 // map to the same as char.
Chris Lattnerd2d2a112007-07-14 01:29:45 +0000166 return llvm::IntegerType::get(8);
Reid Spencer5f016e22007-07-11 17:01:13 +0000167
168 case BuiltinType::Bool:
Chris Lattner19009e62008-01-09 18:47:25 +0000169 // Note that we always return bool as i1 for use as a scalar type.
Reid Spencer5f016e22007-07-11 17:01:13 +0000170 return llvm::Type::Int1Ty;
171
Chris Lattnerd2d2a112007-07-14 01:29:45 +0000172 case BuiltinType::Char_S:
173 case BuiltinType::Char_U:
174 case BuiltinType::SChar:
175 case BuiltinType::UChar:
Reid Spencer5f016e22007-07-11 17:01:13 +0000176 case BuiltinType::Short:
177 case BuiltinType::UShort:
Reid Spencer5f016e22007-07-11 17:01:13 +0000178 case BuiltinType::Int:
179 case BuiltinType::UInt:
Reid Spencer5f016e22007-07-11 17:01:13 +0000180 case BuiltinType::Long:
181 case BuiltinType::ULong:
Reid Spencer5f016e22007-07-11 17:01:13 +0000182 case BuiltinType::LongLong:
183 case BuiltinType::ULongLong:
Chris Lattner47f7dbf2007-09-04 02:34:27 +0000184 return llvm::IntegerType::get(
185 static_cast<unsigned>(Context.getTypeSize(T, SourceLocation())));
Reid Spencer5f016e22007-07-11 17:01:13 +0000186
187 case BuiltinType::Float: return llvm::Type::FloatTy;
188 case BuiltinType::Double: return llvm::Type::DoubleTy;
189 case BuiltinType::LongDouble:
190 // FIXME: mapping long double onto double.
191 return llvm::Type::DoubleTy;
192 }
193 break;
194 }
195 case Type::Complex: {
196 std::vector<const llvm::Type*> Elts;
197 Elts.push_back(ConvertType(cast<ComplexType>(Ty).getElementType()));
198 Elts.push_back(Elts[0]);
199 return llvm::StructType::get(Elts);
200 }
201 case Type::Pointer: {
202 const PointerType &P = cast<PointerType>(Ty);
Christopher Lambebb97e92008-02-04 02:31:56 +0000203 QualType ETy = P.getPointeeType();
204 return llvm::PointerType::get(ConvertType(ETy), ETy.getAddressSpace());
Reid Spencer5f016e22007-07-11 17:01:13 +0000205 }
206 case Type::Reference: {
207 const ReferenceType &R = cast<ReferenceType>(Ty);
Christopher Lambddc23f32007-12-17 01:11:20 +0000208 return llvm::PointerType::getUnqual(ConvertType(R.getReferenceeType()));
Reid Spencer5f016e22007-07-11 17:01:13 +0000209 }
210
Steve Narofffb22d962007-08-30 01:06:46 +0000211 case Type::VariableArray: {
212 const VariableArrayType &A = cast<VariableArrayType>(Ty);
Reid Spencer5f016e22007-07-11 17:01:13 +0000213 assert(A.getSizeModifier() == ArrayType::Normal &&
214 A.getIndexTypeQualifier() == 0 &&
215 "FIXME: We only handle trivial array types so far!");
Chris Lattner78e30fb2007-08-26 05:02:07 +0000216 if (A.getSizeExpr() == 0) {
217 // int X[] -> [0 x int]
218 return llvm::ArrayType::get(ConvertType(A.getElementType()), 0);
Reid Spencer5f016e22007-07-11 17:01:13 +0000219 } else {
220 assert(0 && "FIXME: VLAs not implemented yet!");
221 }
222 }
Steve Narofffb22d962007-08-30 01:06:46 +0000223 case Type::ConstantArray: {
224 const ConstantArrayType &A = cast<ConstantArrayType>(Ty);
225 const llvm::Type *EltTy = ConvertType(A.getElementType());
226 return llvm::ArrayType::get(EltTy, A.getSize().getZExtValue());
227 }
Chris Lattnera87b63b2007-07-19 05:13:51 +0000228 case Type::OCUVector:
Reid Spencer5f016e22007-07-11 17:01:13 +0000229 case Type::Vector: {
230 const VectorType &VT = cast<VectorType>(Ty);
231 return llvm::VectorType::get(ConvertType(VT.getElementType()),
232 VT.getNumElements());
233 }
234 case Type::FunctionNoProto:
235 case Type::FunctionProto: {
236 const FunctionType &FP = cast<FunctionType>(Ty);
237 const llvm::Type *ResultType;
238
239 if (FP.getResultType()->isVoidType())
240 ResultType = llvm::Type::VoidTy; // Result of function uses llvm void.
241 else
242 ResultType = ConvertType(FP.getResultType());
243
244 // FIXME: Convert argument types.
245 bool isVarArg;
246 std::vector<const llvm::Type*> ArgTys;
247
248 // Struct return passes the struct byref.
249 if (!ResultType->isFirstClassType() && ResultType != llvm::Type::VoidTy) {
Chris Lattnerfae6e292008-02-06 05:29:46 +0000250 ArgTys.push_back(llvm::PointerType::get(ResultType,
251 FP.getResultType().getAddressSpace()));
Reid Spencer5f016e22007-07-11 17:01:13 +0000252 ResultType = llvm::Type::VoidTy;
253 }
254
255 if (const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(&FP)) {
256 DecodeArgumentTypes(*FTP, ArgTys);
257 isVarArg = FTP->isVariadic();
258 } else {
259 isVarArg = true;
260 }
261
Chris Lattner4ef9be72007-11-27 18:20:52 +0000262 return llvm::FunctionType::get(ResultType, ArgTys, isVarArg);
Reid Spencer5f016e22007-07-11 17:01:13 +0000263 }
Christopher Lambebb97e92008-02-04 02:31:56 +0000264
265 case Type::ASQual:
266 return ConvertType(cast<ASQualType>(Ty).getBaseType());
Chris Lattnerb1776cb2007-09-16 19:23:47 +0000267
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000268 case Type::ObjCInterface:
Chris Lattnerb1776cb2007-09-16 19:23:47 +0000269 assert(0 && "FIXME: add missing functionality here");
270 break;
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000271
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000272 case Type::ObjCQualifiedInterface:
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000273 assert(0 && "FIXME: add missing functionality here");
274 break;
Chris Lattnerb1776cb2007-09-16 19:23:47 +0000275
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000276 case Type::ObjCQualifiedId:
Fariborz Jahanianc5692492007-12-17 21:03:50 +0000277 assert(0 && "FIXME: add missing functionality here");
278 break;
279
Chris Lattnerde0efb32008-02-06 05:48:29 +0000280 case Type::Tagged: {
281 const TagDecl *TD = cast<TagType>(Ty).getDecl();
282 const llvm::Type *Res = ConvertTagDeclType(T, TD);
283
284 std::string TypeName(TD->getKindName());
285 TypeName += '.';
286
287 // Name the codegen type after the typedef name
288 // if there is no tag type name available
289 if (TD->getIdentifier())
290 TypeName += TD->getName();
291 else if (const TypedefType *TdT = dyn_cast<TypedefType>(T))
292 TypeName += TdT->getDecl()->getName();
293 else
294 TypeName += "anon";
295
296 TheModule.addTypeName(TypeName, Res);
297 return Res;
298 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000299 }
300
301 // FIXME: implement.
302 return llvm::OpaqueType::get();
303}
304
305void CodeGenTypes::DecodeArgumentTypes(const FunctionTypeProto &FTP,
306 std::vector<const llvm::Type*> &ArgTys) {
307 for (unsigned i = 0, e = FTP.getNumArgs(); i != e; ++i) {
308 const llvm::Type *Ty = ConvertType(FTP.getArgType(i));
309 if (Ty->isFirstClassType())
310 ArgTys.push_back(Ty);
Chris Lattnerfae6e292008-02-06 05:29:46 +0000311 else
312 // byval arguments are always on the stack, which is addr space #0.
313 ArgTys.push_back(llvm::PointerType::getUnqual(Ty));
Reid Spencer5f016e22007-07-11 17:01:13 +0000314 }
315}
316
Chris Lattnerfc3b8e92008-02-06 05:18:32 +0000317/// ConvertTagDeclType - Lay out a tagged decl type like struct or union or
318/// enum.
319const llvm::Type *CodeGenTypes::ConvertTagDeclType(QualType T,
320 const TagDecl *TD) {
321 llvm::DenseMap<const TagDecl*, llvm::PATypeHolder>::iterator TDTI =
322 TagDeclTypes.find(TD);
323
324 // If corresponding llvm type is not a opaque struct type
325 // then use it.
326 if (TDTI != TagDeclTypes.end() && // Don't have a type?
327 // Have a type, but it was opaque before and now we have a definition.
328 (!isa<llvm::OpaqueType>(TDTI->second.get()) || !TD->isDefinition()))
329 return TDTI->second;
330
331 llvm::Type *ResultType = 0;
332
333 if (!TD->isDefinition()) {
334 ResultType = llvm::OpaqueType::get();
335 TagDeclTypes.insert(std::make_pair(TD, ResultType));
336 } else if (TD->getKind() == Decl::Enum) {
337 // Don't bother storing enums in TagDeclTypes.
338 return ConvertType(cast<EnumDecl>(TD)->getIntegerType());
339 } else if (TD->getKind() == Decl::Struct) {
340 const RecordDecl *RD = cast<const RecordDecl>(TD);
341
Chris Lattnerfae6e292008-02-06 05:29:46 +0000342 // This decl could well be recursive. In this case, insert (unless we
343 // already have one) an opaque definition of this type, which the recursive
344 // uses will get. We will then refine this opaque version later.
Chris Lattnerfc3b8e92008-02-06 05:18:32 +0000345 if (TDTI == TagDeclTypes.end()) {
346 // Create new OpaqueType now for later use in case this is a recursive
347 // type. This will later be refined to the actual type.
348 ResultType = llvm::OpaqueType::get();
349 TagDeclTypes.insert(std::make_pair(TD, ResultType));
Chris Lattnerfae6e292008-02-06 05:29:46 +0000350
351 // Insert this into TypeCache so that later uses won't even get to
352 // ConvertTagDeclType.
Chris Lattner4581fff2008-02-06 05:21:55 +0000353 TypeCache.insert(std::make_pair(T.getTypePtr(), ResultType));
Chris Lattnerfc3b8e92008-02-06 05:18:32 +0000354 }
355
356 // Layout fields.
357 RecordOrganizer RO(*this);
358 for (unsigned i = 0, e = RD->getNumMembers(); i != e; ++i)
359 RO.addField(RD->getMember(i));
360 const ASTRecordLayout &RL = Context.getASTRecordLayout(RD,
361 SourceLocation());
362 RO.layoutStructFields(RL);
363
364 // Get llvm::StructType.
365 CGRecordLayout *RLI = new CGRecordLayout(RO.getLLVMType(),
366 RO.getPaddingFields());
367 ResultType = RLI->getLLVMType();
368 TagDeclTypes.insert(std::make_pair(TD, ResultType));
369 CGRecordLayouts[TD] = RLI;
370
371 // Refining away Opaque could cause ResultType to become invalidated.
372 // Keep it in a happy little type holder to handle this.
373 llvm::PATypeHolder Holder(ResultType);
374
375 // Refine the OpaqueType associated with this RecordDecl.
376 cast<llvm::OpaqueType>(TagDeclTypes.find(TD)->second.get())
Chris Lattnerfae6e292008-02-06 05:29:46 +0000377 ->refineAbstractTypeTo(ResultType);
Chris Lattnerfc3b8e92008-02-06 05:18:32 +0000378
379 ResultType = Holder.get();
380 } else if (TD->getKind() == Decl::Union) {
381 const RecordDecl *RD = cast<const RecordDecl>(TD);
382 // Just use the largest element of the union, breaking ties with the
383 // highest aligned member.
384
385 if (RD->getNumMembers() != 0) {
386 RecordOrganizer RO(*this);
387 for (unsigned i = 0, e = RD->getNumMembers(); i != e; ++i)
388 RO.addField(RD->getMember(i));
389 RO.layoutUnionFields();
390
391 // Get llvm::StructType.
392 CGRecordLayout *RLI = new CGRecordLayout(RO.getLLVMType(),
393 RO.getPaddingFields());
394 ResultType = RLI->getLLVMType();
395 TagDeclTypes.insert(std::make_pair(TD, ResultType));
396 CGRecordLayouts[TD] = RLI;
397 } else {
398 std::vector<const llvm::Type*> Fields;
399 ResultType = llvm::StructType::get(Fields);
400 TagDeclTypes.insert(std::make_pair(TD, ResultType));
401 }
402 } else {
Chris Lattnerfae6e292008-02-06 05:29:46 +0000403 assert(0 && "FIXME: Unknown tag decl kind!");
Chris Lattnerfc3b8e92008-02-06 05:18:32 +0000404 }
405
Chris Lattnerfc3b8e92008-02-06 05:18:32 +0000406 return ResultType;
407}
408
Devang Patelb84a06e2007-10-23 02:10:49 +0000409/// getLLVMFieldNo - Return llvm::StructType element number
410/// that corresponds to the field FD.
411unsigned CodeGenTypes::getLLVMFieldNo(const FieldDecl *FD) {
412 llvm::DenseMap<const FieldDecl *, unsigned>::iterator
413 I = FieldInfo.find(FD);
Hartmut Kaiser21fdf412007-10-24 00:07:36 +0000414 assert (I != FieldInfo.end() && "Unable to find field info");
Devang Patelb84a06e2007-10-23 02:10:49 +0000415 return I->second;
416}
417
Devang Patelc4c429a2007-10-24 00:56:23 +0000418/// addFieldInfo - Assign field number to field FD.
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000419void CodeGenTypes::addFieldInfo(const FieldDecl *FD, unsigned No) {
420 FieldInfo[FD] = No;
421}
422
423/// getBitFieldInfo - Return the BitFieldInfo that corresponds to the field FD.
424CodeGenTypes::BitFieldInfo CodeGenTypes::getBitFieldInfo(const FieldDecl *FD) {
425 llvm::DenseMap<const FieldDecl *, BitFieldInfo>::iterator
426 I = BitFields.find(FD);
427 assert (I != BitFields.end() && "Unable to find bitfield info");
428 return I->second;
429}
430
431/// addBitFieldInfo - Assign a start bit and a size to field FD.
432void CodeGenTypes::addBitFieldInfo(const FieldDecl *FD, unsigned Begin,
433 unsigned Size) {
434 BitFields.insert(std::make_pair(FD, BitFieldInfo(Begin, Size)));
Devang Patelb84a06e2007-10-23 02:10:49 +0000435}
436
Devang Patel88a981b2007-11-01 19:11:01 +0000437/// getCGRecordLayout - Return record layout info for the given llvm::Type.
438const CGRecordLayout *
Chris Lattneraf319132008-02-05 06:55:31 +0000439CodeGenTypes::getCGRecordLayout(const TagDecl *TD) const {
440 llvm::DenseMap<const TagDecl*, CGRecordLayout *>::iterator I
441 = CGRecordLayouts.find(TD);
Devang Patel88a981b2007-11-01 19:11:01 +0000442 assert (I != CGRecordLayouts.end()
Devang Patelb84a06e2007-10-23 02:10:49 +0000443 && "Unable to find record layout information for type");
444 return I->second;
445}
446
Devang Patelb84a06e2007-10-23 02:10:49 +0000447/// addField - Add new field.
448void RecordOrganizer::addField(const FieldDecl *FD) {
449 assert (!STy && "Record fields are already laid out");
450 FieldDecls.push_back(FD);
451}
452
Devang Patel86522b92007-10-29 20:50:19 +0000453/// layoutStructFields - Do the actual work and lay out all fields. Create
Devang Patelb84a06e2007-10-23 02:10:49 +0000454/// corresponding llvm struct type. This should be invoked only after
455/// all fields are added.
456/// FIXME : At the moment assume
457/// - one to one mapping between AST FieldDecls and
458/// llvm::StructType elements.
459/// - Ignore bit fields
460/// - Ignore field aligments
461/// - Ignore packed structs
Devang Patel88a981b2007-11-01 19:11:01 +0000462void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {
Devang Patelb84a06e2007-10-23 02:10:49 +0000463 // FIXME : Use SmallVector
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000464 llvmSize = 0;
465 llvmFieldNo = 0;
Devang Patelf9fef922007-11-01 00:07:12 +0000466 Cursor = 0;
Devang Patel0bd41f22007-10-31 23:17:19 +0000467 LLVMFields.clear();
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000468 Offsets.clear();
469
Devang Patelb84a06e2007-10-23 02:10:49 +0000470 for (llvm::SmallVector<const FieldDecl *, 8>::iterator I = FieldDecls.begin(),
Devang Patel655bf3d2007-10-24 00:26:24 +0000471 E = FieldDecls.end(); I != E; ++I) {
Devang Patelb84a06e2007-10-23 02:10:49 +0000472 const FieldDecl *FD = *I;
Devang Patelb84a06e2007-10-23 02:10:49 +0000473
Devang Patel382c6432007-12-11 19:51:39 +0000474 if (FD->isBitField())
475 placeBitField(FD);
476 else {
Devang Patel159e3302007-11-07 01:57:13 +0000477 const llvm::Type *Ty = CGT.ConvertType(FD->getType());
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000478 addLLVMField(Ty);
479 CGT.addFieldInfo(FD, llvmFieldNo - 1);
480 Cursor = llvmSize;
Devang Patel159e3302007-11-07 01:57:13 +0000481 }
Devang Patelb84a06e2007-10-23 02:10:49 +0000482 }
Devang Patel6e8df732007-12-11 00:49:18 +0000483
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000484 unsigned StructAlign = RL.getAlignment();
485 if (llvmSize % StructAlign) {
486 unsigned StructPadding = StructAlign - (llvmSize % StructAlign);
487 addPaddingFields(llvmSize + StructPadding);
488 }
Devang Patel6e8df732007-12-11 00:49:18 +0000489
Devang Patel0bd41f22007-10-31 23:17:19 +0000490 STy = llvm::StructType::get(LLVMFields);
491}
492
Devang Patelf9fef922007-11-01 00:07:12 +0000493/// addPaddingFields - Current cursor is not suitable place to add next field.
494/// Add required padding fields.
Devang Pateldd6ecdb2007-12-21 18:43:53 +0000495void RecordOrganizer::addPaddingFields(unsigned WaterMark) {
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000496 unsigned RequiredBits = WaterMark - llvmSize;
497 unsigned RequiredBytes = (RequiredBits + 7) / 8;
Devang Patelf9fef922007-11-01 00:07:12 +0000498 for (unsigned i = 0; i != RequiredBytes; ++i)
Devang Patel5bfc1a72008-02-05 01:40:48 +0000499 addLLVMField(llvm::Type::Int8Ty, true);
Devang Patelf9fef922007-11-01 00:07:12 +0000500}
501
Devang Patelb70a88e2007-11-07 21:04:59 +0000502/// addLLVMField - Add llvm struct field that corresponds to llvm type Ty.
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000503/// Increment field count.
Devang Patel5bfc1a72008-02-05 01:40:48 +0000504void RecordOrganizer::addLLVMField(const llvm::Type *Ty, bool isPaddingField) {
Devang Patel159e3302007-11-07 01:57:13 +0000505
506 unsigned AlignmentInBits = CGT.getTargetData().getABITypeAlignment(Ty) * 8;
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000507 if (llvmSize % AlignmentInBits) {
Devang Patel159e3302007-11-07 01:57:13 +0000508 // At the moment, insert padding fields even if target specific llvm
509 // type alignment enforces implict padding fields for FD. Later on,
510 // optimize llvm fields by removing implicit padding fields and
511 // combining consequetive padding fields.
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000512 unsigned Padding = AlignmentInBits - (llvmSize % AlignmentInBits);
513 addPaddingFields(llvmSize + Padding);
514 }
Devang Patel159e3302007-11-07 01:57:13 +0000515
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000516 unsigned TySize = CGT.getTargetData().getABITypeSizeInBits(Ty);
517 Offsets.push_back(llvmSize);
518 llvmSize += TySize;
Devang Patel5bfc1a72008-02-05 01:40:48 +0000519 if (isPaddingField)
Devang Pateleae15602008-02-05 02:39:50 +0000520 PaddingFields.insert(llvmFieldNo);
Devang Patel0bd41f22007-10-31 23:17:19 +0000521 LLVMFields.push_back(Ty);
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000522 ++llvmFieldNo;
Devang Patelb84a06e2007-10-23 02:10:49 +0000523}
Devang Patelc4c429a2007-10-24 00:56:23 +0000524
Devang Patel86522b92007-10-29 20:50:19 +0000525/// layoutUnionFields - Do the actual work and lay out all fields. Create
526/// corresponding llvm struct type. This should be invoked only after
527/// all fields are added.
Devang Patelf9fef922007-11-01 00:07:12 +0000528void RecordOrganizer::layoutUnionFields() {
Devang Patel86522b92007-10-29 20:50:19 +0000529
530 unsigned PrimaryEltNo = 0;
531 std::pair<uint64_t, unsigned> PrimaryElt =
532 CGT.getContext().getTypeInfo(FieldDecls[0]->getType(), SourceLocation());
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000533 CGT.addFieldInfo(FieldDecls[0], 0);
Devang Patel86522b92007-10-29 20:50:19 +0000534
535 unsigned Size = FieldDecls.size();
536 for(unsigned i = 1; i != Size; ++i) {
537 const FieldDecl *FD = FieldDecls[i];
Devang Patel159e3302007-11-07 01:57:13 +0000538 assert (!FD->isBitField() && "Bit fields are not yet supported");
Devang Patel86522b92007-10-29 20:50:19 +0000539 std::pair<uint64_t, unsigned> EltInfo =
540 CGT.getContext().getTypeInfo(FD->getType(), SourceLocation());
541
542 // Use largest element, breaking ties with the hightest aligned member.
543 if (EltInfo.first > PrimaryElt.first ||
544 (EltInfo.first == PrimaryElt.first &&
545 EltInfo.second > PrimaryElt.second)) {
546 PrimaryElt = EltInfo;
547 PrimaryEltNo = i;
548 }
549
550 // In union, each field gets first slot.
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000551 CGT.addFieldInfo(FD, 0);
Devang Patel86522b92007-10-29 20:50:19 +0000552 }
553
554 std::vector<const llvm::Type*> Fields;
555 const llvm::Type *Ty = CGT.ConvertType(FieldDecls[PrimaryEltNo]->getType());
556 Fields.push_back(Ty);
557 STy = llvm::StructType::get(Fields);
558}
559
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000560/// placeBitField - Find a place for FD, which is a bit-field.
561/// This function searches for the last aligned field. If the bit-field fits in
562/// it, it is reused. Otherwise, the bit-field is placed in a new field.
Devang Patel382c6432007-12-11 19:51:39 +0000563void RecordOrganizer::placeBitField(const FieldDecl *FD) {
564
565 assert (FD->isBitField() && "FD is not a bit-field");
566 Expr *BitWidth = FD->getBitWidth();
567 llvm::APSInt FieldSize(32);
568 bool isBitField =
569 BitWidth->isIntegerConstantExpr(FieldSize, CGT.getContext());
570 assert (isBitField && "Invalid BitField size expression");
571 uint64_t BitFieldSize = FieldSize.getZExtValue();
Devang Patel5dc043d2007-12-13 01:24:16 +0000572
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000573 bool FoundPrevField = false;
574 unsigned TotalOffsets = Offsets.size();
575 const llvm::Type *Ty = CGT.ConvertType(FD->getType());
576 uint64_t TySize = CGT.getTargetData().getABITypeSizeInBits(Ty);
577
578 if (!TotalOffsets) {
579 // Special case: the first field.
580 CGT.addFieldInfo(FD, llvmFieldNo);
581 CGT.addBitFieldInfo(FD, 0, BitFieldSize);
582 addPaddingFields(BitFieldSize);
583 Cursor = BitFieldSize;
584 return;
Devang Patel382c6432007-12-11 19:51:39 +0000585 }
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000586
587 // Search for the last aligned field.
588 for (unsigned i = TotalOffsets; i != 0; --i) {
589 uint64_t O = Offsets[i - 1];
590 if (O % TySize == 0) {
591 FoundPrevField = true;
592 if (TySize - (Cursor - O) >= BitFieldSize) {
593 // The bitfield fits in the last aligned field.
594 // This is : struct { char a; int CurrentField:10;};
595 // where 'CurrentField' shares first field with 'a'.
596 addPaddingFields(Cursor + BitFieldSize);
Lauro Ramos Venancio9e18d3e2008-01-22 19:15:30 +0000597 CGT.addFieldInfo(FD, i - 1);
598 CGT.addBitFieldInfo(FD, Cursor - O, BitFieldSize);
Lauro Ramos Venancio2c46ce82008-01-21 22:54:57 +0000599 Cursor += BitFieldSize;
600 } else {
601 // Place the bitfield in a new LLVM field.
602 // This is : struct { char a; short CurrentField:10;};
603 // where 'CurrentField' needs a new llvm field.
604 addPaddingFields(O + TySize);
605 CGT.addFieldInfo(FD, llvmFieldNo);
606 CGT.addBitFieldInfo(FD, 0, BitFieldSize);
607 addPaddingFields(O + TySize + BitFieldSize);
608 Cursor = O + TySize + BitFieldSize;
609 }
610 break;
611 }
612 }
613
614 assert(FoundPrevField &&
615 "Unable to find a place for bitfield in struct layout");
Devang Patel382c6432007-12-11 19:51:39 +0000616}