 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
71.4% |
50 / 70 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
91.4% |
64 / 70 |
| |
|
Line Coverage: |
86.0% |
208 / 242 |
| |
 |
|
 |
1 : //===--- 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"
18 : #include "Mangle.h"
19 : #include "clang/AST/ASTContext.h"
20 : #include "clang/AST/RecordLayout.h"
21 : #include "clang/AST/Decl.h"
22 : #include "clang/AST/DeclCXX.h"
23 : #include "clang/AST/DeclObjC.h"
24 : #include "clang/AST/StmtCXX.h"
25 : #include "llvm/ADT/StringExtras.h"
26 : using namespace clang;
27 : using namespace CodeGen;
28 :
29 :
30 :
31 1444: llvm::Value *CodeGenFunction::LoadCXXThis() {
32 : assert(isa<CXXMethodDecl>(CurFuncDecl) &&
1444: branch 1 taken
0: branch 2 not taken
33 1444: "Must be in a C++ member function decl to load 'this'");
34 : assert(cast<CXXMethodDecl>(CurFuncDecl)->isInstance() &&
1444: branch 2 taken
0: branch 3 not taken
35 1444: "Must be in a C++ member function decl to load 'this'");
36 :
37 : // FIXME: What if we're inside a block?
38 : // ans: See how CodeGenFunction::LoadObjCSelf() uses
39 : // CodeGenFunction::BlockForwardSelf() for how to do this.
40 1444: return Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this");
41 : }
42 :
43 38: void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) {
44 38: EmitGlobal(GlobalDecl(D, Ctor_Complete));
45 38: EmitGlobal(GlobalDecl(D, Ctor_Base));
46 38: }
47 :
48 : void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D,
49 476: CXXCtorType Type) {
50 :
51 476: llvm::Function *Fn = GetAddrOfCXXConstructor(D, Type);
52 :
53 476: CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn);
54 :
55 476: SetFunctionDefinitionAttributes(D, Fn);
56 476: SetLLVMFunctionAttributesForDefinition(D, Fn);
57 476: }
58 :
59 : llvm::Function *
60 : CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
61 1164: CXXCtorType Type) {
62 1164: const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>();
63 : const llvm::FunctionType *FTy =
64 : getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type),
65 1164: FPT->isVariadic());
66 :
67 1164: const char *Name = getMangledCXXCtorName(D, Type);
68 : return cast<llvm::Function>(
69 1164: GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
70 : }
71 :
72 : const char *CodeGenModule::getMangledCXXCtorName(const CXXConstructorDecl *D,
73 1638: CXXCtorType Type) {
74 1638: llvm::SmallString<256> Name;
75 1638: getMangleContext().mangleCXXCtor(D, Type, Name);
76 :
77 1638: Name += '\0';
78 1638: return UniqueMangledName(Name.begin(), Name.end());
79 : }
80 :
81 27: void CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) {
12: branch 1 taken
15: branch 2 taken
82 27: if (D->isVirtual())
83 12: EmitGlobal(GlobalDecl(D, Dtor_Deleting));
84 27: EmitGlobal(GlobalDecl(D, Dtor_Complete));
85 27: EmitGlobal(GlobalDecl(D, Dtor_Base));
86 27: }
87 :
88 : void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D,
89 105: CXXDtorType Type) {
90 105: llvm::Function *Fn = GetAddrOfCXXDestructor(D, Type);
91 :
92 105: CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn);
93 :
94 105: SetFunctionDefinitionAttributes(D, Fn);
95 105: SetLLVMFunctionAttributesForDefinition(D, Fn);
96 105: }
97 :
98 : llvm::Function *
99 : CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
100 328: CXXDtorType Type) {
101 : const llvm::FunctionType *FTy =
102 328: getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), false);
103 :
104 328: const char *Name = getMangledCXXDtorName(D, Type);
105 : return cast<llvm::Function>(
106 328: GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
107 : }
108 :
109 : const char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D,
110 458: CXXDtorType Type) {
111 458: llvm::SmallString<256> Name;
112 458: getMangleContext().mangleCXXDtor(D, Type, Name);
113 :
114 458: Name += '\0';
115 458: return UniqueMangledName(Name.begin(), Name.end());
116 : }
117 :
118 : llvm::Constant *
119 : CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
120 : bool Extern,
121 0: const ThunkAdjustment &ThisAdjustment) {
122 : return GenerateCovariantThunk(Fn, GD, Extern,
123 : CovariantThunkAdjustment(ThisAdjustment,
124 0: ThunkAdjustment()));
125 : }
126 :
127 : llvm::Value *
128 : CodeGenFunction::DynamicTypeAdjust(llvm::Value *V,
129 87: const ThunkAdjustment &Adjustment) {
130 87: const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
131 :
132 87: const llvm::Type *OrigTy = V->getType();
29: branch 0 taken
58: branch 1 taken
133 87: if (Adjustment.NonVirtual) {
134 : // Do the non-virtual adjustment
135 29: V = Builder.CreateBitCast(V, Int8PtrTy);
136 29: V = Builder.CreateConstInBoundsGEP1_64(V, Adjustment.NonVirtual);
137 29: V = Builder.CreateBitCast(V, OrigTy);
138 : }
139 :
13: branch 0 taken
74: branch 1 taken
140 87: if (!Adjustment.Virtual)
141 13: return V;
142 :
143 : assert(Adjustment.Virtual % (LLVMPointerWidth / 8) == 0 &&
0: branch 0 not taken
74: branch 1 taken
144 74: "vtable entry unaligned");
145 :
146 : // Do the virtual this adjustment
147 74: const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType());
148 74: const llvm::Type *PtrDiffPtrTy = PtrDiffTy->getPointerTo();
149 :
150 74: llvm::Value *ThisVal = Builder.CreateBitCast(V, Int8PtrTy);
151 74: V = Builder.CreateBitCast(V, PtrDiffPtrTy->getPointerTo());
152 74: V = Builder.CreateLoad(V, "vtable");
153 :
154 74: llvm::Value *VTablePtr = V;
155 74: uint64_t VirtualAdjustment = Adjustment.Virtual / (LLVMPointerWidth / 8);
156 74: V = Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment);
157 74: V = Builder.CreateLoad(V);
158 74: V = Builder.CreateGEP(ThisVal, V);
159 :
160 74: return Builder.CreateBitCast(V, OrigTy);
161 : }
162 :
163 : llvm::Constant *
164 : CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
165 : GlobalDecl GD, bool Extern,
166 87: const CovariantThunkAdjustment &Adjustment) {
167 87: const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
168 87: const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
169 87: QualType ResultType = FPT->getResultType();
170 :
171 87: FunctionArgList Args;
172 : ImplicitParamDecl *ThisDecl =
173 : ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
174 87: MD->getThisType(getContext()));
175 87: Args.push_back(std::make_pair(ThisDecl, ThisDecl->getType()));
1: branch 1 taken
87: branch 2 taken
176 175: for (FunctionDecl::param_const_iterator i = MD->param_begin(),
177 87: e = MD->param_end();
178 : i != e; ++i) {
179 1: ParmVarDecl *D = *i;
180 1: Args.push_back(std::make_pair(D, D->getType()));
181 : }
182 : IdentifierInfo *II
183 87: = &CGM.getContext().Idents.get("__thunk_named_foo_");
184 : FunctionDecl *FD = FunctionDecl::Create(getContext(),
185 : getContext().getTranslationUnitDecl(),
186 : SourceLocation(), II, ResultType, 0,
187 : Extern
188 : ? FunctionDecl::Extern
189 : : FunctionDecl::Static,
87: branch 0 taken
0: branch 1 not taken
87: branch 6 taken
0: branch 7 not taken
190 87: false, true);
191 87: StartFunction(FD, ResultType, Fn, Args, SourceLocation());
192 :
193 : // generate body
194 : const llvm::Type *Ty =
195 : CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
196 87: FPT->isVariadic());
197 87: llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty);
198 :
199 87: CallArgList CallArgs;
200 :
201 87: bool ShouldAdjustReturnPointer = true;
202 87: QualType ArgType = MD->getThisType(getContext());
203 87: llvm::Value *Arg = Builder.CreateLoad(LocalDeclMap[ThisDecl], "this");
51: branch 1 taken
36: branch 2 taken
204 87: if (!Adjustment.ThisAdjustment.isEmpty()) {
205 : // Do the this adjustment.
206 51: const llvm::Type *OrigTy = Callee->getType();
207 51: Arg = DynamicTypeAdjust(Arg, Adjustment.ThisAdjustment);
208 :
36: branch 1 taken
15: branch 2 taken
209 51: if (!Adjustment.ReturnAdjustment.isEmpty()) {
210 : const CovariantThunkAdjustment &ReturnAdjustment =
211 : CovariantThunkAdjustment(ThunkAdjustment(),
212 36: Adjustment.ReturnAdjustment);
213 :
214 36: Callee = CGM.BuildCovariantThunk(GD, Extern, ReturnAdjustment);
215 :
216 36: Callee = Builder.CreateBitCast(Callee, OrigTy);
217 36: ShouldAdjustReturnPointer = false;
218 : }
219 : }
220 :
221 87: CallArgs.push_back(std::make_pair(RValue::get(Arg), ArgType));
222 :
1: branch 1 taken
87: branch 2 taken
223 175: for (FunctionDecl::param_const_iterator i = MD->param_begin(),
224 87: e = MD->param_end();
225 : i != e; ++i) {
226 1: ParmVarDecl *D = *i;
227 1: QualType ArgType = D->getType();
228 :
229 : // llvm::Value *Arg = CGF.GetAddrOfLocalVar(Dst);
230 : Expr *Arg = new (getContext()) DeclRefExpr(D, ArgType.getNonReferenceType(),
1: branch 4 taken
0: branch 5 not taken
231 1: SourceLocation());
232 1: CallArgs.push_back(std::make_pair(EmitCallArg(Arg, ArgType), ArgType));
233 : }
234 :
235 : RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs,
236 : FPT->getCallConv(),
237 : FPT->getNoReturnAttr()),
238 87: Callee, ReturnValueSlot(), CallArgs, MD);
51: branch 0 taken
36: branch 1 taken
36: branch 3 taken
15: branch 4 taken
36: branch 5 taken
51: branch 6 taken
239 87: if (ShouldAdjustReturnPointer && !Adjustment.ReturnAdjustment.isEmpty()) {
240 : bool CanBeZero = !(ResultType->isReferenceType()
241 : // FIXME: attr nonnull can't be zero either
242 36: /* || ResultType->hasAttr<NonNullAttr>() */ );
243 : // Do the return result adjustment.
24: branch 0 taken
12: branch 1 taken
244 36: if (CanBeZero) {
245 24: llvm::BasicBlock *NonZeroBlock = createBasicBlock();
246 24: llvm::BasicBlock *ZeroBlock = createBasicBlock();
247 24: llvm::BasicBlock *ContBlock = createBasicBlock();
248 :
249 24: const llvm::Type *Ty = RV.getScalarVal()->getType();
250 24: llvm::Value *Zero = llvm::Constant::getNullValue(Ty);
251 : Builder.CreateCondBr(Builder.CreateICmpNE(RV.getScalarVal(), Zero),
252 24: NonZeroBlock, ZeroBlock);
253 24: EmitBlock(NonZeroBlock);
254 : llvm::Value *NZ =
255 24: DynamicTypeAdjust(RV.getScalarVal(), Adjustment.ReturnAdjustment);
256 24: EmitBranch(ContBlock);
257 24: EmitBlock(ZeroBlock);
258 24: llvm::Value *Z = RV.getScalarVal();
259 24: EmitBlock(ContBlock);
260 24: llvm::PHINode *RVOrZero = Builder.CreatePHI(Ty);
261 24: RVOrZero->reserveOperandSpace(2);
262 24: RVOrZero->addIncoming(NZ, NonZeroBlock);
263 24: RVOrZero->addIncoming(Z, ZeroBlock);
264 24: RV = RValue::get(RVOrZero);
265 : } else
266 : RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(),
267 12: Adjustment.ReturnAdjustment));
268 : }
269 :
72: branch 2 taken
15: branch 3 taken
270 87: if (!ResultType->isVoidType())
271 72: EmitReturnOfRValue(RV, ResultType);
272 :
273 87: FinishFunction();
274 87: return Fn;
275 : }
276 :
277 : llvm::Constant *
278 : CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
279 94: const ThunkAdjustment &ThisAdjustment) {
280 94: const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
281 :
282 : // Compute mangled name
283 94: llvm::SmallString<256> OutName;
0: branch 1 not taken
94: branch 2 taken
284 94: if (const CXXDestructorDecl* DD = dyn_cast<CXXDestructorDecl>(MD))
285 : getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(), ThisAdjustment,
286 0: OutName);
287 : else
288 94: getMangleContext().mangleThunk(MD, ThisAdjustment, OutName);
289 94: OutName += '\0';
290 94: const char* Name = UniqueMangledName(OutName.begin(), OutName.end());
291 :
292 : // Get function for mangled name
293 94: const llvm::Type *Ty = getTypes().GetFunctionTypeForVtable(MD);
294 94: return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl());
295 : }
296 :
297 : llvm::Constant *
298 : CodeGenModule::GetAddrOfCovariantThunk(GlobalDecl GD,
299 248: const CovariantThunkAdjustment &Adjustment) {
300 248: const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
301 :
302 : // Compute mangled name
303 248: llvm::SmallString<256> OutName;
304 248: getMangleContext().mangleCovariantThunk(MD, Adjustment, OutName);
305 248: OutName += '\0';
306 248: const char* Name = UniqueMangledName(OutName.begin(), OutName.end());
307 :
308 : // Get function for mangled name
309 248: const llvm::Type *Ty = getTypes().GetFunctionTypeForVtable(MD);
310 248: return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl());
311 : }
312 :
313 943: void CodeGenModule::BuildThunksForVirtual(GlobalDecl GD) {
314 943: CGVtableInfo::AdjustmentVectorTy *AdjPtr = getVtableInfo().getAdjustments(GD);
810: branch 0 taken
133: branch 1 taken
315 943: if (!AdjPtr)
316 810: return;
317 133: CGVtableInfo::AdjustmentVectorTy &Adj = *AdjPtr;
318 133: const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
259: branch 1 taken
133: branch 2 taken
319 392: for (unsigned i = 0; i < Adj.size(); i++) {
320 259: GlobalDecl OGD = Adj[i].first;
321 259: const CXXMethodDecl *OMD = cast<CXXMethodDecl>(OGD.getDecl());
322 259: QualType nc_oret = OMD->getType()->getAs<FunctionType>()->getResultType();
323 259: CanQualType oret = getContext().getCanonicalType(nc_oret);
324 259: QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType();
325 259: CanQualType ret = getContext().getCanonicalType(nc_ret);
326 259: ThunkAdjustment ReturnAdjustment;
190: branch 1 taken
69: branch 2 taken
327 259: if (oret != ret) {
328 190: QualType qD = nc_ret->getPointeeType();
329 190: QualType qB = nc_oret->getPointeeType();
330 190: CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
331 190: CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
332 190: ReturnAdjustment = ComputeThunkAdjustment(D, B);
333 : }
334 259: ThunkAdjustment ThisAdjustment = Adj[i].second;
335 259: bool Extern = !cast<CXXRecordDecl>(OMD->getDeclContext())->isInAnonymousNamespace();
69: branch 1 taken
190: branch 2 taken
69: branch 4 taken
0: branch 5 not taken
259: branch 6 taken
0: branch 7 not taken
336 259: if (!ReturnAdjustment.isEmpty() || !ThisAdjustment.isEmpty()) {
337 259: CovariantThunkAdjustment CoAdj(ThisAdjustment, ReturnAdjustment);
338 : llvm::Constant *FnConst;
190: branch 1 taken
69: branch 2 taken
339 259: if (!ReturnAdjustment.isEmpty())
340 190: FnConst = GetAddrOfCovariantThunk(GD, CoAdj);
341 : else
342 69: FnConst = GetAddrOfThunk(GD, ThisAdjustment);
0: branch 1 not taken
259: branch 2 taken
343 259: if (!isa<llvm::Function>(FnConst)) {
344 : llvm::Constant *SubExpr =
345 0: cast<llvm::ConstantExpr>(FnConst)->getOperand(0);
346 0: llvm::Function *OldFn = cast<llvm::Function>(SubExpr);
347 0: std::string Name = OldFn->getNameStr();
348 : GlobalDeclMap.erase(UniqueMangledName(Name.data(),
349 0: Name.data() + Name.size() + 1));
350 : llvm::Constant *NewFnConst;
0: branch 1 not taken
0: branch 2 not taken
351 0: if (!ReturnAdjustment.isEmpty())
352 0: NewFnConst = GetAddrOfCovariantThunk(GD, CoAdj);
353 : else
354 0: NewFnConst = GetAddrOfThunk(GD, ThisAdjustment);
355 0: llvm::Function *NewFn = cast<llvm::Function>(NewFnConst);
356 0: NewFn->takeName(OldFn);
357 : llvm::Constant *NewPtrForOldDecl =
358 0: llvm::ConstantExpr::getBitCast(NewFn, OldFn->getType());
359 0: OldFn->replaceAllUsesWith(NewPtrForOldDecl);
360 0: OldFn->eraseFromParent();
361 0: FnConst = NewFn;
362 : }
363 259: llvm::Function *Fn = cast<llvm::Function>(FnConst);
51: branch 1 taken
208: branch 2 taken
364 259: if (Fn->isDeclaration()) {
365 : llvm::GlobalVariable::LinkageTypes linktype;
366 51: linktype = llvm::GlobalValue::WeakAnyLinkage;
0: branch 0 not taken
51: branch 1 taken
367 51: if (!Extern)
368 0: linktype = llvm::GlobalValue::InternalLinkage;
369 51: Fn->setLinkage(linktype);
51: branch 0 taken
0: branch 1 not taken
51: branch 2 taken
0: branch 3 not taken
370 51: if (!Features.Exceptions && !Features.ObjCNonFragileABI)
371 51: Fn->addFnAttr(llvm::Attribute::NoUnwind);
372 51: Fn->setAlignment(2);
373 51: CodeGenFunction(*this).GenerateCovariantThunk(Fn, GD, Extern, CoAdj);
374 : }
375 : }
376 : }
377 : }
378 :
379 : llvm::Constant *
380 : CodeGenModule::BuildThunk(GlobalDecl GD, bool Extern,
381 0: const ThunkAdjustment &ThisAdjustment) {
382 0: const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
383 0: llvm::SmallString<256> OutName;
0: branch 1 not taken
0: branch 2 not taken
384 0: if (const CXXDestructorDecl *D = dyn_cast<CXXDestructorDecl>(MD)) {
385 : getMangleContext().mangleCXXDtorThunk(D, GD.getDtorType(), ThisAdjustment,
386 0: OutName);
387 : } else
388 0: getMangleContext().mangleThunk(MD, ThisAdjustment, OutName);
389 :
390 : llvm::GlobalVariable::LinkageTypes linktype;
391 0: linktype = llvm::GlobalValue::WeakAnyLinkage;
0: branch 0 not taken
0: branch 1 not taken
392 0: if (!Extern)
393 0: linktype = llvm::GlobalValue::InternalLinkage;
394 0: llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
395 0: const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
396 : const llvm::FunctionType *FTy =
397 : getTypes().GetFunctionType(getTypes().getFunctionInfo(MD),
398 0: FPT->isVariadic());
399 :
400 : llvm::Function *Fn = llvm::Function::Create(FTy, linktype, OutName.str(),
401 0: &getModule());
402 0: CodeGenFunction(*this).GenerateThunk(Fn, GD, Extern, ThisAdjustment);
403 0: llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
404 0: return m;
405 : }
406 :
407 : llvm::Constant *
408 : CodeGenModule::BuildCovariantThunk(const GlobalDecl &GD, bool Extern,
409 36: const CovariantThunkAdjustment &Adjustment) {
410 36: const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
411 36: llvm::SmallString<256> OutName;
412 36: getMangleContext().mangleCovariantThunk(MD, Adjustment, OutName);
413 : llvm::GlobalVariable::LinkageTypes linktype;
414 36: linktype = llvm::GlobalValue::WeakAnyLinkage;
0: branch 0 not taken
36: branch 1 taken
415 36: if (!Extern)
416 0: linktype = llvm::GlobalValue::InternalLinkage;
417 36: llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
418 36: const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
419 : const llvm::FunctionType *FTy =
420 : getTypes().GetFunctionType(getTypes().getFunctionInfo(MD),
421 36: FPT->isVariadic());
422 :
423 : llvm::Function *Fn = llvm::Function::Create(FTy, linktype, OutName.str(),
424 36: &getModule());
425 36: CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, Adjustment);
426 36: llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
427 36: return m;
428 : }
429 :
430 : static llvm::Value *BuildVirtualCall(CodeGenFunction &CGF, uint64_t VtableIndex,
431 22: llvm::Value *This, const llvm::Type *Ty) {
432 22: Ty = Ty->getPointerTo()->getPointerTo()->getPointerTo();
433 :
434 22: llvm::Value *Vtable = CGF.Builder.CreateBitCast(This, Ty);
435 22: Vtable = CGF.Builder.CreateLoad(Vtable);
436 :
437 : llvm::Value *VFuncPtr =
438 22: CGF.Builder.CreateConstInBoundsGEP1_64(Vtable, VtableIndex, "vfn");
439 22: return CGF.Builder.CreateLoad(VFuncPtr);
440 : }
441 :
442 : llvm::Value *
443 : CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This,
444 21: const llvm::Type *Ty) {
445 21: MD = MD->getCanonicalDecl();
446 21: uint64_t VtableIndex = CGM.getVtableInfo().getMethodVtableIndex(MD);
447 :
448 21: return ::BuildVirtualCall(*this, VtableIndex, This, Ty);
449 : }
450 :
451 : llvm::Value *
452 : CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
453 1: llvm::Value *&This, const llvm::Type *Ty) {
454 1: DD = cast<CXXDestructorDecl>(DD->getCanonicalDecl());
455 : uint64_t VtableIndex =
456 1: CGM.getVtableInfo().getMethodVtableIndex(GlobalDecl(DD, Type));
457 :
458 1: return ::BuildVirtualCall(*this, VtableIndex, This, Ty);
459 : }
Generated: 2010-02-10 01:31 by zcov