ItaniumCXXABI.cpp revision 221345
198944Sobrien//===------- ItaniumCXXABI.cpp - Emit LLVM Code from ASTs for a Module ----===// 298944Sobrien// 398944Sobrien// The LLVM Compiler Infrastructure 498944Sobrien// 598944Sobrien// This file is distributed under the University of Illinois Open Source 698944Sobrien// License. See LICENSE.TXT for details. 798944Sobrien// 898944Sobrien//===----------------------------------------------------------------------===// 998944Sobrien// 1098944Sobrien// This provides C++ code generation targeting the Itanium C++ ABI. The class 1198944Sobrien// in this file generates structures that follow the Itanium C++ ABI, which is 1298944Sobrien// documented at: 1398944Sobrien// http://www.codesourcery.com/public/cxx-abi/abi.html 1498944Sobrien// http://www.codesourcery.com/public/cxx-abi/abi-eh.html 1598944Sobrien// 1698944Sobrien// It also supports the closely-related ARM ABI, documented at: 1798944Sobrien// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf 1898944Sobrien// 1998944Sobrien//===----------------------------------------------------------------------===// 2098944Sobrien 2198944Sobrien#include "CGCXXABI.h" 2298944Sobrien#include "CGRecordLayout.h" 2398944Sobrien#include "CodeGenFunction.h" 2498944Sobrien#include "CodeGenModule.h" 2598944Sobrien#include <clang/AST/Mangle.h> 2698944Sobrien#include <clang/AST/Type.h> 2798944Sobrien#include <llvm/Target/TargetData.h> 2898944Sobrien#include <llvm/Value.h> 2998944Sobrien 3098944Sobrienusing namespace clang; 3198944Sobrienusing namespace CodeGen; 3298944Sobrien 3398944Sobriennamespace { 3498944Sobrienclass ItaniumCXXABI : public CodeGen::CGCXXABI { 3598944Sobrienprivate: 3698944Sobrien const llvm::IntegerType *PtrDiffTy; 3798944Sobrienprotected: 3898944Sobrien bool IsARM; 3998944Sobrien 40130803Smarcel // It's a little silly for us to cache this. 4198944Sobrien const llvm::IntegerType *getPtrDiffTy() { 4298944Sobrien if (!PtrDiffTy) { 4398944Sobrien QualType T = getContext().getPointerDiffType(); 4498944Sobrien const llvm::Type *Ty = CGM.getTypes().ConvertTypeRecursive(T); 4598944Sobrien PtrDiffTy = cast<llvm::IntegerType>(Ty); 4698944Sobrien } 4798944Sobrien return PtrDiffTy; 4898944Sobrien } 4998944Sobrien 5098944Sobrien bool NeedsArrayCookie(const CXXNewExpr *expr); 5198944Sobrien bool NeedsArrayCookie(const CXXDeleteExpr *expr, 5298944Sobrien QualType elementType); 5398944Sobrien 5498944Sobrienpublic: 5598944Sobrien ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool IsARM = false) : 5698944Sobrien CGCXXABI(CGM), PtrDiffTy(0), IsARM(IsARM) { } 5798944Sobrien 5898944Sobrien bool isZeroInitializable(const MemberPointerType *MPT); 59130803Smarcel 6098944Sobrien const llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT); 6198944Sobrien 6298944Sobrien llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, 6398944Sobrien llvm::Value *&This, 6498944Sobrien llvm::Value *MemFnPtr, 6598944Sobrien const MemberPointerType *MPT); 6698944Sobrien 6798944Sobrien llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF, 6898944Sobrien llvm::Value *Base, 6998944Sobrien llvm::Value *MemPtr, 7098944Sobrien const MemberPointerType *MPT); 7198944Sobrien 7298944Sobrien llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF, 7398944Sobrien const CastExpr *E, 7498944Sobrien llvm::Value *Src); 7598944Sobrien 7698944Sobrien llvm::Constant *EmitMemberPointerConversion(llvm::Constant *C, 7798944Sobrien const CastExpr *E); 7898944Sobrien 7998944Sobrien llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT); 8098944Sobrien 8198944Sobrien llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD); 8298944Sobrien llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, 8398944Sobrien CharUnits offset); 8498944Sobrien 8598944Sobrien llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF, 8698944Sobrien llvm::Value *L, 8798944Sobrien llvm::Value *R, 8898944Sobrien const MemberPointerType *MPT, 8998944Sobrien bool Inequality); 9098944Sobrien 9198944Sobrien llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF, 9298944Sobrien llvm::Value *Addr, 9398944Sobrien const MemberPointerType *MPT); 9498944Sobrien 9598944Sobrien void BuildConstructorSignature(const CXXConstructorDecl *Ctor, 9698944Sobrien CXXCtorType T, 97130803Smarcel CanQualType &ResTy, 98130803Smarcel llvm::SmallVectorImpl<CanQualType> &ArgTys); 9998944Sobrien 10098944Sobrien void BuildDestructorSignature(const CXXDestructorDecl *Dtor, 10198944Sobrien CXXDtorType T, 10298944Sobrien CanQualType &ResTy, 10398944Sobrien llvm::SmallVectorImpl<CanQualType> &ArgTys); 10498944Sobrien 10598944Sobrien void BuildInstanceFunctionParams(CodeGenFunction &CGF, 10698944Sobrien QualType &ResTy, 10798944Sobrien FunctionArgList &Params); 10898944Sobrien 10998944Sobrien void EmitInstanceFunctionProlog(CodeGenFunction &CGF); 110130803Smarcel 11198944Sobrien CharUnits GetArrayCookieSize(const CXXNewExpr *expr); 11298944Sobrien llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF, 113130803Smarcel llvm::Value *NewPtr, 114130803Smarcel llvm::Value *NumElements, 11598944Sobrien const CXXNewExpr *expr, 11698944Sobrien QualType ElementType); 11798944Sobrien void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr, 11898944Sobrien const CXXDeleteExpr *expr, 11998944Sobrien QualType ElementType, llvm::Value *&NumElements, 12098944Sobrien llvm::Value *&AllocPtr, CharUnits &CookieSize); 12198944Sobrien 12298944Sobrien void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, 12398944Sobrien llvm::GlobalVariable *DeclPtr); 12498944Sobrien}; 12598944Sobrien 12698944Sobrienclass ARMCXXABI : public ItaniumCXXABI { 12798944Sobrienpublic: 12898944Sobrien ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {} 12998944Sobrien 13098944Sobrien void BuildConstructorSignature(const CXXConstructorDecl *Ctor, 13198944Sobrien CXXCtorType T, 13298944Sobrien CanQualType &ResTy, 13398944Sobrien llvm::SmallVectorImpl<CanQualType> &ArgTys); 13498944Sobrien 13598944Sobrien void BuildDestructorSignature(const CXXDestructorDecl *Dtor, 13698944Sobrien CXXDtorType T, 13798944Sobrien CanQualType &ResTy, 13898944Sobrien llvm::SmallVectorImpl<CanQualType> &ArgTys); 13998944Sobrien 14098944Sobrien void BuildInstanceFunctionParams(CodeGenFunction &CGF, 14198944Sobrien QualType &ResTy, 14298944Sobrien FunctionArgList &Params); 14398944Sobrien 14498944Sobrien void EmitInstanceFunctionProlog(CodeGenFunction &CGF); 14598944Sobrien 14698944Sobrien void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy); 14798944Sobrien 14898944Sobrien CharUnits GetArrayCookieSize(const CXXNewExpr *expr); 14998944Sobrien llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF, 15098944Sobrien llvm::Value *NewPtr, 15198944Sobrien llvm::Value *NumElements, 15298944Sobrien const CXXNewExpr *expr, 15398944Sobrien QualType ElementType); 15498944Sobrien void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr, 15598944Sobrien const CXXDeleteExpr *expr, 15698944Sobrien QualType ElementType, llvm::Value *&NumElements, 15798944Sobrien llvm::Value *&AllocPtr, CharUnits &CookieSize); 158130803Smarcel 159130803Smarcelprivate: 160130803Smarcel /// \brief Returns true if the given instance method is one of the 161130803Smarcel /// kinds that the ARM ABI says returns 'this'. 162130803Smarcel static bool HasThisReturn(GlobalDecl GD) { 163130803Smarcel const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 16498944Sobrien return ((isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Deleting) || 16598944Sobrien (isa<CXXConstructorDecl>(MD))); 166130803Smarcel } 16798944Sobrien}; 16898944Sobrien} 16998944Sobrien 17098944SobrienCodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { 17198944Sobrien return new ItaniumCXXABI(CGM); 17298944Sobrien} 17398944Sobrien 17498944SobrienCodeGen::CGCXXABI *CodeGen::CreateARMCXXABI(CodeGenModule &CGM) { 17598944Sobrien return new ARMCXXABI(CGM); 17698944Sobrien} 17798944Sobrien 17898944Sobrienconst llvm::Type * 17998944SobrienItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { 18098944Sobrien if (MPT->isMemberDataPointer()) 18198944Sobrien return getPtrDiffTy(); 18298944Sobrien else 18398944Sobrien return llvm::StructType::get(CGM.getLLVMContext(), 184130803Smarcel getPtrDiffTy(), getPtrDiffTy(), NULL); 185130803Smarcel} 18698944Sobrien 18798944Sobrien/// In the Itanium and ARM ABIs, method pointers have the form: 18898944Sobrien/// struct { ptrdiff_t ptr; ptrdiff_t adj; } memptr; 18998944Sobrien/// 19098944Sobrien/// In the Itanium ABI: 19198944Sobrien/// - method pointers are virtual if (memptr.ptr & 1) is nonzero 19298944Sobrien/// - the this-adjustment is (memptr.adj) 19398944Sobrien/// - the virtual offset is (memptr.ptr - 1) 19498944Sobrien/// 19598944Sobrien/// In the ARM ABI: 19698944Sobrien/// - method pointers are virtual if (memptr.adj & 1) is nonzero 19798944Sobrien/// - the this-adjustment is (memptr.adj >> 1) 19898944Sobrien/// - the virtual offset is (memptr.ptr) 19998944Sobrien/// ARM uses 'adj' for the virtual flag because Thumb functions 20098944Sobrien/// may be only single-byte aligned. 20198944Sobrien/// 20298944Sobrien/// If the member is virtual, the adjusted 'this' pointer points 20398944Sobrien/// to a vtable pointer from which the virtual offset is applied. 20498944Sobrien/// 20598944Sobrien/// If the member is non-virtual, memptr.ptr is the address of 20698944Sobrien/// the function to call. 20798944Sobrienllvm::Value * 20898944SobrienItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, 209130803Smarcel llvm::Value *&This, 21098944Sobrien llvm::Value *MemFnPtr, 21198944Sobrien const MemberPointerType *MPT) { 21298944Sobrien CGBuilderTy &Builder = CGF.Builder; 21398944Sobrien 21498944Sobrien const FunctionProtoType *FPT = 21598944Sobrien MPT->getPointeeType()->getAs<FunctionProtoType>(); 21698944Sobrien const CXXRecordDecl *RD = 21798944Sobrien cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); 21898944Sobrien 21998944Sobrien const llvm::FunctionType *FTy = 22098944Sobrien CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT), 22198944Sobrien FPT->isVariadic()); 22298944Sobrien 22398944Sobrien const llvm::IntegerType *ptrdiff = getPtrDiffTy(); 22498944Sobrien llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(ptrdiff, 1); 22598944Sobrien 226130803Smarcel llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual"); 22798944Sobrien llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual"); 22898944Sobrien llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end"); 22998944Sobrien 23098944Sobrien // Extract memptr.adj, which is in the second field. 23198944Sobrien llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1, "memptr.adj"); 23298944Sobrien 23398944Sobrien // Compute the true adjustment. 234130803Smarcel llvm::Value *Adj = RawAdj; 235130803Smarcel if (IsARM) 236130803Smarcel Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted"); 237130803Smarcel 238130803Smarcel // Apply the adjustment and cast back to the original struct type 239130803Smarcel // for consistency. 240130803Smarcel llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy()); 241130803Smarcel Ptr = Builder.CreateInBoundsGEP(Ptr, Adj); 24298944Sobrien This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted"); 24398944Sobrien 24498944Sobrien // Load the function pointer. 24598944Sobrien llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr"); 24698944Sobrien 24798944Sobrien // If the LSB in the function pointer is 1, the function pointer points to 248130803Smarcel // a virtual function. 249130803Smarcel llvm::Value *IsVirtual; 25098944Sobrien if (IsARM) 25198944Sobrien IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1); 25298944Sobrien else 25398944Sobrien IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1); 25498944Sobrien IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual"); 25598944Sobrien Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual); 25698944Sobrien 25798944Sobrien // In the virtual path, the adjustment left 'This' pointing to the 25898944Sobrien // vtable of the correct base subobject. The "function pointer" is an 259130803Smarcel // offset within the vtable (+1 for the virtual flag on non-ARM). 260130803Smarcel CGF.EmitBlock(FnVirtual); 261130803Smarcel 262130803Smarcel // Cast the adjusted this to a pointer to vtable pointer and load. 26398944Sobrien const llvm::Type *VTableTy = Builder.getInt8PtrTy(); 26498944Sobrien llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo()); 265130803Smarcel VTable = Builder.CreateLoad(VTable, "memptr.vtable"); 266130803Smarcel 267130803Smarcel // Apply the offset. 268130803Smarcel llvm::Value *VTableOffset = FnAsInt; 26998944Sobrien if (!IsARM) VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1); 27098944Sobrien VTable = Builder.CreateGEP(VTable, VTableOffset); 27198944Sobrien 27298944Sobrien // Load the virtual function to call. 27398944Sobrien VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo()); 27498944Sobrien llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "memptr.virtualfn"); 27598944Sobrien CGF.EmitBranch(FnEnd); 27698944Sobrien 27798944Sobrien // In the non-virtual path, the function pointer is actually a 27898944Sobrien // function pointer. 27998944Sobrien CGF.EmitBlock(FnNonVirtual); 28098944Sobrien llvm::Value *NonVirtualFn = 28198944Sobrien Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn"); 28298944Sobrien 28398944Sobrien // We're done. 28498944Sobrien CGF.EmitBlock(FnEnd); 28598944Sobrien llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo(), 2); 286130803Smarcel Callee->addIncoming(VirtualFn, FnVirtual); 287130803Smarcel Callee->addIncoming(NonVirtualFn, FnNonVirtual); 288130803Smarcel return Callee; 28998944Sobrien} 290130803Smarcel 291130803Smarcel/// Compute an l-value by applying the given pointer-to-member to a 292130803Smarcel/// base object. 293130803Smarcelllvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, 294130803Smarcel llvm::Value *Base, 295130803Smarcel llvm::Value *MemPtr, 296130803Smarcel const MemberPointerType *MPT) { 297130803Smarcel assert(MemPtr->getType() == getPtrDiffTy()); 298130803Smarcel 299130803Smarcel CGBuilderTy &Builder = CGF.Builder; 300130803Smarcel 301130803Smarcel unsigned AS = cast<llvm::PointerType>(Base->getType())->getAddressSpace(); 302130803Smarcel 303130803Smarcel // Cast to char*. 304130803Smarcel Base = Builder.CreateBitCast(Base, Builder.getInt8Ty()->getPointerTo(AS)); 305130803Smarcel 306130803Smarcel // Apply the offset, which we assume is non-null. 307130803Smarcel llvm::Value *Addr = Builder.CreateInBoundsGEP(Base, MemPtr, "memptr.offset"); 308130803Smarcel 309130803Smarcel // Cast the address to the appropriate pointer type, adopting the 310130803Smarcel // address space of the base pointer. 311130803Smarcel const llvm::Type *PType 312130803Smarcel = CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS); 313130803Smarcel return Builder.CreateBitCast(Addr, PType); 314130803Smarcel} 315130803Smarcel 316130803Smarcel/// Perform a derived-to-base or base-to-derived member pointer conversion. 317130803Smarcel/// 318130803Smarcel/// Obligatory offset/adjustment diagram: 319130803Smarcel/// <-- offset --> <-- adjustment --> 320130803Smarcel/// |--------------------------|----------------------|--------------------| 321130803Smarcel/// ^Derived address point ^Base address point ^Member address point 322130803Smarcel/// 323130803Smarcel/// So when converting a base member pointer to a derived member pointer, 32498944Sobrien/// we add the offset to the adjustment because the address point has 32598944Sobrien/// decreased; and conversely, when converting a derived MP to a base MP 32698944Sobrien/// we subtract the offset from the adjustment because the address point 32798944Sobrien/// has increased. 32898944Sobrien/// 329130803Smarcel/// The standard forbids (at compile time) conversion to and from 330130803Smarcel/// virtual bases, which is why we don't have to consider them here. 33198944Sobrien/// 33298944Sobrien/// The standard forbids (at run time) casting a derived MP to a base 33398944Sobrien/// MP when the derived MP does not point to a member of the base. 334130803Smarcel/// This is why -1 is a reasonable choice for null data member 335130803Smarcel/// pointers. 33698944Sobrienllvm::Value * 33798944SobrienItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, 33898944Sobrien const CastExpr *E, 33998944Sobrien llvm::Value *Src) { 34098944Sobrien assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || 34198944Sobrien E->getCastKind() == CK_BaseToDerivedMemberPointer); 34298944Sobrien 34398944Sobrien if (isa<llvm::Constant>(Src)) 34498944Sobrien return EmitMemberPointerConversion(cast<llvm::Constant>(Src), E); 34598944Sobrien 346130803Smarcel CGBuilderTy &Builder = CGF.Builder; 347130803Smarcel 348130803Smarcel const MemberPointerType *SrcTy = 349130803Smarcel E->getSubExpr()->getType()->getAs<MemberPointerType>(); 350130803Smarcel const MemberPointerType *DestTy = E->getType()->getAs<MemberPointerType>(); 351130803Smarcel 352130803Smarcel const CXXRecordDecl *SrcDecl = SrcTy->getClass()->getAsCXXRecordDecl(); 353130803Smarcel const CXXRecordDecl *DestDecl = DestTy->getClass()->getAsCXXRecordDecl(); 354130803Smarcel 35598944Sobrien bool DerivedToBase = 356130803Smarcel E->getCastKind() == CK_DerivedToBaseMemberPointer; 357130803Smarcel 35898944Sobrien const CXXRecordDecl *DerivedDecl; 35998944Sobrien if (DerivedToBase) 36098944Sobrien DerivedDecl = SrcDecl; 36198944Sobrien else 36298944Sobrien DerivedDecl = DestDecl; 36398944Sobrien 36498944Sobrien llvm::Constant *Adj = 36598944Sobrien CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl, 36698944Sobrien E->path_begin(), 36798944Sobrien E->path_end()); 36898944Sobrien if (!Adj) return Src; 36998944Sobrien 37098944Sobrien // For member data pointers, this is just a matter of adding the 37198944Sobrien // offset if the source is non-null. 37298944Sobrien if (SrcTy->isMemberDataPointer()) { 37398944Sobrien llvm::Value *Dst; 37498944Sobrien if (DerivedToBase) 37598944Sobrien Dst = Builder.CreateNSWSub(Src, Adj, "adj"); 37698944Sobrien else 37798944Sobrien Dst = Builder.CreateNSWAdd(Src, Adj, "adj"); 37898944Sobrien 37998944Sobrien // Null check. 38098944Sobrien llvm::Value *Null = llvm::Constant::getAllOnesValue(Src->getType()); 38198944Sobrien llvm::Value *IsNull = Builder.CreateICmpEQ(Src, Null, "memptr.isnull"); 38298944Sobrien return Builder.CreateSelect(IsNull, Src, Dst); 38398944Sobrien } 38498944Sobrien 38598944Sobrien // The this-adjustment is left-shifted by 1 on ARM. 38698944Sobrien if (IsARM) { 38798944Sobrien uint64_t Offset = cast<llvm::ConstantInt>(Adj)->getZExtValue(); 38898944Sobrien Offset <<= 1; 38998944Sobrien Adj = llvm::ConstantInt::get(Adj->getType(), Offset); 39098944Sobrien } 39198944Sobrien 39298944Sobrien llvm::Value *SrcAdj = Builder.CreateExtractValue(Src, 1, "src.adj"); 39398944Sobrien llvm::Value *DstAdj; 39498944Sobrien if (DerivedToBase) 39598944Sobrien DstAdj = Builder.CreateNSWSub(SrcAdj, Adj, "adj"); 39698944Sobrien else 39798944Sobrien DstAdj = Builder.CreateNSWAdd(SrcAdj, Adj, "adj"); 39898944Sobrien 39998944Sobrien return Builder.CreateInsertValue(Src, DstAdj, 1); 40098944Sobrien} 40198944Sobrien 40298944Sobrienllvm::Constant * 40398944SobrienItaniumCXXABI::EmitMemberPointerConversion(llvm::Constant *C, 40498944Sobrien const CastExpr *E) { 40598944Sobrien const MemberPointerType *SrcTy = 40698944Sobrien E->getSubExpr()->getType()->getAs<MemberPointerType>(); 40798944Sobrien const MemberPointerType *DestTy = 40898944Sobrien E->getType()->getAs<MemberPointerType>(); 40998944Sobrien 41098944Sobrien bool DerivedToBase = 41198944Sobrien E->getCastKind() == CK_DerivedToBaseMemberPointer; 41298944Sobrien 41398944Sobrien const CXXRecordDecl *DerivedDecl; 41498944Sobrien if (DerivedToBase) 41598944Sobrien DerivedDecl = SrcTy->getClass()->getAsCXXRecordDecl(); 41698944Sobrien else 41798944Sobrien DerivedDecl = DestTy->getClass()->getAsCXXRecordDecl(); 41898944Sobrien 41998944Sobrien // Calculate the offset to the base class. 42098944Sobrien llvm::Constant *Offset = 42198944Sobrien CGM.GetNonVirtualBaseClassOffset(DerivedDecl, 42298944Sobrien E->path_begin(), 42398944Sobrien E->path_end()); 42498944Sobrien // If there's no offset, we're done. 42598944Sobrien if (!Offset) return C; 42698944Sobrien 42798944Sobrien // If the source is a member data pointer, we have to do a null 42898944Sobrien // check and then add the offset. In the common case, we can fold 42998944Sobrien // away the offset. 43098944Sobrien if (SrcTy->isMemberDataPointer()) { 43198944Sobrien assert(C->getType() == getPtrDiffTy()); 43298944Sobrien 43398944Sobrien // If it's a constant int, just create a new constant int. 43498944Sobrien if (llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(C)) { 43598944Sobrien int64_t Src = CI->getSExtValue(); 43698944Sobrien 43798944Sobrien // Null converts to null. 438130803Smarcel if (Src == -1) return CI; 43998944Sobrien 44098944Sobrien // Otherwise, just add the offset. 44198944Sobrien int64_t OffsetV = cast<llvm::ConstantInt>(Offset)->getSExtValue(); 44298944Sobrien int64_t Dst = (DerivedToBase ? Src - OffsetV : Src + OffsetV); 44398944Sobrien return llvm::ConstantInt::get(CI->getType(), Dst, /*signed*/ true); 444130803Smarcel } 44598944Sobrien 44698944Sobrien // Otherwise, we have to form a constant select expression. 44798944Sobrien llvm::Constant *Null = llvm::Constant::getAllOnesValue(C->getType()); 44898944Sobrien 44998944Sobrien llvm::Constant *IsNull = 45098944Sobrien llvm::ConstantExpr::getICmp(llvm::ICmpInst::ICMP_EQ, C, Null); 45198944Sobrien 45298944Sobrien llvm::Constant *Dst; 45398944Sobrien if (DerivedToBase) 45498944Sobrien Dst = llvm::ConstantExpr::getNSWSub(C, Offset); 45598944Sobrien else 45698944Sobrien Dst = llvm::ConstantExpr::getNSWAdd(C, Offset); 45798944Sobrien 45898944Sobrien return llvm::ConstantExpr::getSelect(IsNull, Null, Dst); 45998944Sobrien } 46098944Sobrien 46198944Sobrien // The this-adjustment is left-shifted by 1 on ARM. 46298944Sobrien if (IsARM) { 46398944Sobrien int64_t OffsetV = cast<llvm::ConstantInt>(Offset)->getSExtValue(); 46498944Sobrien OffsetV <<= 1; 46598944Sobrien Offset = llvm::ConstantInt::get(Offset->getType(), OffsetV); 46698944Sobrien } 46798944Sobrien 46898944Sobrien llvm::ConstantStruct *CS = cast<llvm::ConstantStruct>(C); 46998944Sobrien 47098944Sobrien llvm::Constant *Values[2] = { CS->getOperand(0), 0 }; 47198944Sobrien if (DerivedToBase) 47298944Sobrien Values[1] = llvm::ConstantExpr::getSub(CS->getOperand(1), Offset); 47398944Sobrien else 47498944Sobrien Values[1] = llvm::ConstantExpr::getAdd(CS->getOperand(1), Offset); 47598944Sobrien 47698944Sobrien return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2, 47798944Sobrien /*Packed=*/false); 47898944Sobrien} 47998944Sobrien 48098944Sobrien 48198944Sobrienllvm::Constant * 48298944SobrienItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { 48398944Sobrien const llvm::Type *ptrdiff_t = getPtrDiffTy(); 48498944Sobrien 48598944Sobrien // Itanium C++ ABI 2.3: 48698944Sobrien // A NULL pointer is represented as -1. 48798944Sobrien if (MPT->isMemberDataPointer()) 48898944Sobrien return llvm::ConstantInt::get(ptrdiff_t, -1ULL, /*isSigned=*/true); 48998944Sobrien 49098944Sobrien llvm::Constant *Zero = llvm::ConstantInt::get(ptrdiff_t, 0); 49198944Sobrien llvm::Constant *Values[2] = { Zero, Zero }; 49298944Sobrien return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2, 49398944Sobrien /*Packed=*/false); 49498944Sobrien} 49598944Sobrien 49698944Sobrienllvm::Constant * 49798944SobrienItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, 49898944Sobrien CharUnits offset) { 49998944Sobrien // Itanium C++ ABI 2.3: 50098944Sobrien // A pointer to data member is an offset from the base address of 50198944Sobrien // the class object containing it, represented as a ptrdiff_t 50298944Sobrien return llvm::ConstantInt::get(getPtrDiffTy(), offset.getQuantity()); 50398944Sobrien} 50498944Sobrien 50598944Sobrienllvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) { 50698944Sobrien assert(MD->isInstance() && "Member function must not be static!"); 50798944Sobrien MD = MD->getCanonicalDecl(); 50898944Sobrien 50998944Sobrien CodeGenTypes &Types = CGM.getTypes(); 51098944Sobrien const llvm::Type *ptrdiff_t = getPtrDiffTy(); 51198944Sobrien 51298944Sobrien // Get the function pointer (or index if this is a virtual function). 51398944Sobrien llvm::Constant *MemPtr[2]; 51498944Sobrien if (MD->isVirtual()) { 51598944Sobrien uint64_t Index = CGM.getVTables().getMethodVTableIndex(MD); 516130803Smarcel 517130803Smarcel const ASTContext &Context = getContext(); 518130803Smarcel CharUnits PointerWidth = 519130803Smarcel Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0)); 520130803Smarcel uint64_t VTableOffset = (Index * PointerWidth.getQuantity()); 521130803Smarcel 522130803Smarcel if (IsARM) { 523130803Smarcel // ARM C++ ABI 3.2.1: 524130803Smarcel // This ABI specifies that adj contains twice the this 525130803Smarcel // adjustment, plus 1 if the member function is virtual. The 526130803Smarcel // least significant bit of adj then makes exactly the same 527130803Smarcel // discrimination as the least significant bit of ptr does for 528130803Smarcel // Itanium. 529130803Smarcel MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset); 530130803Smarcel MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 1); 531130803Smarcel } else { 532130803Smarcel // Itanium C++ ABI 2.3: 533130803Smarcel // For a virtual function, [the pointer field] is 1 plus the 534130803Smarcel // virtual table offset (in bytes) of the function, 535130803Smarcel // represented as a ptrdiff_t. 536130803Smarcel MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset + 1); 537130803Smarcel MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0); 53898944Sobrien } 53998944Sobrien } else { 54098944Sobrien const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); 54198944Sobrien const llvm::Type *Ty; 54298944Sobrien // Check whether the function has a computable LLVM signature. 54398944Sobrien if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) { 54498944Sobrien // The function has a computable LLVM signature; use the correct type. 54598944Sobrien Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), 54698944Sobrien FPT->isVariadic()); 54798944Sobrien } else { 54898944Sobrien // Use an arbitrary non-function type to tell GetAddrOfFunction that the 54998944Sobrien // function type is incomplete. 55098944Sobrien Ty = ptrdiff_t; 55198944Sobrien } 55298944Sobrien llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty); 55398944Sobrien 55498944Sobrien MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, ptrdiff_t); 55598944Sobrien MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0); 55698944Sobrien } 55798944Sobrien 55898944Sobrien return llvm::ConstantStruct::get(CGM.getLLVMContext(), 55998944Sobrien MemPtr, 2, /*Packed=*/false); 56098944Sobrien} 56198944Sobrien 562130803Smarcel/// The comparison algorithm is pretty easy: the member pointers are 56398944Sobrien/// the same if they're either bitwise identical *or* both null. 56498944Sobrien/// 56598944Sobrien/// ARM is different here only because null-ness is more complicated. 56698944Sobrienllvm::Value * 56798944SobrienItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, 56898944Sobrien llvm::Value *L, 56998944Sobrien llvm::Value *R, 57098944Sobrien const MemberPointerType *MPT, 57198944Sobrien bool Inequality) { 57298944Sobrien CGBuilderTy &Builder = CGF.Builder; 573130803Smarcel 57498944Sobrien llvm::ICmpInst::Predicate Eq; 57598944Sobrien llvm::Instruction::BinaryOps And, Or; 57698944Sobrien if (Inequality) { 57798944Sobrien Eq = llvm::ICmpInst::ICMP_NE; 57898944Sobrien And = llvm::Instruction::Or; 57998944Sobrien Or = llvm::Instruction::And; 58098944Sobrien } else { 58198944Sobrien Eq = llvm::ICmpInst::ICMP_EQ; 58298944Sobrien And = llvm::Instruction::And; 58398944Sobrien Or = llvm::Instruction::Or; 58498944Sobrien } 58598944Sobrien 58698944Sobrien // Member data pointers are easy because there's a unique null 58798944Sobrien // value, so it just comes down to bitwise equality. 58898944Sobrien if (MPT->isMemberDataPointer()) 58998944Sobrien return Builder.CreateICmp(Eq, L, R); 59098944Sobrien 59198944Sobrien // For member function pointers, the tautologies are more complex. 59298944Sobrien // The Itanium tautology is: 59398944Sobrien // (L == R) <==> (L.ptr == R.ptr && (L.ptr == 0 || L.adj == R.adj)) 59498944Sobrien // The ARM tautology is: 59598944Sobrien // (L == R) <==> (L.ptr == R.ptr && 59698944Sobrien // (L.adj == R.adj || 59798944Sobrien // (L.ptr == 0 && ((L.adj|R.adj) & 1) == 0))) 59898944Sobrien // The inequality tautologies have exactly the same structure, except 59998944Sobrien // applying De Morgan's laws. 60098944Sobrien 60198944Sobrien llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr"); 60298944Sobrien llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr"); 60398944Sobrien 60498944Sobrien // This condition tests whether L.ptr == R.ptr. This must always be 60598944Sobrien // true for equality to hold. 60698944Sobrien llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr"); 60798944Sobrien 60898944Sobrien // This condition, together with the assumption that L.ptr == R.ptr, 60998944Sobrien // tests whether the pointers are both null. ARM imposes an extra 610130803Smarcel // condition. 61198944Sobrien llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType()); 61298944Sobrien llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null"); 61398944Sobrien 61498944Sobrien // This condition tests whether L.adj == R.adj. If this isn't 61598944Sobrien // true, the pointers are unequal unless they're both null. 61698944Sobrien llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj"); 61798944Sobrien llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj"); 61898944Sobrien llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj"); 61998944Sobrien 62098944Sobrien // Null member function pointers on ARM clear the low bit of Adj, 62198944Sobrien // so the zero condition has to check that neither low bit is set. 62298944Sobrien if (IsARM) { 62398944Sobrien llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1); 62498944Sobrien 62598944Sobrien // Compute (l.adj | r.adj) & 1 and test it against zero. 62698944Sobrien llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj"); 62798944Sobrien llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One); 62898944Sobrien llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero, 62998944Sobrien "cmp.or.adj"); 63098944Sobrien EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero); 63198944Sobrien } 63298944Sobrien 63398944Sobrien // Tie together all our conditions. 63498944Sobrien llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq); 63598944Sobrien Result = Builder.CreateBinOp(And, PtrEq, Result, 63698944Sobrien Inequality ? "memptr.ne" : "memptr.eq"); 63798944Sobrien return Result; 63898944Sobrien} 63998944Sobrien 64098944Sobrienllvm::Value * 64198944SobrienItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, 64298944Sobrien llvm::Value *MemPtr, 64398944Sobrien const MemberPointerType *MPT) { 64498944Sobrien CGBuilderTy &Builder = CGF.Builder; 64598944Sobrien 64698944Sobrien /// For member data pointers, this is just a check against -1. 64798944Sobrien if (MPT->isMemberDataPointer()) { 64898944Sobrien assert(MemPtr->getType() == getPtrDiffTy()); 64998944Sobrien llvm::Value *NegativeOne = 65098944Sobrien llvm::Constant::getAllOnesValue(MemPtr->getType()); 65198944Sobrien return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool"); 65298944Sobrien } 65398944Sobrien 65498944Sobrien // In Itanium, a member function pointer is not null if 'ptr' is not null. 65598944Sobrien llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr"); 656130803Smarcel 65798944Sobrien llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0); 65898944Sobrien llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool"); 659130803Smarcel 660130803Smarcel // On ARM, a member function pointer is also non-null if the low bit of 'adj' 66198944Sobrien // (the virtual bit) is set. 66298944Sobrien if (IsARM) { 66398944Sobrien llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1); 66498944Sobrien llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj"); 66598944Sobrien llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit"); 66698944Sobrien llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero, 66798944Sobrien "memptr.isvirtual"); 66898944Sobrien Result = Builder.CreateOr(Result, IsVirtual); 66998944Sobrien } 67098944Sobrien 67198944Sobrien return Result; 672130803Smarcel} 673130803Smarcel 674130803Smarcel/// The Itanium ABI requires non-zero initialization only for data 675130803Smarcel/// member pointers, for which '0' is a valid offset. 676130803Smarcelbool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) { 677130803Smarcel return MPT->getPointeeType()->isFunctionType(); 678130803Smarcel} 679130803Smarcel 680130803Smarcel/// The generic ABI passes 'this', plus a VTT if it's initializing a 681130803Smarcel/// base subobject. 682130803Smarcelvoid ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, 683130803Smarcel CXXCtorType Type, 68498944Sobrien CanQualType &ResTy, 68598944Sobrien llvm::SmallVectorImpl<CanQualType> &ArgTys) { 68698944Sobrien ASTContext &Context = getContext(); 68798944Sobrien 688130803Smarcel // 'this' is already there. 68998944Sobrien 69098944Sobrien // Check if we need to add a VTT parameter (which has type void **). 69198944Sobrien if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0) 69298944Sobrien ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); 69398944Sobrien} 69498944Sobrien 69598944Sobrien/// The ARM ABI does the same as the Itanium ABI, but returns 'this'. 69698944Sobrienvoid ARMCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, 69798944Sobrien CXXCtorType Type, 69898944Sobrien CanQualType &ResTy, 69998944Sobrien llvm::SmallVectorImpl<CanQualType> &ArgTys) { 70098944Sobrien ItaniumCXXABI::BuildConstructorSignature(Ctor, Type, ResTy, ArgTys); 70198944Sobrien ResTy = ArgTys[0]; 70298944Sobrien} 70398944Sobrien 70498944Sobrien/// The generic ABI passes 'this', plus a VTT if it's destroying a 70598944Sobrien/// base subobject. 70698944Sobrienvoid ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, 70798944Sobrien CXXDtorType Type, 70898944Sobrien CanQualType &ResTy, 70998944Sobrien llvm::SmallVectorImpl<CanQualType> &ArgTys) { 71098944Sobrien ASTContext &Context = getContext(); 71198944Sobrien 71298944Sobrien // 'this' is already there. 71398944Sobrien 71498944Sobrien // Check if we need to add a VTT parameter (which has type void **). 71598944Sobrien if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0) 71698944Sobrien ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); 71798944Sobrien} 71898944Sobrien 71998944Sobrien/// The ARM ABI does the same as the Itanium ABI, but returns 'this' 72098944Sobrien/// for non-deleting destructors. 72198944Sobrienvoid ARMCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, 72298944Sobrien CXXDtorType Type, 72398944Sobrien CanQualType &ResTy, 72498944Sobrien llvm::SmallVectorImpl<CanQualType> &ArgTys) { 725130803Smarcel ItaniumCXXABI::BuildDestructorSignature(Dtor, Type, ResTy, ArgTys); 726130803Smarcel 727130803Smarcel if (Type != Dtor_Deleting) 72898944Sobrien ResTy = ArgTys[0]; 72998944Sobrien} 73098944Sobrien 73198944Sobrienvoid ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, 73298944Sobrien QualType &ResTy, 73398944Sobrien FunctionArgList &Params) { 73498944Sobrien /// Create the 'this' variable. 73598944Sobrien BuildThisParam(CGF, Params); 73698944Sobrien 73798944Sobrien const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); 73898944Sobrien assert(MD->isInstance()); 73998944Sobrien 74098944Sobrien // Check if we need a VTT parameter as well. 74198944Sobrien if (CodeGenVTables::needsVTTParameter(CGF.CurGD)) { 74298944Sobrien ASTContext &Context = getContext(); 74398944Sobrien 74498944Sobrien // FIXME: avoid the fake decl 74598944Sobrien QualType T = Context.getPointerType(Context.VoidPtrTy); 74698944Sobrien ImplicitParamDecl *VTTDecl 74798944Sobrien = ImplicitParamDecl::Create(Context, 0, MD->getLocation(), 74898944Sobrien &Context.Idents.get("vtt"), T); 74998944Sobrien Params.push_back(VTTDecl); 75098944Sobrien getVTTDecl(CGF) = VTTDecl; 75198944Sobrien } 75298944Sobrien} 75398944Sobrien 75498944Sobrienvoid ARMCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, 75598944Sobrien QualType &ResTy, 75698944Sobrien FunctionArgList &Params) { 75798944Sobrien ItaniumCXXABI::BuildInstanceFunctionParams(CGF, ResTy, Params); 75898944Sobrien 75998944Sobrien // Return 'this' from certain constructors and destructors. 76098944Sobrien if (HasThisReturn(CGF.CurGD)) 76198944Sobrien ResTy = Params[0]->getType(); 76298944Sobrien} 76398944Sobrien 76498944Sobrienvoid ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { 76598944Sobrien /// Initialize the 'this' slot. 76698944Sobrien EmitThisParam(CGF); 767130803Smarcel 768130803Smarcel /// Initialize the 'vtt' slot if needed. 76998944Sobrien if (getVTTDecl(CGF)) { 77098944Sobrien getVTTValue(CGF) 77198944Sobrien = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)), 77298944Sobrien "vtt"); 77398944Sobrien } 774130803Smarcel} 775130803Smarcel 77698944Sobrienvoid ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { 77798944Sobrien ItaniumCXXABI::EmitInstanceFunctionProlog(CGF); 778130803Smarcel 779130803Smarcel /// Initialize the return slot to 'this' at the start of the 780130803Smarcel /// function. 78198944Sobrien if (HasThisReturn(CGF.CurGD)) 78298944Sobrien CGF.Builder.CreateStore(CGF.LoadCXXThis(), CGF.ReturnValue); 78398944Sobrien} 78498944Sobrien 78598944Sobrienvoid ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, 78698944Sobrien RValue RV, QualType ResultType) { 78798944Sobrien if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl())) 78898944Sobrien return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType); 78998944Sobrien 79098944Sobrien // Destructor thunks in the ARM ABI have indeterminate results. 79198944Sobrien const llvm::Type *T = 79298944Sobrien cast<llvm::PointerType>(CGF.ReturnValue->getType())->getElementType(); 79398944Sobrien RValue Undef = RValue::get(llvm::UndefValue::get(T)); 79498944Sobrien return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType); 79598944Sobrien} 79698944Sobrien 79798944Sobrien/************************** Array allocation cookies **************************/ 79898944Sobrien 79998944Sobrienbool ItaniumCXXABI::NeedsArrayCookie(const CXXNewExpr *expr) { 80098944Sobrien // If the class's usual deallocation function takes two arguments, 80198944Sobrien // it needs a cookie. 80298944Sobrien if (expr->doesUsualArrayDeleteWantSize()) 80398944Sobrien return true; 80498944Sobrien 80598944Sobrien // Otherwise, if the class has a non-trivial destructor, it always 80698944Sobrien // needs a cookie. 80798944Sobrien const CXXRecordDecl *record = 80898944Sobrien expr->getAllocatedType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); 80998944Sobrien return (record && !record->hasTrivialDestructor()); 81098944Sobrien} 81198944Sobrien 81298944Sobrienbool ItaniumCXXABI::NeedsArrayCookie(const CXXDeleteExpr *expr, 81398944Sobrien QualType elementType) { 81498944Sobrien // If the class's usual deallocation function takes two arguments, 81598944Sobrien // it needs a cookie. 81698944Sobrien if (expr->doesUsualArrayDeleteWantSize()) 81798944Sobrien return true; 81898944Sobrien 81998944Sobrien // Otherwise, if the class has a non-trivial destructor, it always 82098944Sobrien // needs a cookie. 82198944Sobrien const CXXRecordDecl *record = 82298944Sobrien elementType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); 82398944Sobrien return (record && !record->hasTrivialDestructor()); 82498944Sobrien} 82598944Sobrien 82698944SobrienCharUnits ItaniumCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { 82798944Sobrien if (!NeedsArrayCookie(expr)) 82898944Sobrien return CharUnits::Zero(); 82998944Sobrien 83098944Sobrien // Padding is the maximum of sizeof(size_t) and alignof(elementType) 83198944Sobrien ASTContext &Ctx = getContext(); 83298944Sobrien return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()), 83398944Sobrien Ctx.getTypeAlignInChars(expr->getAllocatedType())); 83498944Sobrien} 83598944Sobrien 83698944Sobrienllvm::Value *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 83798944Sobrien llvm::Value *NewPtr, 83898944Sobrien llvm::Value *NumElements, 83998944Sobrien const CXXNewExpr *expr, 84098944Sobrien QualType ElementType) { 84198944Sobrien assert(NeedsArrayCookie(expr)); 84298944Sobrien 84398944Sobrien unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace(); 84498944Sobrien 84598944Sobrien ASTContext &Ctx = getContext(); 84698944Sobrien QualType SizeTy = Ctx.getSizeType(); 84798944Sobrien CharUnits SizeSize = Ctx.getTypeSizeInChars(SizeTy); 84898944Sobrien 84998944Sobrien // The size of the cookie. 85098944Sobrien CharUnits CookieSize = 85198944Sobrien std::max(SizeSize, Ctx.getTypeAlignInChars(ElementType)); 85298944Sobrien 85398944Sobrien // Compute an offset to the cookie. 85498944Sobrien llvm::Value *CookiePtr = NewPtr; 85598944Sobrien CharUnits CookieOffset = CookieSize - SizeSize; 85698944Sobrien if (!CookieOffset.isZero()) 85798944Sobrien CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_64(CookiePtr, 85898944Sobrien CookieOffset.getQuantity()); 85998944Sobrien 86098944Sobrien // Write the number of elements into the appropriate slot. 86198944Sobrien llvm::Value *NumElementsPtr 86298944Sobrien = CGF.Builder.CreateBitCast(CookiePtr, 86398944Sobrien CGF.ConvertType(SizeTy)->getPointerTo(AS)); 86498944Sobrien CGF.Builder.CreateStore(NumElements, NumElementsPtr); 86598944Sobrien 86698944Sobrien // Finally, compute a pointer to the actual data buffer by skipping 86798944Sobrien // over the cookie completely. 86898944Sobrien return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr, 86998944Sobrien CookieSize.getQuantity()); 87098944Sobrien} 87198944Sobrien 87298944Sobrienvoid ItaniumCXXABI::ReadArrayCookie(CodeGenFunction &CGF, 87398944Sobrien llvm::Value *Ptr, 87498944Sobrien const CXXDeleteExpr *expr, 87598944Sobrien QualType ElementType, 87698944Sobrien llvm::Value *&NumElements, 87798944Sobrien llvm::Value *&AllocPtr, 87898944Sobrien CharUnits &CookieSize) { 87998944Sobrien // Derive a char* in the same address space as the pointer. 88098944Sobrien unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace(); 88198944Sobrien const llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS); 88298944Sobrien 88398944Sobrien // If we don't need an array cookie, bail out early. 88498944Sobrien if (!NeedsArrayCookie(expr, ElementType)) { 88598944Sobrien AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 88698944Sobrien NumElements = 0; 88798944Sobrien CookieSize = CharUnits::Zero(); 88898944Sobrien return; 88998944Sobrien } 89098944Sobrien 89198944Sobrien QualType SizeTy = getContext().getSizeType(); 89298944Sobrien CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy); 89398944Sobrien const llvm::Type *SizeLTy = CGF.ConvertType(SizeTy); 89498944Sobrien 89598944Sobrien CookieSize 89698944Sobrien = std::max(SizeSize, getContext().getTypeAlignInChars(ElementType)); 89798944Sobrien 89898944Sobrien CharUnits NumElementsOffset = CookieSize - SizeSize; 89998944Sobrien 90098944Sobrien // Compute the allocated pointer. 90198944Sobrien AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 90298944Sobrien AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr, 90398944Sobrien -CookieSize.getQuantity()); 90498944Sobrien 90598944Sobrien llvm::Value *NumElementsPtr = AllocPtr; 90698944Sobrien if (!NumElementsOffset.isZero()) 90798944Sobrien NumElementsPtr = 90898944Sobrien CGF.Builder.CreateConstInBoundsGEP1_64(NumElementsPtr, 90998944Sobrien NumElementsOffset.getQuantity()); 91098944Sobrien NumElementsPtr = 91198944Sobrien CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS)); 91298944Sobrien NumElements = CGF.Builder.CreateLoad(NumElementsPtr); 91398944Sobrien} 91498944Sobrien 91598944SobrienCharUnits ARMCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { 91698944Sobrien if (!NeedsArrayCookie(expr)) 91798944Sobrien return CharUnits::Zero(); 91898944Sobrien 91998944Sobrien // On ARM, the cookie is always: 92098944Sobrien // struct array_cookie { 92198944Sobrien // std::size_t element_size; // element_size != 0 92298944Sobrien // std::size_t element_count; 92398944Sobrien // }; 92498944Sobrien // TODO: what should we do if the allocated type actually wants 92598944Sobrien // greater alignment? 92698944Sobrien return getContext().getTypeSizeInChars(getContext().getSizeType()) * 2; 92798944Sobrien} 92898944Sobrien 92998944Sobrienllvm::Value *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 93098944Sobrien llvm::Value *NewPtr, 93198944Sobrien llvm::Value *NumElements, 93298944Sobrien const CXXNewExpr *expr, 93398944Sobrien QualType ElementType) { 93498944Sobrien assert(NeedsArrayCookie(expr)); 93598944Sobrien 93698944Sobrien // NewPtr is a char*. 93798944Sobrien 93898944Sobrien unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace(); 93998944Sobrien 94098944Sobrien ASTContext &Ctx = getContext(); 94198944Sobrien CharUnits SizeSize = Ctx.getTypeSizeInChars(Ctx.getSizeType()); 94298944Sobrien const llvm::IntegerType *SizeTy = 94398944Sobrien cast<llvm::IntegerType>(CGF.ConvertType(Ctx.getSizeType())); 94498944Sobrien 94598944Sobrien // The cookie is always at the start of the buffer. 94698944Sobrien llvm::Value *CookiePtr = NewPtr; 94798944Sobrien 94898944Sobrien // The first element is the element size. 94998944Sobrien CookiePtr = CGF.Builder.CreateBitCast(CookiePtr, SizeTy->getPointerTo(AS)); 95098944Sobrien llvm::Value *ElementSize = llvm::ConstantInt::get(SizeTy, 95198944Sobrien Ctx.getTypeSizeInChars(ElementType).getQuantity()); 95298944Sobrien CGF.Builder.CreateStore(ElementSize, CookiePtr); 95398944Sobrien 95498944Sobrien // The second element is the element count. 95598944Sobrien CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_32(CookiePtr, 1); 95698944Sobrien CGF.Builder.CreateStore(NumElements, CookiePtr); 95798944Sobrien 95898944Sobrien // Finally, compute a pointer to the actual data buffer by skipping 95998944Sobrien // over the cookie completely. 96098944Sobrien CharUnits CookieSize = 2 * SizeSize; 96198944Sobrien return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr, 96298944Sobrien CookieSize.getQuantity()); 96398944Sobrien} 96498944Sobrien 96598944Sobrienvoid ARMCXXABI::ReadArrayCookie(CodeGenFunction &CGF, 96698944Sobrien llvm::Value *Ptr, 96798944Sobrien const CXXDeleteExpr *expr, 96898944Sobrien QualType ElementType, 96998944Sobrien llvm::Value *&NumElements, 97098944Sobrien llvm::Value *&AllocPtr, 97198944Sobrien CharUnits &CookieSize) { 97298944Sobrien // Derive a char* in the same address space as the pointer. 97398944Sobrien unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace(); 97498944Sobrien const llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS); 97598944Sobrien 97698944Sobrien // If we don't need an array cookie, bail out early. 97798944Sobrien if (!NeedsArrayCookie(expr, ElementType)) { 97898944Sobrien AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 97998944Sobrien NumElements = 0; 98098944Sobrien CookieSize = CharUnits::Zero(); 98198944Sobrien return; 98298944Sobrien } 98398944Sobrien 98498944Sobrien QualType SizeTy = getContext().getSizeType(); 98598944Sobrien CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy); 986130803Smarcel const llvm::Type *SizeLTy = CGF.ConvertType(SizeTy); 987130803Smarcel 988130803Smarcel // The cookie size is always 2 * sizeof(size_t). 989130803Smarcel CookieSize = 2 * SizeSize; 990130803Smarcel 991130803Smarcel // The allocated pointer is the input ptr, minus that amount. 992130803Smarcel AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 993130803Smarcel AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr, 994130803Smarcel -CookieSize.getQuantity()); 995130803Smarcel 996130803Smarcel // The number of elements is at offset sizeof(size_t) relative to that. 997130803Smarcel llvm::Value *NumElementsPtr 998130803Smarcel = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr, 999130803Smarcel SizeSize.getQuantity()); 1000130803Smarcel NumElementsPtr = 1001130803Smarcel CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS)); 1002130803Smarcel NumElements = CGF.Builder.CreateLoad(NumElementsPtr); 1003130803Smarcel} 1004130803Smarcel 1005130803Smarcel/*********************** Static local initialization **************************/ 1006130803Smarcel 1007130803Smarcelstatic llvm::Constant *getGuardAcquireFn(CodeGenModule &CGM, 1008130803Smarcel const llvm::PointerType *GuardPtrTy) { 1009130803Smarcel // int __cxa_guard_acquire(__guard *guard_object); 1010130803Smarcel 1011130803Smarcel std::vector<const llvm::Type*> Args(1, GuardPtrTy); 1012130803Smarcel const llvm::FunctionType *FTy = 1013130803Smarcel llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy), 1014130803Smarcel Args, /*isVarArg=*/false); 1015130803Smarcel 1016130803Smarcel return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire"); 1017130803Smarcel} 101898944Sobrien 101998944Sobrienstatic llvm::Constant *getGuardReleaseFn(CodeGenModule &CGM, 102098944Sobrien const llvm::PointerType *GuardPtrTy) { 102198944Sobrien // void __cxa_guard_release(__guard *guard_object); 102298944Sobrien 102398944Sobrien std::vector<const llvm::Type*> Args(1, GuardPtrTy); 102498944Sobrien 102598944Sobrien const llvm::FunctionType *FTy = 102698944Sobrien llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), 102798944Sobrien Args, /*isVarArg=*/false); 102898944Sobrien 102998944Sobrien return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release"); 103098944Sobrien} 103198944Sobrien 103298944Sobrienstatic llvm::Constant *getGuardAbortFn(CodeGenModule &CGM, 103398944Sobrien const llvm::PointerType *GuardPtrTy) { 103498944Sobrien // void __cxa_guard_abort(__guard *guard_object); 103598944Sobrien 103698944Sobrien std::vector<const llvm::Type*> Args(1, GuardPtrTy); 103798944Sobrien 103898944Sobrien const llvm::FunctionType *FTy = 103998944Sobrien llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), 104098944Sobrien Args, /*isVarArg=*/false); 104198944Sobrien 104298944Sobrien return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort"); 104398944Sobrien} 1044130803Smarcel 1045130803Smarcelnamespace { 104698944Sobrien struct CallGuardAbort : EHScopeStack::Cleanup { 104798944Sobrien llvm::GlobalVariable *Guard; 104898944Sobrien CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {} 104998944Sobrien 105098944Sobrien void Emit(CodeGenFunction &CGF, bool IsForEH) { 105198944Sobrien CGF.Builder.CreateCall(getGuardAbortFn(CGF.CGM, Guard->getType()), Guard) 105298944Sobrien ->setDoesNotThrow(); 105398944Sobrien } 105498944Sobrien }; 105598944Sobrien} 105698944Sobrien 105798944Sobrien/// The ARM code here follows the Itanium code closely enough that we 105898944Sobrien/// just special-case it at particular places. 105998944Sobrienvoid ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, 106098944Sobrien const VarDecl &D, 106198944Sobrien llvm::GlobalVariable *GV) { 106298944Sobrien CGBuilderTy &Builder = CGF.Builder; 106398944Sobrien 106498944Sobrien // We only need to use thread-safe statics for local variables; 106598944Sobrien // global initialization is always single-threaded. 106698944Sobrien bool ThreadsafeStatics = (getContext().getLangOptions().ThreadsafeStatics && 106798944Sobrien D.isLocalVarDecl()); 106898944Sobrien 106998944Sobrien const llvm::IntegerType *GuardTy; 107098944Sobrien 107198944Sobrien // If we have a global variable with internal linkage and thread-safe statics 107298944Sobrien // are disabled, we can just let the guard variable be of type i8. 107398944Sobrien bool UseInt8GuardVariable = !ThreadsafeStatics && GV->hasInternalLinkage(); 107498944Sobrien if (UseInt8GuardVariable) 107598944Sobrien GuardTy = Builder.getInt8Ty(); 107698944Sobrien else { 107798944Sobrien // Guard variables are 64 bits in the generic ABI and 32 bits on ARM. 107898944Sobrien GuardTy = (IsARM ? Builder.getInt32Ty() : Builder.getInt64Ty()); 107998944Sobrien } 108098944Sobrien const llvm::PointerType *GuardPtrTy = GuardTy->getPointerTo(); 108198944Sobrien 108298944Sobrien // Create the guard variable. 108398944Sobrien llvm::SmallString<256> GuardVName; 1084130803Smarcel llvm::raw_svector_ostream Out(GuardVName); 1085130803Smarcel getMangleContext().mangleItaniumGuardVariable(&D, Out); 108698944Sobrien Out.flush(); 108798944Sobrien 108898944Sobrien // Just absorb linkage and visibility from the variable. 108998944Sobrien llvm::GlobalVariable *GuardVariable = 109098944Sobrien new llvm::GlobalVariable(CGM.getModule(), GuardTy, 109198944Sobrien false, GV->getLinkage(), 109298944Sobrien llvm::ConstantInt::get(GuardTy, 0), 109398944Sobrien GuardVName.str()); 109498944Sobrien GuardVariable->setVisibility(GV->getVisibility()); 109598944Sobrien 109698944Sobrien // Test whether the variable has completed initialization. 109798944Sobrien llvm::Value *IsInitialized; 109898944Sobrien 109998944Sobrien // ARM C++ ABI 3.2.3.1: 110098944Sobrien // To support the potential use of initialization guard variables 110198944Sobrien // as semaphores that are the target of ARM SWP and LDREX/STREX 110298944Sobrien // synchronizing instructions we define a static initialization 110398944Sobrien // guard variable to be a 4-byte aligned, 4- byte word with the 110498944Sobrien // following inline access protocol. 110598944Sobrien // #define INITIALIZED 1 110698944Sobrien // if ((obj_guard & INITIALIZED) != INITIALIZED) { 110798944Sobrien // if (__cxa_guard_acquire(&obj_guard)) 110898944Sobrien // ... 110998944Sobrien // } 111098944Sobrien if (IsARM && !UseInt8GuardVariable) { 111198944Sobrien llvm::Value *V = Builder.CreateLoad(GuardVariable); 111298944Sobrien V = Builder.CreateAnd(V, Builder.getInt32(1)); 111398944Sobrien IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized"); 111498944Sobrien 111598944Sobrien // Itanium C++ ABI 3.3.2: 111698944Sobrien // The following is pseudo-code showing how these functions can be used: 111798944Sobrien // if (obj_guard.first_byte == 0) { 111898944Sobrien // if ( __cxa_guard_acquire (&obj_guard) ) { 111998944Sobrien // try { 112098944Sobrien // ... initialize the object ...; 112198944Sobrien // } catch (...) { 112298944Sobrien // __cxa_guard_abort (&obj_guard); 112398944Sobrien // throw; 112498944Sobrien // } 112598944Sobrien // ... queue object destructor with __cxa_atexit() ...; 112698944Sobrien // __cxa_guard_release (&obj_guard); 112798944Sobrien // } 112898944Sobrien // } 112998944Sobrien } else { 113098944Sobrien // Load the first byte of the guard variable. 113198944Sobrien const llvm::Type *PtrTy = Builder.getInt8PtrTy(); 113298944Sobrien llvm::Value *V = 113398944Sobrien Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp"); 113498944Sobrien 113598944Sobrien IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized"); 113698944Sobrien } 113798944Sobrien 113898944Sobrien llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check"); 113998944Sobrien llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end"); 114098944Sobrien 114198944Sobrien // Check if the first byte of the guard variable is zero. 114298944Sobrien Builder.CreateCondBr(IsInitialized, InitCheckBlock, EndBlock); 114398944Sobrien 114498944Sobrien CGF.EmitBlock(InitCheckBlock); 114598944Sobrien 114698944Sobrien // Variables used when coping with thread-safe statics and exceptions. 114798944Sobrien if (ThreadsafeStatics) { 114898944Sobrien // Call __cxa_guard_acquire. 114998944Sobrien llvm::Value *V 115098944Sobrien = Builder.CreateCall(getGuardAcquireFn(CGM, GuardPtrTy), GuardVariable); 115198944Sobrien 115298944Sobrien llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); 115398944Sobrien 115498944Sobrien Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), 115598944Sobrien InitBlock, EndBlock); 115698944Sobrien 115798944Sobrien // Call __cxa_guard_abort along the exceptional edge. 115898944Sobrien CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable); 115998944Sobrien 116098944Sobrien CGF.EmitBlock(InitBlock); 116198944Sobrien } 116298944Sobrien 116398944Sobrien // Emit the initializer and add a global destructor if appropriate. 116498944Sobrien CGF.EmitCXXGlobalVarDeclInit(D, GV); 116598944Sobrien 116698944Sobrien if (ThreadsafeStatics) { 116798944Sobrien // Pop the guard-abort cleanup if we pushed one. 116898944Sobrien CGF.PopCleanupBlock(); 116998944Sobrien 117098944Sobrien // Call __cxa_guard_release. This cannot throw. 117198944Sobrien Builder.CreateCall(getGuardReleaseFn(CGM, GuardPtrTy), GuardVariable); 117298944Sobrien } else { 117398944Sobrien Builder.CreateStore(llvm::ConstantInt::get(GuardTy, 1), GuardVariable); 117498944Sobrien } 117598944Sobrien 117698944Sobrien CGF.EmitBlock(EndBlock); 117798944Sobrien} 117898944Sobrien