]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp
MFC r244628:
[FreeBSD/stable/9.git] / contrib / llvm / tools / clang / lib / CodeGen / MicrosoftCXXABI.cpp
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:
29   MicrosoftCXXABI(CodeGenModule &CGM) : CGCXXABI(CGM) {}
30
31   StringRef GetPureVirtualCallName() { return "_purecall"; }
32   // No known support for deleted functions in MSVC yet, so this choice is
33   // arbitrary.
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   void BuildDestructorSignature(const CXXDestructorDecl *Ctor,
46                                 CXXDtorType Type,
47                                 CanQualType &ResTy,
48                                 SmallVectorImpl<CanQualType> &ArgTys) {
49     // 'this' is already in place
50     // TODO: 'for base' flag
51   }
52
53   void BuildInstanceFunctionParams(CodeGenFunction &CGF,
54                                    QualType &ResTy,
55                                    FunctionArgList &Params);
56
57   void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
58
59   void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
60                        llvm::GlobalVariable *DeclPtr,
61                        bool PerformInit);
62
63   void EmitVTables(const CXXRecordDecl *Class);
64
65
66   // ==== Notes on array cookies =========
67   //
68   // MSVC seems to only use cookies when the class has a destructor; a
69   // two-argument usual array deallocation function isn't sufficient.
70   //
71   // For example, this code prints "100" and "1":
72   //   struct A {
73   //     char x;
74   //     void *operator new[](size_t sz) {
75   //       printf("%u\n", sz);
76   //       return malloc(sz);
77   //     }
78   //     void operator delete[](void *p, size_t sz) {
79   //       printf("%u\n", sz);
80   //       free(p);
81   //     }
82   //   };
83   //   int main() {
84   //     A *p = new A[100];
85   //     delete[] p;
86   //   }
87   // Whereas it prints "104" and "104" if you give A a destructor.
88
89   bool requiresArrayCookie(const CXXDeleteExpr *expr, QualType elementType);
90   bool requiresArrayCookie(const CXXNewExpr *expr);
91   CharUnits getArrayCookieSizeImpl(QualType type);
92   llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
93                                      llvm::Value *NewPtr,
94                                      llvm::Value *NumElements,
95                                      const CXXNewExpr *expr,
96                                      QualType ElementType);
97   llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
98                                    llvm::Value *allocPtr,
99                                    CharUnits cookieSize);
100   static bool needThisReturn(GlobalDecl GD);
101 };
102
103 }
104
105 llvm::Value *MicrosoftCXXABI::adjustToCompleteObject(CodeGenFunction &CGF,
106                                                      llvm::Value *ptr,
107                                                      QualType type) {
108   // FIXME: implement
109   return ptr;
110 }
111
112 bool MicrosoftCXXABI::needThisReturn(GlobalDecl GD) {
113   const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
114   return isa<CXXConstructorDecl>(MD);
115 }
116
117 void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
118                                  CXXCtorType Type,
119                                  CanQualType &ResTy,
120                                  SmallVectorImpl<CanQualType> &ArgTys) {
121   // 'this' is already in place
122   // TODO: 'for base' flag
123   // Ctor returns this ptr
124   ResTy = ArgTys[0];
125 }
126
127 void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
128                                                   QualType &ResTy,
129                                                   FunctionArgList &Params) {
130   BuildThisParam(CGF, Params);
131   if (needThisReturn(CGF.CurGD)) {
132     ResTy = Params[0]->getType();
133   }
134 }
135
136 void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
137   EmitThisParam(CGF);
138   if (needThisReturn(CGF.CurGD)) {
139     CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
140   }
141 }
142
143 bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
144                                    QualType elementType) {
145   // Microsoft seems to completely ignore the possibility of a
146   // two-argument usual deallocation function.
147   return elementType.isDestructedType();
148 }
149
150 bool MicrosoftCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {
151   // Microsoft seems to completely ignore the possibility of a
152   // two-argument usual deallocation function.
153   return expr->getAllocatedType().isDestructedType();
154 }
155
156 CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType type) {
157   // The array cookie is always a size_t; we then pad that out to the
158   // alignment of the element type.
159   ASTContext &Ctx = getContext();
160   return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()),
161                   Ctx.getTypeAlignInChars(type));
162 }
163
164 llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
165                                                   llvm::Value *allocPtr,
166                                                   CharUnits cookieSize) {
167   unsigned AS = allocPtr->getType()->getPointerAddressSpace();
168   llvm::Value *numElementsPtr =
169     CGF.Builder.CreateBitCast(allocPtr, CGF.SizeTy->getPointerTo(AS));
170   return CGF.Builder.CreateLoad(numElementsPtr);
171 }
172
173 llvm::Value* MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
174                                                     llvm::Value *newPtr,
175                                                     llvm::Value *numElements,
176                                                     const CXXNewExpr *expr,
177                                                     QualType elementType) {
178   assert(requiresArrayCookie(expr));
179
180   // The size of the cookie.
181   CharUnits cookieSize = getArrayCookieSizeImpl(elementType);
182
183   // Compute an offset to the cookie.
184   llvm::Value *cookiePtr = newPtr;
185
186   // Write the number of elements into the appropriate slot.
187   unsigned AS = newPtr->getType()->getPointerAddressSpace();
188   llvm::Value *numElementsPtr
189     = CGF.Builder.CreateBitCast(cookiePtr, CGF.SizeTy->getPointerTo(AS));
190   CGF.Builder.CreateStore(numElements, numElementsPtr);
191
192   // Finally, compute a pointer to the actual data buffer by skipping
193   // over the cookie completely.
194   return CGF.Builder.CreateConstInBoundsGEP1_64(newPtr,
195                                                 cookieSize.getQuantity());
196 }
197
198 void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
199                                       llvm::GlobalVariable *DeclPtr,
200                                       bool PerformInit) {
201   // FIXME: this code was only tested for global initialization.
202   // Not sure whether we want thread-safe static local variables as VS
203   // doesn't make them thread-safe.
204
205   // Emit the initializer and add a global destructor if appropriate.
206   CGF.EmitCXXGlobalVarDeclInit(D, DeclPtr, PerformInit);
207 }
208
209 void MicrosoftCXXABI::EmitVTables(const CXXRecordDecl *Class) {
210   // FIXME: implement
211 }
212
213 CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
214   return new MicrosoftCXXABI(CGM);
215 }
216