 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
76.9% |
186 / 242 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
95.0% |
230 / 242 |
| |
|
Line Coverage: |
91.6% |
611 / 667 |
| |
 |
|
 |
1 : //===--- CGClass.cpp - Emit LLVM Code for C++ classes ---------------------===//
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 of classes
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "CodeGenFunction.h"
15 : #include "clang/AST/CXXInheritance.h"
16 : #include "clang/AST/RecordLayout.h"
17 :
18 : using namespace clang;
19 : using namespace CodeGen;
20 :
21 : static uint64_t
22 : ComputeNonVirtualBaseClassOffset(ASTContext &Context, CXXBasePaths &Paths,
23 351: unsigned Start) {
24 351: uint64_t Offset = 0;
25 :
26 351: const CXXBasePath &Path = Paths.front();
255: branch 1 taken
351: branch 2 taken
27 1212: for (unsigned i = Start, e = Path.size(); i != e; ++i) {
28 255: const CXXBasePathElement& Element = Path[i];
29 :
30 : // Get the layout.
31 255: const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class);
32 :
33 255: const CXXBaseSpecifier *BS = Element.Base;
255: branch 1 taken
0: branch 2 not taken
34 255: assert(!BS->isVirtual() && "Should not see virtual bases here!");
35 :
36 : const CXXRecordDecl *Base =
37 255: cast<CXXRecordDecl>(BS->getType()->getAs<RecordType>()->getDecl());
38 :
39 : // Add the offset.
40 255: Offset += Layout.getBaseClassOffset(Base) / 8;
41 : }
42 :
43 351: return Offset;
44 : }
45 :
46 : llvm::Constant *
47 : CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *Class,
48 11: const CXXRecordDecl *BaseClass) {
0: branch 0 not taken
11: branch 1 taken
49 11: if (Class == BaseClass)
50 0: return 0;
51 :
52 : CXXBasePaths Paths(/*FindAmbiguities=*/false,
53 11: /*RecordPaths=*/true, /*DetectVirtual=*/false);
0: branch 1 not taken
11: branch 2 taken
54 11: if (!const_cast<CXXRecordDecl *>(Class)->
55 : isDerivedFrom(const_cast<CXXRecordDecl *>(BaseClass), Paths)) {
56 0: assert(false && "Class must be derived from the passed in base class!");
57 : return 0;
58 : }
59 :
60 11: uint64_t Offset = ComputeNonVirtualBaseClassOffset(getContext(), Paths, 0);
6: branch 0 taken
5: branch 1 taken
61 11: if (!Offset)
62 6: return 0;
63 :
64 : const llvm::Type *PtrDiffTy =
65 5: Types.ConvertType(getContext().getPointerDiffType());
66 :
67 5: return llvm::ConstantInt::get(PtrDiffTy, Offset);
68 : }
69 :
70 : // FIXME: This probably belongs in CGVtable, but it relies on
71 : // the static function ComputeNonVirtualBaseClassOffset, so we should make that
72 : // a CodeGenModule member function as well.
73 : ThunkAdjustment
74 : CodeGenModule::ComputeThunkAdjustment(const CXXRecordDecl *ClassDecl,
75 190: const CXXRecordDecl *BaseClassDecl) {
76 : CXXBasePaths Paths(/*FindAmbiguities=*/false,
77 190: /*RecordPaths=*/true, /*DetectVirtual=*/false);
0: branch 1 not taken
190: branch 2 taken
78 190: if (!const_cast<CXXRecordDecl *>(ClassDecl)->
79 : isDerivedFrom(const_cast<CXXRecordDecl *>(BaseClassDecl), Paths)) {
80 0: assert(false && "Class must be derived from the passed in base class!");
81 : return ThunkAdjustment();
82 : }
83 :
84 190: unsigned Start = 0;
85 190: uint64_t VirtualOffset = 0;
86 :
87 190: const CXXBasePath &Path = Paths.front();
88 190: const CXXRecordDecl *VBase = 0;
252: branch 1 taken
190: branch 2 taken
89 442: for (unsigned i = 0, e = Path.size(); i != e; ++i) {
90 252: const CXXBasePathElement& Element = Path[i];
158: branch 1 taken
94: branch 2 taken
91 252: if (Element.Base->isVirtual()) {
92 158: Start = i+1;
93 158: QualType VBaseType = Element.Base->getType();
94 158: VBase = cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl());
95 : }
96 : }
134: branch 0 taken
56: branch 1 taken
97 190: if (VBase)
98 : VirtualOffset =
99 134: getVtableInfo().getVirtualBaseOffsetIndex(ClassDecl, BaseClassDecl);
100 :
101 : uint64_t Offset =
102 190: ComputeNonVirtualBaseClassOffset(getContext(), Paths, Start);
103 190: return ThunkAdjustment(Offset, VirtualOffset);
104 : }
105 :
106 : llvm::Value *
107 : CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
108 : const CXXRecordDecl *Class,
109 : const CXXRecordDecl *BaseClass,
110 261: bool NullCheckValue) {
111 : QualType BTy =
112 : getContext().getCanonicalType(
113 261: getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(BaseClass)));
114 261: const llvm::Type *BasePtrTy = llvm::PointerType::getUnqual(ConvertType(BTy));
115 :
111: branch 0 taken
150: branch 1 taken
116 261: if (Class == BaseClass) {
117 : // Just cast back.
118 111: return Builder.CreateBitCast(Value, BasePtrTy);
119 : }
120 :
121 : CXXBasePaths Paths(/*FindAmbiguities=*/false,
122 150: /*RecordPaths=*/true, /*DetectVirtual=*/false);
0: branch 1 not taken
150: branch 2 taken
123 150: if (!const_cast<CXXRecordDecl *>(Class)->
124 : isDerivedFrom(const_cast<CXXRecordDecl *>(BaseClass), Paths)) {
125 0: assert(false && "Class must be derived from the passed in base class!");
126 : return 0;
127 : }
128 :
129 150: unsigned Start = 0;
130 150: llvm::Value *VirtualOffset = 0;
131 :
132 150: const CXXBasePath &Path = Paths.front();
133 150: const CXXRecordDecl *VBase = 0;
166: branch 1 taken
150: branch 2 taken
134 316: for (unsigned i = 0, e = Path.size(); i != e; ++i) {
135 166: const CXXBasePathElement& Element = Path[i];
14: branch 1 taken
152: branch 2 taken
136 166: if (Element.Base->isVirtual()) {
137 14: Start = i+1;
138 14: QualType VBaseType = Element.Base->getType();
139 14: VBase = cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl());
140 : }
141 : }
142 :
143 : uint64_t Offset =
144 150: ComputeNonVirtualBaseClassOffset(getContext(), Paths, Start);
145 :
113: branch 0 taken
37: branch 1 taken
102: branch 2 taken
11: branch 3 taken
146 150: if (!Offset && !VBase) {
147 : // Just cast back.
148 102: return Builder.CreateBitCast(Value, BasePtrTy);
149 : }
150 :
151 48: llvm::BasicBlock *CastNull = 0;
152 48: llvm::BasicBlock *CastNotNull = 0;
153 48: llvm::BasicBlock *CastEnd = 0;
154 :
9: branch 0 taken
39: branch 1 taken
155 48: if (NullCheckValue) {
156 9: CastNull = createBasicBlock("cast.null");
157 9: CastNotNull = createBasicBlock("cast.notnull");
158 9: CastEnd = createBasicBlock("cast.end");
159 :
160 : llvm::Value *IsNull =
161 : Builder.CreateICmpEQ(Value,
162 9: llvm::Constant::getNullValue(Value->getType()));
163 9: Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
164 9: EmitBlock(CastNotNull);
165 : }
166 :
12: branch 0 taken
36: branch 1 taken
167 48: if (VBase)
168 12: VirtualOffset = GetVirtualBaseClassOffset(Value, Class, VBase);
169 :
170 48: const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType());
171 48: llvm::Value *NonVirtualOffset = 0;
37: branch 0 taken
11: branch 1 taken
172 48: if (Offset)
173 37: NonVirtualOffset = llvm::ConstantInt::get(PtrDiffTy, Offset);
174 :
175 : llvm::Value *BaseOffset;
12: branch 0 taken
36: branch 1 taken
176 48: if (VBase) {
1: branch 0 taken
11: branch 1 taken
177 12: if (NonVirtualOffset)
178 1: BaseOffset = Builder.CreateAdd(VirtualOffset, NonVirtualOffset);
179 : else
180 11: BaseOffset = VirtualOffset;
181 : } else
182 36: BaseOffset = NonVirtualOffset;
183 :
184 : // Apply the base offset.
185 48: const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
186 48: Value = Builder.CreateBitCast(Value, Int8PtrTy);
187 48: Value = Builder.CreateGEP(Value, BaseOffset, "add.ptr");
188 :
189 : // Cast back.
190 48: Value = Builder.CreateBitCast(Value, BasePtrTy);
191 :
9: branch 0 taken
39: branch 1 taken
192 48: if (NullCheckValue) {
193 9: Builder.CreateBr(CastEnd);
194 9: EmitBlock(CastNull);
195 9: Builder.CreateBr(CastEnd);
196 9: EmitBlock(CastEnd);
197 :
198 9: llvm::PHINode *PHI = Builder.CreatePHI(Value->getType());
199 9: PHI->reserveOperandSpace(2);
200 9: PHI->addIncoming(Value, CastNotNull);
201 : PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()),
202 9: CastNull);
203 9: Value = PHI;
204 : }
205 :
206 48: return Value;
207 : }
208 :
209 : llvm::Value *
210 : CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
211 : const CXXRecordDecl *Class,
212 : const CXXRecordDecl *DerivedClass,
213 4: bool NullCheckValue) {
214 : QualType DerivedTy =
215 : getContext().getCanonicalType(
216 4: getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(DerivedClass)));
217 4: const llvm::Type *DerivedPtrTy = ConvertType(DerivedTy)->getPointerTo();
218 :
0: branch 0 not taken
4: branch 1 taken
219 4: if (Class == DerivedClass) {
220 : // Just cast back.
221 0: return Builder.CreateBitCast(Value, DerivedPtrTy);
222 : }
223 :
224 : llvm::Value *NonVirtualOffset =
225 4: CGM.GetNonVirtualBaseClassOffset(DerivedClass, Class);
226 :
4: branch 0 taken
0: branch 1 not taken
227 4: if (!NonVirtualOffset) {
228 : // No offset, we can just cast back.
229 4: return Builder.CreateBitCast(Value, DerivedPtrTy);
230 : }
231 :
232 0: llvm::BasicBlock *CastNull = 0;
233 0: llvm::BasicBlock *CastNotNull = 0;
234 0: llvm::BasicBlock *CastEnd = 0;
235 :
0: branch 0 not taken
0: branch 1 not taken
236 0: if (NullCheckValue) {
237 0: CastNull = createBasicBlock("cast.null");
238 0: CastNotNull = createBasicBlock("cast.notnull");
239 0: CastEnd = createBasicBlock("cast.end");
240 :
241 : llvm::Value *IsNull =
242 : Builder.CreateICmpEQ(Value,
243 0: llvm::Constant::getNullValue(Value->getType()));
244 0: Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
245 0: EmitBlock(CastNotNull);
246 : }
247 :
248 : // Apply the offset.
249 0: Value = Builder.CreatePtrToInt(Value, NonVirtualOffset->getType());
250 0: Value = Builder.CreateSub(Value, NonVirtualOffset);
251 0: Value = Builder.CreateIntToPtr(Value, DerivedPtrTy);
252 :
253 : // Just cast.
254 0: Value = Builder.CreateBitCast(Value, DerivedPtrTy);
255 :
0: branch 0 not taken
0: branch 1 not taken
256 0: if (NullCheckValue) {
257 0: Builder.CreateBr(CastEnd);
258 0: EmitBlock(CastNull);
259 0: Builder.CreateBr(CastEnd);
260 0: EmitBlock(CastEnd);
261 :
262 0: llvm::PHINode *PHI = Builder.CreatePHI(Value->getType());
263 0: PHI->reserveOperandSpace(2);
264 0: PHI->addIncoming(Value, CastNotNull);
265 : PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()),
266 0: CastNull);
267 0: Value = PHI;
268 : }
269 :
270 0: return Value;
271 : }
272 :
273 : /// EmitClassAggrMemberwiseCopy - This routine generates code to copy a class
274 : /// array of objects from SrcValue to DestValue. Copying can be either a bitwise
275 : /// copy or via a copy constructor call.
276 : // FIXME. Consolidate this with EmitCXXAggrConstructorCall.
277 : void CodeGenFunction::EmitClassAggrMemberwiseCopy(llvm::Value *Dest,
278 : llvm::Value *Src,
279 : const ArrayType *Array,
280 : const CXXRecordDecl *BaseClassDecl,
281 4: QualType Ty) {
282 4: const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array);
0: branch 0 not taken
4: branch 1 taken
283 4: assert(CA && "VLA cannot be copied over");
284 4: bool BitwiseCopy = BaseClassDecl->hasTrivialCopyConstructor();
285 :
286 : // Create a temporary for the loop index and initialize it with 0.
287 : llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext),
288 4: "loop.index");
289 : llvm::Value* zeroConstant =
290 4: llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext));
291 4: Builder.CreateStore(zeroConstant, IndexPtr);
292 : // Start the loop with a block that tests the condition.
293 4: llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
294 4: llvm::BasicBlock *AfterFor = createBasicBlock("for.end");
295 :
296 4: EmitBlock(CondBlock);
297 :
298 4: llvm::BasicBlock *ForBody = createBasicBlock("for.body");
299 : // Generate: if (loop-index < number-of-elements fall to the loop body,
300 : // otherwise, go to the block after the for-loop.
301 4: uint64_t NumElements = getContext().getConstantArrayElementCount(CA);
302 : llvm::Value * NumElementsPtr =
303 4: llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements);
304 4: llvm::Value *Counter = Builder.CreateLoad(IndexPtr);
305 : llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr,
306 4: "isless");
307 : // If the condition is true, execute the body.
308 4: Builder.CreateCondBr(IsLess, ForBody, AfterFor);
309 :
310 4: EmitBlock(ForBody);
311 4: llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc");
312 : // Inside the loop body, emit the constructor call on the array element.
313 4: Counter = Builder.CreateLoad(IndexPtr);
314 4: Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress");
315 4: Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress");
2: branch 0 taken
2: branch 1 taken
316 4: if (BitwiseCopy)
317 2: EmitAggregateCopy(Dest, Src, Ty);
2: branch 0 taken
0: branch 1 not taken
318 2: else if (CXXConstructorDecl *BaseCopyCtor =
319 2: BaseClassDecl->getCopyConstructor(getContext(), 0)) {
320 : llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor,
321 2: Ctor_Complete);
322 2: CallArgList CallArgs;
323 : // Push the this (Dest) ptr.
324 : CallArgs.push_back(std::make_pair(RValue::get(Dest),
325 2: BaseCopyCtor->getThisType(getContext())));
326 :
327 : // Push the Src ptr.
328 : CallArgs.push_back(std::make_pair(RValue::get(Src),
329 2: BaseCopyCtor->getParamDecl(0)->getType()));
330 : const FunctionProtoType *FPT
331 2: = BaseCopyCtor->getType()->getAs<FunctionProtoType>();
332 : EmitCall(CGM.getTypes().getFunctionInfo(CallArgs, FPT),
333 2: Callee, ReturnValueSlot(), CallArgs, BaseCopyCtor);
334 : }
335 4: EmitBlock(ContinueBlock);
336 :
337 : // Emit the increment of the loop counter.
338 4: llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1);
339 4: Counter = Builder.CreateLoad(IndexPtr);
340 4: NextVal = Builder.CreateAdd(Counter, NextVal, "inc");
341 4: Builder.CreateStore(NextVal, IndexPtr);
342 :
343 : // Finally, branch back up to the condition for the next iteration.
344 4: EmitBranch(CondBlock);
345 :
346 : // Emit the fall-through block.
347 4: EmitBlock(AfterFor, true);
348 4: }
349 :
350 : /// EmitClassAggrCopyAssignment - This routine generates code to assign a class
351 : /// array of objects from SrcValue to DestValue. Assignment can be either a
352 : /// bitwise assignment or via a copy assignment operator function call.
353 : /// FIXME. This can be consolidated with EmitClassAggrMemberwiseCopy
354 : void CodeGenFunction::EmitClassAggrCopyAssignment(llvm::Value *Dest,
355 : llvm::Value *Src,
356 : const ArrayType *Array,
357 : const CXXRecordDecl *BaseClassDecl,
358 2: QualType Ty) {
359 2: const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array);
0: branch 0 not taken
2: branch 1 taken
360 2: assert(CA && "VLA cannot be asssigned");
361 2: bool BitwiseAssign = BaseClassDecl->hasTrivialCopyAssignment();
362 :
363 : // Create a temporary for the loop index and initialize it with 0.
364 : llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext),
365 2: "loop.index");
366 : llvm::Value* zeroConstant =
367 2: llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext));
368 2: Builder.CreateStore(zeroConstant, IndexPtr);
369 : // Start the loop with a block that tests the condition.
370 2: llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
371 2: llvm::BasicBlock *AfterFor = createBasicBlock("for.end");
372 :
373 2: EmitBlock(CondBlock);
374 :
375 2: llvm::BasicBlock *ForBody = createBasicBlock("for.body");
376 : // Generate: if (loop-index < number-of-elements fall to the loop body,
377 : // otherwise, go to the block after the for-loop.
378 2: uint64_t NumElements = getContext().getConstantArrayElementCount(CA);
379 : llvm::Value * NumElementsPtr =
380 2: llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements);
381 2: llvm::Value *Counter = Builder.CreateLoad(IndexPtr);
382 : llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr,
383 2: "isless");
384 : // If the condition is true, execute the body.
385 2: Builder.CreateCondBr(IsLess, ForBody, AfterFor);
386 :
387 2: EmitBlock(ForBody);
388 2: llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc");
389 : // Inside the loop body, emit the assignment operator call on array element.
390 2: Counter = Builder.CreateLoad(IndexPtr);
391 2: Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress");
392 2: Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress");
393 2: const CXXMethodDecl *MD = 0;
0: branch 0 not taken
2: branch 1 taken
394 2: if (BitwiseAssign)
395 0: EmitAggregateCopy(Dest, Src, Ty);
396 : else {
397 2: BaseClassDecl->hasConstCopyAssignment(getContext(), MD);
0: branch 0 not taken
2: branch 1 taken
398 2: assert(MD && "EmitClassAggrCopyAssignment - No user assign");
399 2: const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
400 : const llvm::Type *LTy =
401 : CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
402 2: FPT->isVariadic());
403 2: llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, LTy);
404 :
405 2: CallArgList CallArgs;
406 : // Push the this (Dest) ptr.
407 : CallArgs.push_back(std::make_pair(RValue::get(Dest),
408 2: MD->getThisType(getContext())));
409 :
410 : // Push the Src ptr.
411 2: QualType SrcTy = MD->getParamDecl(0)->getType();
412 : RValue SrcValue = SrcTy->isReferenceType() ? RValue::get(Src) :
1: branch 2 taken
1: branch 3 taken
413 2: RValue::getAggregate(Src);
414 2: CallArgs.push_back(std::make_pair(SrcValue, SrcTy));
415 : EmitCall(CGM.getTypes().getFunctionInfo(CallArgs, FPT),
416 2: Callee, ReturnValueSlot(), CallArgs, MD);
417 : }
418 2: EmitBlock(ContinueBlock);
419 :
420 : // Emit the increment of the loop counter.
421 2: llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1);
422 2: Counter = Builder.CreateLoad(IndexPtr);
423 2: NextVal = Builder.CreateAdd(Counter, NextVal, "inc");
424 2: Builder.CreateStore(NextVal, IndexPtr);
425 :
426 : // Finally, branch back up to the condition for the next iteration.
427 2: EmitBranch(CondBlock);
428 :
429 : // Emit the fall-through block.
430 2: EmitBlock(AfterFor, true);
431 2: }
432 :
433 : /// GetVTTParameter - Return the VTT parameter that should be passed to a
434 : /// base constructor/destructor with virtual bases.
435 893: static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD) {
809: branch 1 taken
84: branch 2 taken
436 893: if (!CGVtableInfo::needsVTTParameter(GD)) {
437 : // This constructor/destructor does not need a VTT parameter.
438 809: return 0;
439 : }
440 :
441 84: const CXXRecordDecl *RD = cast<CXXMethodDecl>(CGF.CurFuncDecl)->getParent();
442 84: const CXXRecordDecl *Base = cast<CXXMethodDecl>(GD.getDecl())->getParent();
443 :
444 : llvm::Value *VTT;
445 :
446 : uint64_t SubVTTIndex =
447 84: CGF.CGM.getVtableInfo().getSubVTTIndex(RD, Base);
0: branch 0 not taken
84: branch 1 taken
448 84: assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
449 :
8: branch 1 taken
76: branch 2 taken
450 84: if (CGVtableInfo::needsVTTParameter(CGF.CurGD)) {
451 : // A VTT parameter was passed to the constructor, use it.
452 8: VTT = CGF.LoadCXXVTT();
453 8: VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT, SubVTTIndex);
454 : } else {
455 : // We're the complete constructor, so get the VTT by name.
456 76: VTT = CGF.CGM.getVtableInfo().getVTT(RD);
457 76: VTT = CGF.Builder.CreateConstInBoundsGEP2_64(VTT, 0, SubVTTIndex);
458 : }
459 :
460 84: return VTT;
461 : }
462 :
463 :
464 : /// EmitClassMemberwiseCopy - This routine generates code to copy a class
465 : /// object from SrcValue to DestValue. Copying can be either a bitwise copy
466 : /// or via a copy constructor call.
467 : void CodeGenFunction::EmitClassMemberwiseCopy(
468 : llvm::Value *Dest, llvm::Value *Src,
469 : const CXXRecordDecl *ClassDecl,
470 16: const CXXRecordDecl *BaseClassDecl, QualType Ty) {
471 16: CXXCtorType CtorType = Ctor_Complete;
472 :
6: branch 0 taken
10: branch 1 taken
473 16: if (ClassDecl) {
474 : Dest = GetAddressOfBaseClass(Dest, ClassDecl, BaseClassDecl,
475 6: /*NullCheckValue=*/false);
476 : Src = GetAddressOfBaseClass(Src, ClassDecl, BaseClassDecl,
477 6: /*NullCheckValue=*/false);
478 :
479 : // We want to call the base constructor.
480 6: CtorType = Ctor_Base;
481 : }
14: branch 1 taken
2: branch 2 taken
482 16: if (BaseClassDecl->hasTrivialCopyConstructor()) {
483 14: EmitAggregateCopy(Dest, Src, Ty);
484 14: return;
485 : }
486 :
2: branch 0 taken
0: branch 1 not taken
487 2: if (CXXConstructorDecl *BaseCopyCtor =
488 2: BaseClassDecl->getCopyConstructor(getContext(), 0)) {
489 2: llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, CtorType);
490 2: CallArgList CallArgs;
491 : // Push the this (Dest) ptr.
492 : CallArgs.push_back(std::make_pair(RValue::get(Dest),
493 2: BaseCopyCtor->getThisType(getContext())));
494 :
495 : // Push the VTT parameter, if necessary.
0: branch 0 not taken
2: branch 1 taken
496 2: if (llvm::Value *VTT =
497 2: GetVTTParameter(*this, GlobalDecl(BaseCopyCtor, CtorType))) {
498 0: QualType T = getContext().getPointerType(getContext().VoidPtrTy);
499 0: CallArgs.push_back(std::make_pair(RValue::get(VTT), T));
500 : }
501 :
502 : // Push the Src ptr.
503 : CallArgs.push_back(std::make_pair(RValue::get(Src),
504 2: BaseCopyCtor->getParamDecl(0)->getType()));
505 : const FunctionProtoType *FPT =
506 2: BaseCopyCtor->getType()->getAs<FunctionProtoType>();
507 : EmitCall(CGM.getTypes().getFunctionInfo(CallArgs, FPT),
508 2: Callee, ReturnValueSlot(), CallArgs, BaseCopyCtor);
509 : }
510 : }
511 :
512 : /// EmitClassCopyAssignment - This routine generates code to copy assign a class
513 : /// object from SrcValue to DestValue. Assignment can be either a bitwise
514 : /// assignment of via an assignment operator call.
515 : // FIXME. Consolidate this with EmitClassMemberwiseCopy as they share a lot.
516 : void CodeGenFunction::EmitClassCopyAssignment(
517 : llvm::Value *Dest, llvm::Value *Src,
518 : const CXXRecordDecl *ClassDecl,
519 : const CXXRecordDecl *BaseClassDecl,
520 13: QualType Ty) {
7: branch 0 taken
6: branch 1 taken
521 13: if (ClassDecl) {
522 : Dest = GetAddressOfBaseClass(Dest, ClassDecl, BaseClassDecl,
523 7: /*NullCheckValue=*/false);
524 : Src = GetAddressOfBaseClass(Src, ClassDecl, BaseClassDecl,
525 7: /*NullCheckValue=*/false);
526 : }
2: branch 1 taken
11: branch 2 taken
527 13: if (BaseClassDecl->hasTrivialCopyAssignment()) {
528 2: EmitAggregateCopy(Dest, Src, Ty);
529 2: return;
530 : }
531 :
532 11: const CXXMethodDecl *MD = 0;
533 11: BaseClassDecl->hasConstCopyAssignment(getContext(), MD);
0: branch 0 not taken
11: branch 1 taken
534 11: assert(MD && "EmitClassCopyAssignment - missing copy assign");
535 :
536 11: const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
537 : const llvm::Type *LTy =
538 : CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
539 11: FPT->isVariadic());
540 11: llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, LTy);
541 :
542 11: CallArgList CallArgs;
543 : // Push the this (Dest) ptr.
544 : CallArgs.push_back(std::make_pair(RValue::get(Dest),
545 11: MD->getThisType(getContext())));
546 :
547 : // Push the Src ptr.
548 11: QualType SrcTy = MD->getParamDecl(0)->getType();
549 : RValue SrcValue = SrcTy->isReferenceType() ? RValue::get(Src) :
10: branch 2 taken
1: branch 3 taken
550 11: RValue::getAggregate(Src);
551 11: CallArgs.push_back(std::make_pair(SrcValue, SrcTy));
552 : EmitCall(CGM.getTypes().getFunctionInfo(CallArgs, FPT),
553 11: Callee, ReturnValueSlot(), CallArgs, MD);
554 : }
555 :
556 : /// SynthesizeDefaultConstructor - synthesize a default constructor
557 : void
558 : CodeGenFunction::SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor,
559 : CXXCtorType Type,
560 : llvm::Function *Fn,
561 267: const FunctionArgList &Args) {
267: branch 1 taken
0: branch 2 not taken
562 267: assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor");
563 : StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args,
564 267: SourceLocation());
565 267: EmitCtorPrologue(Ctor, Type);
566 267: FinishFunction();
567 267: }
568 :
569 : /// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a
570 : /// copy constructor, in accordance with section 12.8 (p7 and p8) of C++03
571 : /// The implicitly-defined copy constructor for class X performs a memberwise
572 : /// copy of its subobjects. The order of copying is the same as the order of
573 : /// initialization of bases and members in a user-defined constructor
574 : /// Each subobject is copied in the manner appropriate to its type:
575 : /// if the subobject is of class type, the copy constructor for the class is
576 : /// used;
577 : /// if the subobject is an array, each element is copied, in the manner
578 : /// appropriate to the element type;
579 : /// if the subobject is of scalar type, the built-in assignment operator is
580 : /// used.
581 : /// Virtual base class subobjects shall be copied only once by the
582 : /// implicitly-defined copy constructor
583 :
584 : void
585 : CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor,
586 : CXXCtorType Type,
587 : llvm::Function *Fn,
588 5: const FunctionArgList &Args) {
589 5: const CXXRecordDecl *ClassDecl = Ctor->getParent();
590 : assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&
5: branch 1 taken
0: branch 2 not taken
591 5: "SynthesizeCXXCopyConstructor - copy constructor has definition already");
5: branch 1 taken
0: branch 2 not taken
592 5: assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor");
593 : StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args,
594 5: SourceLocation());
595 :
596 5: FunctionArgList::const_iterator i = Args.begin();
597 5: const VarDecl *ThisArg = i->first;
598 5: llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg);
599 5: llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this");
600 5: const VarDecl *SrcArg = (i+1)->first;
601 5: llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg);
602 5: llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj);
603 :
6: branch 2 taken
5: branch 3 taken
604 11: for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin();
605 : Base != ClassDecl->bases_end(); ++Base) {
606 : // FIXME. copy constrution of virtual base NYI
0: branch 1 not taken
6: branch 2 taken
607 6: if (Base->isVirtual())
608 0: continue;
609 :
610 : CXXRecordDecl *BaseClassDecl
611 6: = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
612 : EmitClassMemberwiseCopy(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl,
613 6: Base->getType());
614 : }
615 :
32: branch 3 taken
5: branch 4 taken
616 42: for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
617 5: E = ClassDecl->field_end(); I != E; ++I) {
618 32: const FieldDecl *Field = *I;
619 :
620 32: QualType FieldType = getContext().getCanonicalType(Field->getType());
621 : const ConstantArrayType *Array =
622 32: getContext().getAsConstantArrayType(FieldType);
6: branch 0 taken
26: branch 1 taken
623 32: if (Array)
624 6: FieldType = getContext().getBaseElementType(FieldType);
625 :
14: branch 2 taken
18: branch 3 taken
626 32: if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
627 : CXXRecordDecl *FieldClassDecl
628 14: = cast<CXXRecordDecl>(FieldClassType->getDecl());
629 14: LValue LHS = EmitLValueForField(LoadOfThis, Field, 0);
630 14: LValue RHS = EmitLValueForField(LoadOfSrc, Field, 0);
4: branch 0 taken
10: branch 1 taken
631 14: if (Array) {
632 4: const llvm::Type *BasePtr = ConvertType(FieldType);
633 4: BasePtr = llvm::PointerType::getUnqual(BasePtr);
634 : llvm::Value *DestBaseAddrPtr =
635 4: Builder.CreateBitCast(LHS.getAddress(), BasePtr);
636 : llvm::Value *SrcBaseAddrPtr =
637 4: Builder.CreateBitCast(RHS.getAddress(), BasePtr);
638 : EmitClassAggrMemberwiseCopy(DestBaseAddrPtr, SrcBaseAddrPtr, Array,
639 4: FieldClassDecl, FieldType);
640 : }
641 : else
642 : EmitClassMemberwiseCopy(LHS.getAddress(), RHS.getAddress(),
643 10: 0 /*ClassDecl*/, FieldClassDecl, FieldType);
644 14: continue;
645 : }
646 :
647 : // Do a built-in assignment of scalar data members.
648 18: LValue LHS = EmitLValueForFieldInitialization(LoadOfThis, Field, 0);
649 18: LValue RHS = EmitLValueForFieldInitialization(LoadOfSrc, Field, 0);
650 :
14: branch 2 taken
4: branch 3 taken
651 18: if (!hasAggregateLLVMType(Field->getType())) {
652 14: RValue RVRHS = EmitLoadOfLValue(RHS, Field->getType());
653 14: EmitStoreThroughLValue(RVRHS, LHS, Field->getType());
2: branch 3 taken
2: branch 4 taken
654 4: } else if (Field->getType()->isAnyComplexType()) {
655 : ComplexPairTy Pair = LoadComplexFromAddr(RHS.getAddress(),
656 2: RHS.isVolatileQualified());
657 2: StoreComplexToAddr(Pair, LHS.getAddress(), LHS.isVolatileQualified());
658 : } else {
659 2: EmitAggregateCopy(LHS.getAddress(), RHS.getAddress(), Field->getType());
660 : }
661 : }
662 :
663 5: InitializeVtablePtrs(ClassDecl);
664 5: FinishFunction();
665 5: }
666 :
667 : /// SynthesizeCXXCopyAssignment - Implicitly define copy assignment operator.
668 : /// Before the implicitly-declared copy assignment operator for a class is
669 : /// implicitly defined, all implicitly- declared copy assignment operators for
670 : /// its direct base classes and its nonstatic data members shall have been
671 : /// implicitly defined. [12.8-p12]
672 : /// The implicitly-defined copy assignment operator for class X performs
673 : /// memberwise assignment of its subob- jects. The direct base classes of X are
674 : /// assigned first, in the order of their declaration in
675 : /// the base-specifier-list, and then the immediate nonstatic data members of X
676 : /// are assigned, in the order in which they were declared in the class
677 : /// definition.Each subobject is assigned in the manner appropriate to its type:
678 : /// if the subobject is of class type, the copy assignment operator for the
679 : /// class is used (as if by explicit qualification; that is, ignoring any
680 : /// possible virtual overriding functions in more derived classes);
681 : ///
682 : /// if the subobject is an array, each element is assigned, in the manner
683 : /// appropriate to the element type;
684 : ///
685 : /// if the subobject is of scalar type, the built-in assignment operator is
686 : /// used.
687 : void CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD,
688 : llvm::Function *Fn,
689 8: const FunctionArgList &Args) {
690 :
691 8: const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext());
692 : assert(!ClassDecl->hasUserDeclaredCopyAssignment() &&
8: branch 1 taken
0: branch 2 not taken
693 8: "SynthesizeCXXCopyAssignment - copy assignment has user declaration");
694 8: StartFunction(CD, CD->getResultType(), Fn, Args, SourceLocation());
695 :
696 8: FunctionArgList::const_iterator i = Args.begin();
697 8: const VarDecl *ThisArg = i->first;
698 8: llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg);
699 8: llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this");
700 8: const VarDecl *SrcArg = (i+1)->first;
701 8: llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg);
702 8: llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj);
703 :
7: branch 2 taken
8: branch 3 taken
704 15: for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin();
705 : Base != ClassDecl->bases_end(); ++Base) {
706 : // FIXME. copy assignment of virtual base NYI
0: branch 1 not taken
7: branch 2 taken
707 7: if (Base->isVirtual())
708 0: continue;
709 :
710 : CXXRecordDecl *BaseClassDecl
711 7: = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
712 : EmitClassCopyAssignment(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl,
713 7: Base->getType());
714 : }
715 :
24: branch 3 taken
8: branch 4 taken
716 40: for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
717 8: FieldEnd = ClassDecl->field_end();
718 : Field != FieldEnd; ++Field) {
719 24: QualType FieldType = getContext().getCanonicalType((*Field)->getType());
720 : const ConstantArrayType *Array =
721 24: getContext().getAsConstantArrayType(FieldType);
3: branch 0 taken
21: branch 1 taken
722 24: if (Array)
723 3: FieldType = getContext().getBaseElementType(FieldType);
724 :
8: branch 2 taken
16: branch 3 taken
725 24: if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
726 : CXXRecordDecl *FieldClassDecl
727 8: = cast<CXXRecordDecl>(FieldClassType->getDecl());
728 8: LValue LHS = EmitLValueForField(LoadOfThis, *Field, 0);
729 8: LValue RHS = EmitLValueForField(LoadOfSrc, *Field, 0);
2: branch 0 taken
6: branch 1 taken
730 8: if (Array) {
731 2: const llvm::Type *BasePtr = ConvertType(FieldType);
732 2: BasePtr = llvm::PointerType::getUnqual(BasePtr);
733 : llvm::Value *DestBaseAddrPtr =
734 2: Builder.CreateBitCast(LHS.getAddress(), BasePtr);
735 : llvm::Value *SrcBaseAddrPtr =
736 2: Builder.CreateBitCast(RHS.getAddress(), BasePtr);
737 : EmitClassAggrCopyAssignment(DestBaseAddrPtr, SrcBaseAddrPtr, Array,
738 2: FieldClassDecl, FieldType);
739 : }
740 : else
741 : EmitClassCopyAssignment(LHS.getAddress(), RHS.getAddress(),
742 6: 0 /*ClassDecl*/, FieldClassDecl, FieldType);
743 8: continue;
744 : }
745 : // Do a built-in assignment of scalar data members.
746 16: LValue LHS = EmitLValueForField(LoadOfThis, *Field, 0);
747 16: LValue RHS = EmitLValueForField(LoadOfSrc, *Field, 0);
13: branch 3 taken
3: branch 4 taken
748 16: if (!hasAggregateLLVMType(Field->getType())) {
749 13: RValue RVRHS = EmitLoadOfLValue(RHS, Field->getType());
750 13: EmitStoreThroughLValue(RVRHS, LHS, Field->getType());
1: branch 4 taken
2: branch 5 taken
751 3: } else if (Field->getType()->isAnyComplexType()) {
752 : ComplexPairTy Pair = LoadComplexFromAddr(RHS.getAddress(),
753 1: RHS.isVolatileQualified());
754 1: StoreComplexToAddr(Pair, LHS.getAddress(), LHS.isVolatileQualified());
755 : } else {
756 2: EmitAggregateCopy(LHS.getAddress(), RHS.getAddress(), Field->getType());
757 : }
758 : }
759 :
760 : // return *this;
761 8: Builder.CreateStore(LoadOfThis, ReturnValue);
762 :
763 8: FinishFunction();
764 8: }
765 :
766 : static void EmitBaseInitializer(CodeGenFunction &CGF,
767 : const CXXRecordDecl *ClassDecl,
768 : CXXBaseOrMemberInitializer *BaseInit,
769 429: CXXCtorType CtorType) {
770 : assert(BaseInit->isBaseInitializer() &&
429: branch 1 taken
0: branch 2 not taken
771 429: "Must have base initializer!");
772 :
773 429: llvm::Value *ThisPtr = CGF.LoadCXXThis();
774 :
775 429: const Type *BaseType = BaseInit->getBaseClass();
776 : CXXRecordDecl *BaseClassDecl =
777 429: cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
778 :
779 : // FIXME: This method of determining whether a base is virtual is ridiculous;
780 : // it should be part of BaseInit.
781 429: bool isBaseVirtual = false;
800: branch 1 taken
148: branch 2 taken
782 1377: for (CXXRecordDecl::base_class_const_iterator I = ClassDecl->vbases_begin(),
783 429: E = ClassDecl->vbases_end(); I != E; ++I)
281: branch 4 taken
519: branch 5 taken
784 800: if (I->getType()->getAs<RecordType>()->getDecl() == BaseClassDecl) {
785 281: isBaseVirtual = true;
786 281: break;
787 : }
788 :
789 : // The base constructor doesn't construct virtual bases.
200: branch 0 taken
229: branch 1 taken
145: branch 2 taken
55: branch 3 taken
790 429: if (CtorType == Ctor_Base && isBaseVirtual)
791 145: return;
792 :
793 : // Compute the offset to the base; we do this directly instead of using
794 : // GetAddressOfBaseClass because the class doesn't have a vtable pointer
795 : // at this point.
796 : // FIXME: This could be refactored back into GetAddressOfBaseClass if it took
797 : // an extra parameter for whether the derived class is the complete object
798 : // class.
799 : const ASTRecordLayout &Layout =
800 284: CGF.getContext().getASTRecordLayout(ClassDecl);
801 : uint64_t Offset;
136: branch 0 taken
148: branch 1 taken
802 284: if (isBaseVirtual)
803 136: Offset = Layout.getVBaseClassOffset(BaseClassDecl);
804 : else
805 148: Offset = Layout.getBaseClassOffset(BaseClassDecl);
806 284: const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
807 284: const llvm::Type *BaseClassType = CGF.ConvertType(QualType(BaseType, 0));
808 284: llvm::Value *V = CGF.Builder.CreateBitCast(ThisPtr, Int8PtrTy);
809 284: V = CGF.Builder.CreateConstInBoundsGEP1_64(V, Offset/8);
810 284: V = CGF.Builder.CreateBitCast(V, BaseClassType->getPointerTo());
811 284: CGF.EmitAggExpr(BaseInit->getInit(), V, false, false, true);
812 :
0: branch 0 not taken
284: branch 1 taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 5 not taken
284: branch 6 taken
813 284: if (CGF.Exceptions && !BaseClassDecl->hasTrivialDestructor()) {
814 : // FIXME: Is this OK for C++0x delegating constructors?
815 0: CodeGenFunction::EHCleanupBlock Cleanup(CGF);
816 :
817 0: llvm::Value *ThisPtr = CGF.LoadCXXThis();
818 0: llvm::Value *V = CGF.Builder.CreateBitCast(ThisPtr, Int8PtrTy);
819 0: V = CGF.Builder.CreateConstInBoundsGEP1_64(V, Offset / 8);
820 0: V = CGF.Builder.CreateBitCast(V, BaseClassType->getPointerTo());
821 :
822 0: CXXDestructorDecl *DD = BaseClassDecl->getDestructor(CGF.getContext());
823 0: CGF.EmitCXXDestructorCall(DD, Dtor_Base, V);
824 : }
825 : }
826 :
827 : static void EmitMemberInitializer(CodeGenFunction &CGF,
828 : const CXXRecordDecl *ClassDecl,
829 230: CXXBaseOrMemberInitializer *MemberInit) {
830 : assert(MemberInit->isMemberInitializer() &&
230: branch 1 taken
0: branch 2 not taken
831 230: "Must have member initializer!");
832 :
833 : // non-static data member initializers.
834 230: FieldDecl *Field = MemberInit->getMember();
835 230: QualType FieldType = CGF.getContext().getCanonicalType(Field->getType());
836 :
837 230: llvm::Value *ThisPtr = CGF.LoadCXXThis();
838 230: LValue LHS = CGF.EmitLValueForFieldInitialization(ThisPtr, Field, 0);
839 :
840 : // If we are initializing an anonymous union field, drill down to the field.
17: branch 1 taken
213: branch 2 taken
841 230: if (MemberInit->getAnonUnionMember()) {
842 17: Field = MemberInit->getAnonUnionMember();
843 17: LHS = CGF.EmitLValueForField(LHS.getAddress(), Field, 0);
844 17: FieldType = Field->getType();
845 : }
846 :
847 : // FIXME: If there's no initializer and the CXXBaseOrMemberInitializer
848 : // was implicitly generated, we shouldn't be zeroing memory.
849 : RValue RHS;
5: branch 2 taken
225: branch 3 taken
850 230: if (FieldType->isReferenceType()) {
851 : RHS = CGF.EmitReferenceBindingToExpr(MemberInit->getInit(),
852 5: /*IsInitializer=*/true);
853 5: CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
22: branch 2 taken
203: branch 3 taken
0: branch 5 not taken
22: branch 6 taken
0: branch 7 not taken
225: branch 8 taken
854 225: } else if (FieldType->isArrayType() && !MemberInit->getInit()) {
855 0: CGF.EmitMemSetToZero(LHS.getAddress(), Field->getType());
151: branch 2 taken
74: branch 3 taken
856 225: } else if (!CGF.hasAggregateLLVMType(Field->getType())) {
857 151: RHS = RValue::get(CGF.EmitScalarExpr(MemberInit->getInit(), true));
858 151: CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
2: branch 4 taken
72: branch 5 taken
859 74: } else if (MemberInit->getInit()->getType()->isAnyComplexType()) {
860 : CGF.EmitComplexExprIntoAddr(MemberInit->getInit(), LHS.getAddress(),
861 2: LHS.isVolatileQualified());
862 : } else {
863 : CGF.EmitAggExpr(MemberInit->getInit(), LHS.getAddress(),
864 72: LHS.isVolatileQualified(), false, true);
865 :
72: branch 0 taken
0: branch 1 not taken
866 72: if (!CGF.Exceptions)
867 72: return;
868 :
869 0: const RecordType *RT = FieldType->getAs<RecordType>();
0: branch 0 not taken
0: branch 1 not taken
870 0: if (!RT)
871 0: return;
872 :
873 0: CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
0: branch 1 not taken
0: branch 2 not taken
874 0: if (!RD->hasTrivialDestructor()) {
875 : // FIXME: Is this OK for C++0x delegating constructors?
876 0: CodeGenFunction::EHCleanupBlock Cleanup(CGF);
877 :
878 0: llvm::Value *ThisPtr = CGF.LoadCXXThis();
879 0: LValue LHS = CGF.EmitLValueForField(ThisPtr, Field, 0);
880 :
881 0: CXXDestructorDecl *DD = RD->getDestructor(CGF.getContext());
882 0: CGF.EmitCXXDestructorCall(DD, Dtor_Complete, LHS.getAddress());
883 : }
884 : }
885 : }
886 :
887 : /// EmitCtorPrologue - This routine generates necessary code to initialize
888 : /// base classes and non-static data members belonging to this constructor.
889 : /// FIXME: This needs to take a CXXCtorType.
890 : void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
891 471: CXXCtorType CtorType) {
892 471: const CXXRecordDecl *ClassDecl = CD->getParent();
893 :
894 471: llvm::SmallVector<CXXBaseOrMemberInitializer *, 8> MemberInitializers;
895 :
896 : // FIXME: Add vbase initialization
897 :
659: branch 1 taken
471: branch 2 taken
898 1601: for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(),
899 471: E = CD->init_end();
900 : B != E; ++B) {
901 659: CXXBaseOrMemberInitializer *Member = (*B);
902 :
903 : assert(LiveTemporaries.empty() &&
659: branch 1 taken
0: branch 2 not taken
904 659: "Should not have any live temporaries at initializer start!");
905 :
429: branch 1 taken
230: branch 2 taken
906 659: if (Member->isBaseInitializer())
907 429: EmitBaseInitializer(*this, ClassDecl, Member, CtorType);
908 : else
909 230: MemberInitializers.push_back(Member);
910 : }
911 :
912 471: InitializeVtablePtrs(ClassDecl);
913 :
230: branch 1 taken
471: branch 2 taken
914 1402: for (unsigned I = 0, E = MemberInitializers.size(); I != E; ++I) {
915 : assert(LiveTemporaries.empty() &&
230: branch 1 taken
0: branch 2 not taken
916 230: "Should not have any live temporaries at initializer start!");
917 :
918 230: EmitMemberInitializer(*this, ClassDecl, MemberInitializers[I]);
919 471: }
920 471: }
921 :
922 : /// EmitDtorEpilogue - Emit all code that comes at the end of class's
923 : /// destructor. This is to call destructors on members and base classes
924 : /// in reverse order of their construction.
925 : /// FIXME: This needs to take a CXXDtorType.
926 : void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
927 105: CXXDtorType DtorType) {
928 : assert(!DD->isTrivial() &&
105: branch 1 taken
0: branch 2 not taken
929 105: "Should not emit dtor epilogue for trivial dtor!");
930 :
931 105: const CXXRecordDecl *ClassDecl = DD->getParent();
932 :
933 : // Collect the fields.
934 105: llvm::SmallVector<const FieldDecl *, 16> FieldDecls;
67: branch 3 taken
105: branch 4 taken
935 277: for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
936 105: E = ClassDecl->field_end(); I != E; ++I) {
937 67: const FieldDecl *Field = *I;
938 :
939 67: QualType FieldType = getContext().getCanonicalType(Field->getType());
940 67: FieldType = getContext().getBaseElementType(FieldType);
941 :
942 67: const RecordType *RT = FieldType->getAs<RecordType>();
48: branch 0 taken
19: branch 1 taken
943 67: if (!RT)
944 48: continue;
945 :
946 19: CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
0: branch 1 not taken
19: branch 2 taken
947 19: if (FieldClassDecl->hasTrivialDestructor())
948 0: continue;
949 :
950 19: FieldDecls.push_back(Field);
951 : }
952 :
953 : // Now destroy the fields.
19: branch 1 taken
105: branch 2 taken
954 124: for (size_t i = FieldDecls.size(); i > 0; --i) {
955 19: const FieldDecl *Field = FieldDecls[i - 1];
956 :
957 19: QualType FieldType = Field->getType();
958 : const ConstantArrayType *Array =
959 19: getContext().getAsConstantArrayType(FieldType);
6: branch 0 taken
13: branch 1 taken
960 19: if (Array)
961 6: FieldType = getContext().getBaseElementType(FieldType);
962 :
963 19: const RecordType *RT = FieldType->getAs<RecordType>();
964 19: CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
965 :
966 19: llvm::Value *ThisPtr = LoadCXXThis();
967 :
968 : LValue LHS = EmitLValueForField(ThisPtr, Field,
969 : // FIXME: Qualifiers?
970 19: /*CVRQualifiers=*/0);
6: branch 0 taken
13: branch 1 taken
971 19: if (Array) {
972 6: const llvm::Type *BasePtr = ConvertType(FieldType);
973 6: BasePtr = llvm::PointerType::getUnqual(BasePtr);
974 : llvm::Value *BaseAddrPtr =
975 6: Builder.CreateBitCast(LHS.getAddress(), BasePtr);
976 : EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()),
977 6: Array, BaseAddrPtr);
978 : } else
979 : EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()),
980 13: Dtor_Complete, LHS.getAddress());
981 : }
982 :
983 : // Destroy non-virtual bases.
43: branch 2 taken
105: branch 3 taken
984 148: for (CXXRecordDecl::reverse_base_class_const_iterator I =
985 105: ClassDecl->bases_rbegin(), E = ClassDecl->bases_rend(); I != E; ++I) {
986 43: const CXXBaseSpecifier &Base = *I;
987 :
988 : // Ignore virtual bases.
3: branch 1 taken
40: branch 2 taken
989 43: if (Base.isVirtual())
990 3: continue;
991 :
992 : CXXRecordDecl *BaseClassDecl
993 40: = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
994 :
995 : // Ignore trivial destructors.
0: branch 1 not taken
40: branch 2 taken
996 40: if (BaseClassDecl->hasTrivialDestructor())
997 0: continue;
998 40: const CXXDestructorDecl *D = BaseClassDecl->getDestructor(getContext());
999 :
1000 : llvm::Value *V = GetAddressOfBaseClass(LoadCXXThis(),
1001 : ClassDecl, BaseClassDecl,
1002 40: /*NullCheckValue=*/false);
1003 40: EmitCXXDestructorCall(D, Dtor_Base, V);
1004 : }
1005 :
1006 : // If we're emitting a base destructor, we don't want to emit calls to the
1007 : // virtual bases.
26: branch 0 taken
79: branch 1 taken
1008 105: if (DtorType == Dtor_Base)
1009 26: return;
1010 :
1011 : // Handle virtual bases.
4: branch 2 taken
79: branch 3 taken
1012 83: for (CXXRecordDecl::reverse_base_class_const_iterator I =
1013 79: ClassDecl->vbases_rbegin(), E = ClassDecl->vbases_rend(); I != E; ++I) {
1014 4: const CXXBaseSpecifier &Base = *I;
1015 : CXXRecordDecl *BaseClassDecl
1016 4: = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
1017 :
1018 : // Ignore trivial destructors.
0: branch 1 not taken
4: branch 2 taken
1019 4: if (BaseClassDecl->hasTrivialDestructor())
1020 0: continue;
1021 4: const CXXDestructorDecl *D = BaseClassDecl->getDestructor(getContext());
1022 : llvm::Value *V = GetAddressOfBaseClass(LoadCXXThis(),
1023 : ClassDecl, BaseClassDecl,
1024 4: /*NullCheckValue=*/false);
1025 4: EmitCXXDestructorCall(D, Dtor_Base, V);
1026 : }
1027 :
1028 : // If we have a deleting destructor, emit a call to the delete operator.
21: branch 0 taken
58: branch 1 taken
1029 79: if (DtorType == Dtor_Deleting) {
1030 : assert(DD->getOperatorDelete() &&
21: branch 1 taken
0: branch 2 not taken
1031 21: "operator delete missing - EmitDtorEpilogue");
1032 : EmitDeleteCall(DD->getOperatorDelete(), LoadCXXThis(),
1033 21: getContext().getTagDeclType(ClassDecl));
79: branch 1 taken
26: branch 2 taken
1034 105: }
1035 : }
1036 :
1037 : void CodeGenFunction::SynthesizeDefaultDestructor(const CXXDestructorDecl *Dtor,
1038 : CXXDtorType DtorType,
1039 : llvm::Function *Fn,
1040 17: const FunctionArgList &Args) {
1041 : assert(!Dtor->getParent()->hasUserDeclaredDestructor() &&
17: branch 2 taken
0: branch 3 not taken
1042 17: "SynthesizeDefaultDestructor - destructor has user declaration");
1043 :
1044 : StartFunction(GlobalDecl(Dtor, DtorType), Dtor->getResultType(), Fn, Args,
1045 17: SourceLocation());
1046 17: InitializeVtablePtrs(Dtor->getParent());
1047 17: EmitDtorEpilogue(Dtor, DtorType);
1048 17: FinishFunction();
1049 17: }
1050 :
1051 : /// EmitCXXAggrConstructorCall - This routine essentially creates a (nested)
1052 : /// for-loop to call the default constructor on individual members of the
1053 : /// array.
1054 : /// 'D' is the default constructor for elements of the array, 'ArrayTy' is the
1055 : /// array type and 'ArrayPtr' points to the beginning fo the array.
1056 : /// It is assumed that all relevant checks have been made by the caller.
1057 : void
1058 : CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
1059 : const ConstantArrayType *ArrayTy,
1060 : llvm::Value *ArrayPtr,
1061 : CallExpr::const_arg_iterator ArgBeg,
1062 27: CallExpr::const_arg_iterator ArgEnd) {
1063 :
1064 27: const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
1065 : llvm::Value * NumElements =
1066 : llvm::ConstantInt::get(SizeTy,
1067 27: getContext().getConstantArrayElementCount(ArrayTy));
1068 :
1069 27: EmitCXXAggrConstructorCall(D, NumElements, ArrayPtr, ArgBeg, ArgEnd);
1070 27: }
1071 :
1072 : void
1073 : CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
1074 : llvm::Value *NumElements,
1075 : llvm::Value *ArrayPtr,
1076 : CallExpr::const_arg_iterator ArgBeg,
1077 40: CallExpr::const_arg_iterator ArgEnd) {
1078 40: const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
1079 :
1080 : // Create a temporary for the loop index and initialize it with 0.
1081 40: llvm::Value *IndexPtr = CreateTempAlloca(SizeTy, "loop.index");
1082 40: llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy);
1083 40: Builder.CreateStore(Zero, IndexPtr);
1084 :
1085 : // Start the loop with a block that tests the condition.
1086 40: llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
1087 40: llvm::BasicBlock *AfterFor = createBasicBlock("for.end");
1088 :
1089 40: EmitBlock(CondBlock);
1090 :
1091 40: llvm::BasicBlock *ForBody = createBasicBlock("for.body");
1092 :
1093 : // Generate: if (loop-index < number-of-elements fall to the loop body,
1094 : // otherwise, go to the block after the for-loop.
1095 40: llvm::Value *Counter = Builder.CreateLoad(IndexPtr);
1096 40: llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElements, "isless");
1097 : // If the condition is true, execute the body.
1098 40: Builder.CreateCondBr(IsLess, ForBody, AfterFor);
1099 :
1100 40: EmitBlock(ForBody);
1101 :
1102 40: llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc");
1103 : // Inside the loop body, emit the constructor call on the array element.
1104 40: Counter = Builder.CreateLoad(IndexPtr);
1105 : llvm::Value *Address = Builder.CreateInBoundsGEP(ArrayPtr, Counter,
1106 40: "arrayidx");
1107 :
1108 : // C++ [class.temporary]p4:
1109 : // There are two contexts in which temporaries are destroyed at a different
1110 : // point than the end of the full-expression. The first context is when a
1111 : // default constructor is called to initialize an element of an array.
1112 : // If the constructor has one or more default arguments, the destruction of
1113 : // every temporary created in a default argument expression is sequenced
1114 : // before the construction of the next array element, if any.
1115 :
1116 : // Keep track of the current number of live temporaries.
1117 40: unsigned OldNumLiveTemporaries = LiveTemporaries.size();
1118 :
1119 40: EmitCXXConstructorCall(D, Ctor_Complete, Address, ArgBeg, ArgEnd);
1120 :
1121 : // Pop temporaries.
8: branch 1 taken
40: branch 2 taken
1122 88: while (LiveTemporaries.size() > OldNumLiveTemporaries)
1123 8: PopCXXTemporary();
1124 :
1125 40: EmitBlock(ContinueBlock);
1126 :
1127 : // Emit the increment of the loop counter.
1128 40: llvm::Value *NextVal = llvm::ConstantInt::get(SizeTy, 1);
1129 40: Counter = Builder.CreateLoad(IndexPtr);
1130 40: NextVal = Builder.CreateAdd(Counter, NextVal, "inc");
1131 40: Builder.CreateStore(NextVal, IndexPtr);
1132 :
1133 : // Finally, branch back up to the condition for the next iteration.
1134 40: EmitBranch(CondBlock);
1135 :
1136 : // Emit the fall-through block.
1137 40: EmitBlock(AfterFor, true);
1138 40: }
1139 :
1140 : /// EmitCXXAggrDestructorCall - calls the default destructor on array
1141 : /// elements in reverse order of construction.
1142 : void
1143 : CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
1144 : const ArrayType *Array,
1145 14: llvm::Value *This) {
1146 14: const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array);
0: branch 0 not taken
14: branch 1 taken
1147 14: assert(CA && "Do we support VLA for destruction ?");
1148 14: uint64_t ElementCount = getContext().getConstantArrayElementCount(CA);
1149 :
1150 14: const llvm::Type *SizeLTy = ConvertType(getContext().getSizeType());
1151 14: llvm::Value* ElementCountPtr = llvm::ConstantInt::get(SizeLTy, ElementCount);
1152 14: EmitCXXAggrDestructorCall(D, ElementCountPtr, This);
1153 14: }
1154 :
1155 : /// EmitCXXAggrDestructorCall - calls the default destructor on array
1156 : /// elements in reverse order of construction.
1157 : void
1158 : CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
1159 : llvm::Value *UpperCount,
1160 22: llvm::Value *This) {
1161 22: const llvm::Type *SizeLTy = ConvertType(getContext().getSizeType());
1162 22: llvm::Value *One = llvm::ConstantInt::get(SizeLTy, 1);
1163 :
1164 : // Create a temporary for the loop index and initialize it with count of
1165 : // array elements.
1166 22: llvm::Value *IndexPtr = CreateTempAlloca(SizeLTy, "loop.index");
1167 :
1168 : // Store the number of elements in the index pointer.
1169 22: Builder.CreateStore(UpperCount, IndexPtr);
1170 :
1171 : // Start the loop with a block that tests the condition.
1172 22: llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
1173 22: llvm::BasicBlock *AfterFor = createBasicBlock("for.end");
1174 :
1175 22: EmitBlock(CondBlock);
1176 :
1177 22: llvm::BasicBlock *ForBody = createBasicBlock("for.body");
1178 :
1179 : // Generate: if (loop-index != 0 fall to the loop body,
1180 : // otherwise, go to the block after the for-loop.
1181 : llvm::Value* zeroConstant =
1182 22: llvm::Constant::getNullValue(SizeLTy);
1183 22: llvm::Value *Counter = Builder.CreateLoad(IndexPtr);
1184 : llvm::Value *IsNE = Builder.CreateICmpNE(Counter, zeroConstant,
1185 22: "isne");
1186 : // If the condition is true, execute the body.
1187 22: Builder.CreateCondBr(IsNE, ForBody, AfterFor);
1188 :
1189 22: EmitBlock(ForBody);
1190 :
1191 22: llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc");
1192 : // Inside the loop body, emit the constructor call on the array element.
1193 22: Counter = Builder.CreateLoad(IndexPtr);
1194 22: Counter = Builder.CreateSub(Counter, One);
1195 22: llvm::Value *Address = Builder.CreateInBoundsGEP(This, Counter, "arrayidx");
1196 22: EmitCXXDestructorCall(D, Dtor_Complete, Address);
1197 :
1198 22: EmitBlock(ContinueBlock);
1199 :
1200 : // Emit the decrement of the loop counter.
1201 22: Counter = Builder.CreateLoad(IndexPtr);
1202 22: Counter = Builder.CreateSub(Counter, One, "dec");
1203 22: Builder.CreateStore(Counter, IndexPtr);
1204 :
1205 : // Finally, branch back up to the condition for the next iteration.
1206 22: EmitBranch(CondBlock);
1207 :
1208 : // Emit the fall-through block.
1209 22: EmitBlock(AfterFor, true);
1210 22: }
1211 :
1212 : /// GenerateCXXAggrDestructorHelper - Generates a helper function which when
1213 : /// invoked, calls the default destructor on array elements in reverse order of
1214 : /// construction.
1215 : llvm::Constant *
1216 : CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
1217 : const ArrayType *Array,
1218 6: llvm::Value *This) {
1219 6: FunctionArgList Args;
1220 : ImplicitParamDecl *Dst =
1221 : ImplicitParamDecl::Create(getContext(), 0,
1222 : SourceLocation(), 0,
1223 6: getContext().getPointerType(getContext().VoidTy));
1224 6: Args.push_back(std::make_pair(Dst, Dst->getType()));
1225 :
1226 6: llvm::SmallString<16> Name;
1227 6: llvm::raw_svector_ostream(Name) << "__tcf_" << (++UniqueAggrDestructorCount);
1228 6: QualType R = getContext().VoidTy;
1229 : const CGFunctionInfo &FI
1230 6: = CGM.getTypes().getFunctionInfo(R, Args, CC_Default, false);
1231 6: const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false);
1232 : llvm::Function *Fn =
1233 : llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
1234 : Name.str(),
1235 6: &CGM.getModule());
1236 6: IdentifierInfo *II = &CGM.getContext().Idents.get(Name.str());
1237 : FunctionDecl *FD = FunctionDecl::Create(getContext(),
1238 : getContext().getTranslationUnitDecl(),
1239 : SourceLocation(), II, R, 0,
1240 : FunctionDecl::Static,
6: branch 4 taken
0: branch 5 not taken
1241 6: false, true);
1242 6: StartFunction(FD, R, Fn, Args, SourceLocation());
1243 6: QualType BaseElementTy = getContext().getBaseElementType(Array);
1244 6: const llvm::Type *BasePtr = ConvertType(BaseElementTy);
1245 6: BasePtr = llvm::PointerType::getUnqual(BasePtr);
1246 6: llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr);
1247 6: EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
1248 6: FinishFunction();
1249 : llvm::Type *Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),
1250 6: 0);
1251 6: llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
1252 6: return m;
1253 : }
1254 :
1255 :
1256 : void
1257 : CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
1258 : CXXCtorType Type,
1259 : llvm::Value *This,
1260 : CallExpr::const_arg_iterator ArgBeg,
1261 733: CallExpr::const_arg_iterator ArgEnd) {
51: branch 1 taken
682: branch 2 taken
1262 733: if (D->isTrivial()) {
3: branch 1 taken
48: branch 2 taken
1263 51: if (ArgBeg == ArgEnd) {
1264 : // Trivial default constructor, no codegen required.
1265 : assert(D->isDefaultConstructor() &&
3: branch 1 taken
0: branch 2 not taken
1266 3: "trivial 0-arg ctor not a default ctor");
1267 3: return;
1268 : }
1269 :
48: branch 2 taken
0: branch 3 not taken
1270 48: assert(ArgBeg + 1 == ArgEnd && "unexpected argcount for trivial ctor");
48: branch 1 taken
0: branch 2 not taken
1271 48: assert(D->isCopyConstructor() && "trivial 1-arg ctor not a copy ctor");
1272 :
1273 48: const Expr *E = (*ArgBeg);
1274 48: QualType Ty = E->getType();
1275 48: llvm::Value *Src = EmitLValue(E).getAddress();
1276 48: EmitAggregateCopy(This, Src, Ty);
1277 48: return;
1278 : }
1279 :
1280 682: llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(D, Type));
1281 682: llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type);
1282 :
1283 682: EmitCXXMemberCall(D, Callee, ReturnValueSlot(), This, VTT, ArgBeg, ArgEnd);
1284 : }
1285 :
1286 : void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
1287 : CXXDtorType Type,
1288 209: llvm::Value *This) {
1289 209: llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(DD, Type));
1290 209: llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(DD, Type);
1291 :
1292 209: EmitCXXMemberCall(DD, Callee, ReturnValueSlot(), This, VTT, 0, 0);
1293 209: }
1294 :
1295 : llvm::Value *
1296 : CodeGenFunction::GetVirtualBaseClassOffset(llvm::Value *This,
1297 : const CXXRecordDecl *ClassDecl,
1298 12: const CXXRecordDecl *BaseClassDecl) {
1299 : const llvm::Type *Int8PtrTy =
1300 12: llvm::Type::getInt8Ty(VMContext)->getPointerTo();
1301 :
1302 : llvm::Value *VTablePtr = Builder.CreateBitCast(This,
1303 12: Int8PtrTy->getPointerTo());
1304 12: VTablePtr = Builder.CreateLoad(VTablePtr, "vtable");
1305 :
1306 : int64_t VBaseOffsetIndex =
1307 12: CGM.getVtableInfo().getVirtualBaseOffsetIndex(ClassDecl, BaseClassDecl);
1308 :
1309 : llvm::Value *VBaseOffsetPtr =
1310 12: Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetIndex, "vbase.offset.ptr");
1311 : const llvm::Type *PtrDiffTy =
1312 12: ConvertType(getContext().getPointerDiffType());
1313 :
1314 : VBaseOffsetPtr = Builder.CreateBitCast(VBaseOffsetPtr,
1315 12: PtrDiffTy->getPointerTo());
1316 :
1317 12: llvm::Value *VBaseOffset = Builder.CreateLoad(VBaseOffsetPtr, "vbase.offset");
1318 :
1319 12: return VBaseOffset;
1320 : }
1321 :
1322 581: void CodeGenFunction::InitializeVtablePtrs(const CXXRecordDecl *ClassDecl) {
239: branch 1 taken
342: branch 2 taken
1323 581: if (!ClassDecl->isDynamicClass())
1324 239: return;
1325 :
1326 342: llvm::Constant *Vtable = CGM.getVtableInfo().getVtable(ClassDecl);
1327 : CGVtableInfo::AddrSubMap_t& AddressPoints =
1328 342: *(*CGM.getVtableInfo().AddressPoints[ClassDecl])[ClassDecl];
1329 342: llvm::Value *ThisPtr = LoadCXXThis();
1330 342: const ASTRecordLayout &Layout = getContext().getASTRecordLayout(ClassDecl);
1331 :
1332 : // Store address points for virtual bases
282: branch 0 taken
342: branch 1 taken
1333 624: for (CXXRecordDecl::base_class_const_iterator I =
1334 342: ClassDecl->vbases_begin(), E = ClassDecl->vbases_end(); I != E; ++I) {
1335 282: const CXXBaseSpecifier &Base = *I;
1336 : CXXRecordDecl *BaseClassDecl
1337 282: = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
1338 282: uint64_t Offset = Layout.getVBaseClassOffset(BaseClassDecl);
1339 : InitializeVtablePtrsRecursive(BaseClassDecl, Vtable, AddressPoints,
1340 282: ThisPtr, Offset);
1341 : }
1342 :
1343 : // Store address points for non-virtual bases and current class
1344 342: InitializeVtablePtrsRecursive(ClassDecl, Vtable, AddressPoints, ThisPtr, 0);
1345 : }
1346 :
1347 : void CodeGenFunction::InitializeVtablePtrsRecursive(
1348 : const CXXRecordDecl *ClassDecl,
1349 : llvm::Constant *Vtable,
1350 : CGVtableInfo::AddrSubMap_t& AddressPoints,
1351 : llvm::Value *ThisPtr,
1352 829: uint64_t Offset) {
736: branch 1 taken
93: branch 2 taken
1353 829: if (!ClassDecl->isDynamicClass())
1354 93: return;
1355 :
1356 : // Store address points for non-virtual bases
1357 736: const ASTRecordLayout &Layout = getContext().getASTRecordLayout(ClassDecl);
504: branch 0 taken
736: branch 1 taken
1358 1240: for (CXXRecordDecl::base_class_const_iterator I =
1359 736: ClassDecl->bases_begin(), E = ClassDecl->bases_end(); I != E; ++I) {
1360 504: const CXXBaseSpecifier &Base = *I;
299: branch 1 taken
205: branch 2 taken
1361 504: if (Base.isVirtual())
1362 299: continue;
1363 : CXXRecordDecl *BaseClassDecl
1364 205: = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
1365 205: uint64_t NewOffset = Offset + Layout.getBaseClassOffset(BaseClassDecl);
1366 : InitializeVtablePtrsRecursive(BaseClassDecl, Vtable, AddressPoints,
1367 205: ThisPtr, NewOffset);
1368 : }
1369 :
1370 : // Compute the address point
1371 : assert(AddressPoints.count(std::make_pair(ClassDecl, Offset)) &&
736: branch 2 taken
0: branch 3 not taken
1372 736: "Missing address point for class");
1373 736: uint64_t AddressPoint = AddressPoints[std::make_pair(ClassDecl, Offset)];
1374 : llvm::Value *VtableAddressPoint =
1375 736: Builder.CreateConstInBoundsGEP2_64(Vtable, 0, AddressPoint);
1376 :
1377 : // Compute the address to store the address point
1378 736: const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
1379 736: llvm::Value *VtableField = Builder.CreateBitCast(ThisPtr, Int8PtrTy);
1380 736: VtableField = Builder.CreateConstInBoundsGEP1_64(VtableField, Offset/8);
1381 : const llvm::Type *AddressPointPtrTy =
1382 736: VtableAddressPoint->getType()->getPointerTo();
1383 736: VtableField = Builder.CreateBitCast(VtableField, AddressPointPtrTy);
1384 :
1385 : // Store address point
1386 736: Builder.CreateStore(VtableAddressPoint, VtableField);
1387 : }
1388 :
1389 8: llvm::Value *CodeGenFunction::LoadCXXVTT() {
1390 : assert((isa<CXXConstructorDecl>(CurFuncDecl) ||
1391 : isa<CXXDestructorDecl>(CurFuncDecl)) &&
0: branch 1 not taken
8: branch 2 taken
0: branch 4 not taken
0: branch 5 not taken
1392 8: "Must be in a C++ ctor or dtor to load the vtt parameter");
1393 :
1394 8: return Builder.CreateLoad(LocalDeclMap[CXXVTTDecl], "vtt");
1395 : }
Generated: 2010-02-10 01:31 by zcov