ItaniumCXXABI.cpp revision 226633
1208600Srdivacky//===------- ItaniumCXXABI.cpp - Emit LLVM Code from ASTs for a Module ----===// 2208600Srdivacky// 3208600Srdivacky// The LLVM Compiler Infrastructure 4208600Srdivacky// 5208600Srdivacky// This file is distributed under the University of Illinois Open Source 6208600Srdivacky// License. See LICENSE.TXT for details. 7208600Srdivacky// 8208600Srdivacky//===----------------------------------------------------------------------===// 9208600Srdivacky// 10221345Sdim// This provides C++ code generation targeting the Itanium C++ ABI. The class 11208600Srdivacky// in this file generates structures that follow the Itanium C++ ABI, which is 12208600Srdivacky// documented at: 13208600Srdivacky// http://www.codesourcery.com/public/cxx-abi/abi.html 14208600Srdivacky// http://www.codesourcery.com/public/cxx-abi/abi-eh.html 15212904Sdim// 16212904Sdim// It also supports the closely-related ARM ABI, documented at: 17212904Sdim// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf 18212904Sdim// 19208600Srdivacky//===----------------------------------------------------------------------===// 20208600Srdivacky 21208600Srdivacky#include "CGCXXABI.h" 22212904Sdim#include "CGRecordLayout.h" 23212904Sdim#include "CodeGenFunction.h" 24208600Srdivacky#include "CodeGenModule.h" 25218893Sdim#include <clang/AST/Mangle.h> 26212904Sdim#include <clang/AST/Type.h> 27224145Sdim#include <llvm/Intrinsics.h> 28212904Sdim#include <llvm/Target/TargetData.h> 29212904Sdim#include <llvm/Value.h> 30208600Srdivacky 31208600Srdivackyusing namespace clang; 32212904Sdimusing namespace CodeGen; 33208600Srdivacky 34208600Srdivackynamespace { 35212904Sdimclass ItaniumCXXABI : public CodeGen::CGCXXABI { 36212904Sdimprivate: 37224145Sdim llvm::IntegerType *PtrDiffTy; 38212904Sdimprotected: 39212904Sdim bool IsARM; 40212904Sdim 41212904Sdim // It's a little silly for us to cache this. 42224145Sdim llvm::IntegerType *getPtrDiffTy() { 43212904Sdim if (!PtrDiffTy) { 44212904Sdim QualType T = getContext().getPointerDiffType(); 45224145Sdim llvm::Type *Ty = CGM.getTypes().ConvertType(T); 46212904Sdim PtrDiffTy = cast<llvm::IntegerType>(Ty); 47212904Sdim } 48212904Sdim return PtrDiffTy; 49212904Sdim } 50212904Sdim 51218893Sdim bool NeedsArrayCookie(const CXXNewExpr *expr); 52218893Sdim bool NeedsArrayCookie(const CXXDeleteExpr *expr, 53218893Sdim QualType elementType); 54212904Sdim 55208600Srdivackypublic: 56212904Sdim ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool IsARM = false) : 57218893Sdim CGCXXABI(CGM), PtrDiffTy(0), IsARM(IsARM) { } 58208600Srdivacky 59212904Sdim bool isZeroInitializable(const MemberPointerType *MPT); 60212904Sdim 61224145Sdim llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT); 62212904Sdim 63212904Sdim llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, 64212904Sdim llvm::Value *&This, 65212904Sdim llvm::Value *MemFnPtr, 66212904Sdim const MemberPointerType *MPT); 67212904Sdim 68212904Sdim llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF, 69212904Sdim llvm::Value *Base, 70212904Sdim llvm::Value *MemPtr, 71212904Sdim const MemberPointerType *MPT); 72212904Sdim 73212904Sdim llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF, 74212904Sdim const CastExpr *E, 75212904Sdim llvm::Value *Src); 76212904Sdim 77212904Sdim llvm::Constant *EmitMemberPointerConversion(llvm::Constant *C, 78212904Sdim const CastExpr *E); 79212904Sdim 80212904Sdim llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT); 81212904Sdim 82212904Sdim llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD); 83218893Sdim llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, 84218893Sdim CharUnits offset); 85212904Sdim 86212904Sdim llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF, 87212904Sdim llvm::Value *L, 88212904Sdim llvm::Value *R, 89212904Sdim const MemberPointerType *MPT, 90212904Sdim bool Inequality); 91212904Sdim 92212904Sdim llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF, 93212904Sdim llvm::Value *Addr, 94212904Sdim const MemberPointerType *MPT); 95212904Sdim 96212904Sdim void BuildConstructorSignature(const CXXConstructorDecl *Ctor, 97212904Sdim CXXCtorType T, 98212904Sdim CanQualType &ResTy, 99226633Sdim SmallVectorImpl<CanQualType> &ArgTys); 100212904Sdim 101212904Sdim void BuildDestructorSignature(const CXXDestructorDecl *Dtor, 102212904Sdim CXXDtorType T, 103212904Sdim CanQualType &ResTy, 104226633Sdim SmallVectorImpl<CanQualType> &ArgTys); 105212904Sdim 106212904Sdim void BuildInstanceFunctionParams(CodeGenFunction &CGF, 107212904Sdim QualType &ResTy, 108212904Sdim FunctionArgList &Params); 109212904Sdim 110212904Sdim void EmitInstanceFunctionProlog(CodeGenFunction &CGF); 111212904Sdim 112218893Sdim CharUnits GetArrayCookieSize(const CXXNewExpr *expr); 113212904Sdim llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF, 114212904Sdim llvm::Value *NewPtr, 115212904Sdim llvm::Value *NumElements, 116218893Sdim const CXXNewExpr *expr, 117212904Sdim QualType ElementType); 118212904Sdim void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr, 119218893Sdim const CXXDeleteExpr *expr, 120212904Sdim QualType ElementType, llvm::Value *&NumElements, 121212904Sdim llvm::Value *&AllocPtr, CharUnits &CookieSize); 122218893Sdim 123218893Sdim void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, 124218893Sdim llvm::GlobalVariable *DeclPtr); 125208600Srdivacky}; 126212904Sdim 127212904Sdimclass ARMCXXABI : public ItaniumCXXABI { 128212904Sdimpublic: 129212904Sdim ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {} 130212904Sdim 131212904Sdim void BuildConstructorSignature(const CXXConstructorDecl *Ctor, 132212904Sdim CXXCtorType T, 133212904Sdim CanQualType &ResTy, 134226633Sdim SmallVectorImpl<CanQualType> &ArgTys); 135212904Sdim 136212904Sdim void BuildDestructorSignature(const CXXDestructorDecl *Dtor, 137212904Sdim CXXDtorType T, 138212904Sdim CanQualType &ResTy, 139226633Sdim SmallVectorImpl<CanQualType> &ArgTys); 140212904Sdim 141212904Sdim void BuildInstanceFunctionParams(CodeGenFunction &CGF, 142212904Sdim QualType &ResTy, 143212904Sdim FunctionArgList &Params); 144212904Sdim 145212904Sdim void EmitInstanceFunctionProlog(CodeGenFunction &CGF); 146212904Sdim 147212904Sdim void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy); 148212904Sdim 149218893Sdim CharUnits GetArrayCookieSize(const CXXNewExpr *expr); 150212904Sdim llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF, 151212904Sdim llvm::Value *NewPtr, 152212904Sdim llvm::Value *NumElements, 153218893Sdim const CXXNewExpr *expr, 154212904Sdim QualType ElementType); 155212904Sdim void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr, 156218893Sdim const CXXDeleteExpr *expr, 157212904Sdim QualType ElementType, llvm::Value *&NumElements, 158212904Sdim llvm::Value *&AllocPtr, CharUnits &CookieSize); 159212904Sdim 160212904Sdimprivate: 161212904Sdim /// \brief Returns true if the given instance method is one of the 162212904Sdim /// kinds that the ARM ABI says returns 'this'. 163212904Sdim static bool HasThisReturn(GlobalDecl GD) { 164212904Sdim const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 165212904Sdim return ((isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Deleting) || 166212904Sdim (isa<CXXConstructorDecl>(MD))); 167212904Sdim } 168212904Sdim}; 169208600Srdivacky} 170208600Srdivacky 171212904SdimCodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { 172208600Srdivacky return new ItaniumCXXABI(CGM); 173208600Srdivacky} 174208600Srdivacky 175212904SdimCodeGen::CGCXXABI *CodeGen::CreateARMCXXABI(CodeGenModule &CGM) { 176212904Sdim return new ARMCXXABI(CGM); 177212904Sdim} 178212904Sdim 179224145Sdimllvm::Type * 180212904SdimItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { 181212904Sdim if (MPT->isMemberDataPointer()) 182212904Sdim return getPtrDiffTy(); 183224145Sdim return llvm::StructType::get(getPtrDiffTy(), getPtrDiffTy(), NULL); 184212904Sdim} 185212904Sdim 186212904Sdim/// In the Itanium and ARM ABIs, method pointers have the form: 187212904Sdim/// struct { ptrdiff_t ptr; ptrdiff_t adj; } memptr; 188212904Sdim/// 189212904Sdim/// In the Itanium ABI: 190212904Sdim/// - method pointers are virtual if (memptr.ptr & 1) is nonzero 191212904Sdim/// - the this-adjustment is (memptr.adj) 192212904Sdim/// - the virtual offset is (memptr.ptr - 1) 193212904Sdim/// 194212904Sdim/// In the ARM ABI: 195212904Sdim/// - method pointers are virtual if (memptr.adj & 1) is nonzero 196212904Sdim/// - the this-adjustment is (memptr.adj >> 1) 197212904Sdim/// - the virtual offset is (memptr.ptr) 198212904Sdim/// ARM uses 'adj' for the virtual flag because Thumb functions 199212904Sdim/// may be only single-byte aligned. 200212904Sdim/// 201212904Sdim/// If the member is virtual, the adjusted 'this' pointer points 202212904Sdim/// to a vtable pointer from which the virtual offset is applied. 203212904Sdim/// 204212904Sdim/// If the member is non-virtual, memptr.ptr is the address of 205212904Sdim/// the function to call. 206212904Sdimllvm::Value * 207212904SdimItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, 208212904Sdim llvm::Value *&This, 209212904Sdim llvm::Value *MemFnPtr, 210212904Sdim const MemberPointerType *MPT) { 211212904Sdim CGBuilderTy &Builder = CGF.Builder; 212212904Sdim 213212904Sdim const FunctionProtoType *FPT = 214212904Sdim MPT->getPointeeType()->getAs<FunctionProtoType>(); 215212904Sdim const CXXRecordDecl *RD = 216212904Sdim cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); 217212904Sdim 218226633Sdim llvm::FunctionType *FTy = 219212904Sdim CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT), 220212904Sdim FPT->isVariadic()); 221212904Sdim 222226633Sdim llvm::IntegerType *ptrdiff = getPtrDiffTy(); 223212904Sdim llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(ptrdiff, 1); 224212904Sdim 225212904Sdim llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual"); 226212904Sdim llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual"); 227212904Sdim llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end"); 228212904Sdim 229212904Sdim // Extract memptr.adj, which is in the second field. 230212904Sdim llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1, "memptr.adj"); 231212904Sdim 232212904Sdim // Compute the true adjustment. 233212904Sdim llvm::Value *Adj = RawAdj; 234212904Sdim if (IsARM) 235212904Sdim Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted"); 236212904Sdim 237212904Sdim // Apply the adjustment and cast back to the original struct type 238212904Sdim // for consistency. 239212904Sdim llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy()); 240212904Sdim Ptr = Builder.CreateInBoundsGEP(Ptr, Adj); 241212904Sdim This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted"); 242212904Sdim 243212904Sdim // Load the function pointer. 244212904Sdim llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr"); 245212904Sdim 246212904Sdim // If the LSB in the function pointer is 1, the function pointer points to 247212904Sdim // a virtual function. 248212904Sdim llvm::Value *IsVirtual; 249212904Sdim if (IsARM) 250212904Sdim IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1); 251212904Sdim else 252212904Sdim IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1); 253212904Sdim IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual"); 254212904Sdim Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual); 255212904Sdim 256212904Sdim // In the virtual path, the adjustment left 'This' pointing to the 257212904Sdim // vtable of the correct base subobject. The "function pointer" is an 258212904Sdim // offset within the vtable (+1 for the virtual flag on non-ARM). 259212904Sdim CGF.EmitBlock(FnVirtual); 260212904Sdim 261212904Sdim // Cast the adjusted this to a pointer to vtable pointer and load. 262226633Sdim llvm::Type *VTableTy = Builder.getInt8PtrTy(); 263212904Sdim llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo()); 264212904Sdim VTable = Builder.CreateLoad(VTable, "memptr.vtable"); 265212904Sdim 266212904Sdim // Apply the offset. 267212904Sdim llvm::Value *VTableOffset = FnAsInt; 268212904Sdim if (!IsARM) VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1); 269212904Sdim VTable = Builder.CreateGEP(VTable, VTableOffset); 270212904Sdim 271212904Sdim // Load the virtual function to call. 272212904Sdim VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo()); 273212904Sdim llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "memptr.virtualfn"); 274212904Sdim CGF.EmitBranch(FnEnd); 275212904Sdim 276212904Sdim // In the non-virtual path, the function pointer is actually a 277212904Sdim // function pointer. 278212904Sdim CGF.EmitBlock(FnNonVirtual); 279212904Sdim llvm::Value *NonVirtualFn = 280212904Sdim Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn"); 281212904Sdim 282212904Sdim // We're done. 283212904Sdim CGF.EmitBlock(FnEnd); 284221345Sdim llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo(), 2); 285212904Sdim Callee->addIncoming(VirtualFn, FnVirtual); 286212904Sdim Callee->addIncoming(NonVirtualFn, FnNonVirtual); 287212904Sdim return Callee; 288212904Sdim} 289212904Sdim 290212904Sdim/// Compute an l-value by applying the given pointer-to-member to a 291212904Sdim/// base object. 292212904Sdimllvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, 293212904Sdim llvm::Value *Base, 294212904Sdim llvm::Value *MemPtr, 295212904Sdim const MemberPointerType *MPT) { 296212904Sdim assert(MemPtr->getType() == getPtrDiffTy()); 297212904Sdim 298212904Sdim CGBuilderTy &Builder = CGF.Builder; 299212904Sdim 300212904Sdim unsigned AS = cast<llvm::PointerType>(Base->getType())->getAddressSpace(); 301212904Sdim 302212904Sdim // Cast to char*. 303212904Sdim Base = Builder.CreateBitCast(Base, Builder.getInt8Ty()->getPointerTo(AS)); 304212904Sdim 305212904Sdim // Apply the offset, which we assume is non-null. 306212904Sdim llvm::Value *Addr = Builder.CreateInBoundsGEP(Base, MemPtr, "memptr.offset"); 307212904Sdim 308212904Sdim // Cast the address to the appropriate pointer type, adopting the 309212904Sdim // address space of the base pointer. 310226633Sdim llvm::Type *PType 311212904Sdim = CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS); 312212904Sdim return Builder.CreateBitCast(Addr, PType); 313212904Sdim} 314212904Sdim 315212904Sdim/// Perform a derived-to-base or base-to-derived member pointer conversion. 316212904Sdim/// 317212904Sdim/// Obligatory offset/adjustment diagram: 318212904Sdim/// <-- offset --> <-- adjustment --> 319212904Sdim/// |--------------------------|----------------------|--------------------| 320212904Sdim/// ^Derived address point ^Base address point ^Member address point 321212904Sdim/// 322212904Sdim/// So when converting a base member pointer to a derived member pointer, 323212904Sdim/// we add the offset to the adjustment because the address point has 324212904Sdim/// decreased; and conversely, when converting a derived MP to a base MP 325212904Sdim/// we subtract the offset from the adjustment because the address point 326212904Sdim/// has increased. 327212904Sdim/// 328212904Sdim/// The standard forbids (at compile time) conversion to and from 329212904Sdim/// virtual bases, which is why we don't have to consider them here. 330212904Sdim/// 331212904Sdim/// The standard forbids (at run time) casting a derived MP to a base 332212904Sdim/// MP when the derived MP does not point to a member of the base. 333212904Sdim/// This is why -1 is a reasonable choice for null data member 334212904Sdim/// pointers. 335212904Sdimllvm::Value * 336212904SdimItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, 337212904Sdim const CastExpr *E, 338212904Sdim llvm::Value *Src) { 339212904Sdim assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || 340212904Sdim E->getCastKind() == CK_BaseToDerivedMemberPointer); 341212904Sdim 342212904Sdim if (isa<llvm::Constant>(Src)) 343212904Sdim return EmitMemberPointerConversion(cast<llvm::Constant>(Src), E); 344212904Sdim 345212904Sdim CGBuilderTy &Builder = CGF.Builder; 346212904Sdim 347212904Sdim const MemberPointerType *SrcTy = 348212904Sdim E->getSubExpr()->getType()->getAs<MemberPointerType>(); 349212904Sdim const MemberPointerType *DestTy = E->getType()->getAs<MemberPointerType>(); 350212904Sdim 351212904Sdim const CXXRecordDecl *SrcDecl = SrcTy->getClass()->getAsCXXRecordDecl(); 352212904Sdim const CXXRecordDecl *DestDecl = DestTy->getClass()->getAsCXXRecordDecl(); 353212904Sdim 354212904Sdim bool DerivedToBase = 355212904Sdim E->getCastKind() == CK_DerivedToBaseMemberPointer; 356212904Sdim 357218893Sdim const CXXRecordDecl *DerivedDecl; 358212904Sdim if (DerivedToBase) 359218893Sdim DerivedDecl = SrcDecl; 360212904Sdim else 361218893Sdim DerivedDecl = DestDecl; 362212904Sdim 363212904Sdim llvm::Constant *Adj = 364212904Sdim CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl, 365212904Sdim E->path_begin(), 366212904Sdim E->path_end()); 367212904Sdim if (!Adj) return Src; 368212904Sdim 369212904Sdim // For member data pointers, this is just a matter of adding the 370212904Sdim // offset if the source is non-null. 371212904Sdim if (SrcTy->isMemberDataPointer()) { 372212904Sdim llvm::Value *Dst; 373212904Sdim if (DerivedToBase) 374212904Sdim Dst = Builder.CreateNSWSub(Src, Adj, "adj"); 375212904Sdim else 376212904Sdim Dst = Builder.CreateNSWAdd(Src, Adj, "adj"); 377212904Sdim 378212904Sdim // Null check. 379212904Sdim llvm::Value *Null = llvm::Constant::getAllOnesValue(Src->getType()); 380212904Sdim llvm::Value *IsNull = Builder.CreateICmpEQ(Src, Null, "memptr.isnull"); 381212904Sdim return Builder.CreateSelect(IsNull, Src, Dst); 382212904Sdim } 383212904Sdim 384212904Sdim // The this-adjustment is left-shifted by 1 on ARM. 385212904Sdim if (IsARM) { 386212904Sdim uint64_t Offset = cast<llvm::ConstantInt>(Adj)->getZExtValue(); 387212904Sdim Offset <<= 1; 388212904Sdim Adj = llvm::ConstantInt::get(Adj->getType(), Offset); 389212904Sdim } 390212904Sdim 391212904Sdim llvm::Value *SrcAdj = Builder.CreateExtractValue(Src, 1, "src.adj"); 392212904Sdim llvm::Value *DstAdj; 393212904Sdim if (DerivedToBase) 394212904Sdim DstAdj = Builder.CreateNSWSub(SrcAdj, Adj, "adj"); 395212904Sdim else 396212904Sdim DstAdj = Builder.CreateNSWAdd(SrcAdj, Adj, "adj"); 397212904Sdim 398212904Sdim return Builder.CreateInsertValue(Src, DstAdj, 1); 399212904Sdim} 400212904Sdim 401212904Sdimllvm::Constant * 402212904SdimItaniumCXXABI::EmitMemberPointerConversion(llvm::Constant *C, 403212904Sdim const CastExpr *E) { 404212904Sdim const MemberPointerType *SrcTy = 405212904Sdim E->getSubExpr()->getType()->getAs<MemberPointerType>(); 406212904Sdim const MemberPointerType *DestTy = 407212904Sdim E->getType()->getAs<MemberPointerType>(); 408212904Sdim 409212904Sdim bool DerivedToBase = 410212904Sdim E->getCastKind() == CK_DerivedToBaseMemberPointer; 411212904Sdim 412212904Sdim const CXXRecordDecl *DerivedDecl; 413212904Sdim if (DerivedToBase) 414212904Sdim DerivedDecl = SrcTy->getClass()->getAsCXXRecordDecl(); 415212904Sdim else 416212904Sdim DerivedDecl = DestTy->getClass()->getAsCXXRecordDecl(); 417212904Sdim 418212904Sdim // Calculate the offset to the base class. 419212904Sdim llvm::Constant *Offset = 420212904Sdim CGM.GetNonVirtualBaseClassOffset(DerivedDecl, 421212904Sdim E->path_begin(), 422212904Sdim E->path_end()); 423212904Sdim // If there's no offset, we're done. 424212904Sdim if (!Offset) return C; 425212904Sdim 426212904Sdim // If the source is a member data pointer, we have to do a null 427212904Sdim // check and then add the offset. In the common case, we can fold 428212904Sdim // away the offset. 429212904Sdim if (SrcTy->isMemberDataPointer()) { 430212904Sdim assert(C->getType() == getPtrDiffTy()); 431212904Sdim 432212904Sdim // If it's a constant int, just create a new constant int. 433212904Sdim if (llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(C)) { 434212904Sdim int64_t Src = CI->getSExtValue(); 435212904Sdim 436212904Sdim // Null converts to null. 437212904Sdim if (Src == -1) return CI; 438212904Sdim 439212904Sdim // Otherwise, just add the offset. 440212904Sdim int64_t OffsetV = cast<llvm::ConstantInt>(Offset)->getSExtValue(); 441212904Sdim int64_t Dst = (DerivedToBase ? Src - OffsetV : Src + OffsetV); 442212904Sdim return llvm::ConstantInt::get(CI->getType(), Dst, /*signed*/ true); 443212904Sdim } 444212904Sdim 445212904Sdim // Otherwise, we have to form a constant select expression. 446212904Sdim llvm::Constant *Null = llvm::Constant::getAllOnesValue(C->getType()); 447212904Sdim 448212904Sdim llvm::Constant *IsNull = 449212904Sdim llvm::ConstantExpr::getICmp(llvm::ICmpInst::ICMP_EQ, C, Null); 450212904Sdim 451212904Sdim llvm::Constant *Dst; 452212904Sdim if (DerivedToBase) 453212904Sdim Dst = llvm::ConstantExpr::getNSWSub(C, Offset); 454212904Sdim else 455212904Sdim Dst = llvm::ConstantExpr::getNSWAdd(C, Offset); 456212904Sdim 457212904Sdim return llvm::ConstantExpr::getSelect(IsNull, Null, Dst); 458212904Sdim } 459212904Sdim 460212904Sdim // The this-adjustment is left-shifted by 1 on ARM. 461212904Sdim if (IsARM) { 462212904Sdim int64_t OffsetV = cast<llvm::ConstantInt>(Offset)->getSExtValue(); 463212904Sdim OffsetV <<= 1; 464212904Sdim Offset = llvm::ConstantInt::get(Offset->getType(), OffsetV); 465212904Sdim } 466212904Sdim 467212904Sdim llvm::ConstantStruct *CS = cast<llvm::ConstantStruct>(C); 468212904Sdim 469212904Sdim llvm::Constant *Values[2] = { CS->getOperand(0), 0 }; 470212904Sdim if (DerivedToBase) 471212904Sdim Values[1] = llvm::ConstantExpr::getSub(CS->getOperand(1), Offset); 472212904Sdim else 473212904Sdim Values[1] = llvm::ConstantExpr::getAdd(CS->getOperand(1), Offset); 474212904Sdim 475224145Sdim return llvm::ConstantStruct::get(CS->getType(), Values); 476212904Sdim} 477212904Sdim 478212904Sdim 479212904Sdimllvm::Constant * 480212904SdimItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { 481226633Sdim llvm::Type *ptrdiff_t = getPtrDiffTy(); 482212904Sdim 483212904Sdim // Itanium C++ ABI 2.3: 484212904Sdim // A NULL pointer is represented as -1. 485212904Sdim if (MPT->isMemberDataPointer()) 486212904Sdim return llvm::ConstantInt::get(ptrdiff_t, -1ULL, /*isSigned=*/true); 487212904Sdim 488212904Sdim llvm::Constant *Zero = llvm::ConstantInt::get(ptrdiff_t, 0); 489212904Sdim llvm::Constant *Values[2] = { Zero, Zero }; 490224145Sdim return llvm::ConstantStruct::getAnon(Values); 491212904Sdim} 492212904Sdim 493218893Sdimllvm::Constant * 494218893SdimItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, 495218893Sdim CharUnits offset) { 496212904Sdim // Itanium C++ ABI 2.3: 497212904Sdim // A pointer to data member is an offset from the base address of 498212904Sdim // the class object containing it, represented as a ptrdiff_t 499218893Sdim return llvm::ConstantInt::get(getPtrDiffTy(), offset.getQuantity()); 500212904Sdim} 501212904Sdim 502212904Sdimllvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) { 503212904Sdim assert(MD->isInstance() && "Member function must not be static!"); 504212904Sdim MD = MD->getCanonicalDecl(); 505212904Sdim 506212904Sdim CodeGenTypes &Types = CGM.getTypes(); 507226633Sdim llvm::Type *ptrdiff_t = getPtrDiffTy(); 508212904Sdim 509212904Sdim // Get the function pointer (or index if this is a virtual function). 510212904Sdim llvm::Constant *MemPtr[2]; 511212904Sdim if (MD->isVirtual()) { 512226633Sdim uint64_t Index = CGM.getVTableContext().getMethodVTableIndex(MD); 513212904Sdim 514221345Sdim const ASTContext &Context = getContext(); 515221345Sdim CharUnits PointerWidth = 516226633Sdim Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); 517221345Sdim uint64_t VTableOffset = (Index * PointerWidth.getQuantity()); 518212904Sdim 519212904Sdim if (IsARM) { 520212904Sdim // ARM C++ ABI 3.2.1: 521212904Sdim // This ABI specifies that adj contains twice the this 522212904Sdim // adjustment, plus 1 if the member function is virtual. The 523212904Sdim // least significant bit of adj then makes exactly the same 524212904Sdim // discrimination as the least significant bit of ptr does for 525212904Sdim // Itanium. 526212904Sdim MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset); 527212904Sdim MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 1); 528212904Sdim } else { 529212904Sdim // Itanium C++ ABI 2.3: 530212904Sdim // For a virtual function, [the pointer field] is 1 plus the 531212904Sdim // virtual table offset (in bytes) of the function, 532212904Sdim // represented as a ptrdiff_t. 533212904Sdim MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset + 1); 534212904Sdim MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0); 535212904Sdim } 536212904Sdim } else { 537221345Sdim const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); 538226633Sdim llvm::Type *Ty; 539212904Sdim // Check whether the function has a computable LLVM signature. 540224145Sdim if (Types.isFuncTypeConvertible(FPT)) { 541212904Sdim // The function has a computable LLVM signature; use the correct type. 542221345Sdim Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), 543221345Sdim FPT->isVariadic()); 544212904Sdim } else { 545212904Sdim // Use an arbitrary non-function type to tell GetAddrOfFunction that the 546212904Sdim // function type is incomplete. 547212904Sdim Ty = ptrdiff_t; 548212904Sdim } 549221345Sdim llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty); 550212904Sdim 551221345Sdim MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, ptrdiff_t); 552212904Sdim MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0); 553212904Sdim } 554212904Sdim 555224145Sdim return llvm::ConstantStruct::getAnon(MemPtr); 556212904Sdim} 557212904Sdim 558212904Sdim/// The comparison algorithm is pretty easy: the member pointers are 559212904Sdim/// the same if they're either bitwise identical *or* both null. 560212904Sdim/// 561212904Sdim/// ARM is different here only because null-ness is more complicated. 562212904Sdimllvm::Value * 563212904SdimItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, 564212904Sdim llvm::Value *L, 565212904Sdim llvm::Value *R, 566212904Sdim const MemberPointerType *MPT, 567212904Sdim bool Inequality) { 568212904Sdim CGBuilderTy &Builder = CGF.Builder; 569212904Sdim 570212904Sdim llvm::ICmpInst::Predicate Eq; 571212904Sdim llvm::Instruction::BinaryOps And, Or; 572212904Sdim if (Inequality) { 573212904Sdim Eq = llvm::ICmpInst::ICMP_NE; 574212904Sdim And = llvm::Instruction::Or; 575212904Sdim Or = llvm::Instruction::And; 576212904Sdim } else { 577212904Sdim Eq = llvm::ICmpInst::ICMP_EQ; 578212904Sdim And = llvm::Instruction::And; 579212904Sdim Or = llvm::Instruction::Or; 580212904Sdim } 581212904Sdim 582212904Sdim // Member data pointers are easy because there's a unique null 583212904Sdim // value, so it just comes down to bitwise equality. 584212904Sdim if (MPT->isMemberDataPointer()) 585212904Sdim return Builder.CreateICmp(Eq, L, R); 586212904Sdim 587212904Sdim // For member function pointers, the tautologies are more complex. 588212904Sdim // The Itanium tautology is: 589212904Sdim // (L == R) <==> (L.ptr == R.ptr && (L.ptr == 0 || L.adj == R.adj)) 590212904Sdim // The ARM tautology is: 591212904Sdim // (L == R) <==> (L.ptr == R.ptr && 592212904Sdim // (L.adj == R.adj || 593212904Sdim // (L.ptr == 0 && ((L.adj|R.adj) & 1) == 0))) 594212904Sdim // The inequality tautologies have exactly the same structure, except 595212904Sdim // applying De Morgan's laws. 596212904Sdim 597212904Sdim llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr"); 598212904Sdim llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr"); 599212904Sdim 600212904Sdim // This condition tests whether L.ptr == R.ptr. This must always be 601212904Sdim // true for equality to hold. 602212904Sdim llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr"); 603212904Sdim 604212904Sdim // This condition, together with the assumption that L.ptr == R.ptr, 605212904Sdim // tests whether the pointers are both null. ARM imposes an extra 606212904Sdim // condition. 607212904Sdim llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType()); 608212904Sdim llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null"); 609212904Sdim 610212904Sdim // This condition tests whether L.adj == R.adj. If this isn't 611212904Sdim // true, the pointers are unequal unless they're both null. 612212904Sdim llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj"); 613212904Sdim llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj"); 614212904Sdim llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj"); 615212904Sdim 616212904Sdim // Null member function pointers on ARM clear the low bit of Adj, 617212904Sdim // so the zero condition has to check that neither low bit is set. 618212904Sdim if (IsARM) { 619212904Sdim llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1); 620212904Sdim 621212904Sdim // Compute (l.adj | r.adj) & 1 and test it against zero. 622212904Sdim llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj"); 623212904Sdim llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One); 624212904Sdim llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero, 625212904Sdim "cmp.or.adj"); 626212904Sdim EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero); 627212904Sdim } 628212904Sdim 629212904Sdim // Tie together all our conditions. 630212904Sdim llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq); 631212904Sdim Result = Builder.CreateBinOp(And, PtrEq, Result, 632212904Sdim Inequality ? "memptr.ne" : "memptr.eq"); 633212904Sdim return Result; 634212904Sdim} 635212904Sdim 636212904Sdimllvm::Value * 637212904SdimItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, 638212904Sdim llvm::Value *MemPtr, 639212904Sdim const MemberPointerType *MPT) { 640212904Sdim CGBuilderTy &Builder = CGF.Builder; 641212904Sdim 642212904Sdim /// For member data pointers, this is just a check against -1. 643212904Sdim if (MPT->isMemberDataPointer()) { 644212904Sdim assert(MemPtr->getType() == getPtrDiffTy()); 645212904Sdim llvm::Value *NegativeOne = 646212904Sdim llvm::Constant::getAllOnesValue(MemPtr->getType()); 647212904Sdim return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool"); 648212904Sdim } 649212904Sdim 650221345Sdim // In Itanium, a member function pointer is not null if 'ptr' is not null. 651212904Sdim llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr"); 652212904Sdim 653212904Sdim llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0); 654212904Sdim llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool"); 655212904Sdim 656221345Sdim // On ARM, a member function pointer is also non-null if the low bit of 'adj' 657221345Sdim // (the virtual bit) is set. 658212904Sdim if (IsARM) { 659212904Sdim llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1); 660212904Sdim llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj"); 661212904Sdim llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit"); 662221345Sdim llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero, 663221345Sdim "memptr.isvirtual"); 664221345Sdim Result = Builder.CreateOr(Result, IsVirtual); 665212904Sdim } 666212904Sdim 667212904Sdim return Result; 668212904Sdim} 669212904Sdim 670212904Sdim/// The Itanium ABI requires non-zero initialization only for data 671212904Sdim/// member pointers, for which '0' is a valid offset. 672212904Sdimbool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) { 673212904Sdim return MPT->getPointeeType()->isFunctionType(); 674212904Sdim} 675212904Sdim 676212904Sdim/// The generic ABI passes 'this', plus a VTT if it's initializing a 677212904Sdim/// base subobject. 678212904Sdimvoid ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, 679212904Sdim CXXCtorType Type, 680212904Sdim CanQualType &ResTy, 681226633Sdim SmallVectorImpl<CanQualType> &ArgTys) { 682212904Sdim ASTContext &Context = getContext(); 683212904Sdim 684212904Sdim // 'this' is already there. 685212904Sdim 686212904Sdim // Check if we need to add a VTT parameter (which has type void **). 687212904Sdim if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0) 688212904Sdim ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); 689212904Sdim} 690212904Sdim 691212904Sdim/// The ARM ABI does the same as the Itanium ABI, but returns 'this'. 692212904Sdimvoid ARMCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, 693212904Sdim CXXCtorType Type, 694212904Sdim CanQualType &ResTy, 695226633Sdim SmallVectorImpl<CanQualType> &ArgTys) { 696212904Sdim ItaniumCXXABI::BuildConstructorSignature(Ctor, Type, ResTy, ArgTys); 697212904Sdim ResTy = ArgTys[0]; 698212904Sdim} 699212904Sdim 700212904Sdim/// The generic ABI passes 'this', plus a VTT if it's destroying a 701212904Sdim/// base subobject. 702212904Sdimvoid ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, 703212904Sdim CXXDtorType Type, 704212904Sdim CanQualType &ResTy, 705226633Sdim SmallVectorImpl<CanQualType> &ArgTys) { 706212904Sdim ASTContext &Context = getContext(); 707212904Sdim 708212904Sdim // 'this' is already there. 709212904Sdim 710212904Sdim // Check if we need to add a VTT parameter (which has type void **). 711212904Sdim if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0) 712212904Sdim ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); 713212904Sdim} 714212904Sdim 715212904Sdim/// The ARM ABI does the same as the Itanium ABI, but returns 'this' 716212904Sdim/// for non-deleting destructors. 717212904Sdimvoid ARMCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, 718212904Sdim CXXDtorType Type, 719212904Sdim CanQualType &ResTy, 720226633Sdim SmallVectorImpl<CanQualType> &ArgTys) { 721212904Sdim ItaniumCXXABI::BuildDestructorSignature(Dtor, Type, ResTy, ArgTys); 722212904Sdim 723212904Sdim if (Type != Dtor_Deleting) 724212904Sdim ResTy = ArgTys[0]; 725212904Sdim} 726212904Sdim 727212904Sdimvoid ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, 728212904Sdim QualType &ResTy, 729212904Sdim FunctionArgList &Params) { 730212904Sdim /// Create the 'this' variable. 731212904Sdim BuildThisParam(CGF, Params); 732212904Sdim 733212904Sdim const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); 734212904Sdim assert(MD->isInstance()); 735212904Sdim 736212904Sdim // Check if we need a VTT parameter as well. 737212904Sdim if (CodeGenVTables::needsVTTParameter(CGF.CurGD)) { 738212904Sdim ASTContext &Context = getContext(); 739212904Sdim 740212904Sdim // FIXME: avoid the fake decl 741212904Sdim QualType T = Context.getPointerType(Context.VoidPtrTy); 742212904Sdim ImplicitParamDecl *VTTDecl 743212904Sdim = ImplicitParamDecl::Create(Context, 0, MD->getLocation(), 744212904Sdim &Context.Idents.get("vtt"), T); 745221345Sdim Params.push_back(VTTDecl); 746212904Sdim getVTTDecl(CGF) = VTTDecl; 747212904Sdim } 748212904Sdim} 749212904Sdim 750212904Sdimvoid ARMCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, 751212904Sdim QualType &ResTy, 752212904Sdim FunctionArgList &Params) { 753212904Sdim ItaniumCXXABI::BuildInstanceFunctionParams(CGF, ResTy, Params); 754212904Sdim 755212904Sdim // Return 'this' from certain constructors and destructors. 756212904Sdim if (HasThisReturn(CGF.CurGD)) 757221345Sdim ResTy = Params[0]->getType(); 758212904Sdim} 759212904Sdim 760212904Sdimvoid ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { 761212904Sdim /// Initialize the 'this' slot. 762212904Sdim EmitThisParam(CGF); 763212904Sdim 764212904Sdim /// Initialize the 'vtt' slot if needed. 765212904Sdim if (getVTTDecl(CGF)) { 766212904Sdim getVTTValue(CGF) 767212904Sdim = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)), 768212904Sdim "vtt"); 769212904Sdim } 770212904Sdim} 771212904Sdim 772212904Sdimvoid ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { 773212904Sdim ItaniumCXXABI::EmitInstanceFunctionProlog(CGF); 774212904Sdim 775212904Sdim /// Initialize the return slot to 'this' at the start of the 776212904Sdim /// function. 777212904Sdim if (HasThisReturn(CGF.CurGD)) 778212904Sdim CGF.Builder.CreateStore(CGF.LoadCXXThis(), CGF.ReturnValue); 779212904Sdim} 780212904Sdim 781212904Sdimvoid ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, 782212904Sdim RValue RV, QualType ResultType) { 783212904Sdim if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl())) 784212904Sdim return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType); 785212904Sdim 786212904Sdim // Destructor thunks in the ARM ABI have indeterminate results. 787226633Sdim llvm::Type *T = 788212904Sdim cast<llvm::PointerType>(CGF.ReturnValue->getType())->getElementType(); 789212904Sdim RValue Undef = RValue::get(llvm::UndefValue::get(T)); 790212904Sdim return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType); 791212904Sdim} 792212904Sdim 793212904Sdim/************************** Array allocation cookies **************************/ 794212904Sdim 795218893Sdimbool ItaniumCXXABI::NeedsArrayCookie(const CXXNewExpr *expr) { 796218893Sdim // If the class's usual deallocation function takes two arguments, 797218893Sdim // it needs a cookie. 798218893Sdim if (expr->doesUsualArrayDeleteWantSize()) 799218893Sdim return true; 800212904Sdim 801224145Sdim // Automatic Reference Counting: 802224145Sdim // We need an array cookie for pointers with strong or weak lifetime. 803224145Sdim QualType AllocatedType = expr->getAllocatedType(); 804224145Sdim if (getContext().getLangOptions().ObjCAutoRefCount && 805224145Sdim AllocatedType->isObjCLifetimeType()) { 806224145Sdim switch (AllocatedType.getObjCLifetime()) { 807224145Sdim case Qualifiers::OCL_None: 808224145Sdim case Qualifiers::OCL_ExplicitNone: 809224145Sdim case Qualifiers::OCL_Autoreleasing: 810224145Sdim return false; 811224145Sdim 812224145Sdim case Qualifiers::OCL_Strong: 813224145Sdim case Qualifiers::OCL_Weak: 814224145Sdim return true; 815224145Sdim } 816224145Sdim } 817224145Sdim 818218893Sdim // Otherwise, if the class has a non-trivial destructor, it always 819218893Sdim // needs a cookie. 820218893Sdim const CXXRecordDecl *record = 821224145Sdim AllocatedType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); 822218893Sdim return (record && !record->hasTrivialDestructor()); 823218893Sdim} 824212904Sdim 825218893Sdimbool ItaniumCXXABI::NeedsArrayCookie(const CXXDeleteExpr *expr, 826218893Sdim QualType elementType) { 827212904Sdim // If the class's usual deallocation function takes two arguments, 828218893Sdim // it needs a cookie. 829218893Sdim if (expr->doesUsualArrayDeleteWantSize()) 830218893Sdim return true; 831212904Sdim 832226633Sdim return elementType.isDestructedType(); 833212904Sdim} 834212904Sdim 835218893SdimCharUnits ItaniumCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { 836218893Sdim if (!NeedsArrayCookie(expr)) 837212904Sdim return CharUnits::Zero(); 838212904Sdim 839218893Sdim // Padding is the maximum of sizeof(size_t) and alignof(elementType) 840212904Sdim ASTContext &Ctx = getContext(); 841212904Sdim return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()), 842218893Sdim Ctx.getTypeAlignInChars(expr->getAllocatedType())); 843212904Sdim} 844212904Sdim 845212904Sdimllvm::Value *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 846212904Sdim llvm::Value *NewPtr, 847212904Sdim llvm::Value *NumElements, 848218893Sdim const CXXNewExpr *expr, 849212904Sdim QualType ElementType) { 850218893Sdim assert(NeedsArrayCookie(expr)); 851212904Sdim 852212904Sdim unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace(); 853212904Sdim 854212904Sdim ASTContext &Ctx = getContext(); 855212904Sdim QualType SizeTy = Ctx.getSizeType(); 856212904Sdim CharUnits SizeSize = Ctx.getTypeSizeInChars(SizeTy); 857212904Sdim 858212904Sdim // The size of the cookie. 859212904Sdim CharUnits CookieSize = 860212904Sdim std::max(SizeSize, Ctx.getTypeAlignInChars(ElementType)); 861212904Sdim 862212904Sdim // Compute an offset to the cookie. 863212904Sdim llvm::Value *CookiePtr = NewPtr; 864212904Sdim CharUnits CookieOffset = CookieSize - SizeSize; 865212904Sdim if (!CookieOffset.isZero()) 866212904Sdim CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_64(CookiePtr, 867212904Sdim CookieOffset.getQuantity()); 868212904Sdim 869212904Sdim // Write the number of elements into the appropriate slot. 870212904Sdim llvm::Value *NumElementsPtr 871212904Sdim = CGF.Builder.CreateBitCast(CookiePtr, 872212904Sdim CGF.ConvertType(SizeTy)->getPointerTo(AS)); 873212904Sdim CGF.Builder.CreateStore(NumElements, NumElementsPtr); 874212904Sdim 875212904Sdim // Finally, compute a pointer to the actual data buffer by skipping 876212904Sdim // over the cookie completely. 877212904Sdim return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr, 878212904Sdim CookieSize.getQuantity()); 879212904Sdim} 880212904Sdim 881212904Sdimvoid ItaniumCXXABI::ReadArrayCookie(CodeGenFunction &CGF, 882212904Sdim llvm::Value *Ptr, 883218893Sdim const CXXDeleteExpr *expr, 884212904Sdim QualType ElementType, 885212904Sdim llvm::Value *&NumElements, 886212904Sdim llvm::Value *&AllocPtr, 887212904Sdim CharUnits &CookieSize) { 888212904Sdim // Derive a char* in the same address space as the pointer. 889212904Sdim unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace(); 890226633Sdim llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS); 891212904Sdim 892212904Sdim // If we don't need an array cookie, bail out early. 893218893Sdim if (!NeedsArrayCookie(expr, ElementType)) { 894212904Sdim AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 895212904Sdim NumElements = 0; 896212904Sdim CookieSize = CharUnits::Zero(); 897212904Sdim return; 898212904Sdim } 899212904Sdim 900212904Sdim QualType SizeTy = getContext().getSizeType(); 901212904Sdim CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy); 902226633Sdim llvm::Type *SizeLTy = CGF.ConvertType(SizeTy); 903212904Sdim 904212904Sdim CookieSize 905212904Sdim = std::max(SizeSize, getContext().getTypeAlignInChars(ElementType)); 906212904Sdim 907212904Sdim CharUnits NumElementsOffset = CookieSize - SizeSize; 908212904Sdim 909212904Sdim // Compute the allocated pointer. 910212904Sdim AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 911212904Sdim AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr, 912212904Sdim -CookieSize.getQuantity()); 913212904Sdim 914212904Sdim llvm::Value *NumElementsPtr = AllocPtr; 915212904Sdim if (!NumElementsOffset.isZero()) 916212904Sdim NumElementsPtr = 917212904Sdim CGF.Builder.CreateConstInBoundsGEP1_64(NumElementsPtr, 918212904Sdim NumElementsOffset.getQuantity()); 919212904Sdim NumElementsPtr = 920212904Sdim CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS)); 921212904Sdim NumElements = CGF.Builder.CreateLoad(NumElementsPtr); 922212904Sdim} 923212904Sdim 924218893SdimCharUnits ARMCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { 925218893Sdim if (!NeedsArrayCookie(expr)) 926212904Sdim return CharUnits::Zero(); 927212904Sdim 928212904Sdim // On ARM, the cookie is always: 929212904Sdim // struct array_cookie { 930212904Sdim // std::size_t element_size; // element_size != 0 931212904Sdim // std::size_t element_count; 932212904Sdim // }; 933212904Sdim // TODO: what should we do if the allocated type actually wants 934212904Sdim // greater alignment? 935212904Sdim return getContext().getTypeSizeInChars(getContext().getSizeType()) * 2; 936212904Sdim} 937212904Sdim 938212904Sdimllvm::Value *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 939212904Sdim llvm::Value *NewPtr, 940212904Sdim llvm::Value *NumElements, 941218893Sdim const CXXNewExpr *expr, 942212904Sdim QualType ElementType) { 943218893Sdim assert(NeedsArrayCookie(expr)); 944212904Sdim 945212904Sdim // NewPtr is a char*. 946212904Sdim 947212904Sdim unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace(); 948212904Sdim 949212904Sdim ASTContext &Ctx = getContext(); 950212904Sdim CharUnits SizeSize = Ctx.getTypeSizeInChars(Ctx.getSizeType()); 951226633Sdim llvm::IntegerType *SizeTy = 952212904Sdim cast<llvm::IntegerType>(CGF.ConvertType(Ctx.getSizeType())); 953212904Sdim 954212904Sdim // The cookie is always at the start of the buffer. 955212904Sdim llvm::Value *CookiePtr = NewPtr; 956212904Sdim 957212904Sdim // The first element is the element size. 958212904Sdim CookiePtr = CGF.Builder.CreateBitCast(CookiePtr, SizeTy->getPointerTo(AS)); 959212904Sdim llvm::Value *ElementSize = llvm::ConstantInt::get(SizeTy, 960212904Sdim Ctx.getTypeSizeInChars(ElementType).getQuantity()); 961212904Sdim CGF.Builder.CreateStore(ElementSize, CookiePtr); 962212904Sdim 963212904Sdim // The second element is the element count. 964212904Sdim CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_32(CookiePtr, 1); 965212904Sdim CGF.Builder.CreateStore(NumElements, CookiePtr); 966212904Sdim 967212904Sdim // Finally, compute a pointer to the actual data buffer by skipping 968212904Sdim // over the cookie completely. 969212904Sdim CharUnits CookieSize = 2 * SizeSize; 970212904Sdim return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr, 971212904Sdim CookieSize.getQuantity()); 972212904Sdim} 973212904Sdim 974212904Sdimvoid ARMCXXABI::ReadArrayCookie(CodeGenFunction &CGF, 975212904Sdim llvm::Value *Ptr, 976218893Sdim const CXXDeleteExpr *expr, 977212904Sdim QualType ElementType, 978212904Sdim llvm::Value *&NumElements, 979212904Sdim llvm::Value *&AllocPtr, 980212904Sdim CharUnits &CookieSize) { 981212904Sdim // Derive a char* in the same address space as the pointer. 982212904Sdim unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace(); 983226633Sdim llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS); 984212904Sdim 985212904Sdim // If we don't need an array cookie, bail out early. 986218893Sdim if (!NeedsArrayCookie(expr, ElementType)) { 987212904Sdim AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 988212904Sdim NumElements = 0; 989212904Sdim CookieSize = CharUnits::Zero(); 990212904Sdim return; 991212904Sdim } 992212904Sdim 993212904Sdim QualType SizeTy = getContext().getSizeType(); 994212904Sdim CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy); 995226633Sdim llvm::Type *SizeLTy = CGF.ConvertType(SizeTy); 996212904Sdim 997212904Sdim // The cookie size is always 2 * sizeof(size_t). 998212904Sdim CookieSize = 2 * SizeSize; 999212904Sdim 1000212904Sdim // The allocated pointer is the input ptr, minus that amount. 1001212904Sdim AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 1002212904Sdim AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr, 1003212904Sdim -CookieSize.getQuantity()); 1004212904Sdim 1005212904Sdim // The number of elements is at offset sizeof(size_t) relative to that. 1006212904Sdim llvm::Value *NumElementsPtr 1007212904Sdim = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr, 1008212904Sdim SizeSize.getQuantity()); 1009212904Sdim NumElementsPtr = 1010212904Sdim CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS)); 1011212904Sdim NumElements = CGF.Builder.CreateLoad(NumElementsPtr); 1012212904Sdim} 1013212904Sdim 1014218893Sdim/*********************** Static local initialization **************************/ 1015218893Sdim 1016218893Sdimstatic llvm::Constant *getGuardAcquireFn(CodeGenModule &CGM, 1017224145Sdim llvm::PointerType *GuardPtrTy) { 1018218893Sdim // int __cxa_guard_acquire(__guard *guard_object); 1019226633Sdim llvm::FunctionType *FTy = 1020218893Sdim llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy), 1021226633Sdim GuardPtrTy, /*isVarArg=*/false); 1022218893Sdim 1023218893Sdim return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire"); 1024218893Sdim} 1025218893Sdim 1026218893Sdimstatic llvm::Constant *getGuardReleaseFn(CodeGenModule &CGM, 1027224145Sdim llvm::PointerType *GuardPtrTy) { 1028218893Sdim // void __cxa_guard_release(__guard *guard_object); 1029226633Sdim llvm::FunctionType *FTy = 1030218893Sdim llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), 1031226633Sdim GuardPtrTy, /*isVarArg=*/false); 1032218893Sdim 1033218893Sdim return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release"); 1034218893Sdim} 1035218893Sdim 1036218893Sdimstatic llvm::Constant *getGuardAbortFn(CodeGenModule &CGM, 1037224145Sdim llvm::PointerType *GuardPtrTy) { 1038218893Sdim // void __cxa_guard_abort(__guard *guard_object); 1039226633Sdim llvm::FunctionType *FTy = 1040218893Sdim llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), 1041226633Sdim GuardPtrTy, /*isVarArg=*/false); 1042218893Sdim 1043218893Sdim return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort"); 1044218893Sdim} 1045218893Sdim 1046218893Sdimnamespace { 1047218893Sdim struct CallGuardAbort : EHScopeStack::Cleanup { 1048218893Sdim llvm::GlobalVariable *Guard; 1049218893Sdim CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {} 1050218893Sdim 1051224145Sdim void Emit(CodeGenFunction &CGF, Flags flags) { 1052218893Sdim CGF.Builder.CreateCall(getGuardAbortFn(CGF.CGM, Guard->getType()), Guard) 1053218893Sdim ->setDoesNotThrow(); 1054218893Sdim } 1055218893Sdim }; 1056218893Sdim} 1057218893Sdim 1058218893Sdim/// The ARM code here follows the Itanium code closely enough that we 1059218893Sdim/// just special-case it at particular places. 1060218893Sdimvoid ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, 1061218893Sdim const VarDecl &D, 1062218893Sdim llvm::GlobalVariable *GV) { 1063218893Sdim CGBuilderTy &Builder = CGF.Builder; 1064218893Sdim 1065218893Sdim // We only need to use thread-safe statics for local variables; 1066218893Sdim // global initialization is always single-threaded. 1067224145Sdim bool threadsafe = 1068224145Sdim (getContext().getLangOptions().ThreadsafeStatics && D.isLocalVarDecl()); 1069221345Sdim 1070226633Sdim llvm::IntegerType *GuardTy; 1071221345Sdim 1072221345Sdim // If we have a global variable with internal linkage and thread-safe statics 1073221345Sdim // are disabled, we can just let the guard variable be of type i8. 1074224145Sdim bool useInt8GuardVariable = !threadsafe && GV->hasInternalLinkage(); 1075224145Sdim if (useInt8GuardVariable) { 1076224145Sdim GuardTy = CGF.Int8Ty; 1077224145Sdim } else { 1078221345Sdim // Guard variables are 64 bits in the generic ABI and 32 bits on ARM. 1079224145Sdim GuardTy = (IsARM ? CGF.Int32Ty : CGF.Int64Ty); 1080221345Sdim } 1081224145Sdim llvm::PointerType *GuardPtrTy = GuardTy->getPointerTo(); 1082218893Sdim 1083218893Sdim // Create the guard variable. 1084218893Sdim llvm::SmallString<256> GuardVName; 1085218893Sdim llvm::raw_svector_ostream Out(GuardVName); 1086218893Sdim getMangleContext().mangleItaniumGuardVariable(&D, Out); 1087218893Sdim Out.flush(); 1088218893Sdim 1089218893Sdim // Just absorb linkage and visibility from the variable. 1090218893Sdim llvm::GlobalVariable *GuardVariable = 1091218893Sdim new llvm::GlobalVariable(CGM.getModule(), GuardTy, 1092218893Sdim false, GV->getLinkage(), 1093218893Sdim llvm::ConstantInt::get(GuardTy, 0), 1094218893Sdim GuardVName.str()); 1095218893Sdim GuardVariable->setVisibility(GV->getVisibility()); 1096218893Sdim 1097218893Sdim // Test whether the variable has completed initialization. 1098218893Sdim llvm::Value *IsInitialized; 1099218893Sdim 1100218893Sdim // ARM C++ ABI 3.2.3.1: 1101218893Sdim // To support the potential use of initialization guard variables 1102218893Sdim // as semaphores that are the target of ARM SWP and LDREX/STREX 1103218893Sdim // synchronizing instructions we define a static initialization 1104218893Sdim // guard variable to be a 4-byte aligned, 4- byte word with the 1105218893Sdim // following inline access protocol. 1106218893Sdim // #define INITIALIZED 1 1107218893Sdim // if ((obj_guard & INITIALIZED) != INITIALIZED) { 1108218893Sdim // if (__cxa_guard_acquire(&obj_guard)) 1109218893Sdim // ... 1110218893Sdim // } 1111224145Sdim if (IsARM && !useInt8GuardVariable) { 1112218893Sdim llvm::Value *V = Builder.CreateLoad(GuardVariable); 1113218893Sdim V = Builder.CreateAnd(V, Builder.getInt32(1)); 1114218893Sdim IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized"); 1115218893Sdim 1116218893Sdim // Itanium C++ ABI 3.3.2: 1117218893Sdim // The following is pseudo-code showing how these functions can be used: 1118218893Sdim // if (obj_guard.first_byte == 0) { 1119218893Sdim // if ( __cxa_guard_acquire (&obj_guard) ) { 1120218893Sdim // try { 1121218893Sdim // ... initialize the object ...; 1122218893Sdim // } catch (...) { 1123218893Sdim // __cxa_guard_abort (&obj_guard); 1124218893Sdim // throw; 1125218893Sdim // } 1126218893Sdim // ... queue object destructor with __cxa_atexit() ...; 1127218893Sdim // __cxa_guard_release (&obj_guard); 1128218893Sdim // } 1129218893Sdim // } 1130218893Sdim } else { 1131218893Sdim // Load the first byte of the guard variable. 1132226633Sdim llvm::Type *PtrTy = Builder.getInt8PtrTy(); 1133226633Sdim llvm::LoadInst *LI = 1134226633Sdim Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy)); 1135226633Sdim LI->setAlignment(1); 1136218893Sdim 1137226633Sdim // Itanium ABI: 1138226633Sdim // An implementation supporting thread-safety on multiprocessor 1139226633Sdim // systems must also guarantee that references to the initialized 1140226633Sdim // object do not occur before the load of the initialization flag. 1141226633Sdim // 1142226633Sdim // In LLVM, we do this by marking the load Acquire. 1143226633Sdim if (threadsafe) 1144226633Sdim LI->setAtomic(llvm::Acquire); 1145226633Sdim 1146226633Sdim IsInitialized = Builder.CreateIsNull(LI, "guard.uninitialized"); 1147218893Sdim } 1148218893Sdim 1149218893Sdim llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check"); 1150218893Sdim llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end"); 1151218893Sdim 1152218893Sdim // Check if the first byte of the guard variable is zero. 1153226633Sdim Builder.CreateCondBr(IsInitialized, InitCheckBlock, EndBlock); 1154218893Sdim 1155218893Sdim CGF.EmitBlock(InitCheckBlock); 1156218893Sdim 1157218893Sdim // Variables used when coping with thread-safe statics and exceptions. 1158224145Sdim if (threadsafe) { 1159218893Sdim // Call __cxa_guard_acquire. 1160218893Sdim llvm::Value *V 1161218893Sdim = Builder.CreateCall(getGuardAcquireFn(CGM, GuardPtrTy), GuardVariable); 1162218893Sdim 1163218893Sdim llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); 1164218893Sdim 1165218893Sdim Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), 1166218893Sdim InitBlock, EndBlock); 1167218893Sdim 1168218893Sdim // Call __cxa_guard_abort along the exceptional edge. 1169218893Sdim CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable); 1170218893Sdim 1171218893Sdim CGF.EmitBlock(InitBlock); 1172218893Sdim } 1173218893Sdim 1174218893Sdim // Emit the initializer and add a global destructor if appropriate. 1175218893Sdim CGF.EmitCXXGlobalVarDeclInit(D, GV); 1176218893Sdim 1177224145Sdim if (threadsafe) { 1178218893Sdim // Pop the guard-abort cleanup if we pushed one. 1179218893Sdim CGF.PopCleanupBlock(); 1180218893Sdim 1181218893Sdim // Call __cxa_guard_release. This cannot throw. 1182218893Sdim Builder.CreateCall(getGuardReleaseFn(CGM, GuardPtrTy), GuardVariable); 1183218893Sdim } else { 1184218893Sdim Builder.CreateStore(llvm::ConstantInt::get(GuardTy, 1), GuardVariable); 1185218893Sdim } 1186218893Sdim 1187218893Sdim CGF.EmitBlock(EndBlock); 1188218893Sdim} 1189