blob: e84b68104bd0f566ac2f4726bf3d660bd1edce9f [file] [log] [blame]
Anders Carlsson87fc5a52008-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
Mike Stump11289f42009-09-09 15:08:12 +000014// We might split this into multiple files if it gets too unwieldy
Anders Carlsson87fc5a52008-08-22 16:00:37 +000015
16#include "CodeGenFunction.h"
17#include "CodeGenModule.h"
Anders Carlsson1235bbc2009-04-13 18:03:33 +000018#include "Mangle.h"
Anders Carlsson87fc5a52008-08-22 16:00:37 +000019#include "clang/AST/ASTContext.h"
Fariborz Jahaniandedf1e42009-07-25 21:12:28 +000020#include "clang/AST/RecordLayout.h"
Anders Carlsson87fc5a52008-08-22 16:00:37 +000021#include "clang/AST/Decl.h"
Anders Carlssone5fd6f22009-04-03 22:50:24 +000022#include "clang/AST/DeclCXX.h"
Anders Carlsson131be8b2008-08-23 19:42:54 +000023#include "clang/AST/DeclObjC.h"
Anders Carlsson52d78a52009-09-27 18:58:34 +000024#include "clang/AST/StmtCXX.h"
John McCalld4324142010-02-19 01:32:20 +000025#include "clang/CodeGen/CodeGenOptions.h"
Anders Carlsson87fc5a52008-08-22 16:00:37 +000026#include "llvm/ADT/StringExtras.h"
Anders Carlsson87fc5a52008-08-22 16:00:37 +000027using namespace clang;
28using namespace CodeGen;
29
John McCalld4324142010-02-19 01:32:20 +000030/// Try to emit a definition as a global alias for another definition.
31bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
32 GlobalDecl TargetDecl) {
33 if (!getCodeGenOpts().CXXCtorDtorAliases)
34 return true;
35
36 // Find the referrent.
37 llvm::GlobalValue *Ref = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
38
39 // Look for an existing entry.
40 const char *MangledName = getMangledName(AliasDecl);
41 llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
42 if (Entry) {
43 assert(Entry->isDeclaration() && "definition already exists for alias");
44 assert(Entry->getType() == Ref->getType() &&
45 "declaration exists with different type");
46 }
47
48 // The alias will use the linkage of the referrent. If we can't
49 // support aliases with that linkage, fail.
50 llvm::GlobalValue::LinkageTypes Linkage
51 = getFunctionLinkage(cast<FunctionDecl>(AliasDecl.getDecl()));
52
53 switch (Linkage) {
54 // We can definitely emit aliases to definitions with external linkage.
55 case llvm::GlobalValue::ExternalLinkage:
56 case llvm::GlobalValue::ExternalWeakLinkage:
57 break;
58
59 // Same with local linkage.
60 case llvm::GlobalValue::InternalLinkage:
61 case llvm::GlobalValue::PrivateLinkage:
62 case llvm::GlobalValue::LinkerPrivateLinkage:
63 break;
64
65 // We should try to support linkonce linkages.
66 case llvm::GlobalValue::LinkOnceAnyLinkage:
67 case llvm::GlobalValue::LinkOnceODRLinkage:
68 return true;
69
70 // Other linkages will probably never be supported.
71 default:
72 return true;
73 }
74
75 // Create the alias with no name.
76 llvm::GlobalAlias *Alias =
77 new llvm::GlobalAlias(Ref->getType(), Linkage, "", Ref, &getModule());
78
79 // Switch any previous uses to the alias and continue.
80 if (Entry) {
81 Entry->replaceAllUsesWith(Alias);
82 Entry->eraseFromParent();
83 }
84 Entry = Alias;
85
86 // Finally, set up the alias with its proper name and attributes.
87 Alias->setName(MangledName);
88 SetCommonAttributes(AliasDecl.getDecl(), Alias);
89
90 return false;
91}
Anders Carlssonbd7d11f2009-05-11 23:37:08 +000092
Anders Carlsson4034a952009-05-27 04:18:27 +000093
Anders Carlssonf7475242009-04-15 15:55:24 +000094void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) {
John McCalld4324142010-02-19 01:32:20 +000095 // The constructor used for constructing this as a complete class;
96 // constucts the virtual bases, then calls the base constructor.
John McCall67cea742010-02-17 03:52:49 +000097 EmitGlobal(GlobalDecl(D, Ctor_Complete));
John McCalld4324142010-02-19 01:32:20 +000098
99 // The constructor used for constructing this as a base class;
100 // ignores virtual bases.
John McCall334ce7c2010-02-18 21:31:48 +0000101 EmitGlobal(GlobalDecl(D, Ctor_Base));
Anders Carlssonf7475242009-04-15 15:55:24 +0000102}
Anders Carlssone8eeffd2009-04-16 23:57:24 +0000103
Mike Stump11289f42009-09-09 15:08:12 +0000104void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D,
Anders Carlssoneaa28f72009-04-17 01:58:57 +0000105 CXXCtorType Type) {
John McCalld4324142010-02-19 01:32:20 +0000106 // The complete constructor is equivalent to the base constructor
107 // for classes with no virtual bases. Try to emit it as an alias.
108 if (Type == Ctor_Complete &&
109 !D->getParent()->getNumVBases() &&
110 !TryEmitDefinitionAsAlias(GlobalDecl(D, Ctor_Complete),
111 GlobalDecl(D, Ctor_Base)))
112 return;
Mike Stump11289f42009-09-09 15:08:12 +0000113
John McCalld4324142010-02-19 01:32:20 +0000114 llvm::Function *Fn = cast<llvm::Function>(GetAddrOfCXXConstructor(D, Type));
Mike Stump11289f42009-09-09 15:08:12 +0000115
Anders Carlsson73fcc952009-09-11 00:07:24 +0000116 CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn);
Mike Stump11289f42009-09-09 15:08:12 +0000117
Anders Carlssoneaa28f72009-04-17 01:58:57 +0000118 SetFunctionDefinitionAttributes(D, Fn);
119 SetLLVMFunctionAttributesForDefinition(D, Fn);
120}
121
John McCalld4324142010-02-19 01:32:20 +0000122llvm::GlobalValue *
Mike Stump11289f42009-09-09 15:08:12 +0000123CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
Anders Carlssone8eeffd2009-04-16 23:57:24 +0000124 CXXCtorType Type) {
John McCalld4324142010-02-19 01:32:20 +0000125 const char *Name = getMangledCXXCtorName(D, Type);
126 if (llvm::GlobalValue *V = GlobalDeclMap[Name])
127 return V;
128
Fariborz Jahanianc2d71b52009-11-06 18:47:57 +0000129 const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>();
Anders Carlssone8eeffd2009-04-16 23:57:24 +0000130 const llvm::FunctionType *FTy =
Anders Carlsson82ba57c2009-11-25 03:15:49 +0000131 getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type),
Fariborz Jahanianc2d71b52009-11-06 18:47:57 +0000132 FPT->isVariadic());
Chris Lattnere0be0df2009-05-12 21:21:08 +0000133 return cast<llvm::Function>(
134 GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
Anders Carlssone8eeffd2009-04-16 23:57:24 +0000135}
Anders Carlssoneaa28f72009-04-17 01:58:57 +0000136
Mike Stump11289f42009-09-09 15:08:12 +0000137const char *CodeGenModule::getMangledCXXCtorName(const CXXConstructorDecl *D,
Anders Carlssoneaa28f72009-04-17 01:58:57 +0000138 CXXCtorType Type) {
139 llvm::SmallString<256> Name;
Daniel Dunbare128dd12009-11-21 09:06:22 +0000140 getMangleContext().mangleCXXCtor(D, Type, Name);
Mike Stump11289f42009-09-09 15:08:12 +0000141
Anders Carlssoneaa28f72009-04-17 01:58:57 +0000142 Name += '\0';
143 return UniqueMangledName(Name.begin(), Name.end());
144}
145
146void CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) {
John McCalld4324142010-02-19 01:32:20 +0000147 // The destructor in a virtual table is always a 'deleting'
148 // destructor, which calls the complete destructor and then uses the
149 // appropriate operator delete.
Eli Friedmanb572c922009-11-14 04:19:37 +0000150 if (D->isVirtual())
Eli Friedmand777ccc2009-12-15 02:06:15 +0000151 EmitGlobal(GlobalDecl(D, Dtor_Deleting));
John McCalld4324142010-02-19 01:32:20 +0000152
153 // The destructor used for destructing this as a most-derived class;
154 // call the base destructor and then destructs any virtual bases.
John McCall334ce7c2010-02-18 21:31:48 +0000155 EmitGlobal(GlobalDecl(D, Dtor_Complete));
John McCalld4324142010-02-19 01:32:20 +0000156
157 // The destructor used for destructing this as a base class; ignores
158 // virtual bases.
John McCall334ce7c2010-02-18 21:31:48 +0000159 EmitGlobal(GlobalDecl(D, Dtor_Base));
Anders Carlssoneaa28f72009-04-17 01:58:57 +0000160}
161
Mike Stump11289f42009-09-09 15:08:12 +0000162void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D,
Anders Carlssoneaa28f72009-04-17 01:58:57 +0000163 CXXDtorType Type) {
John McCalld4324142010-02-19 01:32:20 +0000164 // The complete destructor is equivalent to the base destructor for
165 // classes with no virtual bases, so try to emit it as an alias.
166 if (Type == Dtor_Complete &&
167 !D->getParent()->getNumVBases() &&
168 !TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Complete),
169 GlobalDecl(D, Dtor_Base)))
170 return;
171
172 llvm::Function *Fn = cast<llvm::Function>(GetAddrOfCXXDestructor(D, Type));
Mike Stump11289f42009-09-09 15:08:12 +0000173
Anders Carlsson73fcc952009-09-11 00:07:24 +0000174 CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn);
Mike Stump11289f42009-09-09 15:08:12 +0000175
Anders Carlssoneaa28f72009-04-17 01:58:57 +0000176 SetFunctionDefinitionAttributes(D, Fn);
177 SetLLVMFunctionAttributesForDefinition(D, Fn);
178}
179
John McCalld4324142010-02-19 01:32:20 +0000180llvm::GlobalValue *
Mike Stump11289f42009-09-09 15:08:12 +0000181CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
Anders Carlssoneaa28f72009-04-17 01:58:57 +0000182 CXXDtorType Type) {
John McCalld4324142010-02-19 01:32:20 +0000183 const char *Name = getMangledCXXDtorName(D, Type);
184 if (llvm::GlobalValue *V = GlobalDeclMap[Name])
185 return V;
186
Anders Carlssoneaa28f72009-04-17 01:58:57 +0000187 const llvm::FunctionType *FTy =
Anders Carlsson82ba57c2009-11-25 03:15:49 +0000188 getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), false);
Mike Stump11289f42009-09-09 15:08:12 +0000189
Chris Lattnere0be0df2009-05-12 21:21:08 +0000190 return cast<llvm::Function>(
191 GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
Anders Carlssoneaa28f72009-04-17 01:58:57 +0000192}
193
Mike Stump11289f42009-09-09 15:08:12 +0000194const char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D,
Anders Carlssoneaa28f72009-04-17 01:58:57 +0000195 CXXDtorType Type) {
196 llvm::SmallString<256> Name;
Daniel Dunbare128dd12009-11-21 09:06:22 +0000197 getMangleContext().mangleCXXDtor(D, Type, Name);
Mike Stump11289f42009-09-09 15:08:12 +0000198
Anders Carlssoneaa28f72009-04-17 01:58:57 +0000199 Name += '\0';
200 return UniqueMangledName(Name.begin(), Name.end());
201}
Fariborz Jahanian83381cc2009-07-20 23:18:55 +0000202
Anders Carlssonc7785402009-11-26 02:32:05 +0000203llvm::Constant *
Eli Friedman551fe842009-12-03 04:27:05 +0000204CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
Anders Carlssonc7785402009-11-26 02:32:05 +0000205 bool Extern,
206 const ThunkAdjustment &ThisAdjustment) {
Mike Stumpe2d4a2c2009-12-03 03:47:56 +0000207 return GenerateCovariantThunk(Fn, GD, Extern,
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000208 CovariantThunkAdjustment(ThisAdjustment,
209 ThunkAdjustment()));
Mike Stump5a522352009-09-04 18:27:16 +0000210}
211
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000212llvm::Value *
213CodeGenFunction::DynamicTypeAdjust(llvm::Value *V,
214 const ThunkAdjustment &Adjustment) {
215 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
216
Mike Stump77738202009-11-03 16:59:27 +0000217 const llvm::Type *OrigTy = V->getType();
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000218 if (Adjustment.NonVirtual) {
Mike Stump77738202009-11-03 16:59:27 +0000219 // Do the non-virtual adjustment
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000220 V = Builder.CreateBitCast(V, Int8PtrTy);
221 V = Builder.CreateConstInBoundsGEP1_64(V, Adjustment.NonVirtual);
Mike Stump77738202009-11-03 16:59:27 +0000222 V = Builder.CreateBitCast(V, OrigTy);
223 }
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000224
225 if (!Adjustment.Virtual)
226 return V;
227
228 assert(Adjustment.Virtual % (LLVMPointerWidth / 8) == 0 &&
229 "vtable entry unaligned");
230
231 // Do the virtual this adjustment
232 const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType());
233 const llvm::Type *PtrDiffPtrTy = PtrDiffTy->getPointerTo();
234
235 llvm::Value *ThisVal = Builder.CreateBitCast(V, Int8PtrTy);
236 V = Builder.CreateBitCast(V, PtrDiffPtrTy->getPointerTo());
237 V = Builder.CreateLoad(V, "vtable");
238
239 llvm::Value *VTablePtr = V;
240 uint64_t VirtualAdjustment = Adjustment.Virtual / (LLVMPointerWidth / 8);
241 V = Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment);
242 V = Builder.CreateLoad(V);
243 V = Builder.CreateGEP(ThisVal, V);
244
245 return Builder.CreateBitCast(V, OrigTy);
Mike Stump77738202009-11-03 16:59:27 +0000246}
247
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000248llvm::Constant *
249CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
Eli Friedman551fe842009-12-03 04:27:05 +0000250 GlobalDecl GD, bool Extern,
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000251 const CovariantThunkAdjustment &Adjustment) {
Mike Stumpe2d4a2c2009-12-03 03:47:56 +0000252 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
John McCallab26cfa2010-02-05 21:31:56 +0000253 const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
254 QualType ResultType = FPT->getResultType();
Mike Stump80f6ac52009-09-11 23:25:56 +0000255
256 FunctionArgList Args;
257 ImplicitParamDecl *ThisDecl =
258 ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
259 MD->getThisType(getContext()));
260 Args.push_back(std::make_pair(ThisDecl, ThisDecl->getType()));
261 for (FunctionDecl::param_const_iterator i = MD->param_begin(),
262 e = MD->param_end();
263 i != e; ++i) {
264 ParmVarDecl *D = *i;
265 Args.push_back(std::make_pair(D, D->getType()));
266 }
267 IdentifierInfo *II
268 = &CGM.getContext().Idents.get("__thunk_named_foo_");
269 FunctionDecl *FD = FunctionDecl::Create(getContext(),
270 getContext().getTranslationUnitDecl(),
Mike Stump33ccd9e2009-11-02 23:22:01 +0000271 SourceLocation(), II, ResultType, 0,
Mike Stump80f6ac52009-09-11 23:25:56 +0000272 Extern
273 ? FunctionDecl::Extern
274 : FunctionDecl::Static,
275 false, true);
Mike Stump33ccd9e2009-11-02 23:22:01 +0000276 StartFunction(FD, ResultType, Fn, Args, SourceLocation());
277
278 // generate body
Mike Stumpf3589722009-11-03 02:12:59 +0000279 const llvm::Type *Ty =
280 CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
281 FPT->isVariadic());
Eli Friedman551fe842009-12-03 04:27:05 +0000282 llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty);
Mike Stumpe2d4a2c2009-12-03 03:47:56 +0000283
Mike Stump33ccd9e2009-11-02 23:22:01 +0000284 CallArgList CallArgs;
285
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000286 bool ShouldAdjustReturnPointer = true;
Mike Stumpf3589722009-11-03 02:12:59 +0000287 QualType ArgType = MD->getThisType(getContext());
288 llvm::Value *Arg = Builder.CreateLoad(LocalDeclMap[ThisDecl], "this");
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000289 if (!Adjustment.ThisAdjustment.isEmpty()) {
Mike Stump77738202009-11-03 16:59:27 +0000290 // Do the this adjustment.
Mike Stump71609a22009-11-04 00:53:51 +0000291 const llvm::Type *OrigTy = Callee->getType();
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000292 Arg = DynamicTypeAdjust(Arg, Adjustment.ThisAdjustment);
293
294 if (!Adjustment.ReturnAdjustment.isEmpty()) {
295 const CovariantThunkAdjustment &ReturnAdjustment =
296 CovariantThunkAdjustment(ThunkAdjustment(),
297 Adjustment.ReturnAdjustment);
298
Mike Stumpe2d4a2c2009-12-03 03:47:56 +0000299 Callee = CGM.BuildCovariantThunk(GD, Extern, ReturnAdjustment);
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000300
Mike Stump71609a22009-11-04 00:53:51 +0000301 Callee = Builder.CreateBitCast(Callee, OrigTy);
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000302 ShouldAdjustReturnPointer = false;
Mike Stump71609a22009-11-04 00:53:51 +0000303 }
304 }
305
Mike Stumpf3589722009-11-03 02:12:59 +0000306 CallArgs.push_back(std::make_pair(RValue::get(Arg), ArgType));
307
Mike Stump33ccd9e2009-11-02 23:22:01 +0000308 for (FunctionDecl::param_const_iterator i = MD->param_begin(),
309 e = MD->param_end();
310 i != e; ++i) {
311 ParmVarDecl *D = *i;
312 QualType ArgType = D->getType();
313
314 // llvm::Value *Arg = CGF.GetAddrOfLocalVar(Dst);
Eli Friedman4039f352009-12-03 04:49:52 +0000315 Expr *Arg = new (getContext()) DeclRefExpr(D, ArgType.getNonReferenceType(),
316 SourceLocation());
Mike Stump33ccd9e2009-11-02 23:22:01 +0000317 CallArgs.push_back(std::make_pair(EmitCallArg(Arg, ArgType), ArgType));
318 }
319
John McCallab26cfa2010-02-05 21:31:56 +0000320 RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs,
321 FPT->getCallConv(),
322 FPT->getNoReturnAttr()),
Anders Carlsson61a401c2009-12-24 19:25:24 +0000323 Callee, ReturnValueSlot(), CallArgs, MD);
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000324 if (ShouldAdjustReturnPointer && !Adjustment.ReturnAdjustment.isEmpty()) {
Mike Stumpc5507682009-11-05 06:32:02 +0000325 bool CanBeZero = !(ResultType->isReferenceType()
326 // FIXME: attr nonnull can't be zero either
327 /* || ResultType->hasAttr<NonNullAttr>() */ );
Mike Stump77738202009-11-03 16:59:27 +0000328 // Do the return result adjustment.
Mike Stumpc5507682009-11-05 06:32:02 +0000329 if (CanBeZero) {
330 llvm::BasicBlock *NonZeroBlock = createBasicBlock();
331 llvm::BasicBlock *ZeroBlock = createBasicBlock();
332 llvm::BasicBlock *ContBlock = createBasicBlock();
Mike Stumpb8da7a02009-11-05 06:12:26 +0000333
Mike Stumpc5507682009-11-05 06:32:02 +0000334 const llvm::Type *Ty = RV.getScalarVal()->getType();
335 llvm::Value *Zero = llvm::Constant::getNullValue(Ty);
336 Builder.CreateCondBr(Builder.CreateICmpNE(RV.getScalarVal(), Zero),
337 NonZeroBlock, ZeroBlock);
338 EmitBlock(NonZeroBlock);
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000339 llvm::Value *NZ =
340 DynamicTypeAdjust(RV.getScalarVal(), Adjustment.ReturnAdjustment);
Mike Stumpc5507682009-11-05 06:32:02 +0000341 EmitBranch(ContBlock);
342 EmitBlock(ZeroBlock);
343 llvm::Value *Z = RV.getScalarVal();
344 EmitBlock(ContBlock);
345 llvm::PHINode *RVOrZero = Builder.CreatePHI(Ty);
346 RVOrZero->reserveOperandSpace(2);
347 RVOrZero->addIncoming(NZ, NonZeroBlock);
348 RVOrZero->addIncoming(Z, ZeroBlock);
349 RV = RValue::get(RVOrZero);
350 } else
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000351 RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(),
352 Adjustment.ReturnAdjustment));
Mike Stump33ccd9e2009-11-02 23:22:01 +0000353 }
354
Mike Stump31e1d432009-11-02 23:47:45 +0000355 if (!ResultType->isVoidType())
356 EmitReturnOfRValue(RV, ResultType);
357
Mike Stump80f6ac52009-09-11 23:25:56 +0000358 FinishFunction();
359 return Fn;
360}
361
Anders Carlssonc7785402009-11-26 02:32:05 +0000362llvm::Constant *
Eli Friedman8174f2c2009-12-06 22:01:30 +0000363CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
364 const ThunkAdjustment &ThisAdjustment) {
365 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
366
367 // Compute mangled name
368 llvm::SmallString<256> OutName;
369 if (const CXXDestructorDecl* DD = dyn_cast<CXXDestructorDecl>(MD))
370 getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(), ThisAdjustment,
371 OutName);
372 else
373 getMangleContext().mangleThunk(MD, ThisAdjustment, OutName);
374 OutName += '\0';
375 const char* Name = UniqueMangledName(OutName.begin(), OutName.end());
376
377 // Get function for mangled name
378 const llvm::Type *Ty = getTypes().GetFunctionTypeForVtable(MD);
379 return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl());
380}
381
382llvm::Constant *
383CodeGenModule::GetAddrOfCovariantThunk(GlobalDecl GD,
384 const CovariantThunkAdjustment &Adjustment) {
385 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
386
387 // Compute mangled name
388 llvm::SmallString<256> OutName;
389 getMangleContext().mangleCovariantThunk(MD, Adjustment, OutName);
390 OutName += '\0';
391 const char* Name = UniqueMangledName(OutName.begin(), OutName.end());
392
393 // Get function for mangled name
394 const llvm::Type *Ty = getTypes().GetFunctionTypeForVtable(MD);
395 return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl());
396}
397
398void CodeGenModule::BuildThunksForVirtual(GlobalDecl GD) {
Eli Friedman31bc3ad2009-12-07 23:56:34 +0000399 CGVtableInfo::AdjustmentVectorTy *AdjPtr = getVtableInfo().getAdjustments(GD);
400 if (!AdjPtr)
401 return;
402 CGVtableInfo::AdjustmentVectorTy &Adj = *AdjPtr;
Eli Friedman8174f2c2009-12-06 22:01:30 +0000403 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
Eli Friedman31bc3ad2009-12-07 23:56:34 +0000404 for (unsigned i = 0; i < Adj.size(); i++) {
405 GlobalDecl OGD = Adj[i].first;
406 const CXXMethodDecl *OMD = cast<CXXMethodDecl>(OGD.getDecl());
Eli Friedman8174f2c2009-12-06 22:01:30 +0000407 QualType nc_oret = OMD->getType()->getAs<FunctionType>()->getResultType();
408 CanQualType oret = getContext().getCanonicalType(nc_oret);
409 QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType();
410 CanQualType ret = getContext().getCanonicalType(nc_ret);
411 ThunkAdjustment ReturnAdjustment;
412 if (oret != ret) {
413 QualType qD = nc_ret->getPointeeType();
414 QualType qB = nc_oret->getPointeeType();
415 CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
416 CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
417 ReturnAdjustment = ComputeThunkAdjustment(D, B);
418 }
Eli Friedman31bc3ad2009-12-07 23:56:34 +0000419 ThunkAdjustment ThisAdjustment = Adj[i].second;
Eli Friedman8174f2c2009-12-06 22:01:30 +0000420 bool Extern = !cast<CXXRecordDecl>(OMD->getDeclContext())->isInAnonymousNamespace();
421 if (!ReturnAdjustment.isEmpty() || !ThisAdjustment.isEmpty()) {
422 CovariantThunkAdjustment CoAdj(ThisAdjustment, ReturnAdjustment);
423 llvm::Constant *FnConst;
424 if (!ReturnAdjustment.isEmpty())
425 FnConst = GetAddrOfCovariantThunk(GD, CoAdj);
426 else
427 FnConst = GetAddrOfThunk(GD, ThisAdjustment);
428 if (!isa<llvm::Function>(FnConst)) {
Eli Friedman31bc3ad2009-12-07 23:56:34 +0000429 llvm::Constant *SubExpr =
430 cast<llvm::ConstantExpr>(FnConst)->getOperand(0);
431 llvm::Function *OldFn = cast<llvm::Function>(SubExpr);
432 std::string Name = OldFn->getNameStr();
433 GlobalDeclMap.erase(UniqueMangledName(Name.data(),
434 Name.data() + Name.size() + 1));
435 llvm::Constant *NewFnConst;
436 if (!ReturnAdjustment.isEmpty())
437 NewFnConst = GetAddrOfCovariantThunk(GD, CoAdj);
438 else
439 NewFnConst = GetAddrOfThunk(GD, ThisAdjustment);
440 llvm::Function *NewFn = cast<llvm::Function>(NewFnConst);
441 NewFn->takeName(OldFn);
442 llvm::Constant *NewPtrForOldDecl =
443 llvm::ConstantExpr::getBitCast(NewFn, OldFn->getType());
444 OldFn->replaceAllUsesWith(NewPtrForOldDecl);
445 OldFn->eraseFromParent();
446 FnConst = NewFn;
Eli Friedman8174f2c2009-12-06 22:01:30 +0000447 }
448 llvm::Function *Fn = cast<llvm::Function>(FnConst);
449 if (Fn->isDeclaration()) {
450 llvm::GlobalVariable::LinkageTypes linktype;
451 linktype = llvm::GlobalValue::WeakAnyLinkage;
452 if (!Extern)
453 linktype = llvm::GlobalValue::InternalLinkage;
454 Fn->setLinkage(linktype);
455 if (!Features.Exceptions && !Features.ObjCNonFragileABI)
456 Fn->addFnAttr(llvm::Attribute::NoUnwind);
457 Fn->setAlignment(2);
458 CodeGenFunction(*this).GenerateCovariantThunk(Fn, GD, Extern, CoAdj);
459 }
460 }
Eli Friedman8174f2c2009-12-06 22:01:30 +0000461 }
462}
463
464llvm::Constant *
Eli Friedman551fe842009-12-03 04:27:05 +0000465CodeGenModule::BuildThunk(GlobalDecl GD, bool Extern,
Anders Carlssonc7785402009-11-26 02:32:05 +0000466 const ThunkAdjustment &ThisAdjustment) {
Mike Stumpe2d4a2c2009-12-03 03:47:56 +0000467 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
Mike Stump5a522352009-09-04 18:27:16 +0000468 llvm::SmallString<256> OutName;
Mike Stumpe2d4a2c2009-12-03 03:47:56 +0000469 if (const CXXDestructorDecl *D = dyn_cast<CXXDestructorDecl>(MD)) {
470 getMangleContext().mangleCXXDtorThunk(D, GD.getDtorType(), ThisAdjustment,
471 OutName);
472 } else
473 getMangleContext().mangleThunk(MD, ThisAdjustment, OutName);
Anders Carlssonc7785402009-11-26 02:32:05 +0000474
Mike Stump5a522352009-09-04 18:27:16 +0000475 llvm::GlobalVariable::LinkageTypes linktype;
476 linktype = llvm::GlobalValue::WeakAnyLinkage;
477 if (!Extern)
478 linktype = llvm::GlobalValue::InternalLinkage;
479 llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
John McCall9dd450b2009-09-21 23:43:11 +0000480 const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
Mike Stump5a522352009-09-04 18:27:16 +0000481 const llvm::FunctionType *FTy =
482 getTypes().GetFunctionType(getTypes().getFunctionInfo(MD),
483 FPT->isVariadic());
484
Daniel Dunbare128dd12009-11-21 09:06:22 +0000485 llvm::Function *Fn = llvm::Function::Create(FTy, linktype, OutName.str(),
Mike Stump5a522352009-09-04 18:27:16 +0000486 &getModule());
Mike Stumpe2d4a2c2009-12-03 03:47:56 +0000487 CodeGenFunction(*this).GenerateThunk(Fn, GD, Extern, ThisAdjustment);
Mike Stump5a522352009-09-04 18:27:16 +0000488 llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
489 return m;
490}
491
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000492llvm::Constant *
Mike Stumpe2d4a2c2009-12-03 03:47:56 +0000493CodeGenModule::BuildCovariantThunk(const GlobalDecl &GD, bool Extern,
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000494 const CovariantThunkAdjustment &Adjustment) {
Mike Stumpe2d4a2c2009-12-03 03:47:56 +0000495 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
Mike Stump80f6ac52009-09-11 23:25:56 +0000496 llvm::SmallString<256> OutName;
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000497 getMangleContext().mangleCovariantThunk(MD, Adjustment, OutName);
Mike Stump80f6ac52009-09-11 23:25:56 +0000498 llvm::GlobalVariable::LinkageTypes linktype;
499 linktype = llvm::GlobalValue::WeakAnyLinkage;
500 if (!Extern)
501 linktype = llvm::GlobalValue::InternalLinkage;
502 llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
John McCall9dd450b2009-09-21 23:43:11 +0000503 const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
Mike Stump80f6ac52009-09-11 23:25:56 +0000504 const llvm::FunctionType *FTy =
505 getTypes().GetFunctionType(getTypes().getFunctionInfo(MD),
506 FPT->isVariadic());
507
Daniel Dunbare128dd12009-11-21 09:06:22 +0000508 llvm::Function *Fn = llvm::Function::Create(FTy, linktype, OutName.str(),
Mike Stump80f6ac52009-09-11 23:25:56 +0000509 &getModule());
Anders Carlsson2f87c4f2009-11-26 03:09:37 +0000510 CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, Adjustment);
Mike Stump80f6ac52009-09-11 23:25:56 +0000511 llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
512 return m;
513}
514
Anders Carlssonf942ee02009-11-27 20:47:55 +0000515static llvm::Value *BuildVirtualCall(CodeGenFunction &CGF, uint64_t VtableIndex,
Anders Carlssone828c362009-11-13 04:45:41 +0000516 llvm::Value *This, const llvm::Type *Ty) {
517 Ty = Ty->getPointerTo()->getPointerTo()->getPointerTo();
Anders Carlsson32bfb1c2009-10-03 14:56:57 +0000518
Anders Carlssone828c362009-11-13 04:45:41 +0000519 llvm::Value *Vtable = CGF.Builder.CreateBitCast(This, Ty);
520 Vtable = CGF.Builder.CreateLoad(Vtable);
521
522 llvm::Value *VFuncPtr =
523 CGF.Builder.CreateConstInBoundsGEP1_64(Vtable, VtableIndex, "vfn");
524 return CGF.Builder.CreateLoad(VFuncPtr);
525}
526
527llvm::Value *
528CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This,
529 const llvm::Type *Ty) {
530 MD = MD->getCanonicalDecl();
Anders Carlssonf942ee02009-11-27 20:47:55 +0000531 uint64_t VtableIndex = CGM.getVtableInfo().getMethodVtableIndex(MD);
Anders Carlssone828c362009-11-13 04:45:41 +0000532
533 return ::BuildVirtualCall(*this, VtableIndex, This, Ty);
534}
535
536llvm::Value *
537CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
538 llvm::Value *&This, const llvm::Type *Ty) {
539 DD = cast<CXXDestructorDecl>(DD->getCanonicalDecl());
Anders Carlssonf942ee02009-11-27 20:47:55 +0000540 uint64_t VtableIndex =
Anders Carlssonfb4dda42009-11-13 17:08:56 +0000541 CGM.getVtableInfo().getMethodVtableIndex(GlobalDecl(DD, Type));
Anders Carlssone828c362009-11-13 04:45:41 +0000542
543 return ::BuildVirtualCall(*this, VtableIndex, This, Ty);
Mike Stumpa5588bf2009-08-26 20:46:33 +0000544}