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