MicrosoftCXXABI.cpp revision 59660c21178b6af518bd4b564e032d5c9cc218cb
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 22using namespace clang; 23using namespace CodeGen; 24 25namespace { 26 27class MicrosoftCXXABI : public CGCXXABI { 28public: 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 50 void BuildInstanceFunctionParams(CodeGenFunction &CGF, 51 QualType &ResTy, 52 FunctionArgList &Params); 53 54 void EmitInstanceFunctionProlog(CodeGenFunction &CGF); 55 56 void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, 57 llvm::GlobalVariable *DeclPtr, 58 bool PerformInit); 59 60 // ==== Notes on array cookies ========= 61 // 62 // MSVC seems to only use cookies when the class has a destructor; a 63 // two-argument usual array deallocation function isn't sufficient. 64 // 65 // For example, this code prints "100" and "1": 66 // struct A { 67 // char x; 68 // void *operator new[](size_t sz) { 69 // printf("%u\n", sz); 70 // return malloc(sz); 71 // } 72 // void operator delete[](void *p, size_t sz) { 73 // printf("%u\n", sz); 74 // free(p); 75 // } 76 // }; 77 // int main() { 78 // A *p = new A[100]; 79 // delete[] p; 80 // } 81 // Whereas it prints "104" and "104" if you give A a destructor. 82 83 bool requiresArrayCookie(const CXXDeleteExpr *expr, QualType elementType); 84 bool requiresArrayCookie(const CXXNewExpr *expr); 85 CharUnits getArrayCookieSizeImpl(QualType type); 86 llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF, 87 llvm::Value *NewPtr, 88 llvm::Value *NumElements, 89 const CXXNewExpr *expr, 90 QualType ElementType); 91 llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, 92 llvm::Value *allocPtr, 93 CharUnits cookieSize); 94 static bool needThisReturn(GlobalDecl GD); 95}; 96 97} 98 99llvm::Value *MicrosoftCXXABI::adjustToCompleteObject(CodeGenFunction &CGF, 100 llvm::Value *ptr, 101 QualType type) { 102 // FIXME: implement 103 return ptr; 104} 105 106bool MicrosoftCXXABI::needThisReturn(GlobalDecl GD) { 107 const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl()); 108 return isa<CXXConstructorDecl>(MD); 109} 110 111void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, 112 CXXCtorType Type, 113 CanQualType &ResTy, 114 SmallVectorImpl<CanQualType> &ArgTys) { 115 // 'this' is already in place 116 // TODO: 'for base' flag 117 // Ctor returns this ptr 118 ResTy = ArgTys[0]; 119} 120 121void MicrosoftCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, 122 CXXDtorType Type, 123 CanQualType &ResTy, 124 SmallVectorImpl<CanQualType> &ArgTys) { 125 // 'this' is already in place 126 // TODO: 'for base' flag 127 128 if (Type == Dtor_Deleting) { 129 // The scalar deleting destructor takes an implicit bool parameter. 130 ArgTys.push_back(CGM.getContext().BoolTy); 131 } 132} 133 134static bool IsDeletingDtor(GlobalDecl GD) { 135 const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl()); 136 if (isa<CXXDestructorDecl>(MD)) { 137 return GD.getDtorType() == Dtor_Deleting; 138 } 139 return false; 140} 141 142void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, 143 QualType &ResTy, 144 FunctionArgList &Params) { 145 BuildThisParam(CGF, Params); 146 if (needThisReturn(CGF.CurGD)) { 147 ResTy = Params[0]->getType(); 148 } 149 if (IsDeletingDtor(CGF.CurGD)) { 150 ASTContext &Context = getContext(); 151 152 ImplicitParamDecl *ShouldDelete 153 = ImplicitParamDecl::Create(Context, 0, 154 CGF.CurGD.getDecl()->getLocation(), 155 &Context.Idents.get("should_call_delete"), 156 Context.BoolTy); 157 Params.push_back(ShouldDelete); 158 getStructorImplicitParamDecl(CGF) = ShouldDelete; 159 } 160} 161 162void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { 163 EmitThisParam(CGF); 164 if (needThisReturn(CGF.CurGD)) { 165 CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue); 166 } 167 if (IsDeletingDtor(CGF.CurGD)) { 168 assert(getStructorImplicitParamDecl(CGF) && 169 "no implicit parameter for a deleting destructor?"); 170 getStructorImplicitParamValue(CGF) 171 = CGF.Builder.CreateLoad( 172 CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)), 173 "should_call_delete"); 174 } 175} 176 177bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr, 178 QualType elementType) { 179 // Microsoft seems to completely ignore the possibility of a 180 // two-argument usual deallocation function. 181 return elementType.isDestructedType(); 182} 183 184bool MicrosoftCXXABI::requiresArrayCookie(const CXXNewExpr *expr) { 185 // Microsoft seems to completely ignore the possibility of a 186 // two-argument usual deallocation function. 187 return expr->getAllocatedType().isDestructedType(); 188} 189 190CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType type) { 191 // The array cookie is always a size_t; we then pad that out to the 192 // alignment of the element type. 193 ASTContext &Ctx = getContext(); 194 return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()), 195 Ctx.getTypeAlignInChars(type)); 196} 197 198llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, 199 llvm::Value *allocPtr, 200 CharUnits cookieSize) { 201 unsigned AS = allocPtr->getType()->getPointerAddressSpace(); 202 llvm::Value *numElementsPtr = 203 CGF.Builder.CreateBitCast(allocPtr, CGF.SizeTy->getPointerTo(AS)); 204 return CGF.Builder.CreateLoad(numElementsPtr); 205} 206 207llvm::Value* MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 208 llvm::Value *newPtr, 209 llvm::Value *numElements, 210 const CXXNewExpr *expr, 211 QualType elementType) { 212 assert(requiresArrayCookie(expr)); 213 214 // The size of the cookie. 215 CharUnits cookieSize = getArrayCookieSizeImpl(elementType); 216 217 // Compute an offset to the cookie. 218 llvm::Value *cookiePtr = newPtr; 219 220 // Write the number of elements into the appropriate slot. 221 unsigned AS = newPtr->getType()->getPointerAddressSpace(); 222 llvm::Value *numElementsPtr 223 = CGF.Builder.CreateBitCast(cookiePtr, CGF.SizeTy->getPointerTo(AS)); 224 CGF.Builder.CreateStore(numElements, numElementsPtr); 225 226 // Finally, compute a pointer to the actual data buffer by skipping 227 // over the cookie completely. 228 return CGF.Builder.CreateConstInBoundsGEP1_64(newPtr, 229 cookieSize.getQuantity()); 230} 231 232void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, 233 llvm::GlobalVariable *DeclPtr, 234 bool PerformInit) { 235 // FIXME: this code was only tested for global initialization. 236 // Not sure whether we want thread-safe static local variables as VS 237 // doesn't make them thread-safe. 238 239 // Emit the initializer and add a global destructor if appropriate. 240 CGF.EmitCXXGlobalVarDeclInit(D, DeclPtr, PerformInit); 241} 242 243CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) { 244 return new MicrosoftCXXABI(CGM); 245} 246 247