clang API Documentation
00001 //===--- MicrosoftCXXABI.cpp - Emit LLVM Code from ASTs for a Module ------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This provides C++ code generation targeting the Microsoft Visual C++ ABI. 00011 // The class in this file generates structures that follow the Microsoft 00012 // Visual C++ ABI, which is actually not very well documented at all outside 00013 // of Microsoft. 00014 // 00015 //===----------------------------------------------------------------------===// 00016 00017 #include "CGCXXABI.h" 00018 #include "CodeGenModule.h" 00019 #include "clang/AST/Decl.h" 00020 #include "clang/AST/DeclCXX.h" 00021 00022 using namespace clang; 00023 using namespace CodeGen; 00024 00025 namespace { 00026 00027 class MicrosoftCXXABI : public CGCXXABI { 00028 public: 00029 MicrosoftCXXABI(CodeGenModule &CGM) : CGCXXABI(CGM) {} 00030 00031 void BuildConstructorSignature(const CXXConstructorDecl *Ctor, 00032 CXXCtorType Type, 00033 CanQualType &ResTy, 00034 SmallVectorImpl<CanQualType> &ArgTys) { 00035 // 'this' is already in place 00036 // TODO: 'for base' flag 00037 } 00038 00039 void BuildDestructorSignature(const CXXDestructorDecl *Ctor, 00040 CXXDtorType Type, 00041 CanQualType &ResTy, 00042 SmallVectorImpl<CanQualType> &ArgTys) { 00043 // 'this' is already in place 00044 // TODO: 'for base' flag 00045 } 00046 00047 void BuildInstanceFunctionParams(CodeGenFunction &CGF, 00048 QualType &ResTy, 00049 FunctionArgList &Params) { 00050 BuildThisParam(CGF, Params); 00051 // TODO: 'for base' flag 00052 } 00053 00054 void EmitInstanceFunctionProlog(CodeGenFunction &CGF) { 00055 EmitThisParam(CGF); 00056 // TODO: 'for base' flag 00057 } 00058 00059 void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, 00060 llvm::GlobalVariable *DeclPtr, 00061 bool PerformInit); 00062 00063 00064 // ==== Notes on array cookies ========= 00065 // 00066 // MSVC seems to only use cookies when the class has a destructor; a 00067 // two-argument usual array deallocation function isn't sufficient. 00068 // 00069 // For example, this code prints "100" and "1": 00070 // struct A { 00071 // char x; 00072 // void *operator new[](size_t sz) { 00073 // printf("%u\n", sz); 00074 // return malloc(sz); 00075 // } 00076 // void operator delete[](void *p, size_t sz) { 00077 // printf("%u\n", sz); 00078 // free(p); 00079 // } 00080 // }; 00081 // int main() { 00082 // A *p = new A[100]; 00083 // delete[] p; 00084 // } 00085 // Whereas it prints "104" and "104" if you give A a destructor. 00086 00087 bool requiresArrayCookie(const CXXDeleteExpr *expr, QualType elementType); 00088 bool requiresArrayCookie(const CXXNewExpr *expr); 00089 CharUnits getArrayCookieSizeImpl(QualType type); 00090 llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF, 00091 llvm::Value *NewPtr, 00092 llvm::Value *NumElements, 00093 const CXXNewExpr *expr, 00094 QualType ElementType); 00095 llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, 00096 llvm::Value *allocPtr, 00097 CharUnits cookieSize); 00098 }; 00099 00100 } 00101 00102 bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr, 00103 QualType elementType) { 00104 // Microsoft seems to completely ignore the possibility of a 00105 // two-argument usual deallocation function. 00106 return elementType.isDestructedType(); 00107 } 00108 00109 bool MicrosoftCXXABI::requiresArrayCookie(const CXXNewExpr *expr) { 00110 // Microsoft seems to completely ignore the possibility of a 00111 // two-argument usual deallocation function. 00112 return expr->getAllocatedType().isDestructedType(); 00113 } 00114 00115 CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType type) { 00116 // The array cookie is always a size_t; we then pad that out to the 00117 // alignment of the element type. 00118 ASTContext &Ctx = getContext(); 00119 return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()), 00120 Ctx.getTypeAlignInChars(type)); 00121 } 00122 00123 llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, 00124 llvm::Value *allocPtr, 00125 CharUnits cookieSize) { 00126 unsigned AS = cast<llvm::PointerType>(allocPtr->getType())->getAddressSpace(); 00127 llvm::Value *numElementsPtr = 00128 CGF.Builder.CreateBitCast(allocPtr, CGF.SizeTy->getPointerTo(AS)); 00129 return CGF.Builder.CreateLoad(numElementsPtr); 00130 } 00131 00132 llvm::Value* MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 00133 llvm::Value *newPtr, 00134 llvm::Value *numElements, 00135 const CXXNewExpr *expr, 00136 QualType elementType) { 00137 assert(requiresArrayCookie(expr)); 00138 00139 // The size of the cookie. 00140 CharUnits cookieSize = getArrayCookieSizeImpl(elementType); 00141 00142 // Compute an offset to the cookie. 00143 llvm::Value *cookiePtr = newPtr; 00144 00145 // Write the number of elements into the appropriate slot. 00146 unsigned AS = cast<llvm::PointerType>(newPtr->getType())->getAddressSpace(); 00147 llvm::Value *numElementsPtr 00148 = CGF.Builder.CreateBitCast(cookiePtr, CGF.SizeTy->getPointerTo(AS)); 00149 CGF.Builder.CreateStore(numElements, numElementsPtr); 00150 00151 // Finally, compute a pointer to the actual data buffer by skipping 00152 // over the cookie completely. 00153 return CGF.Builder.CreateConstInBoundsGEP1_64(newPtr, 00154 cookieSize.getQuantity()); 00155 } 00156 00157 void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, 00158 llvm::GlobalVariable *DeclPtr, 00159 bool PerformInit) { 00160 // FIXME: this code was only tested for global initialization. 00161 // Not sure whether we want thread-safe static local variables as VS 00162 // doesn't make them thread-safe. 00163 00164 // Emit the initializer and add a global destructor if appropriate. 00165 CGF.EmitCXXGlobalVarDeclInit(D, DeclPtr, PerformInit); 00166 } 00167 00168 CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) { 00169 return new MicrosoftCXXABI(CGM); 00170 } 00171