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 
33   void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
34                                  CXXCtorType Type,
35                                  CanQualType &ResTy,
36                                  SmallVectorImpl<CanQualType> &ArgTys) {
37     // 'this' is already in place
38     // TODO: 'for base' flag
39   }
40 
41   void BuildDestructorSignature(const CXXDestructorDecl *Ctor,
42                                 CXXDtorType Type,
43                                 CanQualType &ResTy,
44                                 SmallVectorImpl<CanQualType> &ArgTys) {
45     // 'this' is already in place
46     // TODO: 'for base' flag
47   }
48 
49   void BuildInstanceFunctionParams(CodeGenFunction &CGF,
50                                    QualType &ResTy,
51                                    FunctionArgList &Params) {
52     BuildThisParam(CGF, Params);
53     // TODO: 'for base' flag
54   }
55 
56   void EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
57     EmitThisParam(CGF);
58     // TODO: 'for base' flag
59   }
60 
61   void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
62                        llvm::GlobalVariable *DeclPtr,
63                        bool PerformInit);
64 
65   void EmitVTables(const CXXRecordDecl *Class);
66 
67 
68   // ==== Notes on array cookies =========
69   //
70   // MSVC seems to only use cookies when the class has a destructor; a
71   // two-argument usual array deallocation function isn't sufficient.
72   //
73   // For example, this code prints "100" and "1":
74   //   struct A {
75   //     char x;
76   //     void *operator new[](size_t sz) {
77   //       printf("%u\n", sz);
78   //       return malloc(sz);
79   //     }
80   //     void operator delete[](void *p, size_t sz) {
81   //       printf("%u\n", sz);
82   //       free(p);
83   //     }
84   //   };
85   //   int main() {
86   //     A *p = new A[100];
87   //     delete[] p;
88   //   }
89   // Whereas it prints "104" and "104" if you give A a destructor.
90 
91   bool requiresArrayCookie(const CXXDeleteExpr *expr, QualType elementType);
92   bool requiresArrayCookie(const CXXNewExpr *expr);
93   CharUnits getArrayCookieSizeImpl(QualType type);
94   llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
95                                      llvm::Value *NewPtr,
96                                      llvm::Value *NumElements,
97                                      const CXXNewExpr *expr,
98                                      QualType ElementType);
99   llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
100                                    llvm::Value *allocPtr,
101                                    CharUnits cookieSize);
102 };
103 
104 }
105 
106 bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
107                                    QualType elementType) {
108   // Microsoft seems to completely ignore the possibility of a
109   // two-argument usual deallocation function.
110   return elementType.isDestructedType();
111 }
112 
113 bool MicrosoftCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {
114   // Microsoft seems to completely ignore the possibility of a
115   // two-argument usual deallocation function.
116   return expr->getAllocatedType().isDestructedType();
117 }
118 
119 CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType type) {
120   // The array cookie is always a size_t; we then pad that out to the
121   // alignment of the element type.
122   ASTContext &Ctx = getContext();
123   return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()),
124                   Ctx.getTypeAlignInChars(type));
125 }
126 
127 llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
128                                                   llvm::Value *allocPtr,
129                                                   CharUnits cookieSize) {
130   unsigned AS = cast<llvm::PointerType>(allocPtr->getType())->getAddressSpace();
131   llvm::Value *numElementsPtr =
132     CGF.Builder.CreateBitCast(allocPtr, CGF.SizeTy->getPointerTo(AS));
133   return CGF.Builder.CreateLoad(numElementsPtr);
134 }
135 
136 llvm::Value* MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
137                                                     llvm::Value *newPtr,
138                                                     llvm::Value *numElements,
139                                                     const CXXNewExpr *expr,
140                                                     QualType elementType) {
141   assert(requiresArrayCookie(expr));
142 
143   // The size of the cookie.
144   CharUnits cookieSize = getArrayCookieSizeImpl(elementType);
145 
146   // Compute an offset to the cookie.
147   llvm::Value *cookiePtr = newPtr;
148 
149   // Write the number of elements into the appropriate slot.
150   unsigned AS = cast<llvm::PointerType>(newPtr->getType())->getAddressSpace();
151   llvm::Value *numElementsPtr
152     = CGF.Builder.CreateBitCast(cookiePtr, CGF.SizeTy->getPointerTo(AS));
153   CGF.Builder.CreateStore(numElements, numElementsPtr);
154 
155   // Finally, compute a pointer to the actual data buffer by skipping
156   // over the cookie completely.
157   return CGF.Builder.CreateConstInBoundsGEP1_64(newPtr,
158                                                 cookieSize.getQuantity());
159 }
160 
161 void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
162                                       llvm::GlobalVariable *DeclPtr,
163                                       bool PerformInit) {
164   // FIXME: this code was only tested for global initialization.
165   // Not sure whether we want thread-safe static local variables as VS
166   // doesn't make them thread-safe.
167 
168   // Emit the initializer and add a global destructor if appropriate.
169   CGF.EmitCXXGlobalVarDeclInit(D, DeclPtr, PerformInit);
170 }
171 
172 void MicrosoftCXXABI::EmitVTables(const CXXRecordDecl *Class) {
173   // FIXME: implement
174 }
175 
176 CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
177   return new MicrosoftCXXABI(CGM);
178 }
179 
180