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 217