blob: 724364f5e23d5663909cccb25b78f1c757be0e68 [file] [log] [blame]
Anders Carlssone1b29ef2008-08-22 16:00:37 +00001//===--- CGDecl.cpp - Emit LLVM Code for declarations ---------------------===//
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// This contains code dealing with C++ code generation.
11//
12//===----------------------------------------------------------------------===//
13
14// We might split this into multiple files if it gets too unwieldy
15
16#include "CodeGenFunction.h"
17#include "CodeGenModule.h"
Anders Carlsson283a0622009-04-13 18:03:33 +000018#include "Mangle.h"
Anders Carlssone1b29ef2008-08-22 16:00:37 +000019#include "clang/AST/ASTContext.h"
20#include "clang/AST/Decl.h"
Anders Carlsson774e7c62009-04-03 22:50:24 +000021#include "clang/AST/DeclCXX.h"
Anders Carlsson86e96442008-08-23 19:42:54 +000022#include "clang/AST/DeclObjC.h"
Anders Carlssone1b29ef2008-08-22 16:00:37 +000023#include "llvm/ADT/StringExtras.h"
Anders Carlssone1b29ef2008-08-22 16:00:37 +000024using namespace clang;
25using namespace CodeGen;
26
Daniel Dunbar0096acf2009-02-25 19:24:29 +000027void
28CodeGenFunction::GenerateStaticCXXBlockVarDeclInit(const VarDecl &D,
29 llvm::GlobalVariable *GV) {
30 // FIXME: This should use __cxa_guard_{acquire,release}?
31
Anders Carlssone1b29ef2008-08-22 16:00:37 +000032 assert(!getContext().getLangOptions().ThreadsafeStatics &&
33 "thread safe statics are currently not supported!");
Anders Carlssone1b29ef2008-08-22 16:00:37 +000034
Anders Carlsson283a0622009-04-13 18:03:33 +000035 llvm::SmallString<256> GuardVName;
36 llvm::raw_svector_ostream GuardVOut(GuardVName);
37 mangleGuardVariable(&D, getContext(), GuardVOut);
38
Anders Carlssone1b29ef2008-08-22 16:00:37 +000039 // Create the guard variable.
40 llvm::GlobalValue *GuardV =
Owen Anderson1c431b32009-07-08 19:05:04 +000041 new llvm::GlobalVariable(CGM.getModule(), llvm::Type::Int64Ty, false,
Daniel Dunbar0096acf2009-02-25 19:24:29 +000042 GV->getLinkage(),
Owen Andersona1cf15f2009-07-14 23:10:40 +000043 VMContext.getNullValue(llvm::Type::Int64Ty),
Owen Anderson1c431b32009-07-08 19:05:04 +000044 GuardVName.c_str());
Anders Carlssone1b29ef2008-08-22 16:00:37 +000045
Anders Carlssone1b29ef2008-08-22 16:00:37 +000046 // Load the first byte of the guard variable.
Owen Andersona1cf15f2009-07-14 23:10:40 +000047 const llvm::Type *PtrTy = VMContext.getPointerType(llvm::Type::Int8Ty, 0);
Anders Carlssone1b29ef2008-08-22 16:00:37 +000048 llvm::Value *V = Builder.CreateLoad(Builder.CreateBitCast(GuardV, PtrTy),
49 "tmp");
50
51 // Compare it against 0.
Owen Andersona1cf15f2009-07-14 23:10:40 +000052 llvm::Value *nullValue = VMContext.getNullValue(llvm::Type::Int8Ty);
Anders Carlssone1b29ef2008-08-22 16:00:37 +000053 llvm::Value *ICmp = Builder.CreateICmpEQ(V, nullValue , "tobool");
54
Daniel Dunbar55e87422008-11-11 02:29:29 +000055 llvm::BasicBlock *InitBlock = createBasicBlock("init");
Daniel Dunbar9615ecb2008-11-13 01:38:36 +000056 llvm::BasicBlock *EndBlock = createBasicBlock("init.end");
Anders Carlssone1b29ef2008-08-22 16:00:37 +000057
58 // If the guard variable is 0, jump to the initializer code.
59 Builder.CreateCondBr(ICmp, InitBlock, EndBlock);
60
61 EmitBlock(InitBlock);
62
Anders Carlssone1b29ef2008-08-22 16:00:37 +000063 const Expr *Init = D.getInit();
64 if (!hasAggregateLLVMType(Init->getType())) {
65 llvm::Value *V = EmitScalarExpr(Init);
66 Builder.CreateStore(V, GV, D.getType().isVolatileQualified());
67 } else if (Init->getType()->isAnyComplexType()) {
68 EmitComplexExprIntoAddr(Init, GV, D.getType().isVolatileQualified());
69 } else {
70 EmitAggExpr(Init, GV, D.getType().isVolatileQualified());
71 }
72
Owen Anderson4a28d5d2009-07-24 23:12:58 +000073 Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::Int8Ty, 1),
Anders Carlssone1b29ef2008-08-22 16:00:37 +000074 Builder.CreateBitCast(GuardV, PtrTy));
75
76 EmitBlock(EndBlock);
Anders Carlssone1b29ef2008-08-22 16:00:37 +000077}
78
Anders Carlssonb9de2c52009-05-11 23:37:08 +000079RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD,
80 llvm::Value *Callee,
81 llvm::Value *This,
82 CallExpr::const_arg_iterator ArgBeg,
83 CallExpr::const_arg_iterator ArgEnd) {
84 assert(MD->isInstance() &&
85 "Trying to emit a member call expr on a static method!");
86
87 const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType();
88
89 CallArgList Args;
90
91 // Push the this ptr.
92 Args.push_back(std::make_pair(RValue::get(This),
93 MD->getThisType(getContext())));
94
95 // And the rest of the call args
96 EmitCallArgs(Args, FPT, ArgBeg, ArgEnd);
97
98 QualType ResultType = MD->getType()->getAsFunctionType()->getResultType();
99 return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args),
100 Callee, Args, MD);
101}
102
Anders Carlsson774e7c62009-04-03 22:50:24 +0000103RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) {
104 const MemberExpr *ME = cast<MemberExpr>(CE->getCallee());
105 const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
Anders Carlssonb9de2c52009-05-11 23:37:08 +0000106
Anders Carlssone9918d22009-04-08 20:31:57 +0000107 const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType();
Anders Carlsson774e7c62009-04-03 22:50:24 +0000108 const llvm::Type *Ty =
Anders Carlssone9918d22009-04-08 20:31:57 +0000109 CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
110 FPT->isVariadic());
Chris Lattnerb4880ba2009-05-12 21:21:08 +0000111 llvm::Constant *Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), Ty);
Anders Carlsson774e7c62009-04-03 22:50:24 +0000112
Anders Carlssonb9de2c52009-05-11 23:37:08 +0000113 llvm::Value *This;
Anders Carlsson774e7c62009-04-03 22:50:24 +0000114
Anders Carlsson774e7c62009-04-03 22:50:24 +0000115 if (ME->isArrow())
Anders Carlssonb9de2c52009-05-11 23:37:08 +0000116 This = EmitScalarExpr(ME->getBase());
Anders Carlsson774e7c62009-04-03 22:50:24 +0000117 else {
118 LValue BaseLV = EmitLValue(ME->getBase());
Anders Carlssonb9de2c52009-05-11 23:37:08 +0000119 This = BaseLV.getAddress();
Anders Carlsson774e7c62009-04-03 22:50:24 +0000120 }
121
Anders Carlssonb9de2c52009-05-11 23:37:08 +0000122 return EmitCXXMemberCall(MD, Callee, This,
123 CE->arg_begin(), CE->arg_end());
Anders Carlsson774e7c62009-04-03 22:50:24 +0000124}
Anders Carlsson5f4307b2009-04-14 16:58:56 +0000125
Anders Carlsson0f294632009-05-27 04:18:27 +0000126RValue
127CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
128 const CXXMethodDecl *MD) {
129 assert(MD->isInstance() &&
130 "Trying to emit a member call expr on a static method!");
131
132
133 const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType();
134 const llvm::Type *Ty =
135 CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
136 FPT->isVariadic());
137 llvm::Constant *Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), Ty);
138
139 llvm::Value *This = EmitLValue(E->getArg(0)).getAddress();
140
141 return EmitCXXMemberCall(MD, Callee, This,
142 E->arg_begin() + 1, E->arg_end());
143}
144
Anders Carlsson5f4307b2009-04-14 16:58:56 +0000145llvm::Value *CodeGenFunction::LoadCXXThis() {
146 assert(isa<CXXMethodDecl>(CurFuncDecl) &&
147 "Must be in a C++ member function decl to load 'this'");
148 assert(cast<CXXMethodDecl>(CurFuncDecl)->isInstance() &&
149 "Must be in a C++ member function decl to load 'this'");
150
151 // FIXME: What if we're inside a block?
Mike Stumpf5408fe2009-05-16 07:57:57 +0000152 // ans: See how CodeGenFunction::LoadObjCSelf() uses
153 // CodeGenFunction::BlockForwardSelf() for how to do this.
Anders Carlsson5f4307b2009-04-14 16:58:56 +0000154 return Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this");
155}
Anders Carlsson95d4e5d2009-04-15 15:55:24 +0000156
Anders Carlssonb14095a2009-04-17 00:06:03 +0000157void
158CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
159 CXXCtorType Type,
160 llvm::Value *This,
161 CallExpr::const_arg_iterator ArgBeg,
162 CallExpr::const_arg_iterator ArgEnd) {
Anders Carlssonb9de2c52009-05-11 23:37:08 +0000163 llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type);
164
165 EmitCXXMemberCall(D, Callee, This, ArgBeg, ArgEnd);
Anders Carlssonb14095a2009-04-17 00:06:03 +0000166}
167
Anders Carlsson7267c162009-05-29 21:03:38 +0000168void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *D,
169 CXXDtorType Type,
170 llvm::Value *This) {
171 llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(D, Type);
172
173 EmitCXXMemberCall(D, Callee, This, 0, 0);
174}
175
Anders Carlssonb14095a2009-04-17 00:06:03 +0000176void
Anders Carlsson31ccf372009-05-03 17:47:16 +0000177CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
178 const CXXConstructExpr *E) {
Anders Carlssonb14095a2009-04-17 00:06:03 +0000179 assert(Dest && "Must have a destination!");
180
181 const CXXRecordDecl *RD =
Ted Kremenek35366a62009-07-17 17:50:17 +0000182 cast<CXXRecordDecl>(E->getType()->getAsRecordType()->getDecl());
Anders Carlssonb14095a2009-04-17 00:06:03 +0000183 if (RD->hasTrivialConstructor())
184 return;
185
186 // Call the constructor.
187 EmitCXXConstructorCall(E->getConstructor(), Ctor_Complete, Dest,
188 E->arg_begin(), E->arg_end());
189}
190
Anders Carlssona00703d2009-05-31 01:40:14 +0000191llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
Anders Carlssoned4e3672009-05-31 20:21:44 +0000192 if (E->isArray()) {
193 ErrorUnsupported(E, "new[] expression");
Owen Andersona1cf15f2009-07-14 23:10:40 +0000194 return VMContext.getUndef(ConvertType(E->getType()));
Anders Carlssoned4e3672009-05-31 20:21:44 +0000195 }
196
197 QualType AllocType = E->getAllocatedType();
198 FunctionDecl *NewFD = E->getOperatorNew();
199 const FunctionProtoType *NewFTy = NewFD->getType()->getAsFunctionProtoType();
200
201 CallArgList NewArgs;
202
203 // The allocation size is the first argument.
204 QualType SizeTy = getContext().getSizeType();
205 llvm::Value *AllocSize =
Owen Anderson4a28d5d2009-07-24 23:12:58 +0000206 llvm::ConstantInt::get(ConvertType(SizeTy),
Anders Carlssoned4e3672009-05-31 20:21:44 +0000207 getContext().getTypeSize(AllocType) / 8);
208
209 NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy));
210
211 // Emit the rest of the arguments.
212 // FIXME: Ideally, this should just use EmitCallArgs.
213 CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin();
214
215 // First, use the types from the function type.
216 // We start at 1 here because the first argument (the allocation size)
217 // has already been emitted.
218 for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) {
219 QualType ArgType = NewFTy->getArgType(i);
220
221 assert(getContext().getCanonicalType(ArgType.getNonReferenceType()).
222 getTypePtr() ==
223 getContext().getCanonicalType(NewArg->getType()).getTypePtr() &&
224 "type mismatch in call argument!");
225
226 NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType),
227 ArgType));
228
229 }
230
231 // Either we've emitted all the call args, or we have a call to a
232 // variadic function.
233 assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) &&
234 "Extra arguments in non-variadic function!");
235
236 // If we still have any arguments, emit them using the type of the argument.
237 for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end();
238 NewArg != NewArgEnd; ++NewArg) {
239 QualType ArgType = NewArg->getType();
240 NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType),
241 ArgType));
242 }
243
244 // Emit the call to new.
245 RValue RV =
246 EmitCall(CGM.getTypes().getFunctionInfo(NewFTy->getResultType(), NewArgs),
247 CGM.GetAddrOfFunction(GlobalDecl(NewFD)),
248 NewArgs, NewFD);
249
Anders Carlssond3fd6ba2009-05-31 21:53:59 +0000250 // If an allocation function is declared with an empty exception specification
251 // it returns null to indicate failure to allocate storage. [expr.new]p13.
252 // (We don't need to check for null when there's no new initializer and
253 // we're allocating a POD type).
254 bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() &&
255 !(AllocType->isPODType() && !E->hasInitializer());
Anders Carlssoned4e3672009-05-31 20:21:44 +0000256
Anders Carlssonf1108532009-06-01 00:05:16 +0000257 llvm::BasicBlock *NewNull = 0;
258 llvm::BasicBlock *NewNotNull = 0;
259 llvm::BasicBlock *NewEnd = 0;
260
261 llvm::Value *NewPtr = RV.getScalarVal();
262
Anders Carlssond3fd6ba2009-05-31 21:53:59 +0000263 if (NullCheckResult) {
Anders Carlssonf1108532009-06-01 00:05:16 +0000264 NewNull = createBasicBlock("new.null");
265 NewNotNull = createBasicBlock("new.notnull");
266 NewEnd = createBasicBlock("new.end");
267
268 llvm::Value *IsNull =
269 Builder.CreateICmpEQ(NewPtr,
Owen Andersona1cf15f2009-07-14 23:10:40 +0000270 VMContext.getNullValue(NewPtr->getType()),
Anders Carlssonf1108532009-06-01 00:05:16 +0000271 "isnull");
272
273 Builder.CreateCondBr(IsNull, NewNull, NewNotNull);
274 EmitBlock(NewNotNull);
Anders Carlssond3fd6ba2009-05-31 21:53:59 +0000275 }
276
Anders Carlssonf1108532009-06-01 00:05:16 +0000277 NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType()));
Anders Carlssond3fd6ba2009-05-31 21:53:59 +0000278
Anders Carlsson6d0ffad2009-05-31 20:56:36 +0000279 if (AllocType->isPODType()) {
Anders Carlsson215bd202009-06-01 00:26:14 +0000280 if (E->getNumConstructorArgs() > 0) {
Anders Carlsson6d0ffad2009-05-31 20:56:36 +0000281 assert(E->getNumConstructorArgs() == 1 &&
282 "Can only have one argument to initializer of POD type.");
283
284 const Expr *Init = E->getConstructorArg(0);
285
Anders Carlsson3923e952009-05-31 21:07:58 +0000286 if (!hasAggregateLLVMType(AllocType))
Anders Carlsson6d0ffad2009-05-31 20:56:36 +0000287 Builder.CreateStore(EmitScalarExpr(Init), NewPtr);
Anders Carlsson3923e952009-05-31 21:07:58 +0000288 else if (AllocType->isAnyComplexType())
289 EmitComplexExprIntoAddr(Init, NewPtr, AllocType.isVolatileQualified());
Anders Carlsson627a3e52009-05-31 21:12:26 +0000290 else
291 EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified());
Anders Carlsson6d0ffad2009-05-31 20:56:36 +0000292 }
Anders Carlssond3fd6ba2009-05-31 21:53:59 +0000293 } else {
294 // Call the constructor.
295 CXXConstructorDecl *Ctor = E->getConstructor();
Anders Carlsson6d0ffad2009-05-31 20:56:36 +0000296
Anders Carlssond3fd6ba2009-05-31 21:53:59 +0000297 EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr,
298 E->constructor_arg_begin(),
299 E->constructor_arg_end());
Anders Carlssoned4e3672009-05-31 20:21:44 +0000300 }
Anders Carlssond3fd6ba2009-05-31 21:53:59 +0000301
Anders Carlssonf1108532009-06-01 00:05:16 +0000302 if (NullCheckResult) {
303 Builder.CreateBr(NewEnd);
304 EmitBlock(NewNull);
305 Builder.CreateBr(NewEnd);
306 EmitBlock(NewEnd);
307
308 llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType());
309 PHI->reserveOperandSpace(2);
310 PHI->addIncoming(NewPtr, NewNotNull);
Owen Andersona1cf15f2009-07-14 23:10:40 +0000311 PHI->addIncoming(VMContext.getNullValue(NewPtr->getType()), NewNull);
Anders Carlssonf1108532009-06-01 00:05:16 +0000312
313 NewPtr = PHI;
314 }
315
Anders Carlssond3fd6ba2009-05-31 21:53:59 +0000316 return NewPtr;
Anders Carlssona00703d2009-05-31 01:40:14 +0000317}
318
Anders Carlsson27ae5362009-04-17 01:58:57 +0000319static bool canGenerateCXXstructor(const CXXRecordDecl *RD,
320 ASTContext &Context) {
Anders Carlsson59d8e0f2009-04-15 21:02:13 +0000321 // The class has base classes - we don't support that right now.
322 if (RD->getNumBases() > 0)
323 return false;
324
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +0000325 for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
326 I != E; ++I) {
Anders Carlsson59d8e0f2009-04-15 21:02:13 +0000327 // We don't support ctors for fields that aren't POD.
328 if (!I->getType()->isPODType())
329 return false;
330 }
331
332 return true;
333}
334
Anders Carlsson95d4e5d2009-04-15 15:55:24 +0000335void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) {
Anders Carlsson27ae5362009-04-17 01:58:57 +0000336 if (!canGenerateCXXstructor(D->getParent(), getContext())) {
Anders Carlsson59d8e0f2009-04-15 21:02:13 +0000337 ErrorUnsupported(D, "C++ constructor", true);
338 return;
339 }
Anders Carlsson95d4e5d2009-04-15 15:55:24 +0000340
Anders Carlsson2a131fb2009-05-05 04:44:02 +0000341 EmitGlobal(GlobalDecl(D, Ctor_Complete));
342 EmitGlobal(GlobalDecl(D, Ctor_Base));
Anders Carlsson95d4e5d2009-04-15 15:55:24 +0000343}
Anders Carlsson363c1842009-04-16 23:57:24 +0000344
Anders Carlsson27ae5362009-04-17 01:58:57 +0000345void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D,
346 CXXCtorType Type) {
347
348 llvm::Function *Fn = GetAddrOfCXXConstructor(D, Type);
349
350 CodeGenFunction(*this).GenerateCode(D, Fn);
351
352 SetFunctionDefinitionAttributes(D, Fn);
353 SetLLVMFunctionAttributesForDefinition(D, Fn);
354}
355
Anders Carlsson363c1842009-04-16 23:57:24 +0000356llvm::Function *
357CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
358 CXXCtorType Type) {
359 const llvm::FunctionType *FTy =
360 getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false);
361
362 const char *Name = getMangledCXXCtorName(D, Type);
Chris Lattnerb4880ba2009-05-12 21:21:08 +0000363 return cast<llvm::Function>(
364 GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
Anders Carlsson363c1842009-04-16 23:57:24 +0000365}
Anders Carlsson27ae5362009-04-17 01:58:57 +0000366
367const char *CodeGenModule::getMangledCXXCtorName(const CXXConstructorDecl *D,
368 CXXCtorType Type) {
369 llvm::SmallString<256> Name;
370 llvm::raw_svector_ostream Out(Name);
371 mangleCXXCtor(D, Type, Context, Out);
372
373 Name += '\0';
374 return UniqueMangledName(Name.begin(), Name.end());
375}
376
377void CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) {
378 if (!canGenerateCXXstructor(D->getParent(), getContext())) {
379 ErrorUnsupported(D, "C++ destructor", true);
380 return;
381 }
382
383 EmitCXXDestructor(D, Dtor_Complete);
384 EmitCXXDestructor(D, Dtor_Base);
385}
386
387void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D,
388 CXXDtorType Type) {
389 llvm::Function *Fn = GetAddrOfCXXDestructor(D, Type);
390
391 CodeGenFunction(*this).GenerateCode(D, Fn);
392
393 SetFunctionDefinitionAttributes(D, Fn);
394 SetLLVMFunctionAttributesForDefinition(D, Fn);
395}
396
397llvm::Function *
398CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
399 CXXDtorType Type) {
400 const llvm::FunctionType *FTy =
401 getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false);
402
403 const char *Name = getMangledCXXDtorName(D, Type);
Chris Lattnerb4880ba2009-05-12 21:21:08 +0000404 return cast<llvm::Function>(
405 GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
Anders Carlsson27ae5362009-04-17 01:58:57 +0000406}
407
408const char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D,
409 CXXDtorType Type) {
410 llvm::SmallString<256> Name;
411 llvm::raw_svector_ostream Out(Name);
412 mangleCXXDtor(D, Type, Context, Out);
413
414 Name += '\0';
415 return UniqueMangledName(Name.begin(), Name.end());
416}
Fariborz Jahaniane7d346b2009-07-20 23:18:55 +0000417
418/// EmitCtorPrologue - This routine generates necessary code to initialize
419/// base classes and non-static data members belonging to this constructor.
420void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) {
421 for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(),
422 E = CD->init_end();
423 B != E; ++B) {
424 CXXBaseOrMemberInitializer *Member = (*B);
425 if (Member->isBaseInitializer()) {
426 // FIXME. Added base initialilzers here.
427 assert(false && "FIXME. base initialization unsupported");
428 }
429 else {
430 // non-static data member initilaizers.
431 FieldDecl *Field = Member->getMember();
432 QualType FieldType = getContext().getCanonicalType((Field)->getType());
433 assert(!getContext().getAsArrayType(FieldType)
434 && "FIXME. Field arrays initialization unsupported");
Fariborz Jahanian50b8eea2009-07-24 17:57:02 +0000435
Fariborz Jahaniane7d346b2009-07-20 23:18:55 +0000436 llvm::Value *LoadOfThis = LoadCXXThis();
437 LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0);
Fariborz Jahanian50b8eea2009-07-24 17:57:02 +0000438 if (FieldType->getAsRecordType()) {
439
440 assert(Member->getConstructor() &&
441 "EmitCtorPrologue - no constructor to initialize member");
442 EmitCXXConstructorCall(Member->getConstructor(),
443 Ctor_Complete, LHS.getAddress(),
444 Member->const_arg_begin(),
445 Member->const_arg_end());
446 continue;
447 }
Fariborz Jahaniane7d346b2009-07-20 23:18:55 +0000448
449 assert(Member->getNumArgs() == 1 && "Initializer count must be 1 only");
Fariborz Jahanian50b8eea2009-07-24 17:57:02 +0000450 Expr *RhsExpr = *Member->arg_begin();
Fariborz Jahaniane7d346b2009-07-20 23:18:55 +0000451 llvm::Value *RHS = EmitScalarExpr(RhsExpr, true);
452 if (LHS.isBitfield())
453 EmitStoreThroughBitfieldLValue(RValue::get(RHS), LHS, FieldType, 0);
454 else
455 EmitStoreThroughLValue(RValue::get(RHS), LHS, FieldType);
456 }
457 }
458}