blob: 6c9a6fdd615016b4f6e3c63e3e3c384bef9a7b89 [file] [log] [blame]
Charles Davisc3926642010-06-09 23:25:41 +00001//===--- MicrosoftCXXABI.cpp - Emit LLVM Code from ASTs for a Module ------===//
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//
Chris Lattnerfc8f0e12011-04-15 05:22:18 +000010// This provides C++ code generation targeting the Microsoft Visual C++ ABI.
Charles Davisc3926642010-06-09 23:25:41 +000011// The class in this file generates structures that follow the Microsoft
12// Visual C++ ABI, which is actually not very well documented at all outside
13// of Microsoft.
14//
15//===----------------------------------------------------------------------===//
16
17#include "CGCXXABI.h"
18#include "CodeGenModule.h"
Charles Davisc3926642010-06-09 23:25:41 +000019#include "clang/AST/Decl.h"
20#include "clang/AST/DeclCXX.h"
Charles Davisc3926642010-06-09 23:25:41 +000021
22using namespace clang;
23using namespace CodeGen;
24
25namespace {
26
Charles Davis071cc7d2010-08-16 03:33:14 +000027class MicrosoftCXXABI : public CGCXXABI {
Charles Davisc3926642010-06-09 23:25:41 +000028public:
Peter Collingbourne14110472011-01-13 18:57:25 +000029 MicrosoftCXXABI(CodeGenModule &CGM) : CGCXXABI(CGM) {}
John McCall4c40d982010-08-31 07:33:07 +000030
Joao Matos285baac2012-07-17 17:10:11 +000031 StringRef GetPureVirtualCallName() { return "_purecall"; }
David Blaikie2eb9a952012-10-16 22:56:05 +000032 // No known support for deleted functions in MSVC yet, so this choice is
33 // arbitrary.
34 StringRef GetDeletedVirtualCallName() { return "_purecall"; }
Joao Matos285baac2012-07-17 17:10:11 +000035
John McCallecd03b42012-09-25 10:10:39 +000036 llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF,
37 llvm::Value *ptr,
38 QualType type);
39
John McCall4c40d982010-08-31 07:33:07 +000040 void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
41 CXXCtorType Type,
42 CanQualType &ResTy,
John McCallbd315742012-09-25 08:00:39 +000043 SmallVectorImpl<CanQualType> &ArgTys);
John McCall4c40d982010-08-31 07:33:07 +000044
45 void BuildDestructorSignature(const CXXDestructorDecl *Ctor,
46 CXXDtorType Type,
47 CanQualType &ResTy,
Timur Iskhodzhanov59660c22013-02-13 08:37:51 +000048 SmallVectorImpl<CanQualType> &ArgTys);
John McCall4c40d982010-08-31 07:33:07 +000049
50 void BuildInstanceFunctionParams(CodeGenFunction &CGF,
51 QualType &ResTy,
John McCallbd315742012-09-25 08:00:39 +000052 FunctionArgList &Params);
John McCall4c40d982010-08-31 07:33:07 +000053
John McCallbd315742012-09-25 08:00:39 +000054 void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
John McCallfd708262011-01-27 02:46:02 +000055
Timur Iskhodzhanov0f9827f2013-02-15 14:45:22 +000056 RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,
57 const CXXDestructorDecl *Dtor,
58 CXXDtorType DtorType,
59 SourceLocation CallLoc,
60 ReturnValueSlot ReturnValue,
61 llvm::Value *This);
62
John McCall20bb1752012-05-01 06:13:13 +000063 void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
64 llvm::GlobalVariable *DeclPtr,
65 bool PerformInit);
66
John McCallfd708262011-01-27 02:46:02 +000067 // ==== Notes on array cookies =========
68 //
69 // MSVC seems to only use cookies when the class has a destructor; a
70 // two-argument usual array deallocation function isn't sufficient.
71 //
72 // For example, this code prints "100" and "1":
73 // struct A {
74 // char x;
75 // void *operator new[](size_t sz) {
76 // printf("%u\n", sz);
77 // return malloc(sz);
78 // }
79 // void operator delete[](void *p, size_t sz) {
80 // printf("%u\n", sz);
81 // free(p);
82 // }
83 // };
84 // int main() {
85 // A *p = new A[100];
86 // delete[] p;
87 // }
88 // Whereas it prints "104" and "104" if you give A a destructor.
John McCalle2b45e22012-05-01 05:23:51 +000089
90 bool requiresArrayCookie(const CXXDeleteExpr *expr, QualType elementType);
91 bool requiresArrayCookie(const CXXNewExpr *expr);
92 CharUnits getArrayCookieSizeImpl(QualType type);
93 llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
94 llvm::Value *NewPtr,
95 llvm::Value *NumElements,
96 const CXXNewExpr *expr,
97 QualType ElementType);
98 llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
99 llvm::Value *allocPtr,
100 CharUnits cookieSize);
John McCallbd315742012-09-25 08:00:39 +0000101 static bool needThisReturn(GlobalDecl GD);
Charles Davisc3926642010-06-09 23:25:41 +0000102};
103
104}
105
John McCallecd03b42012-09-25 10:10:39 +0000106llvm::Value *MicrosoftCXXABI::adjustToCompleteObject(CodeGenFunction &CGF,
107 llvm::Value *ptr,
108 QualType type) {
109 // FIXME: implement
110 return ptr;
111}
112
John McCallbd315742012-09-25 08:00:39 +0000113bool MicrosoftCXXABI::needThisReturn(GlobalDecl GD) {
114 const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
115 return isa<CXXConstructorDecl>(MD);
116}
117
118void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
119 CXXCtorType Type,
120 CanQualType &ResTy,
121 SmallVectorImpl<CanQualType> &ArgTys) {
122 // 'this' is already in place
123 // TODO: 'for base' flag
124 // Ctor returns this ptr
125 ResTy = ArgTys[0];
126}
127
Timur Iskhodzhanov59660c22013-02-13 08:37:51 +0000128void MicrosoftCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
129 CXXDtorType Type,
130 CanQualType &ResTy,
131 SmallVectorImpl<CanQualType> &ArgTys) {
132 // 'this' is already in place
133 // TODO: 'for base' flag
134
135 if (Type == Dtor_Deleting) {
136 // The scalar deleting destructor takes an implicit bool parameter.
137 ArgTys.push_back(CGM.getContext().BoolTy);
138 }
139}
140
141static bool IsDeletingDtor(GlobalDecl GD) {
142 const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
143 if (isa<CXXDestructorDecl>(MD)) {
144 return GD.getDtorType() == Dtor_Deleting;
145 }
146 return false;
147}
148
John McCallbd315742012-09-25 08:00:39 +0000149void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
150 QualType &ResTy,
151 FunctionArgList &Params) {
152 BuildThisParam(CGF, Params);
153 if (needThisReturn(CGF.CurGD)) {
154 ResTy = Params[0]->getType();
155 }
Timur Iskhodzhanov59660c22013-02-13 08:37:51 +0000156 if (IsDeletingDtor(CGF.CurGD)) {
157 ASTContext &Context = getContext();
158
159 ImplicitParamDecl *ShouldDelete
160 = ImplicitParamDecl::Create(Context, 0,
161 CGF.CurGD.getDecl()->getLocation(),
162 &Context.Idents.get("should_call_delete"),
163 Context.BoolTy);
164 Params.push_back(ShouldDelete);
165 getStructorImplicitParamDecl(CGF) = ShouldDelete;
166 }
John McCallbd315742012-09-25 08:00:39 +0000167}
168
169void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
170 EmitThisParam(CGF);
171 if (needThisReturn(CGF.CurGD)) {
172 CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
173 }
Timur Iskhodzhanov59660c22013-02-13 08:37:51 +0000174 if (IsDeletingDtor(CGF.CurGD)) {
175 assert(getStructorImplicitParamDecl(CGF) &&
176 "no implicit parameter for a deleting destructor?");
177 getStructorImplicitParamValue(CGF)
178 = CGF.Builder.CreateLoad(
179 CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)),
180 "should_call_delete");
181 }
John McCallbd315742012-09-25 08:00:39 +0000182}
183
Timur Iskhodzhanov0f9827f2013-02-15 14:45:22 +0000184RValue MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
185 const CXXDestructorDecl *Dtor,
186 CXXDtorType DtorType,
187 SourceLocation CallLoc,
188 ReturnValueSlot ReturnValue,
189 llvm::Value *This) {
190 assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
191
192 // We have only one destructor in the vftable but can get both behaviors
193 // by passing an implicit bool parameter.
194 const CGFunctionInfo *FInfo
195 = &CGM.getTypes().arrangeCXXDestructor(Dtor, Dtor_Deleting);
196 llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
197 llvm::Value *Callee = CGF.BuildVirtualCall(Dtor, Dtor_Deleting, This, Ty);
198
199 ASTContext &Context = CGF.getContext();
200 llvm::Value *ImplicitParam
201 = llvm::ConstantInt::get(llvm::IntegerType::getInt1Ty(CGF.getLLVMContext()),
202 DtorType == Dtor_Deleting);
203
204 return CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValue, This,
205 ImplicitParam, Context.BoolTy, 0, 0);
206}
207
John McCalle2b45e22012-05-01 05:23:51 +0000208bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
209 QualType elementType) {
210 // Microsoft seems to completely ignore the possibility of a
211 // two-argument usual deallocation function.
212 return elementType.isDestructedType();
213}
214
215bool MicrosoftCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {
216 // Microsoft seems to completely ignore the possibility of a
217 // two-argument usual deallocation function.
218 return expr->getAllocatedType().isDestructedType();
219}
220
221CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType type) {
222 // The array cookie is always a size_t; we then pad that out to the
223 // alignment of the element type.
224 ASTContext &Ctx = getContext();
225 return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()),
226 Ctx.getTypeAlignInChars(type));
227}
228
229llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
230 llvm::Value *allocPtr,
231 CharUnits cookieSize) {
Micah Villmow956a5a12012-10-25 15:39:14 +0000232 unsigned AS = allocPtr->getType()->getPointerAddressSpace();
John McCalle2b45e22012-05-01 05:23:51 +0000233 llvm::Value *numElementsPtr =
234 CGF.Builder.CreateBitCast(allocPtr, CGF.SizeTy->getPointerTo(AS));
235 return CGF.Builder.CreateLoad(numElementsPtr);
236}
237
238llvm::Value* MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
239 llvm::Value *newPtr,
240 llvm::Value *numElements,
241 const CXXNewExpr *expr,
242 QualType elementType) {
243 assert(requiresArrayCookie(expr));
244
245 // The size of the cookie.
246 CharUnits cookieSize = getArrayCookieSizeImpl(elementType);
247
248 // Compute an offset to the cookie.
249 llvm::Value *cookiePtr = newPtr;
250
251 // Write the number of elements into the appropriate slot.
Micah Villmow956a5a12012-10-25 15:39:14 +0000252 unsigned AS = newPtr->getType()->getPointerAddressSpace();
John McCalle2b45e22012-05-01 05:23:51 +0000253 llvm::Value *numElementsPtr
254 = CGF.Builder.CreateBitCast(cookiePtr, CGF.SizeTy->getPointerTo(AS));
255 CGF.Builder.CreateStore(numElements, numElementsPtr);
256
257 // Finally, compute a pointer to the actual data buffer by skipping
258 // over the cookie completely.
259 return CGF.Builder.CreateConstInBoundsGEP1_64(newPtr,
260 cookieSize.getQuantity());
261}
262
John McCall20bb1752012-05-01 06:13:13 +0000263void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
264 llvm::GlobalVariable *DeclPtr,
265 bool PerformInit) {
266 // FIXME: this code was only tested for global initialization.
267 // Not sure whether we want thread-safe static local variables as VS
268 // doesn't make them thread-safe.
269
270 // Emit the initializer and add a global destructor if appropriate.
271 CGF.EmitCXXGlobalVarDeclInit(D, DeclPtr, PerformInit);
272}
273
Charles Davis071cc7d2010-08-16 03:33:14 +0000274CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
Charles Davisc3926642010-06-09 23:25:41 +0000275 return new MicrosoftCXXABI(CGM);
276}
277