1218887Sdim//===----- CGCXXABI.cpp - Interface to C++ ABIs -----------------*- C++ -*-===// 2218887Sdim// 3218887Sdim// The LLVM Compiler Infrastructure 4218887Sdim// 5218887Sdim// This file is distributed under the University of Illinois Open Source 6218887Sdim// License. See LICENSE.TXT for details. 7218887Sdim// 8218887Sdim//===----------------------------------------------------------------------===// 9218887Sdim// 10218887Sdim// This provides an abstract class for C++ code generation. Concrete subclasses 11218887Sdim// of this implement code generation for specific C++ ABIs. 12218887Sdim// 13218887Sdim//===----------------------------------------------------------------------===// 14218887Sdim 15218887Sdim#include "CGCXXABI.h" 16218887Sdim 17218887Sdimusing namespace clang; 18218887Sdimusing namespace CodeGen; 19218887Sdim 20218887SdimCGCXXABI::~CGCXXABI() { } 21218887Sdim 22249423Sdimvoid CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) { 23226633Sdim DiagnosticsEngine &Diags = CGF.CGM.getDiags(); 24226633Sdim unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, 25239462Sdim "cannot yet compile %0 in this ABI"); 26218887Sdim Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()), 27218887Sdim DiagID) 28218887Sdim << S; 29218887Sdim} 30218887Sdim 31249423Sdimllvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) { 32218887Sdim return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T)); 33218887Sdim} 34218887Sdim 35224145Sdimllvm::Type * 36218887SdimCGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { 37218887Sdim return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType()); 38218887Sdim} 39218887Sdim 40218887Sdimllvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, 41218887Sdim llvm::Value *&This, 42218887Sdim llvm::Value *MemPtr, 43218887Sdim const MemberPointerType *MPT) { 44218887Sdim ErrorUnsupportedABI(CGF, "calls through member pointers"); 45218887Sdim 46218887Sdim const FunctionProtoType *FPT = 47218887Sdim MPT->getPointeeType()->getAs<FunctionProtoType>(); 48218887Sdim const CXXRecordDecl *RD = 49218887Sdim cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); 50234353Sdim llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( 51234353Sdim CGM.getTypes().arrangeCXXMethodType(RD, FPT)); 52218887Sdim return llvm::Constant::getNullValue(FTy->getPointerTo()); 53218887Sdim} 54218887Sdim 55218887Sdimllvm::Value *CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, 56218887Sdim llvm::Value *Base, 57218887Sdim llvm::Value *MemPtr, 58218887Sdim const MemberPointerType *MPT) { 59218887Sdim ErrorUnsupportedABI(CGF, "loads of member pointers"); 60226633Sdim llvm::Type *Ty = CGF.ConvertType(MPT->getPointeeType())->getPointerTo(); 61218887Sdim return llvm::Constant::getNullValue(Ty); 62218887Sdim} 63218887Sdim 64218887Sdimllvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, 65218887Sdim const CastExpr *E, 66218887Sdim llvm::Value *Src) { 67218887Sdim ErrorUnsupportedABI(CGF, "member function pointer conversions"); 68249423Sdim return GetBogusMemberPointer(E->getType()); 69218887Sdim} 70218887Sdim 71234353Sdimllvm::Constant *CGCXXABI::EmitMemberPointerConversion(const CastExpr *E, 72234353Sdim llvm::Constant *Src) { 73249423Sdim return GetBogusMemberPointer(E->getType()); 74234353Sdim} 75234353Sdim 76218887Sdimllvm::Value * 77218887SdimCGCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, 78218887Sdim llvm::Value *L, 79218887Sdim llvm::Value *R, 80218887Sdim const MemberPointerType *MPT, 81218887Sdim bool Inequality) { 82218887Sdim ErrorUnsupportedABI(CGF, "member function pointer comparison"); 83218887Sdim return CGF.Builder.getFalse(); 84218887Sdim} 85218887Sdim 86218887Sdimllvm::Value * 87218887SdimCGCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, 88218887Sdim llvm::Value *MemPtr, 89218887Sdim const MemberPointerType *MPT) { 90218887Sdim ErrorUnsupportedABI(CGF, "member function pointer null testing"); 91218887Sdim return CGF.Builder.getFalse(); 92218887Sdim} 93218887Sdim 94218887Sdimllvm::Constant * 95218887SdimCGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { 96249423Sdim return GetBogusMemberPointer(QualType(MPT, 0)); 97218887Sdim} 98218887Sdim 99218887Sdimllvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) { 100249423Sdim return GetBogusMemberPointer( 101218887Sdim CGM.getContext().getMemberPointerType(MD->getType(), 102218887Sdim MD->getParent()->getTypeForDecl())); 103218887Sdim} 104218887Sdim 105218887Sdimllvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, 106218887Sdim CharUnits offset) { 107249423Sdim return GetBogusMemberPointer(QualType(MPT, 0)); 108218887Sdim} 109218887Sdim 110234353Sdimllvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) { 111249423Sdim return GetBogusMemberPointer(MPT); 112234353Sdim} 113234353Sdim 114218887Sdimbool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) { 115218887Sdim // Fake answer. 116218887Sdim return true; 117218887Sdim} 118218887Sdim 119221345Sdimvoid CGCXXABI::BuildThisParam(CodeGenFunction &CGF, FunctionArgList ¶ms) { 120218887Sdim const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); 121218887Sdim 122218887Sdim // FIXME: I'm not entirely sure I like using a fake decl just for code 123218887Sdim // generation. Maybe we can come up with a better way? 124218887Sdim ImplicitParamDecl *ThisDecl 125218887Sdim = ImplicitParamDecl::Create(CGM.getContext(), 0, MD->getLocation(), 126218887Sdim &CGM.getContext().Idents.get("this"), 127218887Sdim MD->getThisType(CGM.getContext())); 128221345Sdim params.push_back(ThisDecl); 129218887Sdim getThisDecl(CGF) = ThisDecl; 130218887Sdim} 131218887Sdim 132218887Sdimvoid CGCXXABI::EmitThisParam(CodeGenFunction &CGF) { 133218887Sdim /// Initialize the 'this' slot. 134218887Sdim assert(getThisDecl(CGF) && "no 'this' variable for function"); 135218887Sdim getThisValue(CGF) 136218887Sdim = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)), 137218887Sdim "this"); 138218887Sdim} 139218887Sdim 140218887Sdimvoid CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, 141218887Sdim RValue RV, QualType ResultType) { 142218887Sdim CGF.EmitReturnOfRValue(RV, ResultType); 143218887Sdim} 144218887Sdim 145218887SdimCharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { 146239462Sdim if (!requiresArrayCookie(expr)) 147239462Sdim return CharUnits::Zero(); 148239462Sdim return getArrayCookieSizeImpl(expr->getAllocatedType()); 149239462Sdim} 150239462Sdim 151239462SdimCharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) { 152239462Sdim // BOGUS 153218887Sdim return CharUnits::Zero(); 154218887Sdim} 155218887Sdim 156218887Sdimllvm::Value *CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 157218887Sdim llvm::Value *NewPtr, 158218887Sdim llvm::Value *NumElements, 159218887Sdim const CXXNewExpr *expr, 160218887Sdim QualType ElementType) { 161218887Sdim // Should never be called. 162218887Sdim ErrorUnsupportedABI(CGF, "array cookie initialization"); 163218887Sdim return 0; 164218887Sdim} 165218887Sdim 166239462Sdimbool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr, 167239462Sdim QualType elementType) { 168239462Sdim // If the class's usual deallocation function takes two arguments, 169239462Sdim // it needs a cookie. 170239462Sdim if (expr->doesUsualArrayDeleteWantSize()) 171239462Sdim return true; 172218887Sdim 173239462Sdim return elementType.isDestructedType(); 174218887Sdim} 175218887Sdim 176239462Sdimbool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) { 177239462Sdim // If the class's usual deallocation function takes two arguments, 178239462Sdim // it needs a cookie. 179239462Sdim if (expr->doesUsualArrayDeleteWantSize()) 180239462Sdim return true; 181239462Sdim 182239462Sdim return expr->getAllocatedType().isDestructedType(); 183239462Sdim} 184239462Sdim 185239462Sdimvoid CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *ptr, 186239462Sdim const CXXDeleteExpr *expr, QualType eltTy, 187239462Sdim llvm::Value *&numElements, 188239462Sdim llvm::Value *&allocPtr, CharUnits &cookieSize) { 189239462Sdim // Derive a char* in the same address space as the pointer. 190243830Sdim unsigned AS = ptr->getType()->getPointerAddressSpace(); 191239462Sdim llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS); 192239462Sdim ptr = CGF.Builder.CreateBitCast(ptr, charPtrTy); 193239462Sdim 194239462Sdim // If we don't need an array cookie, bail out early. 195239462Sdim if (!requiresArrayCookie(expr, eltTy)) { 196239462Sdim allocPtr = ptr; 197239462Sdim numElements = 0; 198239462Sdim cookieSize = CharUnits::Zero(); 199239462Sdim return; 200239462Sdim } 201239462Sdim 202239462Sdim cookieSize = getArrayCookieSizeImpl(eltTy); 203239462Sdim allocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(ptr, 204239462Sdim -cookieSize.getQuantity()); 205239462Sdim numElements = readArrayCookieImpl(CGF, allocPtr, cookieSize); 206239462Sdim} 207239462Sdim 208239462Sdimllvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, 209239462Sdim llvm::Value *ptr, 210239462Sdim CharUnits cookieSize) { 211239462Sdim ErrorUnsupportedABI(CGF, "reading a new[] cookie"); 212239462Sdim return llvm::ConstantInt::get(CGF.SizeTy, 0); 213239462Sdim} 214239462Sdim 215218887Sdimvoid CGCXXABI::EmitGuardedInit(CodeGenFunction &CGF, 216218887Sdim const VarDecl &D, 217234353Sdim llvm::GlobalVariable *GV, 218234353Sdim bool PerformInit) { 219218887Sdim ErrorUnsupportedABI(CGF, "static local variable initialization"); 220218887Sdim} 221234353Sdim 222239462Sdimvoid CGCXXABI::registerGlobalDtor(CodeGenFunction &CGF, 223251662Sdim const VarDecl &D, 224239462Sdim llvm::Constant *dtor, 225239462Sdim llvm::Constant *addr) { 226251662Sdim if (D.getTLSKind()) 227251662Sdim CGM.ErrorUnsupported(&D, "non-trivial TLS destruction"); 228251662Sdim 229239462Sdim // The default behavior is to use atexit. 230239462Sdim CGF.registerGlobalDtorWithAtExit(dtor, addr); 231239462Sdim} 232239462Sdim 233234353Sdim/// Returns the adjustment, in bytes, required for the given 234234353Sdim/// member-pointer operation. Returns null if no adjustment is 235234353Sdim/// required. 236234353Sdimllvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) { 237234353Sdim assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || 238234353Sdim E->getCastKind() == CK_BaseToDerivedMemberPointer); 239234353Sdim 240234353Sdim QualType derivedType; 241234353Sdim if (E->getCastKind() == CK_DerivedToBaseMemberPointer) 242234353Sdim derivedType = E->getSubExpr()->getType(); 243234353Sdim else 244234353Sdim derivedType = E->getType(); 245234353Sdim 246234353Sdim const CXXRecordDecl *derivedClass = 247234353Sdim derivedType->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl(); 248234353Sdim 249234353Sdim return CGM.GetNonVirtualBaseClassOffset(derivedClass, 250234353Sdim E->path_begin(), 251234353Sdim E->path_end()); 252234353Sdim} 253249423Sdim 254249423Sdimllvm::BasicBlock *CGCXXABI::EmitCtorCompleteObjectHandler( 255249423Sdim CodeGenFunction &CGF) { 256249423Sdim if (CGM.getTarget().getCXXABI().hasConstructorVariants()) 257249423Sdim llvm_unreachable("shouldn't be called in this ABI"); 258249423Sdim 259249423Sdim ErrorUnsupportedABI(CGF, "complete object detection in ctor"); 260249423Sdim return 0; 261249423Sdim} 262251662Sdim 263251662Sdimvoid CGCXXABI::EmitThreadLocalInitFuncs( 264251662Sdim llvm::ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *> > Decls, 265251662Sdim llvm::Function *InitFunc) { 266251662Sdim} 267251662Sdim 268251662SdimLValue CGCXXABI::EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF, 269251662Sdim const DeclRefExpr *DRE) { 270251662Sdim ErrorUnsupportedABI(CGF, "odr-use of thread_local global"); 271251662Sdim return LValue(); 272251662Sdim} 273