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" 23239462Sdim#include "CGVTables.h" 24212904Sdim#include "CodeGenFunction.h" 25208600Srdivacky#include "CodeGenModule.h" 26243830Sdim#include "clang/AST/Mangle.h" 27243830Sdim#include "clang/AST/Type.h" 28249423Sdim#include "llvm/IR/DataLayout.h" 29249423Sdim#include "llvm/IR/Intrinsics.h" 30249423Sdim#include "llvm/IR/Value.h" 31208600Srdivacky 32208600Srdivackyusing namespace clang; 33212904Sdimusing namespace CodeGen; 34208600Srdivacky 35208600Srdivackynamespace { 36212904Sdimclass ItaniumCXXABI : public CodeGen::CGCXXABI { 37212904Sdimprotected: 38212904Sdim bool IsARM; 39212904Sdim 40208600Srdivackypublic: 41212904Sdim ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool IsARM = false) : 42249423Sdim CGCXXABI(CGM), IsARM(IsARM) { } 43208600Srdivacky 44251662Sdim bool isReturnTypeIndirect(const CXXRecordDecl *RD) const { 45251662Sdim // Structures with either a non-trivial destructor or a non-trivial 46251662Sdim // copy constructor are always indirect. 47251662Sdim return !RD->hasTrivialDestructor() || RD->hasNonTrivialCopyConstructor(); 48251662Sdim } 49251662Sdim 50251662Sdim RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const { 51251662Sdim // Structures with either a non-trivial destructor or a non-trivial 52251662Sdim // copy constructor are always indirect. 53251662Sdim if (!RD->hasTrivialDestructor() || RD->hasNonTrivialCopyConstructor()) 54251662Sdim return RAA_Indirect; 55251662Sdim return RAA_Default; 56251662Sdim } 57251662Sdim 58212904Sdim bool isZeroInitializable(const MemberPointerType *MPT); 59212904Sdim 60224145Sdim llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT); 61212904Sdim 62212904Sdim llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, 63212904Sdim llvm::Value *&This, 64212904Sdim llvm::Value *MemFnPtr, 65212904Sdim const MemberPointerType *MPT); 66212904Sdim 67212904Sdim llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF, 68212904Sdim llvm::Value *Base, 69212904Sdim llvm::Value *MemPtr, 70212904Sdim const MemberPointerType *MPT); 71212904Sdim 72212904Sdim llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF, 73212904Sdim const CastExpr *E, 74212904Sdim llvm::Value *Src); 75234353Sdim llvm::Constant *EmitMemberPointerConversion(const CastExpr *E, 76234353Sdim llvm::Constant *Src); 77212904Sdim 78212904Sdim llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT); 79212904Sdim 80212904Sdim llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD); 81218893Sdim llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, 82218893Sdim CharUnits offset); 83234353Sdim llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT); 84234353Sdim llvm::Constant *BuildMemberPointer(const CXXMethodDecl *MD, 85234353Sdim CharUnits ThisAdjustment); 86212904Sdim 87212904Sdim llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF, 88212904Sdim llvm::Value *L, 89212904Sdim llvm::Value *R, 90212904Sdim const MemberPointerType *MPT, 91212904Sdim bool Inequality); 92212904Sdim 93212904Sdim llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF, 94212904Sdim llvm::Value *Addr, 95212904Sdim const MemberPointerType *MPT); 96212904Sdim 97243830Sdim llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF, 98243830Sdim llvm::Value *ptr, 99243830Sdim QualType type); 100243830Sdim 101212904Sdim void BuildConstructorSignature(const CXXConstructorDecl *Ctor, 102212904Sdim CXXCtorType T, 103212904Sdim CanQualType &ResTy, 104226633Sdim SmallVectorImpl<CanQualType> &ArgTys); 105212904Sdim 106212904Sdim void BuildDestructorSignature(const CXXDestructorDecl *Dtor, 107212904Sdim CXXDtorType T, 108212904Sdim CanQualType &ResTy, 109226633Sdim SmallVectorImpl<CanQualType> &ArgTys); 110212904Sdim 111212904Sdim void BuildInstanceFunctionParams(CodeGenFunction &CGF, 112212904Sdim QualType &ResTy, 113212904Sdim FunctionArgList &Params); 114212904Sdim 115212904Sdim void EmitInstanceFunctionProlog(CodeGenFunction &CGF); 116212904Sdim 117249423Sdim llvm::Value *EmitConstructorCall(CodeGenFunction &CGF, 118249423Sdim const CXXConstructorDecl *D, 119249423Sdim CXXCtorType Type, bool ForVirtualBase, 120249423Sdim bool Delegating, 121249423Sdim llvm::Value *This, 122249423Sdim CallExpr::const_arg_iterator ArgBeg, 123249423Sdim CallExpr::const_arg_iterator ArgEnd); 124249423Sdim 125249423Sdim RValue EmitVirtualDestructorCall(CodeGenFunction &CGF, 126249423Sdim const CXXDestructorDecl *Dtor, 127249423Sdim CXXDtorType DtorType, 128249423Sdim SourceLocation CallLoc, 129249423Sdim ReturnValueSlot ReturnValue, 130249423Sdim llvm::Value *This); 131249423Sdim 132239462Sdim StringRef GetPureVirtualCallName() { return "__cxa_pure_virtual"; } 133243830Sdim StringRef GetDeletedVirtualCallName() { return "__cxa_deleted_virtual"; } 134239462Sdim 135239462Sdim CharUnits getArrayCookieSizeImpl(QualType elementType); 136212904Sdim llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF, 137212904Sdim llvm::Value *NewPtr, 138212904Sdim llvm::Value *NumElements, 139218893Sdim const CXXNewExpr *expr, 140212904Sdim QualType ElementType); 141239462Sdim llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, 142239462Sdim llvm::Value *allocPtr, 143239462Sdim CharUnits cookieSize); 144218893Sdim 145218893Sdim void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, 146234353Sdim llvm::GlobalVariable *DeclPtr, bool PerformInit); 147251662Sdim void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, 148251662Sdim llvm::Constant *dtor, llvm::Constant *addr); 149251662Sdim 150251662Sdim llvm::Function *getOrCreateThreadLocalWrapper(const VarDecl *VD, 151251662Sdim llvm::GlobalVariable *Var); 152251662Sdim void EmitThreadLocalInitFuncs( 153251662Sdim llvm::ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *> > Decls, 154251662Sdim llvm::Function *InitFunc); 155251662Sdim LValue EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF, 156251662Sdim const DeclRefExpr *DRE); 157208600Srdivacky}; 158212904Sdim 159212904Sdimclass ARMCXXABI : public ItaniumCXXABI { 160212904Sdimpublic: 161212904Sdim ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {} 162212904Sdim 163212904Sdim void BuildConstructorSignature(const CXXConstructorDecl *Ctor, 164212904Sdim CXXCtorType T, 165212904Sdim CanQualType &ResTy, 166226633Sdim SmallVectorImpl<CanQualType> &ArgTys); 167212904Sdim 168212904Sdim void BuildDestructorSignature(const CXXDestructorDecl *Dtor, 169212904Sdim CXXDtorType T, 170212904Sdim CanQualType &ResTy, 171226633Sdim SmallVectorImpl<CanQualType> &ArgTys); 172212904Sdim 173212904Sdim void BuildInstanceFunctionParams(CodeGenFunction &CGF, 174212904Sdim QualType &ResTy, 175212904Sdim FunctionArgList &Params); 176212904Sdim 177212904Sdim void EmitInstanceFunctionProlog(CodeGenFunction &CGF); 178212904Sdim 179212904Sdim void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy); 180212904Sdim 181239462Sdim CharUnits getArrayCookieSizeImpl(QualType elementType); 182212904Sdim llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF, 183212904Sdim llvm::Value *NewPtr, 184212904Sdim llvm::Value *NumElements, 185218893Sdim const CXXNewExpr *expr, 186212904Sdim QualType ElementType); 187239462Sdim llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, llvm::Value *allocPtr, 188239462Sdim CharUnits cookieSize); 189212904Sdim 190212904Sdim /// \brief Returns true if the given instance method is one of the 191212904Sdim /// kinds that the ARM ABI says returns 'this'. 192249423Sdim bool HasThisReturn(GlobalDecl GD) const { 193249423Sdim const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(GD.getDecl()); 194249423Sdim if (!MD) return false; 195212904Sdim return ((isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Deleting) || 196212904Sdim (isa<CXXConstructorDecl>(MD))); 197212904Sdim } 198212904Sdim}; 199208600Srdivacky} 200208600Srdivacky 201212904SdimCodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { 202251662Sdim switch (CGM.getTarget().getCXXABI().getKind()) { 203249423Sdim // For IR-generation purposes, there's no significant difference 204249423Sdim // between the ARM and iOS ABIs. 205249423Sdim case TargetCXXABI::GenericARM: 206249423Sdim case TargetCXXABI::iOS: 207249423Sdim return new ARMCXXABI(CGM); 208208600Srdivacky 209249423Sdim // Note that AArch64 uses the generic ItaniumCXXABI class since it doesn't 210249423Sdim // include the other 32-bit ARM oddities: constructor/destructor return values 211249423Sdim // and array cookies. 212249423Sdim case TargetCXXABI::GenericAArch64: 213249423Sdim return new ItaniumCXXABI(CGM, /*IsARM = */ true); 214249423Sdim 215249423Sdim case TargetCXXABI::GenericItanium: 216249423Sdim return new ItaniumCXXABI(CGM); 217249423Sdim 218249423Sdim case TargetCXXABI::Microsoft: 219249423Sdim llvm_unreachable("Microsoft ABI is not Itanium-based"); 220249423Sdim } 221249423Sdim llvm_unreachable("bad ABI kind"); 222212904Sdim} 223212904Sdim 224224145Sdimllvm::Type * 225212904SdimItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { 226212904Sdim if (MPT->isMemberDataPointer()) 227249423Sdim return CGM.PtrDiffTy; 228249423Sdim return llvm::StructType::get(CGM.PtrDiffTy, CGM.PtrDiffTy, NULL); 229212904Sdim} 230212904Sdim 231212904Sdim/// In the Itanium and ARM ABIs, method pointers have the form: 232212904Sdim/// struct { ptrdiff_t ptr; ptrdiff_t adj; } memptr; 233212904Sdim/// 234212904Sdim/// In the Itanium ABI: 235212904Sdim/// - method pointers are virtual if (memptr.ptr & 1) is nonzero 236212904Sdim/// - the this-adjustment is (memptr.adj) 237212904Sdim/// - the virtual offset is (memptr.ptr - 1) 238212904Sdim/// 239212904Sdim/// In the ARM ABI: 240212904Sdim/// - method pointers are virtual if (memptr.adj & 1) is nonzero 241212904Sdim/// - the this-adjustment is (memptr.adj >> 1) 242212904Sdim/// - the virtual offset is (memptr.ptr) 243212904Sdim/// ARM uses 'adj' for the virtual flag because Thumb functions 244212904Sdim/// may be only single-byte aligned. 245212904Sdim/// 246212904Sdim/// If the member is virtual, the adjusted 'this' pointer points 247212904Sdim/// to a vtable pointer from which the virtual offset is applied. 248212904Sdim/// 249212904Sdim/// If the member is non-virtual, memptr.ptr is the address of 250212904Sdim/// the function to call. 251212904Sdimllvm::Value * 252212904SdimItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, 253212904Sdim llvm::Value *&This, 254212904Sdim llvm::Value *MemFnPtr, 255212904Sdim const MemberPointerType *MPT) { 256212904Sdim CGBuilderTy &Builder = CGF.Builder; 257212904Sdim 258212904Sdim const FunctionProtoType *FPT = 259212904Sdim MPT->getPointeeType()->getAs<FunctionProtoType>(); 260212904Sdim const CXXRecordDecl *RD = 261212904Sdim cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); 262212904Sdim 263226633Sdim llvm::FunctionType *FTy = 264234353Sdim CGM.getTypes().GetFunctionType( 265234353Sdim CGM.getTypes().arrangeCXXMethodType(RD, FPT)); 266212904Sdim 267249423Sdim llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1); 268212904Sdim 269212904Sdim llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual"); 270212904Sdim llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual"); 271212904Sdim llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end"); 272212904Sdim 273212904Sdim // Extract memptr.adj, which is in the second field. 274212904Sdim llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1, "memptr.adj"); 275212904Sdim 276212904Sdim // Compute the true adjustment. 277212904Sdim llvm::Value *Adj = RawAdj; 278212904Sdim if (IsARM) 279212904Sdim Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted"); 280212904Sdim 281212904Sdim // Apply the adjustment and cast back to the original struct type 282212904Sdim // for consistency. 283212904Sdim llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy()); 284212904Sdim Ptr = Builder.CreateInBoundsGEP(Ptr, Adj); 285212904Sdim This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted"); 286212904Sdim 287212904Sdim // Load the function pointer. 288212904Sdim llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr"); 289212904Sdim 290212904Sdim // If the LSB in the function pointer is 1, the function pointer points to 291212904Sdim // a virtual function. 292212904Sdim llvm::Value *IsVirtual; 293212904Sdim if (IsARM) 294212904Sdim IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1); 295212904Sdim else 296212904Sdim IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1); 297212904Sdim IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual"); 298212904Sdim Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual); 299212904Sdim 300212904Sdim // In the virtual path, the adjustment left 'This' pointing to the 301212904Sdim // vtable of the correct base subobject. The "function pointer" is an 302212904Sdim // offset within the vtable (+1 for the virtual flag on non-ARM). 303212904Sdim CGF.EmitBlock(FnVirtual); 304212904Sdim 305212904Sdim // Cast the adjusted this to a pointer to vtable pointer and load. 306226633Sdim llvm::Type *VTableTy = Builder.getInt8PtrTy(); 307212904Sdim llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo()); 308212904Sdim VTable = Builder.CreateLoad(VTable, "memptr.vtable"); 309212904Sdim 310212904Sdim // Apply the offset. 311212904Sdim llvm::Value *VTableOffset = FnAsInt; 312212904Sdim if (!IsARM) VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1); 313212904Sdim VTable = Builder.CreateGEP(VTable, VTableOffset); 314212904Sdim 315212904Sdim // Load the virtual function to call. 316212904Sdim VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo()); 317212904Sdim llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "memptr.virtualfn"); 318212904Sdim CGF.EmitBranch(FnEnd); 319212904Sdim 320212904Sdim // In the non-virtual path, the function pointer is actually a 321212904Sdim // function pointer. 322212904Sdim CGF.EmitBlock(FnNonVirtual); 323212904Sdim llvm::Value *NonVirtualFn = 324212904Sdim Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn"); 325212904Sdim 326212904Sdim // We're done. 327212904Sdim CGF.EmitBlock(FnEnd); 328221345Sdim llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo(), 2); 329212904Sdim Callee->addIncoming(VirtualFn, FnVirtual); 330212904Sdim Callee->addIncoming(NonVirtualFn, FnNonVirtual); 331212904Sdim return Callee; 332212904Sdim} 333212904Sdim 334212904Sdim/// Compute an l-value by applying the given pointer-to-member to a 335212904Sdim/// base object. 336212904Sdimllvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, 337212904Sdim llvm::Value *Base, 338212904Sdim llvm::Value *MemPtr, 339212904Sdim const MemberPointerType *MPT) { 340249423Sdim assert(MemPtr->getType() == CGM.PtrDiffTy); 341212904Sdim 342212904Sdim CGBuilderTy &Builder = CGF.Builder; 343212904Sdim 344243830Sdim unsigned AS = Base->getType()->getPointerAddressSpace(); 345212904Sdim 346212904Sdim // Cast to char*. 347212904Sdim Base = Builder.CreateBitCast(Base, Builder.getInt8Ty()->getPointerTo(AS)); 348212904Sdim 349212904Sdim // Apply the offset, which we assume is non-null. 350212904Sdim llvm::Value *Addr = Builder.CreateInBoundsGEP(Base, MemPtr, "memptr.offset"); 351212904Sdim 352212904Sdim // Cast the address to the appropriate pointer type, adopting the 353212904Sdim // address space of the base pointer. 354226633Sdim llvm::Type *PType 355212904Sdim = CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS); 356212904Sdim return Builder.CreateBitCast(Addr, PType); 357212904Sdim} 358212904Sdim 359234353Sdim/// Perform a bitcast, derived-to-base, or base-to-derived member pointer 360234353Sdim/// conversion. 361212904Sdim/// 362234353Sdim/// Bitcast conversions are always a no-op under Itanium. 363234353Sdim/// 364212904Sdim/// Obligatory offset/adjustment diagram: 365212904Sdim/// <-- offset --> <-- adjustment --> 366212904Sdim/// |--------------------------|----------------------|--------------------| 367212904Sdim/// ^Derived address point ^Base address point ^Member address point 368212904Sdim/// 369212904Sdim/// So when converting a base member pointer to a derived member pointer, 370212904Sdim/// we add the offset to the adjustment because the address point has 371212904Sdim/// decreased; and conversely, when converting a derived MP to a base MP 372212904Sdim/// we subtract the offset from the adjustment because the address point 373212904Sdim/// has increased. 374212904Sdim/// 375212904Sdim/// The standard forbids (at compile time) conversion to and from 376212904Sdim/// virtual bases, which is why we don't have to consider them here. 377212904Sdim/// 378212904Sdim/// The standard forbids (at run time) casting a derived MP to a base 379212904Sdim/// MP when the derived MP does not point to a member of the base. 380212904Sdim/// This is why -1 is a reasonable choice for null data member 381212904Sdim/// pointers. 382212904Sdimllvm::Value * 383212904SdimItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, 384212904Sdim const CastExpr *E, 385234353Sdim llvm::Value *src) { 386212904Sdim assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || 387234353Sdim E->getCastKind() == CK_BaseToDerivedMemberPointer || 388234353Sdim E->getCastKind() == CK_ReinterpretMemberPointer); 389212904Sdim 390234353Sdim // Under Itanium, reinterprets don't require any additional processing. 391234353Sdim if (E->getCastKind() == CK_ReinterpretMemberPointer) return src; 392212904Sdim 393234353Sdim // Use constant emission if we can. 394234353Sdim if (isa<llvm::Constant>(src)) 395234353Sdim return EmitMemberPointerConversion(E, cast<llvm::Constant>(src)); 396212904Sdim 397234353Sdim llvm::Constant *adj = getMemberPointerAdjustment(E); 398234353Sdim if (!adj) return src; 399212904Sdim 400234353Sdim CGBuilderTy &Builder = CGF.Builder; 401234353Sdim bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer); 402212904Sdim 403234353Sdim const MemberPointerType *destTy = 404234353Sdim E->getType()->castAs<MemberPointerType>(); 405212904Sdim 406212904Sdim // For member data pointers, this is just a matter of adding the 407212904Sdim // offset if the source is non-null. 408234353Sdim if (destTy->isMemberDataPointer()) { 409234353Sdim llvm::Value *dst; 410234353Sdim if (isDerivedToBase) 411234353Sdim dst = Builder.CreateNSWSub(src, adj, "adj"); 412212904Sdim else 413234353Sdim dst = Builder.CreateNSWAdd(src, adj, "adj"); 414212904Sdim 415212904Sdim // Null check. 416234353Sdim llvm::Value *null = llvm::Constant::getAllOnesValue(src->getType()); 417234353Sdim llvm::Value *isNull = Builder.CreateICmpEQ(src, null, "memptr.isnull"); 418234353Sdim return Builder.CreateSelect(isNull, src, dst); 419212904Sdim } 420212904Sdim 421212904Sdim // The this-adjustment is left-shifted by 1 on ARM. 422212904Sdim if (IsARM) { 423234353Sdim uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue(); 424234353Sdim offset <<= 1; 425234353Sdim adj = llvm::ConstantInt::get(adj->getType(), offset); 426212904Sdim } 427212904Sdim 428234353Sdim llvm::Value *srcAdj = Builder.CreateExtractValue(src, 1, "src.adj"); 429234353Sdim llvm::Value *dstAdj; 430234353Sdim if (isDerivedToBase) 431234353Sdim dstAdj = Builder.CreateNSWSub(srcAdj, adj, "adj"); 432212904Sdim else 433234353Sdim dstAdj = Builder.CreateNSWAdd(srcAdj, adj, "adj"); 434212904Sdim 435234353Sdim return Builder.CreateInsertValue(src, dstAdj, 1); 436212904Sdim} 437212904Sdim 438212904Sdimllvm::Constant * 439234353SdimItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E, 440234353Sdim llvm::Constant *src) { 441234353Sdim assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || 442234353Sdim E->getCastKind() == CK_BaseToDerivedMemberPointer || 443234353Sdim E->getCastKind() == CK_ReinterpretMemberPointer); 444212904Sdim 445234353Sdim // Under Itanium, reinterprets don't require any additional processing. 446234353Sdim if (E->getCastKind() == CK_ReinterpretMemberPointer) return src; 447212904Sdim 448234353Sdim // If the adjustment is trivial, we don't need to do anything. 449234353Sdim llvm::Constant *adj = getMemberPointerAdjustment(E); 450234353Sdim if (!adj) return src; 451212904Sdim 452234353Sdim bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer); 453212904Sdim 454234353Sdim const MemberPointerType *destTy = 455234353Sdim E->getType()->castAs<MemberPointerType>(); 456212904Sdim 457234353Sdim // For member data pointers, this is just a matter of adding the 458234353Sdim // offset if the source is non-null. 459234353Sdim if (destTy->isMemberDataPointer()) { 460234353Sdim // null maps to null. 461234353Sdim if (src->isAllOnesValue()) return src; 462212904Sdim 463234353Sdim if (isDerivedToBase) 464234353Sdim return llvm::ConstantExpr::getNSWSub(src, adj); 465212904Sdim else 466234353Sdim return llvm::ConstantExpr::getNSWAdd(src, adj); 467212904Sdim } 468212904Sdim 469212904Sdim // The this-adjustment is left-shifted by 1 on ARM. 470212904Sdim if (IsARM) { 471234353Sdim uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue(); 472234353Sdim offset <<= 1; 473234353Sdim adj = llvm::ConstantInt::get(adj->getType(), offset); 474212904Sdim } 475212904Sdim 476234353Sdim llvm::Constant *srcAdj = llvm::ConstantExpr::getExtractValue(src, 1); 477234353Sdim llvm::Constant *dstAdj; 478234353Sdim if (isDerivedToBase) 479234353Sdim dstAdj = llvm::ConstantExpr::getNSWSub(srcAdj, adj); 480212904Sdim else 481234353Sdim dstAdj = llvm::ConstantExpr::getNSWAdd(srcAdj, adj); 482212904Sdim 483234353Sdim return llvm::ConstantExpr::getInsertValue(src, dstAdj, 1); 484234353Sdim} 485212904Sdim 486212904Sdimllvm::Constant * 487212904SdimItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { 488212904Sdim // Itanium C++ ABI 2.3: 489212904Sdim // A NULL pointer is represented as -1. 490212904Sdim if (MPT->isMemberDataPointer()) 491249423Sdim return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL, /*isSigned=*/true); 492212904Sdim 493249423Sdim llvm::Constant *Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0); 494212904Sdim llvm::Constant *Values[2] = { Zero, Zero }; 495224145Sdim return llvm::ConstantStruct::getAnon(Values); 496212904Sdim} 497212904Sdim 498218893Sdimllvm::Constant * 499218893SdimItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, 500218893Sdim CharUnits offset) { 501212904Sdim // Itanium C++ ABI 2.3: 502212904Sdim // A pointer to data member is an offset from the base address of 503212904Sdim // the class object containing it, represented as a ptrdiff_t 504249423Sdim return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity()); 505212904Sdim} 506212904Sdim 507212904Sdimllvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) { 508234353Sdim return BuildMemberPointer(MD, CharUnits::Zero()); 509234353Sdim} 510234353Sdim 511234353Sdimllvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD, 512234353Sdim CharUnits ThisAdjustment) { 513212904Sdim assert(MD->isInstance() && "Member function must not be static!"); 514212904Sdim MD = MD->getCanonicalDecl(); 515212904Sdim 516212904Sdim CodeGenTypes &Types = CGM.getTypes(); 517212904Sdim 518212904Sdim // Get the function pointer (or index if this is a virtual function). 519212904Sdim llvm::Constant *MemPtr[2]; 520212904Sdim if (MD->isVirtual()) { 521226633Sdim uint64_t Index = CGM.getVTableContext().getMethodVTableIndex(MD); 522212904Sdim 523221345Sdim const ASTContext &Context = getContext(); 524221345Sdim CharUnits PointerWidth = 525226633Sdim Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); 526221345Sdim uint64_t VTableOffset = (Index * PointerWidth.getQuantity()); 527212904Sdim 528212904Sdim if (IsARM) { 529212904Sdim // ARM C++ ABI 3.2.1: 530212904Sdim // This ABI specifies that adj contains twice the this 531212904Sdim // adjustment, plus 1 if the member function is virtual. The 532212904Sdim // least significant bit of adj then makes exactly the same 533212904Sdim // discrimination as the least significant bit of ptr does for 534212904Sdim // Itanium. 535249423Sdim MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset); 536249423Sdim MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy, 537234353Sdim 2 * ThisAdjustment.getQuantity() + 1); 538212904Sdim } else { 539212904Sdim // Itanium C++ ABI 2.3: 540212904Sdim // For a virtual function, [the pointer field] is 1 plus the 541212904Sdim // virtual table offset (in bytes) of the function, 542212904Sdim // represented as a ptrdiff_t. 543249423Sdim MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset + 1); 544249423Sdim MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy, 545234353Sdim ThisAdjustment.getQuantity()); 546212904Sdim } 547212904Sdim } else { 548221345Sdim const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); 549226633Sdim llvm::Type *Ty; 550212904Sdim // Check whether the function has a computable LLVM signature. 551224145Sdim if (Types.isFuncTypeConvertible(FPT)) { 552212904Sdim // The function has a computable LLVM signature; use the correct type. 553234353Sdim Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD)); 554212904Sdim } else { 555212904Sdim // Use an arbitrary non-function type to tell GetAddrOfFunction that the 556212904Sdim // function type is incomplete. 557249423Sdim Ty = CGM.PtrDiffTy; 558212904Sdim } 559221345Sdim llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty); 560212904Sdim 561249423Sdim MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy); 562249423Sdim MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy, (IsARM ? 2 : 1) * 563234353Sdim ThisAdjustment.getQuantity()); 564212904Sdim } 565212904Sdim 566224145Sdim return llvm::ConstantStruct::getAnon(MemPtr); 567212904Sdim} 568212904Sdim 569234353Sdimllvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP, 570234353Sdim QualType MPType) { 571234353Sdim const MemberPointerType *MPT = MPType->castAs<MemberPointerType>(); 572234353Sdim const ValueDecl *MPD = MP.getMemberPointerDecl(); 573234353Sdim if (!MPD) 574234353Sdim return EmitNullMemberPointer(MPT); 575234353Sdim 576234353Sdim // Compute the this-adjustment. 577234353Sdim CharUnits ThisAdjustment = CharUnits::Zero(); 578234353Sdim ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath(); 579234353Sdim bool DerivedMember = MP.isMemberPointerToDerivedMember(); 580234353Sdim const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext()); 581234353Sdim for (unsigned I = 0, N = Path.size(); I != N; ++I) { 582234353Sdim const CXXRecordDecl *Base = RD; 583234353Sdim const CXXRecordDecl *Derived = Path[I]; 584234353Sdim if (DerivedMember) 585234353Sdim std::swap(Base, Derived); 586234353Sdim ThisAdjustment += 587234353Sdim getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base); 588234353Sdim RD = Path[I]; 589234353Sdim } 590234353Sdim if (DerivedMember) 591234353Sdim ThisAdjustment = -ThisAdjustment; 592234353Sdim 593234353Sdim if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) 594234353Sdim return BuildMemberPointer(MD, ThisAdjustment); 595234353Sdim 596234353Sdim CharUnits FieldOffset = 597234353Sdim getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD)); 598234353Sdim return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset); 599234353Sdim} 600234353Sdim 601212904Sdim/// The comparison algorithm is pretty easy: the member pointers are 602212904Sdim/// the same if they're either bitwise identical *or* both null. 603212904Sdim/// 604212904Sdim/// ARM is different here only because null-ness is more complicated. 605212904Sdimllvm::Value * 606212904SdimItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, 607212904Sdim llvm::Value *L, 608212904Sdim llvm::Value *R, 609212904Sdim const MemberPointerType *MPT, 610212904Sdim bool Inequality) { 611212904Sdim CGBuilderTy &Builder = CGF.Builder; 612212904Sdim 613212904Sdim llvm::ICmpInst::Predicate Eq; 614212904Sdim llvm::Instruction::BinaryOps And, Or; 615212904Sdim if (Inequality) { 616212904Sdim Eq = llvm::ICmpInst::ICMP_NE; 617212904Sdim And = llvm::Instruction::Or; 618212904Sdim Or = llvm::Instruction::And; 619212904Sdim } else { 620212904Sdim Eq = llvm::ICmpInst::ICMP_EQ; 621212904Sdim And = llvm::Instruction::And; 622212904Sdim Or = llvm::Instruction::Or; 623212904Sdim } 624212904Sdim 625212904Sdim // Member data pointers are easy because there's a unique null 626212904Sdim // value, so it just comes down to bitwise equality. 627212904Sdim if (MPT->isMemberDataPointer()) 628212904Sdim return Builder.CreateICmp(Eq, L, R); 629212904Sdim 630212904Sdim // For member function pointers, the tautologies are more complex. 631212904Sdim // The Itanium tautology is: 632212904Sdim // (L == R) <==> (L.ptr == R.ptr && (L.ptr == 0 || L.adj == R.adj)) 633212904Sdim // The ARM tautology is: 634212904Sdim // (L == R) <==> (L.ptr == R.ptr && 635212904Sdim // (L.adj == R.adj || 636212904Sdim // (L.ptr == 0 && ((L.adj|R.adj) & 1) == 0))) 637212904Sdim // The inequality tautologies have exactly the same structure, except 638212904Sdim // applying De Morgan's laws. 639212904Sdim 640212904Sdim llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr"); 641212904Sdim llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr"); 642212904Sdim 643212904Sdim // This condition tests whether L.ptr == R.ptr. This must always be 644212904Sdim // true for equality to hold. 645212904Sdim llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr"); 646212904Sdim 647212904Sdim // This condition, together with the assumption that L.ptr == R.ptr, 648212904Sdim // tests whether the pointers are both null. ARM imposes an extra 649212904Sdim // condition. 650212904Sdim llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType()); 651212904Sdim llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null"); 652212904Sdim 653212904Sdim // This condition tests whether L.adj == R.adj. If this isn't 654212904Sdim // true, the pointers are unequal unless they're both null. 655212904Sdim llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj"); 656212904Sdim llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj"); 657212904Sdim llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj"); 658212904Sdim 659212904Sdim // Null member function pointers on ARM clear the low bit of Adj, 660212904Sdim // so the zero condition has to check that neither low bit is set. 661212904Sdim if (IsARM) { 662212904Sdim llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1); 663212904Sdim 664212904Sdim // Compute (l.adj | r.adj) & 1 and test it against zero. 665212904Sdim llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj"); 666212904Sdim llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One); 667212904Sdim llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero, 668212904Sdim "cmp.or.adj"); 669212904Sdim EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero); 670212904Sdim } 671212904Sdim 672212904Sdim // Tie together all our conditions. 673212904Sdim llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq); 674212904Sdim Result = Builder.CreateBinOp(And, PtrEq, Result, 675212904Sdim Inequality ? "memptr.ne" : "memptr.eq"); 676212904Sdim return Result; 677212904Sdim} 678212904Sdim 679212904Sdimllvm::Value * 680212904SdimItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, 681212904Sdim llvm::Value *MemPtr, 682212904Sdim const MemberPointerType *MPT) { 683212904Sdim CGBuilderTy &Builder = CGF.Builder; 684212904Sdim 685212904Sdim /// For member data pointers, this is just a check against -1. 686212904Sdim if (MPT->isMemberDataPointer()) { 687249423Sdim assert(MemPtr->getType() == CGM.PtrDiffTy); 688212904Sdim llvm::Value *NegativeOne = 689212904Sdim llvm::Constant::getAllOnesValue(MemPtr->getType()); 690212904Sdim return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool"); 691212904Sdim } 692212904Sdim 693221345Sdim // In Itanium, a member function pointer is not null if 'ptr' is not null. 694212904Sdim llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr"); 695212904Sdim 696212904Sdim llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0); 697212904Sdim llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool"); 698212904Sdim 699221345Sdim // On ARM, a member function pointer is also non-null if the low bit of 'adj' 700221345Sdim // (the virtual bit) is set. 701212904Sdim if (IsARM) { 702212904Sdim llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1); 703212904Sdim llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj"); 704212904Sdim llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit"); 705221345Sdim llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero, 706221345Sdim "memptr.isvirtual"); 707221345Sdim Result = Builder.CreateOr(Result, IsVirtual); 708212904Sdim } 709212904Sdim 710212904Sdim return Result; 711212904Sdim} 712212904Sdim 713212904Sdim/// The Itanium ABI requires non-zero initialization only for data 714212904Sdim/// member pointers, for which '0' is a valid offset. 715212904Sdimbool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) { 716212904Sdim return MPT->getPointeeType()->isFunctionType(); 717212904Sdim} 718212904Sdim 719243830Sdim/// The Itanium ABI always places an offset to the complete object 720243830Sdim/// at entry -2 in the vtable. 721243830Sdimllvm::Value *ItaniumCXXABI::adjustToCompleteObject(CodeGenFunction &CGF, 722243830Sdim llvm::Value *ptr, 723243830Sdim QualType type) { 724243830Sdim // Grab the vtable pointer as an intptr_t*. 725243830Sdim llvm::Value *vtable = CGF.GetVTablePtr(ptr, CGF.IntPtrTy->getPointerTo()); 726243830Sdim 727243830Sdim // Track back to entry -2 and pull out the offset there. 728243830Sdim llvm::Value *offsetPtr = 729243830Sdim CGF.Builder.CreateConstInBoundsGEP1_64(vtable, -2, "complete-offset.ptr"); 730243830Sdim llvm::LoadInst *offset = CGF.Builder.CreateLoad(offsetPtr); 731243830Sdim offset->setAlignment(CGF.PointerAlignInBytes); 732243830Sdim 733243830Sdim // Apply the offset. 734243830Sdim ptr = CGF.Builder.CreateBitCast(ptr, CGF.Int8PtrTy); 735243830Sdim return CGF.Builder.CreateInBoundsGEP(ptr, offset); 736243830Sdim} 737243830Sdim 738212904Sdim/// The generic ABI passes 'this', plus a VTT if it's initializing a 739212904Sdim/// base subobject. 740212904Sdimvoid ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, 741212904Sdim CXXCtorType Type, 742212904Sdim CanQualType &ResTy, 743226633Sdim SmallVectorImpl<CanQualType> &ArgTys) { 744212904Sdim ASTContext &Context = getContext(); 745212904Sdim 746212904Sdim // 'this' is already there. 747212904Sdim 748212904Sdim // Check if we need to add a VTT parameter (which has type void **). 749212904Sdim if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0) 750212904Sdim ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); 751212904Sdim} 752212904Sdim 753212904Sdim/// The ARM ABI does the same as the Itanium ABI, but returns 'this'. 754212904Sdimvoid ARMCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, 755212904Sdim CXXCtorType Type, 756212904Sdim CanQualType &ResTy, 757226633Sdim SmallVectorImpl<CanQualType> &ArgTys) { 758212904Sdim ItaniumCXXABI::BuildConstructorSignature(Ctor, Type, ResTy, ArgTys); 759212904Sdim ResTy = ArgTys[0]; 760212904Sdim} 761212904Sdim 762212904Sdim/// The generic ABI passes 'this', plus a VTT if it's destroying a 763212904Sdim/// base subobject. 764212904Sdimvoid ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, 765212904Sdim CXXDtorType Type, 766212904Sdim CanQualType &ResTy, 767226633Sdim SmallVectorImpl<CanQualType> &ArgTys) { 768212904Sdim ASTContext &Context = getContext(); 769212904Sdim 770212904Sdim // 'this' is already there. 771212904Sdim 772212904Sdim // Check if we need to add a VTT parameter (which has type void **). 773212904Sdim if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0) 774212904Sdim ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); 775212904Sdim} 776212904Sdim 777212904Sdim/// The ARM ABI does the same as the Itanium ABI, but returns 'this' 778212904Sdim/// for non-deleting destructors. 779212904Sdimvoid ARMCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, 780212904Sdim CXXDtorType Type, 781212904Sdim CanQualType &ResTy, 782226633Sdim SmallVectorImpl<CanQualType> &ArgTys) { 783212904Sdim ItaniumCXXABI::BuildDestructorSignature(Dtor, Type, ResTy, ArgTys); 784212904Sdim 785212904Sdim if (Type != Dtor_Deleting) 786212904Sdim ResTy = ArgTys[0]; 787212904Sdim} 788212904Sdim 789212904Sdimvoid ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, 790212904Sdim QualType &ResTy, 791212904Sdim FunctionArgList &Params) { 792212904Sdim /// Create the 'this' variable. 793212904Sdim BuildThisParam(CGF, Params); 794212904Sdim 795212904Sdim const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); 796212904Sdim assert(MD->isInstance()); 797212904Sdim 798212904Sdim // Check if we need a VTT parameter as well. 799212904Sdim if (CodeGenVTables::needsVTTParameter(CGF.CurGD)) { 800212904Sdim ASTContext &Context = getContext(); 801212904Sdim 802212904Sdim // FIXME: avoid the fake decl 803212904Sdim QualType T = Context.getPointerType(Context.VoidPtrTy); 804212904Sdim ImplicitParamDecl *VTTDecl 805212904Sdim = ImplicitParamDecl::Create(Context, 0, MD->getLocation(), 806212904Sdim &Context.Idents.get("vtt"), T); 807221345Sdim Params.push_back(VTTDecl); 808212904Sdim getVTTDecl(CGF) = VTTDecl; 809212904Sdim } 810212904Sdim} 811212904Sdim 812212904Sdimvoid ARMCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, 813212904Sdim QualType &ResTy, 814212904Sdim FunctionArgList &Params) { 815212904Sdim ItaniumCXXABI::BuildInstanceFunctionParams(CGF, ResTy, Params); 816212904Sdim 817212904Sdim // Return 'this' from certain constructors and destructors. 818212904Sdim if (HasThisReturn(CGF.CurGD)) 819221345Sdim ResTy = Params[0]->getType(); 820212904Sdim} 821212904Sdim 822212904Sdimvoid ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { 823212904Sdim /// Initialize the 'this' slot. 824212904Sdim EmitThisParam(CGF); 825212904Sdim 826212904Sdim /// Initialize the 'vtt' slot if needed. 827212904Sdim if (getVTTDecl(CGF)) { 828212904Sdim getVTTValue(CGF) 829212904Sdim = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)), 830212904Sdim "vtt"); 831212904Sdim } 832212904Sdim} 833212904Sdim 834212904Sdimvoid ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { 835212904Sdim ItaniumCXXABI::EmitInstanceFunctionProlog(CGF); 836212904Sdim 837212904Sdim /// Initialize the return slot to 'this' at the start of the 838212904Sdim /// function. 839212904Sdim if (HasThisReturn(CGF.CurGD)) 840234353Sdim CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue); 841212904Sdim} 842212904Sdim 843249423Sdimllvm::Value *ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF, 844249423Sdim const CXXConstructorDecl *D, 845249423Sdim CXXCtorType Type, bool ForVirtualBase, 846249423Sdim bool Delegating, 847249423Sdim llvm::Value *This, 848249423Sdim CallExpr::const_arg_iterator ArgBeg, 849249423Sdim CallExpr::const_arg_iterator ArgEnd) { 850249423Sdim llvm::Value *VTT = CGF.GetVTTParameter(GlobalDecl(D, Type), ForVirtualBase, 851249423Sdim Delegating); 852249423Sdim QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy); 853249423Sdim llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); 854249423Sdim 855249423Sdim // FIXME: Provide a source location here. 856249423Sdim CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This, 857249423Sdim VTT, VTTTy, ArgBeg, ArgEnd); 858249423Sdim return Callee; 859249423Sdim} 860249423Sdim 861249423SdimRValue ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF, 862249423Sdim const CXXDestructorDecl *Dtor, 863249423Sdim CXXDtorType DtorType, 864249423Sdim SourceLocation CallLoc, 865249423Sdim ReturnValueSlot ReturnValue, 866249423Sdim llvm::Value *This) { 867249423Sdim assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete); 868249423Sdim 869249423Sdim const CGFunctionInfo *FInfo 870249423Sdim = &CGM.getTypes().arrangeCXXDestructor(Dtor, DtorType); 871249423Sdim llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo); 872249423Sdim llvm::Value *Callee = CGF.BuildVirtualCall(Dtor, DtorType, This, Ty); 873249423Sdim 874249423Sdim return CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValue, This, 875249423Sdim /*ImplicitParam=*/0, QualType(), 0, 0); 876249423Sdim} 877249423Sdim 878212904Sdimvoid ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, 879212904Sdim RValue RV, QualType ResultType) { 880212904Sdim if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl())) 881212904Sdim return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType); 882212904Sdim 883212904Sdim // Destructor thunks in the ARM ABI have indeterminate results. 884226633Sdim llvm::Type *T = 885212904Sdim cast<llvm::PointerType>(CGF.ReturnValue->getType())->getElementType(); 886212904Sdim RValue Undef = RValue::get(llvm::UndefValue::get(T)); 887212904Sdim return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType); 888212904Sdim} 889212904Sdim 890212904Sdim/************************** Array allocation cookies **************************/ 891212904Sdim 892239462SdimCharUnits ItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) { 893239462Sdim // The array cookie is a size_t; pad that up to the element alignment. 894239462Sdim // The cookie is actually right-justified in that space. 895239462Sdim return std::max(CharUnits::fromQuantity(CGM.SizeSizeInBytes), 896239462Sdim CGM.getContext().getTypeAlignInChars(elementType)); 897218893Sdim} 898212904Sdim 899212904Sdimllvm::Value *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 900212904Sdim llvm::Value *NewPtr, 901212904Sdim llvm::Value *NumElements, 902218893Sdim const CXXNewExpr *expr, 903212904Sdim QualType ElementType) { 904239462Sdim assert(requiresArrayCookie(expr)); 905212904Sdim 906243830Sdim unsigned AS = NewPtr->getType()->getPointerAddressSpace(); 907212904Sdim 908212904Sdim ASTContext &Ctx = getContext(); 909212904Sdim QualType SizeTy = Ctx.getSizeType(); 910212904Sdim CharUnits SizeSize = Ctx.getTypeSizeInChars(SizeTy); 911212904Sdim 912212904Sdim // The size of the cookie. 913212904Sdim CharUnits CookieSize = 914212904Sdim std::max(SizeSize, Ctx.getTypeAlignInChars(ElementType)); 915239462Sdim assert(CookieSize == getArrayCookieSizeImpl(ElementType)); 916212904Sdim 917212904Sdim // Compute an offset to the cookie. 918212904Sdim llvm::Value *CookiePtr = NewPtr; 919212904Sdim CharUnits CookieOffset = CookieSize - SizeSize; 920212904Sdim if (!CookieOffset.isZero()) 921212904Sdim CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_64(CookiePtr, 922212904Sdim CookieOffset.getQuantity()); 923212904Sdim 924212904Sdim // Write the number of elements into the appropriate slot. 925212904Sdim llvm::Value *NumElementsPtr 926212904Sdim = CGF.Builder.CreateBitCast(CookiePtr, 927212904Sdim CGF.ConvertType(SizeTy)->getPointerTo(AS)); 928212904Sdim CGF.Builder.CreateStore(NumElements, NumElementsPtr); 929212904Sdim 930212904Sdim // Finally, compute a pointer to the actual data buffer by skipping 931212904Sdim // over the cookie completely. 932212904Sdim return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr, 933212904Sdim CookieSize.getQuantity()); 934212904Sdim} 935212904Sdim 936239462Sdimllvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, 937239462Sdim llvm::Value *allocPtr, 938239462Sdim CharUnits cookieSize) { 939239462Sdim // The element size is right-justified in the cookie. 940239462Sdim llvm::Value *numElementsPtr = allocPtr; 941239462Sdim CharUnits numElementsOffset = 942239462Sdim cookieSize - CharUnits::fromQuantity(CGF.SizeSizeInBytes); 943239462Sdim if (!numElementsOffset.isZero()) 944239462Sdim numElementsPtr = 945239462Sdim CGF.Builder.CreateConstInBoundsGEP1_64(numElementsPtr, 946239462Sdim numElementsOffset.getQuantity()); 947212904Sdim 948243830Sdim unsigned AS = allocPtr->getType()->getPointerAddressSpace(); 949239462Sdim numElementsPtr = 950239462Sdim CGF.Builder.CreateBitCast(numElementsPtr, CGF.SizeTy->getPointerTo(AS)); 951239462Sdim return CGF.Builder.CreateLoad(numElementsPtr); 952212904Sdim} 953212904Sdim 954239462SdimCharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) { 955249423Sdim // ARM says that the cookie is always: 956212904Sdim // struct array_cookie { 957212904Sdim // std::size_t element_size; // element_size != 0 958212904Sdim // std::size_t element_count; 959212904Sdim // }; 960249423Sdim // But the base ABI doesn't give anything an alignment greater than 961249423Sdim // 8, so we can dismiss this as typical ABI-author blindness to 962249423Sdim // actual language complexity and round up to the element alignment. 963249423Sdim return std::max(CharUnits::fromQuantity(2 * CGM.SizeSizeInBytes), 964249423Sdim CGM.getContext().getTypeAlignInChars(elementType)); 965212904Sdim} 966212904Sdim 967212904Sdimllvm::Value *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 968249423Sdim llvm::Value *newPtr, 969249423Sdim llvm::Value *numElements, 970218893Sdim const CXXNewExpr *expr, 971249423Sdim QualType elementType) { 972239462Sdim assert(requiresArrayCookie(expr)); 973212904Sdim 974249423Sdim // NewPtr is a char*, but we generalize to arbitrary addrspaces. 975249423Sdim unsigned AS = newPtr->getType()->getPointerAddressSpace(); 976212904Sdim 977212904Sdim // The cookie is always at the start of the buffer. 978249423Sdim llvm::Value *cookie = newPtr; 979212904Sdim 980212904Sdim // The first element is the element size. 981249423Sdim cookie = CGF.Builder.CreateBitCast(cookie, CGF.SizeTy->getPointerTo(AS)); 982249423Sdim llvm::Value *elementSize = llvm::ConstantInt::get(CGF.SizeTy, 983249423Sdim getContext().getTypeSizeInChars(elementType).getQuantity()); 984249423Sdim CGF.Builder.CreateStore(elementSize, cookie); 985212904Sdim 986212904Sdim // The second element is the element count. 987249423Sdim cookie = CGF.Builder.CreateConstInBoundsGEP1_32(cookie, 1); 988249423Sdim CGF.Builder.CreateStore(numElements, cookie); 989212904Sdim 990212904Sdim // Finally, compute a pointer to the actual data buffer by skipping 991212904Sdim // over the cookie completely. 992249423Sdim CharUnits cookieSize = ARMCXXABI::getArrayCookieSizeImpl(elementType); 993249423Sdim return CGF.Builder.CreateConstInBoundsGEP1_64(newPtr, 994249423Sdim cookieSize.getQuantity()); 995212904Sdim} 996212904Sdim 997239462Sdimllvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, 998239462Sdim llvm::Value *allocPtr, 999239462Sdim CharUnits cookieSize) { 1000239462Sdim // The number of elements is at offset sizeof(size_t) relative to 1001239462Sdim // the allocated pointer. 1002239462Sdim llvm::Value *numElementsPtr 1003239462Sdim = CGF.Builder.CreateConstInBoundsGEP1_64(allocPtr, CGF.SizeSizeInBytes); 1004212904Sdim 1005243830Sdim unsigned AS = allocPtr->getType()->getPointerAddressSpace(); 1006239462Sdim numElementsPtr = 1007239462Sdim CGF.Builder.CreateBitCast(numElementsPtr, CGF.SizeTy->getPointerTo(AS)); 1008239462Sdim return CGF.Builder.CreateLoad(numElementsPtr); 1009212904Sdim} 1010212904Sdim 1011218893Sdim/*********************** Static local initialization **************************/ 1012218893Sdim 1013218893Sdimstatic llvm::Constant *getGuardAcquireFn(CodeGenModule &CGM, 1014224145Sdim llvm::PointerType *GuardPtrTy) { 1015218893Sdim // int __cxa_guard_acquire(__guard *guard_object); 1016226633Sdim llvm::FunctionType *FTy = 1017218893Sdim llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy), 1018226633Sdim GuardPtrTy, /*isVarArg=*/false); 1019234353Sdim return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire", 1020249423Sdim llvm::AttributeSet::get(CGM.getLLVMContext(), 1021249423Sdim llvm::AttributeSet::FunctionIndex, 1022249423Sdim llvm::Attribute::NoUnwind)); 1023218893Sdim} 1024218893Sdim 1025218893Sdimstatic llvm::Constant *getGuardReleaseFn(CodeGenModule &CGM, 1026224145Sdim llvm::PointerType *GuardPtrTy) { 1027218893Sdim // void __cxa_guard_release(__guard *guard_object); 1028226633Sdim llvm::FunctionType *FTy = 1029234353Sdim llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false); 1030234353Sdim return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release", 1031249423Sdim llvm::AttributeSet::get(CGM.getLLVMContext(), 1032249423Sdim llvm::AttributeSet::FunctionIndex, 1033249423Sdim llvm::Attribute::NoUnwind)); 1034218893Sdim} 1035218893Sdim 1036218893Sdimstatic llvm::Constant *getGuardAbortFn(CodeGenModule &CGM, 1037224145Sdim llvm::PointerType *GuardPtrTy) { 1038218893Sdim // void __cxa_guard_abort(__guard *guard_object); 1039226633Sdim llvm::FunctionType *FTy = 1040234353Sdim llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false); 1041234353Sdim return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort", 1042249423Sdim llvm::AttributeSet::get(CGM.getLLVMContext(), 1043249423Sdim llvm::AttributeSet::FunctionIndex, 1044249423Sdim llvm::Attribute::NoUnwind)); 1045218893Sdim} 1046218893Sdim 1047218893Sdimnamespace { 1048218893Sdim struct CallGuardAbort : EHScopeStack::Cleanup { 1049218893Sdim llvm::GlobalVariable *Guard; 1050218893Sdim CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {} 1051218893Sdim 1052224145Sdim void Emit(CodeGenFunction &CGF, Flags flags) { 1053249423Sdim CGF.EmitNounwindRuntimeCall(getGuardAbortFn(CGF.CGM, Guard->getType()), 1054249423Sdim Guard); 1055218893Sdim } 1056218893Sdim }; 1057218893Sdim} 1058218893Sdim 1059218893Sdim/// The ARM code here follows the Itanium code closely enough that we 1060218893Sdim/// just special-case it at particular places. 1061218893Sdimvoid ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, 1062218893Sdim const VarDecl &D, 1063234353Sdim llvm::GlobalVariable *var, 1064234353Sdim bool shouldPerformInit) { 1065218893Sdim CGBuilderTy &Builder = CGF.Builder; 1066218893Sdim 1067251662Sdim // We only need to use thread-safe statics for local non-TLS variables; 1068218893Sdim // global initialization is always single-threaded. 1069251662Sdim bool threadsafe = getContext().getLangOpts().ThreadsafeStatics && 1070251662Sdim D.isLocalVarDecl() && !D.getTLSKind(); 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. 1074234353Sdim bool useInt8GuardVariable = !threadsafe && var->hasInternalLinkage(); 1075234353Sdim 1076234353Sdim llvm::IntegerType *guardTy; 1077224145Sdim if (useInt8GuardVariable) { 1078234353Sdim guardTy = CGF.Int8Ty; 1079224145Sdim } else { 1080249423Sdim // Guard variables are 64 bits in the generic ABI and size width on ARM 1081249423Sdim // (i.e. 32-bit on AArch32, 64-bit on AArch64). 1082249423Sdim guardTy = (IsARM ? CGF.SizeTy : CGF.Int64Ty); 1083221345Sdim } 1084234353Sdim llvm::PointerType *guardPtrTy = guardTy->getPointerTo(); 1085218893Sdim 1086234353Sdim // Create the guard variable if we don't already have it (as we 1087234353Sdim // might if we're double-emitting this function body). 1088234353Sdim llvm::GlobalVariable *guard = CGM.getStaticLocalDeclGuardAddress(&D); 1089234353Sdim if (!guard) { 1090234353Sdim // Mangle the name for the guard. 1091234353Sdim SmallString<256> guardName; 1092234353Sdim { 1093234353Sdim llvm::raw_svector_ostream out(guardName); 1094234353Sdim getMangleContext().mangleItaniumGuardVariable(&D, out); 1095234353Sdim out.flush(); 1096234353Sdim } 1097218893Sdim 1098234353Sdim // Create the guard variable with a zero-initializer. 1099234353Sdim // Just absorb linkage and visibility from the guarded variable. 1100234353Sdim guard = new llvm::GlobalVariable(CGM.getModule(), guardTy, 1101234353Sdim false, var->getLinkage(), 1102234353Sdim llvm::ConstantInt::get(guardTy, 0), 1103234353Sdim guardName.str()); 1104234353Sdim guard->setVisibility(var->getVisibility()); 1105251662Sdim // If the variable is thread-local, so is its guard variable. 1106251662Sdim guard->setThreadLocalMode(var->getThreadLocalMode()); 1107218893Sdim 1108234353Sdim CGM.setStaticLocalDeclGuardAddress(&D, guard); 1109234353Sdim } 1110234353Sdim 1111218893Sdim // Test whether the variable has completed initialization. 1112234353Sdim llvm::Value *isInitialized; 1113218893Sdim 1114218893Sdim // ARM C++ ABI 3.2.3.1: 1115218893Sdim // To support the potential use of initialization guard variables 1116218893Sdim // as semaphores that are the target of ARM SWP and LDREX/STREX 1117218893Sdim // synchronizing instructions we define a static initialization 1118218893Sdim // guard variable to be a 4-byte aligned, 4- byte word with the 1119218893Sdim // following inline access protocol. 1120218893Sdim // #define INITIALIZED 1 1121218893Sdim // if ((obj_guard & INITIALIZED) != INITIALIZED) { 1122218893Sdim // if (__cxa_guard_acquire(&obj_guard)) 1123218893Sdim // ... 1124218893Sdim // } 1125224145Sdim if (IsARM && !useInt8GuardVariable) { 1126234353Sdim llvm::Value *V = Builder.CreateLoad(guard); 1127249423Sdim llvm::Value *Test1 = llvm::ConstantInt::get(guardTy, 1); 1128249423Sdim V = Builder.CreateAnd(V, Test1); 1129234353Sdim isInitialized = Builder.CreateIsNull(V, "guard.uninitialized"); 1130218893Sdim 1131218893Sdim // Itanium C++ ABI 3.3.2: 1132218893Sdim // The following is pseudo-code showing how these functions can be used: 1133218893Sdim // if (obj_guard.first_byte == 0) { 1134218893Sdim // if ( __cxa_guard_acquire (&obj_guard) ) { 1135218893Sdim // try { 1136218893Sdim // ... initialize the object ...; 1137218893Sdim // } catch (...) { 1138218893Sdim // __cxa_guard_abort (&obj_guard); 1139218893Sdim // throw; 1140218893Sdim // } 1141218893Sdim // ... queue object destructor with __cxa_atexit() ...; 1142218893Sdim // __cxa_guard_release (&obj_guard); 1143218893Sdim // } 1144218893Sdim // } 1145218893Sdim } else { 1146218893Sdim // Load the first byte of the guard variable. 1147226633Sdim llvm::LoadInst *LI = 1148234353Sdim Builder.CreateLoad(Builder.CreateBitCast(guard, CGM.Int8PtrTy)); 1149226633Sdim LI->setAlignment(1); 1150218893Sdim 1151226633Sdim // Itanium ABI: 1152226633Sdim // An implementation supporting thread-safety on multiprocessor 1153226633Sdim // systems must also guarantee that references to the initialized 1154226633Sdim // object do not occur before the load of the initialization flag. 1155226633Sdim // 1156226633Sdim // In LLVM, we do this by marking the load Acquire. 1157226633Sdim if (threadsafe) 1158226633Sdim LI->setAtomic(llvm::Acquire); 1159226633Sdim 1160234353Sdim isInitialized = Builder.CreateIsNull(LI, "guard.uninitialized"); 1161218893Sdim } 1162218893Sdim 1163218893Sdim llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check"); 1164218893Sdim llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end"); 1165218893Sdim 1166218893Sdim // Check if the first byte of the guard variable is zero. 1167234353Sdim Builder.CreateCondBr(isInitialized, InitCheckBlock, EndBlock); 1168218893Sdim 1169218893Sdim CGF.EmitBlock(InitCheckBlock); 1170218893Sdim 1171218893Sdim // Variables used when coping with thread-safe statics and exceptions. 1172224145Sdim if (threadsafe) { 1173218893Sdim // Call __cxa_guard_acquire. 1174218893Sdim llvm::Value *V 1175249423Sdim = CGF.EmitNounwindRuntimeCall(getGuardAcquireFn(CGM, guardPtrTy), guard); 1176218893Sdim 1177218893Sdim llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); 1178218893Sdim 1179218893Sdim Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), 1180218893Sdim InitBlock, EndBlock); 1181218893Sdim 1182218893Sdim // Call __cxa_guard_abort along the exceptional edge. 1183234353Sdim CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, guard); 1184218893Sdim 1185218893Sdim CGF.EmitBlock(InitBlock); 1186218893Sdim } 1187218893Sdim 1188218893Sdim // Emit the initializer and add a global destructor if appropriate. 1189234353Sdim CGF.EmitCXXGlobalVarDeclInit(D, var, shouldPerformInit); 1190218893Sdim 1191224145Sdim if (threadsafe) { 1192218893Sdim // Pop the guard-abort cleanup if we pushed one. 1193218893Sdim CGF.PopCleanupBlock(); 1194218893Sdim 1195218893Sdim // Call __cxa_guard_release. This cannot throw. 1196249423Sdim CGF.EmitNounwindRuntimeCall(getGuardReleaseFn(CGM, guardPtrTy), guard); 1197218893Sdim } else { 1198234353Sdim Builder.CreateStore(llvm::ConstantInt::get(guardTy, 1), guard); 1199218893Sdim } 1200218893Sdim 1201218893Sdim CGF.EmitBlock(EndBlock); 1202218893Sdim} 1203239462Sdim 1204239462Sdim/// Register a global destructor using __cxa_atexit. 1205239462Sdimstatic void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF, 1206239462Sdim llvm::Constant *dtor, 1207251662Sdim llvm::Constant *addr, 1208251662Sdim bool TLS) { 1209251662Sdim const char *Name = "__cxa_atexit"; 1210251662Sdim if (TLS) { 1211251662Sdim const llvm::Triple &T = CGF.getTarget().getTriple(); 1212251662Sdim Name = T.isMacOSX() ? "_tlv_atexit" : "__cxa_thread_atexit"; 1213251662Sdim } 1214251662Sdim 1215239462Sdim // We're assuming that the destructor function is something we can 1216239462Sdim // reasonably call with the default CC. Go ahead and cast it to the 1217239462Sdim // right prototype. 1218239462Sdim llvm::Type *dtorTy = 1219239462Sdim llvm::FunctionType::get(CGF.VoidTy, CGF.Int8PtrTy, false)->getPointerTo(); 1220239462Sdim 1221239462Sdim // extern "C" int __cxa_atexit(void (*f)(void *), void *p, void *d); 1222239462Sdim llvm::Type *paramTys[] = { dtorTy, CGF.Int8PtrTy, CGF.Int8PtrTy }; 1223239462Sdim llvm::FunctionType *atexitTy = 1224239462Sdim llvm::FunctionType::get(CGF.IntTy, paramTys, false); 1225239462Sdim 1226239462Sdim // Fetch the actual function. 1227251662Sdim llvm::Constant *atexit = CGF.CGM.CreateRuntimeFunction(atexitTy, Name); 1228239462Sdim if (llvm::Function *fn = dyn_cast<llvm::Function>(atexit)) 1229239462Sdim fn->setDoesNotThrow(); 1230239462Sdim 1231239462Sdim // Create a variable that binds the atexit to this shared object. 1232239462Sdim llvm::Constant *handle = 1233239462Sdim CGF.CGM.CreateRuntimeVariable(CGF.Int8Ty, "__dso_handle"); 1234239462Sdim 1235239462Sdim llvm::Value *args[] = { 1236239462Sdim llvm::ConstantExpr::getBitCast(dtor, dtorTy), 1237239462Sdim llvm::ConstantExpr::getBitCast(addr, CGF.Int8PtrTy), 1238239462Sdim handle 1239239462Sdim }; 1240249423Sdim CGF.EmitNounwindRuntimeCall(atexit, args); 1241239462Sdim} 1242239462Sdim 1243239462Sdim/// Register a global destructor as best as we know how. 1244239462Sdimvoid ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF, 1245251662Sdim const VarDecl &D, 1246239462Sdim llvm::Constant *dtor, 1247239462Sdim llvm::Constant *addr) { 1248239462Sdim // Use __cxa_atexit if available. 1249251662Sdim if (CGM.getCodeGenOpts().CXAAtExit) 1250251662Sdim return emitGlobalDtorWithCXAAtExit(CGF, dtor, addr, D.getTLSKind()); 1251239462Sdim 1252251662Sdim if (D.getTLSKind()) 1253251662Sdim CGM.ErrorUnsupported(&D, "non-trivial TLS destruction"); 1254251662Sdim 1255239462Sdim // In Apple kexts, we want to add a global destructor entry. 1256239462Sdim // FIXME: shouldn't this be guarded by some variable? 1257243830Sdim if (CGM.getLangOpts().AppleKext) { 1258239462Sdim // Generate a global destructor entry. 1259239462Sdim return CGM.AddCXXDtorEntry(dtor, addr); 1260239462Sdim } 1261239462Sdim 1262239462Sdim CGF.registerGlobalDtorWithAtExit(dtor, addr); 1263239462Sdim} 1264251662Sdim 1265251662Sdim/// Get the appropriate linkage for the wrapper function. This is essentially 1266251662Sdim/// the weak form of the variable's linkage; every translation unit which wneeds 1267251662Sdim/// the wrapper emits a copy, and we want the linker to merge them. 1268251662Sdimstatic llvm::GlobalValue::LinkageTypes getThreadLocalWrapperLinkage( 1269251662Sdim llvm::GlobalValue::LinkageTypes VarLinkage) { 1270251662Sdim if (llvm::GlobalValue::isLinkerPrivateLinkage(VarLinkage)) 1271251662Sdim return llvm::GlobalValue::LinkerPrivateWeakLinkage; 1272251662Sdim // For internal linkage variables, we don't need an external or weak wrapper. 1273251662Sdim if (llvm::GlobalValue::isLocalLinkage(VarLinkage)) 1274251662Sdim return VarLinkage; 1275251662Sdim return llvm::GlobalValue::WeakODRLinkage; 1276251662Sdim} 1277251662Sdim 1278251662Sdimllvm::Function * 1279251662SdimItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD, 1280251662Sdim llvm::GlobalVariable *Var) { 1281251662Sdim // Mangle the name for the thread_local wrapper function. 1282251662Sdim SmallString<256> WrapperName; 1283251662Sdim { 1284251662Sdim llvm::raw_svector_ostream Out(WrapperName); 1285251662Sdim getMangleContext().mangleItaniumThreadLocalWrapper(VD, Out); 1286251662Sdim Out.flush(); 1287251662Sdim } 1288251662Sdim 1289251662Sdim if (llvm::Value *V = Var->getParent()->getNamedValue(WrapperName)) 1290251662Sdim return cast<llvm::Function>(V); 1291251662Sdim 1292251662Sdim llvm::Type *RetTy = Var->getType(); 1293251662Sdim if (VD->getType()->isReferenceType()) 1294251662Sdim RetTy = RetTy->getPointerElementType(); 1295251662Sdim 1296251662Sdim llvm::FunctionType *FnTy = llvm::FunctionType::get(RetTy, false); 1297251662Sdim llvm::Function *Wrapper = llvm::Function::Create( 1298251662Sdim FnTy, getThreadLocalWrapperLinkage(Var->getLinkage()), WrapperName.str(), 1299251662Sdim &CGM.getModule()); 1300251662Sdim // Always resolve references to the wrapper at link time. 1301251662Sdim Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility); 1302251662Sdim return Wrapper; 1303251662Sdim} 1304251662Sdim 1305251662Sdimvoid ItaniumCXXABI::EmitThreadLocalInitFuncs( 1306251662Sdim llvm::ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *> > Decls, 1307251662Sdim llvm::Function *InitFunc) { 1308251662Sdim for (unsigned I = 0, N = Decls.size(); I != N; ++I) { 1309251662Sdim const VarDecl *VD = Decls[I].first; 1310251662Sdim llvm::GlobalVariable *Var = Decls[I].second; 1311251662Sdim 1312251662Sdim // Mangle the name for the thread_local initialization function. 1313251662Sdim SmallString<256> InitFnName; 1314251662Sdim { 1315251662Sdim llvm::raw_svector_ostream Out(InitFnName); 1316251662Sdim getMangleContext().mangleItaniumThreadLocalInit(VD, Out); 1317251662Sdim Out.flush(); 1318251662Sdim } 1319251662Sdim 1320251662Sdim // If we have a definition for the variable, emit the initialization 1321251662Sdim // function as an alias to the global Init function (if any). Otherwise, 1322251662Sdim // produce a declaration of the initialization function. 1323251662Sdim llvm::GlobalValue *Init = 0; 1324251662Sdim bool InitIsInitFunc = false; 1325251662Sdim if (VD->hasDefinition()) { 1326251662Sdim InitIsInitFunc = true; 1327251662Sdim if (InitFunc) 1328251662Sdim Init = 1329251662Sdim new llvm::GlobalAlias(InitFunc->getType(), Var->getLinkage(), 1330251662Sdim InitFnName.str(), InitFunc, &CGM.getModule()); 1331251662Sdim } else { 1332251662Sdim // Emit a weak global function referring to the initialization function. 1333251662Sdim // This function will not exist if the TU defining the thread_local 1334251662Sdim // variable in question does not need any dynamic initialization for 1335251662Sdim // its thread_local variables. 1336251662Sdim llvm::FunctionType *FnTy = llvm::FunctionType::get(CGM.VoidTy, false); 1337251662Sdim Init = llvm::Function::Create( 1338251662Sdim FnTy, llvm::GlobalVariable::ExternalWeakLinkage, InitFnName.str(), 1339251662Sdim &CGM.getModule()); 1340251662Sdim } 1341251662Sdim 1342251662Sdim if (Init) 1343251662Sdim Init->setVisibility(Var->getVisibility()); 1344251662Sdim 1345251662Sdim llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Var); 1346251662Sdim llvm::LLVMContext &Context = CGM.getModule().getContext(); 1347251662Sdim llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper); 1348251662Sdim CGBuilderTy Builder(Entry); 1349251662Sdim if (InitIsInitFunc) { 1350251662Sdim if (Init) 1351251662Sdim Builder.CreateCall(Init); 1352251662Sdim } else { 1353251662Sdim // Don't know whether we have an init function. Call it if it exists. 1354251662Sdim llvm::Value *Have = Builder.CreateIsNotNull(Init); 1355251662Sdim llvm::BasicBlock *InitBB = llvm::BasicBlock::Create(Context, "", Wrapper); 1356251662Sdim llvm::BasicBlock *ExitBB = llvm::BasicBlock::Create(Context, "", Wrapper); 1357251662Sdim Builder.CreateCondBr(Have, InitBB, ExitBB); 1358251662Sdim 1359251662Sdim Builder.SetInsertPoint(InitBB); 1360251662Sdim Builder.CreateCall(Init); 1361251662Sdim Builder.CreateBr(ExitBB); 1362251662Sdim 1363251662Sdim Builder.SetInsertPoint(ExitBB); 1364251662Sdim } 1365251662Sdim 1366251662Sdim // For a reference, the result of the wrapper function is a pointer to 1367251662Sdim // the referenced object. 1368251662Sdim llvm::Value *Val = Var; 1369251662Sdim if (VD->getType()->isReferenceType()) { 1370251662Sdim llvm::LoadInst *LI = Builder.CreateLoad(Val); 1371251662Sdim LI->setAlignment(CGM.getContext().getDeclAlign(VD).getQuantity()); 1372251662Sdim Val = LI; 1373251662Sdim } 1374251662Sdim 1375251662Sdim Builder.CreateRet(Val); 1376251662Sdim } 1377251662Sdim} 1378251662Sdim 1379251662SdimLValue ItaniumCXXABI::EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF, 1380251662Sdim const DeclRefExpr *DRE) { 1381251662Sdim const VarDecl *VD = cast<VarDecl>(DRE->getDecl()); 1382251662Sdim QualType T = VD->getType(); 1383251662Sdim llvm::Type *Ty = CGF.getTypes().ConvertTypeForMem(T); 1384251662Sdim llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD, Ty); 1385251662Sdim llvm::Function *Wrapper = 1386251662Sdim getOrCreateThreadLocalWrapper(VD, cast<llvm::GlobalVariable>(Val)); 1387251662Sdim 1388251662Sdim Val = CGF.Builder.CreateCall(Wrapper); 1389251662Sdim 1390251662Sdim LValue LV; 1391251662Sdim if (VD->getType()->isReferenceType()) 1392251662Sdim LV = CGF.MakeNaturalAlignAddrLValue(Val, T); 1393251662Sdim else 1394251662Sdim LV = CGF.MakeAddrLValue(Val, DRE->getType(), 1395251662Sdim CGF.getContext().getDeclAlign(VD)); 1396251662Sdim // FIXME: need setObjCGCLValueClass? 1397251662Sdim return LV; 1398251662Sdim} 1399