1 //===--- 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 //
10 // This provides C++ code generation targeting the Microsoft Visual C++ ABI.
11 // 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"
19 #include "clang/AST/Decl.h"
20 #include "clang/AST/DeclCXX.h"
21
22 using namespace clang;
23 using namespace CodeGen;
24
25 namespace {
26
27 class MicrosoftCXXABI : public CGCXXABI {
28 public:
MicrosoftCXXABI(CodeGenModule & CGM)29 MicrosoftCXXABI(CodeGenModule &CGM) : CGCXXABI(CGM) {}
30
GetPureVirtualCallName()31 StringRef GetPureVirtualCallName() { return "_purecall"; }
32 // No known support for deleted functions in MSVC yet, so this choice is
33 // arbitrary.
GetDeletedVirtualCallName()34 StringRef GetDeletedVirtualCallName() { return "_purecall"; }
35
36 llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF,
37 llvm::Value *ptr,
38 QualType type);
39
40 void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
41 CXXCtorType Type,
42 CanQualType &ResTy,
43 SmallVectorImpl<CanQualType> &ArgTys);
44
45 llvm::BasicBlock *EmitCtorCompleteObjectHandler(CodeGenFunction &CGF);
46
47 void BuildDestructorSignature(const CXXDestructorDecl *Ctor,
48 CXXDtorType Type,
49 CanQualType &ResTy,
50 SmallVectorImpl<CanQualType> &ArgTys);
51
52 void BuildInstanceFunctionParams(CodeGenFunction &CGF,
53 QualType &ResTy,
54 FunctionArgList &Params);
55
56 void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
57
58 void EmitConstructorCall(CodeGenFunction &CGF,
59 const CXXConstructorDecl *D,
60 CXXCtorType Type, bool ForVirtualBase,
61 bool Delegating,
62 llvm::Value *This,
63 CallExpr::const_arg_iterator ArgBeg,
64 CallExpr::const_arg_iterator ArgEnd);
65
66 RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,
67 const CXXDestructorDecl *Dtor,
68 CXXDtorType DtorType,
69 SourceLocation CallLoc,
70 ReturnValueSlot ReturnValue,
71 llvm::Value *This);
72
73 void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
74 llvm::GlobalVariable *DeclPtr,
75 bool PerformInit);
76
77 // ==== Notes on array cookies =========
78 //
79 // MSVC seems to only use cookies when the class has a destructor; a
80 // two-argument usual array deallocation function isn't sufficient.
81 //
82 // For example, this code prints "100" and "1":
83 // struct A {
84 // char x;
85 // void *operator new[](size_t sz) {
86 // printf("%u\n", sz);
87 // return malloc(sz);
88 // }
89 // void operator delete[](void *p, size_t sz) {
90 // printf("%u\n", sz);
91 // free(p);
92 // }
93 // };
94 // int main() {
95 // A *p = new A[100];
96 // delete[] p;
97 // }
98 // Whereas it prints "104" and "104" if you give A a destructor.
99
100 bool requiresArrayCookie(const CXXDeleteExpr *expr, QualType elementType);
101 bool requiresArrayCookie(const CXXNewExpr *expr);
102 CharUnits getArrayCookieSizeImpl(QualType type);
103 llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
104 llvm::Value *NewPtr,
105 llvm::Value *NumElements,
106 const CXXNewExpr *expr,
107 QualType ElementType);
108 llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
109 llvm::Value *allocPtr,
110 CharUnits cookieSize);
111 static bool needThisReturn(GlobalDecl GD);
112 };
113
114 }
115
adjustToCompleteObject(CodeGenFunction & CGF,llvm::Value * ptr,QualType type)116 llvm::Value *MicrosoftCXXABI::adjustToCompleteObject(CodeGenFunction &CGF,
117 llvm::Value *ptr,
118 QualType type) {
119 // FIXME: implement
120 return ptr;
121 }
122
needThisReturn(GlobalDecl GD)123 bool MicrosoftCXXABI::needThisReturn(GlobalDecl GD) {
124 const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
125 return isa<CXXConstructorDecl>(MD);
126 }
127
BuildConstructorSignature(const CXXConstructorDecl * Ctor,CXXCtorType Type,CanQualType & ResTy,SmallVectorImpl<CanQualType> & ArgTys)128 void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
129 CXXCtorType Type,
130 CanQualType &ResTy,
131 SmallVectorImpl<CanQualType> &ArgTys) {
132 // 'this' is already in place
133
134 // Ctor returns this ptr
135 ResTy = ArgTys[0];
136
137 const CXXRecordDecl *Class = Ctor->getParent();
138 if (Class->getNumVBases()) {
139 // Constructors of classes with virtual bases take an implicit parameter.
140 ArgTys.push_back(CGM.getContext().IntTy);
141 }
142 }
143
EmitCtorCompleteObjectHandler(CodeGenFunction & CGF)144 llvm::BasicBlock *MicrosoftCXXABI::EmitCtorCompleteObjectHandler(
145 CodeGenFunction &CGF) {
146 llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);
147 assert(IsMostDerivedClass &&
148 "ctor for a class with virtual bases must have an implicit parameter");
149 llvm::Value *IsCompleteObject
150 = CGF.Builder.CreateIsNotNull(IsMostDerivedClass, "is_complete_object");
151
152 llvm::BasicBlock *CallVbaseCtorsBB = CGF.createBasicBlock("ctor.init_vbases");
153 llvm::BasicBlock *SkipVbaseCtorsBB = CGF.createBasicBlock("ctor.skip_vbases");
154 CGF.Builder.CreateCondBr(IsCompleteObject,
155 CallVbaseCtorsBB, SkipVbaseCtorsBB);
156
157 CGF.EmitBlock(CallVbaseCtorsBB);
158 // FIXME: emit vbtables somewhere around here.
159
160 // CGF will put the base ctor calls in this basic block for us later.
161
162 return SkipVbaseCtorsBB;
163 }
164
BuildDestructorSignature(const CXXDestructorDecl * Dtor,CXXDtorType Type,CanQualType & ResTy,SmallVectorImpl<CanQualType> & ArgTys)165 void MicrosoftCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
166 CXXDtorType Type,
167 CanQualType &ResTy,
168 SmallVectorImpl<CanQualType> &ArgTys) {
169 // 'this' is already in place
170 // TODO: 'for base' flag
171
172 if (Type == Dtor_Deleting) {
173 // The scalar deleting destructor takes an implicit bool parameter.
174 ArgTys.push_back(CGM.getContext().BoolTy);
175 }
176 }
177
IsDeletingDtor(GlobalDecl GD)178 static bool IsDeletingDtor(GlobalDecl GD) {
179 const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
180 if (isa<CXXDestructorDecl>(MD)) {
181 return GD.getDtorType() == Dtor_Deleting;
182 }
183 return false;
184 }
185
BuildInstanceFunctionParams(CodeGenFunction & CGF,QualType & ResTy,FunctionArgList & Params)186 void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
187 QualType &ResTy,
188 FunctionArgList &Params) {
189 BuildThisParam(CGF, Params);
190 if (needThisReturn(CGF.CurGD)) {
191 ResTy = Params[0]->getType();
192 }
193
194 ASTContext &Context = getContext();
195 const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
196 if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) {
197 ImplicitParamDecl *IsMostDerived
198 = ImplicitParamDecl::Create(Context, 0,
199 CGF.CurGD.getDecl()->getLocation(),
200 &Context.Idents.get("is_most_derived"),
201 Context.IntTy);
202 Params.push_back(IsMostDerived);
203 getStructorImplicitParamDecl(CGF) = IsMostDerived;
204 } else if (IsDeletingDtor(CGF.CurGD)) {
205 ImplicitParamDecl *ShouldDelete
206 = ImplicitParamDecl::Create(Context, 0,
207 CGF.CurGD.getDecl()->getLocation(),
208 &Context.Idents.get("should_call_delete"),
209 Context.BoolTy);
210 Params.push_back(ShouldDelete);
211 getStructorImplicitParamDecl(CGF) = ShouldDelete;
212 }
213 }
214
EmitInstanceFunctionProlog(CodeGenFunction & CGF)215 void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
216 EmitThisParam(CGF);
217 if (needThisReturn(CGF.CurGD)) {
218 CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
219 }
220
221 const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
222 if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) {
223 assert(getStructorImplicitParamDecl(CGF) &&
224 "no implicit parameter for a constructor with virtual bases?");
225 getStructorImplicitParamValue(CGF)
226 = CGF.Builder.CreateLoad(
227 CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)),
228 "is_most_derived");
229 }
230
231 if (IsDeletingDtor(CGF.CurGD)) {
232 assert(getStructorImplicitParamDecl(CGF) &&
233 "no implicit parameter for a deleting destructor?");
234 getStructorImplicitParamValue(CGF)
235 = CGF.Builder.CreateLoad(
236 CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)),
237 "should_call_delete");
238 }
239 }
240
EmitConstructorCall(CodeGenFunction & CGF,const CXXConstructorDecl * D,CXXCtorType Type,bool ForVirtualBase,bool Delegating,llvm::Value * This,CallExpr::const_arg_iterator ArgBeg,CallExpr::const_arg_iterator ArgEnd)241 void MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
242 const CXXConstructorDecl *D,
243 CXXCtorType Type, bool ForVirtualBase,
244 bool Delegating,
245 llvm::Value *This,
246 CallExpr::const_arg_iterator ArgBeg,
247 CallExpr::const_arg_iterator ArgEnd) {
248 assert(Type == Ctor_Complete || Type == Ctor_Base);
249 llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Ctor_Complete);
250
251 llvm::Value *ImplicitParam = 0;
252 QualType ImplicitParamTy;
253 if (D->getParent()->getNumVBases()) {
254 ImplicitParam = llvm::ConstantInt::get(CGM.Int32Ty, Type == Ctor_Complete);
255 ImplicitParamTy = getContext().IntTy;
256 }
257
258 // FIXME: Provide a source location here.
259 CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This,
260 ImplicitParam, ImplicitParamTy,
261 ArgBeg, ArgEnd);
262 }
263
EmitVirtualDestructorCall(CodeGenFunction & CGF,const CXXDestructorDecl * Dtor,CXXDtorType DtorType,SourceLocation CallLoc,ReturnValueSlot ReturnValue,llvm::Value * This)264 RValue MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
265 const CXXDestructorDecl *Dtor,
266 CXXDtorType DtorType,
267 SourceLocation CallLoc,
268 ReturnValueSlot ReturnValue,
269 llvm::Value *This) {
270 assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
271
272 // We have only one destructor in the vftable but can get both behaviors
273 // by passing an implicit bool parameter.
274 const CGFunctionInfo *FInfo
275 = &CGM.getTypes().arrangeCXXDestructor(Dtor, Dtor_Deleting);
276 llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
277 llvm::Value *Callee = CGF.BuildVirtualCall(Dtor, Dtor_Deleting, This, Ty);
278
279 ASTContext &Context = CGF.getContext();
280 llvm::Value *ImplicitParam
281 = llvm::ConstantInt::get(llvm::IntegerType::getInt1Ty(CGF.getLLVMContext()),
282 DtorType == Dtor_Deleting);
283
284 return CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValue, This,
285 ImplicitParam, Context.BoolTy, 0, 0);
286 }
287
requiresArrayCookie(const CXXDeleteExpr * expr,QualType elementType)288 bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
289 QualType elementType) {
290 // Microsoft seems to completely ignore the possibility of a
291 // two-argument usual deallocation function.
292 return elementType.isDestructedType();
293 }
294
requiresArrayCookie(const CXXNewExpr * expr)295 bool MicrosoftCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {
296 // Microsoft seems to completely ignore the possibility of a
297 // two-argument usual deallocation function.
298 return expr->getAllocatedType().isDestructedType();
299 }
300
getArrayCookieSizeImpl(QualType type)301 CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType type) {
302 // The array cookie is always a size_t; we then pad that out to the
303 // alignment of the element type.
304 ASTContext &Ctx = getContext();
305 return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()),
306 Ctx.getTypeAlignInChars(type));
307 }
308
readArrayCookieImpl(CodeGenFunction & CGF,llvm::Value * allocPtr,CharUnits cookieSize)309 llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
310 llvm::Value *allocPtr,
311 CharUnits cookieSize) {
312 unsigned AS = allocPtr->getType()->getPointerAddressSpace();
313 llvm::Value *numElementsPtr =
314 CGF.Builder.CreateBitCast(allocPtr, CGF.SizeTy->getPointerTo(AS));
315 return CGF.Builder.CreateLoad(numElementsPtr);
316 }
317
InitializeArrayCookie(CodeGenFunction & CGF,llvm::Value * newPtr,llvm::Value * numElements,const CXXNewExpr * expr,QualType elementType)318 llvm::Value* MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
319 llvm::Value *newPtr,
320 llvm::Value *numElements,
321 const CXXNewExpr *expr,
322 QualType elementType) {
323 assert(requiresArrayCookie(expr));
324
325 // The size of the cookie.
326 CharUnits cookieSize = getArrayCookieSizeImpl(elementType);
327
328 // Compute an offset to the cookie.
329 llvm::Value *cookiePtr = newPtr;
330
331 // Write the number of elements into the appropriate slot.
332 unsigned AS = newPtr->getType()->getPointerAddressSpace();
333 llvm::Value *numElementsPtr
334 = CGF.Builder.CreateBitCast(cookiePtr, CGF.SizeTy->getPointerTo(AS));
335 CGF.Builder.CreateStore(numElements, numElementsPtr);
336
337 // Finally, compute a pointer to the actual data buffer by skipping
338 // over the cookie completely.
339 return CGF.Builder.CreateConstInBoundsGEP1_64(newPtr,
340 cookieSize.getQuantity());
341 }
342
EmitGuardedInit(CodeGenFunction & CGF,const VarDecl & D,llvm::GlobalVariable * DeclPtr,bool PerformInit)343 void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
344 llvm::GlobalVariable *DeclPtr,
345 bool PerformInit) {
346 // FIXME: this code was only tested for global initialization.
347 // Not sure whether we want thread-safe static local variables as VS
348 // doesn't make them thread-safe.
349
350 // Emit the initializer and add a global destructor if appropriate.
351 CGF.EmitCXXGlobalVarDeclInit(D, DeclPtr, PerformInit);
352 }
353
CreateMicrosoftCXXABI(CodeGenModule & CGM)354 CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
355 return new MicrosoftCXXABI(CGM);
356 }
357
358