• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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