ItaniumCXXABI.cpp revision 9cbe4f0ba01ec304e1e3d071c071f7bca33631c0
13a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis//===------- ItaniumCXXABI.cpp - Emit LLVM Code from ASTs for a Module ----===// 23a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis// 33a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis// The LLVM Compiler Infrastructure 43a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis// 53a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis// This file is distributed under the University of Illinois Open Source 63a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis// License. See LICENSE.TXT for details. 73a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis// 83a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis//===----------------------------------------------------------------------===// 93a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis// 10fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner// This provides C++ code generation targeting the Itanium C++ ABI. The class 113a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis// in this file generates structures that follow the Itanium C++ ABI, which is 123a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis// documented at: 133a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis// http://www.codesourcery.com/public/cxx-abi/abi.html 143a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis// http://www.codesourcery.com/public/cxx-abi/abi-eh.html 15ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall// 16ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall// It also supports the closely-related ARM ABI, documented at: 17ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf 18ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall// 193a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis//===----------------------------------------------------------------------===// 203a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis 213a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis#include "CGCXXABI.h" 220bab0cdab751248ca389a5592bcb70eac5d39260John McCall#include "CGRecordLayout.h" 2393d557bc1867b7d7b102f87290194b4be7932c92John McCall#include "CodeGenFunction.h" 243a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis#include "CodeGenModule.h" 2514110477887e3dc168ffc6c191e72d705051f99ePeter Collingbourne#include <clang/AST/Mangle.h> 2693d557bc1867b7d7b102f87290194b4be7932c92John McCall#include <clang/AST/Type.h> 270502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall#include <llvm/Intrinsics.h> 280bab0cdab751248ca389a5592bcb70eac5d39260John McCall#include <llvm/Target/TargetData.h> 2993d557bc1867b7d7b102f87290194b4be7932c92John McCall#include <llvm/Value.h> 303a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis 313a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davisusing namespace clang; 3293d557bc1867b7d7b102f87290194b4be7932c92John McCallusing namespace CodeGen; 333a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis 343a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davisnamespace { 35071cc7deffad608165b1ddd5263e8bf181861520Charles Davisclass ItaniumCXXABI : public CodeGen::CGCXXABI { 360bab0cdab751248ca389a5592bcb70eac5d39260John McCallprivate: 379cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner llvm::IntegerType *PtrDiffTy; 3893d557bc1867b7d7b102f87290194b4be7932c92John McCallprotected: 39babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall bool IsARM; 400bab0cdab751248ca389a5592bcb70eac5d39260John McCall 410bab0cdab751248ca389a5592bcb70eac5d39260John McCall // It's a little silly for us to cache this. 429cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner llvm::IntegerType *getPtrDiffTy() { 430bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (!PtrDiffTy) { 449cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall QualType T = getContext().getPointerDiffType(); 459cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner llvm::Type *Ty = CGM.getTypes().ConvertType(T); 460bab0cdab751248ca389a5592bcb70eac5d39260John McCall PtrDiffTy = cast<llvm::IntegerType>(Ty); 470bab0cdab751248ca389a5592bcb70eac5d39260John McCall } 480bab0cdab751248ca389a5592bcb70eac5d39260John McCall return PtrDiffTy; 490bab0cdab751248ca389a5592bcb70eac5d39260John McCall } 500bab0cdab751248ca389a5592bcb70eac5d39260John McCall 516ec278d1a354517e20f13a877481453ee7940c78John McCall bool NeedsArrayCookie(const CXXNewExpr *expr); 526ec278d1a354517e20f13a877481453ee7940c78John McCall bool NeedsArrayCookie(const CXXDeleteExpr *expr, 536ec278d1a354517e20f13a877481453ee7940c78John McCall QualType elementType); 541e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 553a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davispublic: 56babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool IsARM = false) : 5714110477887e3dc168ffc6c191e72d705051f99ePeter Collingbourne CGCXXABI(CGM), PtrDiffTy(0), IsARM(IsARM) { } 5893d557bc1867b7d7b102f87290194b4be7932c92John McCall 59f16aa103d3afd42fbca2ab346f191bf745cec092John McCall bool isZeroInitializable(const MemberPointerType *MPT); 60cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 619cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT); 620bab0cdab751248ca389a5592bcb70eac5d39260John McCall 6393d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, 6493d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *&This, 6593d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *MemFnPtr, 6693d557bc1867b7d7b102f87290194b4be7932c92John McCall const MemberPointerType *MPT); 673023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 686c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF, 696c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall llvm::Value *Base, 706c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall llvm::Value *MemPtr, 716c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall const MemberPointerType *MPT); 726c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall 730bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF, 740bab0cdab751248ca389a5592bcb70eac5d39260John McCall const CastExpr *E, 750bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *Src); 76cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 770bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Constant *EmitMemberPointerConversion(llvm::Constant *C, 780bab0cdab751248ca389a5592bcb70eac5d39260John McCall const CastExpr *E); 79cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 800bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT); 81cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 82755d8497e39071aa24acc173ff07083e3256b8f8John McCall llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD); 835808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCall llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, 845808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCall CharUnits offset); 85875ab10245d3bf37252dd822aa1616bb0a391095John McCall 860bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF, 870bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *L, 880bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *R, 890bab0cdab751248ca389a5592bcb70eac5d39260John McCall const MemberPointerType *MPT, 900bab0cdab751248ca389a5592bcb70eac5d39260John McCall bool Inequality); 91e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 920bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF, 930bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *Addr, 940bab0cdab751248ca389a5592bcb70eac5d39260John McCall const MemberPointerType *MPT); 954c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 964c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void BuildConstructorSignature(const CXXConstructorDecl *Ctor, 974c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXCtorType T, 984c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 994c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys); 1004c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1014c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void BuildDestructorSignature(const CXXDestructorDecl *Dtor, 1024c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXDtorType T, 1034c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 1044c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys); 1054c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1064c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void BuildInstanceFunctionParams(CodeGenFunction &CGF, 1074c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall QualType &ResTy, 1084c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall FunctionArgList &Params); 1094c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1104c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void EmitInstanceFunctionProlog(CodeGenFunction &CGF); 1111e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 1126ec278d1a354517e20f13a877481453ee7940c78John McCall CharUnits GetArrayCookieSize(const CXXNewExpr *expr); 1131e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF, 1141e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NewPtr, 1151e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElements, 1166ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXNewExpr *expr, 1171e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType); 1181e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr, 1196ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXDeleteExpr *expr, 1201e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType, llvm::Value *&NumElements, 1211e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&AllocPtr, CharUnits &CookieSize); 1225cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 1233030eb82593097502469a8b3fc26112c79c75605John McCall void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, 1243030eb82593097502469a8b3fc26112c79c75605John McCall llvm::GlobalVariable *DeclPtr); 1253a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis}; 126ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall 127ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCallclass ARMCXXABI : public ItaniumCXXABI { 128ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCallpublic: 129babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {} 1304c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1314c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void BuildConstructorSignature(const CXXConstructorDecl *Ctor, 1324c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXCtorType T, 1334c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 1344c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys); 1354c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1364c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void BuildDestructorSignature(const CXXDestructorDecl *Dtor, 1374c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXDtorType T, 1384c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 1394c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys); 1404c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1414c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void BuildInstanceFunctionParams(CodeGenFunction &CGF, 1424c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall QualType &ResTy, 1434c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall FunctionArgList &Params); 1444c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1454c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void EmitInstanceFunctionProlog(CodeGenFunction &CGF); 1464c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1474c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy); 1484c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1496ec278d1a354517e20f13a877481453ee7940c78John McCall CharUnits GetArrayCookieSize(const CXXNewExpr *expr); 1501e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF, 1511e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NewPtr, 1521e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElements, 1536ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXNewExpr *expr, 1541e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType); 1551e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr, 1566ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXDeleteExpr *expr, 1571e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType, llvm::Value *&NumElements, 1581e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&AllocPtr, CharUnits &CookieSize); 1594c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1604c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallprivate: 1614c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// \brief Returns true if the given instance method is one of the 1624c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// kinds that the ARM ABI says returns 'this'. 1634c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall static bool HasThisReturn(GlobalDecl GD) { 1644c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 1654c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall return ((isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Deleting) || 1664c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall (isa<CXXConstructorDecl>(MD))); 1674c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall } 168ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall}; 1693a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis} 1703a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis 171071cc7deffad608165b1ddd5263e8bf181861520Charles DavisCodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { 1723a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis return new ItaniumCXXABI(CGM); 1733a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis} 1743a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis 175ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCallCodeGen::CGCXXABI *CodeGen::CreateARMCXXABI(CodeGenModule &CGM) { 176ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall return new ARMCXXABI(CGM); 177ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall} 178ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall 1799cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattnerllvm::Type * 1800bab0cdab751248ca389a5592bcb70eac5d39260John McCallItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { 1810bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (MPT->isMemberDataPointer()) 1820bab0cdab751248ca389a5592bcb70eac5d39260John McCall return getPtrDiffTy(); 1837650d95a1a616ea300f37126a8dfc93dc19a662aChris Lattner return llvm::StructType::get(getPtrDiffTy(), getPtrDiffTy(), NULL); 184875ab10245d3bf37252dd822aa1616bb0a391095John McCall} 185875ab10245d3bf37252dd822aa1616bb0a391095John McCall 186babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// In the Itanium and ARM ABIs, method pointers have the form: 187babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// struct { ptrdiff_t ptr; ptrdiff_t adj; } memptr; 188babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// 189babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// In the Itanium ABI: 190babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - method pointers are virtual if (memptr.ptr & 1) is nonzero 191babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - the this-adjustment is (memptr.adj) 192babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - the virtual offset is (memptr.ptr - 1) 193babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// 194babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// In the ARM ABI: 195babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - method pointers are virtual if (memptr.adj & 1) is nonzero 196babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - the this-adjustment is (memptr.adj >> 1) 197babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - the virtual offset is (memptr.ptr) 198babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// ARM uses 'adj' for the virtual flag because Thumb functions 199babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// may be only single-byte aligned. 200babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// 201babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// If the member is virtual, the adjusted 'this' pointer points 202babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// to a vtable pointer from which the virtual offset is applied. 203babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// 204babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// If the member is non-virtual, memptr.ptr is the address of 205babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// the function to call. 20693d557bc1867b7d7b102f87290194b4be7932c92John McCallllvm::Value * 20793d557bc1867b7d7b102f87290194b4be7932c92John McCallItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, 20893d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *&This, 20993d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *MemFnPtr, 21093d557bc1867b7d7b102f87290194b4be7932c92John McCall const MemberPointerType *MPT) { 21193d557bc1867b7d7b102f87290194b4be7932c92John McCall CGBuilderTy &Builder = CGF.Builder; 21293d557bc1867b7d7b102f87290194b4be7932c92John McCall 21393d557bc1867b7d7b102f87290194b4be7932c92John McCall const FunctionProtoType *FPT = 21493d557bc1867b7d7b102f87290194b4be7932c92John McCall MPT->getPointeeType()->getAs<FunctionProtoType>(); 21593d557bc1867b7d7b102f87290194b4be7932c92John McCall const CXXRecordDecl *RD = 21693d557bc1867b7d7b102f87290194b4be7932c92John McCall cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); 21793d557bc1867b7d7b102f87290194b4be7932c92John McCall 21893d557bc1867b7d7b102f87290194b4be7932c92John McCall const llvm::FunctionType *FTy = 21993d557bc1867b7d7b102f87290194b4be7932c92John McCall CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT), 22093d557bc1867b7d7b102f87290194b4be7932c92John McCall FPT->isVariadic()); 22193d557bc1867b7d7b102f87290194b4be7932c92John McCall 2220bab0cdab751248ca389a5592bcb70eac5d39260John McCall const llvm::IntegerType *ptrdiff = getPtrDiffTy(); 223babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(ptrdiff, 1); 22493d557bc1867b7d7b102f87290194b4be7932c92John McCall 225babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual"); 226babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual"); 227babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end"); 228babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall 229d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // Extract memptr.adj, which is in the second field. 230d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1, "memptr.adj"); 231babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall 232babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall // Compute the true adjustment. 233babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *Adj = RawAdj; 234babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall if (IsARM) 235babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted"); 23693d557bc1867b7d7b102f87290194b4be7932c92John McCall 23793d557bc1867b7d7b102f87290194b4be7932c92John McCall // Apply the adjustment and cast back to the original struct type 23893d557bc1867b7d7b102f87290194b4be7932c92John McCall // for consistency. 239babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy()); 240babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall Ptr = Builder.CreateInBoundsGEP(Ptr, Adj); 241babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted"); 24293d557bc1867b7d7b102f87290194b4be7932c92John McCall 24393d557bc1867b7d7b102f87290194b4be7932c92John McCall // Load the function pointer. 244d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr"); 24593d557bc1867b7d7b102f87290194b4be7932c92John McCall 24693d557bc1867b7d7b102f87290194b4be7932c92John McCall // If the LSB in the function pointer is 1, the function pointer points to 24793d557bc1867b7d7b102f87290194b4be7932c92John McCall // a virtual function. 248babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *IsVirtual; 249babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall if (IsARM) 250babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1); 251babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall else 252babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1); 253babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual"); 25493d557bc1867b7d7b102f87290194b4be7932c92John McCall Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual); 25593d557bc1867b7d7b102f87290194b4be7932c92John McCall 25693d557bc1867b7d7b102f87290194b4be7932c92John McCall // In the virtual path, the adjustment left 'This' pointing to the 25793d557bc1867b7d7b102f87290194b4be7932c92John McCall // vtable of the correct base subobject. The "function pointer" is an 258babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall // offset within the vtable (+1 for the virtual flag on non-ARM). 25993d557bc1867b7d7b102f87290194b4be7932c92John McCall CGF.EmitBlock(FnVirtual); 26093d557bc1867b7d7b102f87290194b4be7932c92John McCall 26193d557bc1867b7d7b102f87290194b4be7932c92John McCall // Cast the adjusted this to a pointer to vtable pointer and load. 26293d557bc1867b7d7b102f87290194b4be7932c92John McCall const llvm::Type *VTableTy = Builder.getInt8PtrTy(); 26393d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo()); 264babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall VTable = Builder.CreateLoad(VTable, "memptr.vtable"); 26593d557bc1867b7d7b102f87290194b4be7932c92John McCall 26693d557bc1867b7d7b102f87290194b4be7932c92John McCall // Apply the offset. 267babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *VTableOffset = FnAsInt; 268babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall if (!IsARM) VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1); 269babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall VTable = Builder.CreateGEP(VTable, VTableOffset); 27093d557bc1867b7d7b102f87290194b4be7932c92John McCall 27193d557bc1867b7d7b102f87290194b4be7932c92John McCall // Load the virtual function to call. 27293d557bc1867b7d7b102f87290194b4be7932c92John McCall VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo()); 273babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "memptr.virtualfn"); 27493d557bc1867b7d7b102f87290194b4be7932c92John McCall CGF.EmitBranch(FnEnd); 27593d557bc1867b7d7b102f87290194b4be7932c92John McCall 27693d557bc1867b7d7b102f87290194b4be7932c92John McCall // In the non-virtual path, the function pointer is actually a 27793d557bc1867b7d7b102f87290194b4be7932c92John McCall // function pointer. 27893d557bc1867b7d7b102f87290194b4be7932c92John McCall CGF.EmitBlock(FnNonVirtual); 27993d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *NonVirtualFn = 280babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn"); 28193d557bc1867b7d7b102f87290194b4be7932c92John McCall 28293d557bc1867b7d7b102f87290194b4be7932c92John McCall // We're done. 28393d557bc1867b7d7b102f87290194b4be7932c92John McCall CGF.EmitBlock(FnEnd); 284bbf3bacb3e0c1ebb3e8a4a8b1330404a7e379315Jay Foad llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo(), 2); 28593d557bc1867b7d7b102f87290194b4be7932c92John McCall Callee->addIncoming(VirtualFn, FnVirtual); 28693d557bc1867b7d7b102f87290194b4be7932c92John McCall Callee->addIncoming(NonVirtualFn, FnNonVirtual); 28793d557bc1867b7d7b102f87290194b4be7932c92John McCall return Callee; 28893d557bc1867b7d7b102f87290194b4be7932c92John McCall} 2893023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 2906c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall/// Compute an l-value by applying the given pointer-to-member to a 2916c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall/// base object. 2926c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCallllvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, 2936c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall llvm::Value *Base, 2946c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall llvm::Value *MemPtr, 2956c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall const MemberPointerType *MPT) { 2966c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall assert(MemPtr->getType() == getPtrDiffTy()); 2976c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall 2986c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall CGBuilderTy &Builder = CGF.Builder; 2996c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall 3006c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall unsigned AS = cast<llvm::PointerType>(Base->getType())->getAddressSpace(); 3016c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall 3026c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall // Cast to char*. 3036c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall Base = Builder.CreateBitCast(Base, Builder.getInt8Ty()->getPointerTo(AS)); 3046c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall 3056c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall // Apply the offset, which we assume is non-null. 3066c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall llvm::Value *Addr = Builder.CreateInBoundsGEP(Base, MemPtr, "memptr.offset"); 3076c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall 3086c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall // Cast the address to the appropriate pointer type, adopting the 3096c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall // address space of the base pointer. 310eede61a83e90f3cb03ef8665b67d648dccd6ce42Douglas Gregor const llvm::Type *PType 311eede61a83e90f3cb03ef8665b67d648dccd6ce42Douglas Gregor = CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS); 3126c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall return Builder.CreateBitCast(Addr, PType); 3136c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall} 3146c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall 3153023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall/// Perform a derived-to-base or base-to-derived member pointer conversion. 3160bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// 3170bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// Obligatory offset/adjustment diagram: 3180bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// <-- offset --> <-- adjustment --> 3190bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// |--------------------------|----------------------|--------------------| 3200bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// ^Derived address point ^Base address point ^Member address point 3210bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// 3220bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// So when converting a base member pointer to a derived member pointer, 3230bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// we add the offset to the adjustment because the address point has 3240bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// decreased; and conversely, when converting a derived MP to a base MP 3250bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// we subtract the offset from the adjustment because the address point 3260bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// has increased. 3270bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// 3280bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// The standard forbids (at compile time) conversion to and from 3290bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// virtual bases, which is why we don't have to consider them here. 3300bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// 3310bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// The standard forbids (at run time) casting a derived MP to a base 3320bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// MP when the derived MP does not point to a member of the base. 3330bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// This is why -1 is a reasonable choice for null data member 3340bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// pointers. 335d608cdb7c044365cf4e8764ade1e11e99c176078John McCallllvm::Value * 3360bab0cdab751248ca389a5592bcb70eac5d39260John McCallItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, 3370bab0cdab751248ca389a5592bcb70eac5d39260John McCall const CastExpr *E, 3380bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *Src) { 3392de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || 3402de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall E->getCastKind() == CK_BaseToDerivedMemberPointer); 3413023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 342d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (isa<llvm::Constant>(Src)) 3430bab0cdab751248ca389a5592bcb70eac5d39260John McCall return EmitMemberPointerConversion(cast<llvm::Constant>(Src), E); 344d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 3453023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall CGBuilderTy &Builder = CGF.Builder; 3463023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 3473023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const MemberPointerType *SrcTy = 3483023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall E->getSubExpr()->getType()->getAs<MemberPointerType>(); 3493023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const MemberPointerType *DestTy = E->getType()->getAs<MemberPointerType>(); 3503023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 3513023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const CXXRecordDecl *SrcDecl = SrcTy->getClass()->getAsCXXRecordDecl(); 3523023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const CXXRecordDecl *DestDecl = DestTy->getClass()->getAsCXXRecordDecl(); 3533023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 3543023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall bool DerivedToBase = 3552de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall E->getCastKind() == CK_DerivedToBaseMemberPointer; 3563023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 357dec0984fce504a39a7f085774fb67cfd9957be58Jeffrey Yasskin const CXXRecordDecl *DerivedDecl; 3583023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall if (DerivedToBase) 359dec0984fce504a39a7f085774fb67cfd9957be58Jeffrey Yasskin DerivedDecl = SrcDecl; 3603023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall else 361dec0984fce504a39a7f085774fb67cfd9957be58Jeffrey Yasskin DerivedDecl = DestDecl; 3623023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 363d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Constant *Adj = 364d608cdb7c044365cf4e8764ade1e11e99c176078John McCall CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl, 365d608cdb7c044365cf4e8764ade1e11e99c176078John McCall E->path_begin(), 366d608cdb7c044365cf4e8764ade1e11e99c176078John McCall E->path_end()); 367d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (!Adj) return Src; 368875ab10245d3bf37252dd822aa1616bb0a391095John McCall 3690bab0cdab751248ca389a5592bcb70eac5d39260John McCall // For member data pointers, this is just a matter of adding the 3700bab0cdab751248ca389a5592bcb70eac5d39260John McCall // offset if the source is non-null. 3710bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (SrcTy->isMemberDataPointer()) { 3720bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *Dst; 3730bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (DerivedToBase) 3740bab0cdab751248ca389a5592bcb70eac5d39260John McCall Dst = Builder.CreateNSWSub(Src, Adj, "adj"); 3750bab0cdab751248ca389a5592bcb70eac5d39260John McCall else 3760bab0cdab751248ca389a5592bcb70eac5d39260John McCall Dst = Builder.CreateNSWAdd(Src, Adj, "adj"); 3770bab0cdab751248ca389a5592bcb70eac5d39260John McCall 3780bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Null check. 3790bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *Null = llvm::Constant::getAllOnesValue(Src->getType()); 3800bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *IsNull = Builder.CreateICmpEQ(Src, Null, "memptr.isnull"); 3810bab0cdab751248ca389a5592bcb70eac5d39260John McCall return Builder.CreateSelect(IsNull, Src, Dst); 3820bab0cdab751248ca389a5592bcb70eac5d39260John McCall } 3830bab0cdab751248ca389a5592bcb70eac5d39260John McCall 384d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // The this-adjustment is left-shifted by 1 on ARM. 385d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (IsARM) { 386d608cdb7c044365cf4e8764ade1e11e99c176078John McCall uint64_t Offset = cast<llvm::ConstantInt>(Adj)->getZExtValue(); 387d608cdb7c044365cf4e8764ade1e11e99c176078John McCall Offset <<= 1; 388d608cdb7c044365cf4e8764ade1e11e99c176078John McCall Adj = llvm::ConstantInt::get(Adj->getType(), Offset); 389d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } 390d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 391e14add4a275318e7a9cafd3a01f79fb15a5a08bcJohn McCall llvm::Value *SrcAdj = Builder.CreateExtractValue(Src, 1, "src.adj"); 392d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *DstAdj; 393d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (DerivedToBase) 3940bab0cdab751248ca389a5592bcb70eac5d39260John McCall DstAdj = Builder.CreateNSWSub(SrcAdj, Adj, "adj"); 395d608cdb7c044365cf4e8764ade1e11e99c176078John McCall else 3960bab0cdab751248ca389a5592bcb70eac5d39260John McCall DstAdj = Builder.CreateNSWAdd(SrcAdj, Adj, "adj"); 397d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 398e14add4a275318e7a9cafd3a01f79fb15a5a08bcJohn McCall return Builder.CreateInsertValue(Src, DstAdj, 1); 3993023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall} 400cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 401cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCallllvm::Constant * 4020bab0cdab751248ca389a5592bcb70eac5d39260John McCallItaniumCXXABI::EmitMemberPointerConversion(llvm::Constant *C, 4030bab0cdab751248ca389a5592bcb70eac5d39260John McCall const CastExpr *E) { 404cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const MemberPointerType *SrcTy = 405cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall E->getSubExpr()->getType()->getAs<MemberPointerType>(); 406cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const MemberPointerType *DestTy = 407cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall E->getType()->getAs<MemberPointerType>(); 408cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 409cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall bool DerivedToBase = 4102de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall E->getCastKind() == CK_DerivedToBaseMemberPointer; 411cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 412cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const CXXRecordDecl *DerivedDecl; 413cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall if (DerivedToBase) 414cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall DerivedDecl = SrcTy->getClass()->getAsCXXRecordDecl(); 415cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall else 416cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall DerivedDecl = DestTy->getClass()->getAsCXXRecordDecl(); 417cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 418cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall // Calculate the offset to the base class. 419cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::Constant *Offset = 420cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall CGM.GetNonVirtualBaseClassOffset(DerivedDecl, 421cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall E->path_begin(), 422cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall E->path_end()); 423cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall // If there's no offset, we're done. 424cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall if (!Offset) return C; 425cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 4260bab0cdab751248ca389a5592bcb70eac5d39260John McCall // If the source is a member data pointer, we have to do a null 4270bab0cdab751248ca389a5592bcb70eac5d39260John McCall // check and then add the offset. In the common case, we can fold 4280bab0cdab751248ca389a5592bcb70eac5d39260John McCall // away the offset. 4290bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (SrcTy->isMemberDataPointer()) { 4300bab0cdab751248ca389a5592bcb70eac5d39260John McCall assert(C->getType() == getPtrDiffTy()); 4310bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4320bab0cdab751248ca389a5592bcb70eac5d39260John McCall // If it's a constant int, just create a new constant int. 4330bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(C)) { 4340bab0cdab751248ca389a5592bcb70eac5d39260John McCall int64_t Src = CI->getSExtValue(); 4350bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4360bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Null converts to null. 4370bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (Src == -1) return CI; 4380bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4390bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Otherwise, just add the offset. 4400bab0cdab751248ca389a5592bcb70eac5d39260John McCall int64_t OffsetV = cast<llvm::ConstantInt>(Offset)->getSExtValue(); 4410bab0cdab751248ca389a5592bcb70eac5d39260John McCall int64_t Dst = (DerivedToBase ? Src - OffsetV : Src + OffsetV); 4420bab0cdab751248ca389a5592bcb70eac5d39260John McCall return llvm::ConstantInt::get(CI->getType(), Dst, /*signed*/ true); 4430bab0cdab751248ca389a5592bcb70eac5d39260John McCall } 4440bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4450bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Otherwise, we have to form a constant select expression. 4460bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Constant *Null = llvm::Constant::getAllOnesValue(C->getType()); 4470bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4480bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Constant *IsNull = 4490bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::ConstantExpr::getICmp(llvm::ICmpInst::ICMP_EQ, C, Null); 4500bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4510bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Constant *Dst; 4520bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (DerivedToBase) 4530bab0cdab751248ca389a5592bcb70eac5d39260John McCall Dst = llvm::ConstantExpr::getNSWSub(C, Offset); 4540bab0cdab751248ca389a5592bcb70eac5d39260John McCall else 4550bab0cdab751248ca389a5592bcb70eac5d39260John McCall Dst = llvm::ConstantExpr::getNSWAdd(C, Offset); 4560bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4570bab0cdab751248ca389a5592bcb70eac5d39260John McCall return llvm::ConstantExpr::getSelect(IsNull, Null, Dst); 4580bab0cdab751248ca389a5592bcb70eac5d39260John McCall } 4590bab0cdab751248ca389a5592bcb70eac5d39260John McCall 460875ab10245d3bf37252dd822aa1616bb0a391095John McCall // The this-adjustment is left-shifted by 1 on ARM. 461875ab10245d3bf37252dd822aa1616bb0a391095John McCall if (IsARM) { 4620bab0cdab751248ca389a5592bcb70eac5d39260John McCall int64_t OffsetV = cast<llvm::ConstantInt>(Offset)->getSExtValue(); 463875ab10245d3bf37252dd822aa1616bb0a391095John McCall OffsetV <<= 1; 464875ab10245d3bf37252dd822aa1616bb0a391095John McCall Offset = llvm::ConstantInt::get(Offset->getType(), OffsetV); 465875ab10245d3bf37252dd822aa1616bb0a391095John McCall } 466875ab10245d3bf37252dd822aa1616bb0a391095John McCall 467cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::ConstantStruct *CS = cast<llvm::ConstantStruct>(C); 468cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 4690bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Constant *Values[2] = { CS->getOperand(0), 0 }; 4700bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (DerivedToBase) 4710bab0cdab751248ca389a5592bcb70eac5d39260John McCall Values[1] = llvm::ConstantExpr::getSub(CS->getOperand(1), Offset); 4720bab0cdab751248ca389a5592bcb70eac5d39260John McCall else 4730bab0cdab751248ca389a5592bcb70eac5d39260John McCall Values[1] = llvm::ConstantExpr::getAdd(CS->getOperand(1), Offset); 4740bab0cdab751248ca389a5592bcb70eac5d39260John McCall 475c5cbb909e8a27deb8f1a2b6b7bf56a96051af81aChris Lattner return llvm::ConstantStruct::get(CS->getType(), Values); 476cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall} 477cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 478cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 479cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCallllvm::Constant * 4800bab0cdab751248ca389a5592bcb70eac5d39260John McCallItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { 4810bab0cdab751248ca389a5592bcb70eac5d39260John McCall const llvm::Type *ptrdiff_t = getPtrDiffTy(); 4820bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4830bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Itanium C++ ABI 2.3: 4840bab0cdab751248ca389a5592bcb70eac5d39260John McCall // A NULL pointer is represented as -1. 4850bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (MPT->isMemberDataPointer()) 4860bab0cdab751248ca389a5592bcb70eac5d39260John McCall return llvm::ConstantInt::get(ptrdiff_t, -1ULL, /*isSigned=*/true); 487d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 488d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Constant *Zero = llvm::ConstantInt::get(ptrdiff_t, 0); 489d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Constant *Values[2] = { Zero, Zero }; 490c5cbb909e8a27deb8f1a2b6b7bf56a96051af81aChris Lattner return llvm::ConstantStruct::getAnon(Values); 491cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall} 492cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 4935808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCallllvm::Constant * 4945808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCallItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, 4955808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCall CharUnits offset) { 4960bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Itanium C++ ABI 2.3: 4970bab0cdab751248ca389a5592bcb70eac5d39260John McCall // A pointer to data member is an offset from the base address of 4980bab0cdab751248ca389a5592bcb70eac5d39260John McCall // the class object containing it, represented as a ptrdiff_t 4995808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCall return llvm::ConstantInt::get(getPtrDiffTy(), offset.getQuantity()); 5000bab0cdab751248ca389a5592bcb70eac5d39260John McCall} 5010bab0cdab751248ca389a5592bcb70eac5d39260John McCall 502755d8497e39071aa24acc173ff07083e3256b8f8John McCallllvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) { 503d608cdb7c044365cf4e8764ade1e11e99c176078John McCall assert(MD->isInstance() && "Member function must not be static!"); 504d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MD = MD->getCanonicalDecl(); 505875ab10245d3bf37252dd822aa1616bb0a391095John McCall 506d608cdb7c044365cf4e8764ade1e11e99c176078John McCall CodeGenTypes &Types = CGM.getTypes(); 5070bab0cdab751248ca389a5592bcb70eac5d39260John McCall const llvm::Type *ptrdiff_t = getPtrDiffTy(); 508875ab10245d3bf37252dd822aa1616bb0a391095John McCall 509d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // Get the function pointer (or index if this is a virtual function). 510d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Constant *MemPtr[2]; 511d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (MD->isVirtual()) { 512d608cdb7c044365cf4e8764ade1e11e99c176078John McCall uint64_t Index = CGM.getVTables().getMethodVTableIndex(MD); 513875ab10245d3bf37252dd822aa1616bb0a391095John McCall 5141246ba6f6801390ffc0e1d4b83a2b45e72283b8fKen Dyck const ASTContext &Context = getContext(); 5151246ba6f6801390ffc0e1d4b83a2b45e72283b8fKen Dyck CharUnits PointerWidth = 5161246ba6f6801390ffc0e1d4b83a2b45e72283b8fKen Dyck Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0)); 5171246ba6f6801390ffc0e1d4b83a2b45e72283b8fKen Dyck uint64_t VTableOffset = (Index * PointerWidth.getQuantity()); 518d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 519d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (IsARM) { 520d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // ARM C++ ABI 3.2.1: 521d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // This ABI specifies that adj contains twice the this 522d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // adjustment, plus 1 if the member function is virtual. The 523d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // least significant bit of adj then makes exactly the same 524d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // discrimination as the least significant bit of ptr does for 525d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // Itanium. 526d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset); 527d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 1); 528d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } else { 529d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // Itanium C++ ABI 2.3: 530d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // For a virtual function, [the pointer field] is 1 plus the 531d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // virtual table offset (in bytes) of the function, 532d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // represented as a ptrdiff_t. 533d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset + 1); 534d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0); 535d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } 536d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } else { 537755d8497e39071aa24acc173ff07083e3256b8f8John McCall const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); 538755d8497e39071aa24acc173ff07083e3256b8f8John McCall const llvm::Type *Ty; 539755d8497e39071aa24acc173ff07083e3256b8f8John McCall // Check whether the function has a computable LLVM signature. 540755d8497e39071aa24acc173ff07083e3256b8f8John McCall if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) { 541755d8497e39071aa24acc173ff07083e3256b8f8John McCall // The function has a computable LLVM signature; use the correct type. 542755d8497e39071aa24acc173ff07083e3256b8f8John McCall Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), 543755d8497e39071aa24acc173ff07083e3256b8f8John McCall FPT->isVariadic()); 544d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } else { 545755d8497e39071aa24acc173ff07083e3256b8f8John McCall // Use an arbitrary non-function type to tell GetAddrOfFunction that the 546755d8497e39071aa24acc173ff07083e3256b8f8John McCall // function type is incomplete. 547755d8497e39071aa24acc173ff07083e3256b8f8John McCall Ty = ptrdiff_t; 548d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } 549755d8497e39071aa24acc173ff07083e3256b8f8John McCall llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty); 550d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 551379b5155b4566f63679e1da6b0ceb5fdfa2aec6dJohn McCall MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, ptrdiff_t); 552d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0); 553d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } 554d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 555c5cbb909e8a27deb8f1a2b6b7bf56a96051af81aChris Lattner return llvm::ConstantStruct::getAnon(MemPtr); 556875ab10245d3bf37252dd822aa1616bb0a391095John McCall} 557875ab10245d3bf37252dd822aa1616bb0a391095John McCall 558e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// The comparison algorithm is pretty easy: the member pointers are 559e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// the same if they're either bitwise identical *or* both null. 560e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// 561e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// ARM is different here only because null-ness is more complicated. 562e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCallllvm::Value * 5630bab0cdab751248ca389a5592bcb70eac5d39260John McCallItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, 5640bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *L, 5650bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *R, 5660bab0cdab751248ca389a5592bcb70eac5d39260John McCall const MemberPointerType *MPT, 5670bab0cdab751248ca389a5592bcb70eac5d39260John McCall bool Inequality) { 568e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall CGBuilderTy &Builder = CGF.Builder; 569e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 570e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::ICmpInst::Predicate Eq; 571e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Instruction::BinaryOps And, Or; 572e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall if (Inequality) { 573e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Eq = llvm::ICmpInst::ICMP_NE; 574e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall And = llvm::Instruction::Or; 575e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Or = llvm::Instruction::And; 576e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } else { 577e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Eq = llvm::ICmpInst::ICMP_EQ; 578e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall And = llvm::Instruction::And; 579e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Or = llvm::Instruction::Or; 580e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } 581e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 5820bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Member data pointers are easy because there's a unique null 5830bab0cdab751248ca389a5592bcb70eac5d39260John McCall // value, so it just comes down to bitwise equality. 5840bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (MPT->isMemberDataPointer()) 5850bab0cdab751248ca389a5592bcb70eac5d39260John McCall return Builder.CreateICmp(Eq, L, R); 5860bab0cdab751248ca389a5592bcb70eac5d39260John McCall 5870bab0cdab751248ca389a5592bcb70eac5d39260John McCall // For member function pointers, the tautologies are more complex. 5880bab0cdab751248ca389a5592bcb70eac5d39260John McCall // The Itanium tautology is: 589de719f7131e1ece5c9d6b5ffe21b83286d29f10fJohn McCall // (L == R) <==> (L.ptr == R.ptr && (L.ptr == 0 || L.adj == R.adj)) 5900bab0cdab751248ca389a5592bcb70eac5d39260John McCall // The ARM tautology is: 591de719f7131e1ece5c9d6b5ffe21b83286d29f10fJohn McCall // (L == R) <==> (L.ptr == R.ptr && 592de719f7131e1ece5c9d6b5ffe21b83286d29f10fJohn McCall // (L.adj == R.adj || 593de719f7131e1ece5c9d6b5ffe21b83286d29f10fJohn McCall // (L.ptr == 0 && ((L.adj|R.adj) & 1) == 0))) 5940bab0cdab751248ca389a5592bcb70eac5d39260John McCall // The inequality tautologies have exactly the same structure, except 5950bab0cdab751248ca389a5592bcb70eac5d39260John McCall // applying De Morgan's laws. 5960bab0cdab751248ca389a5592bcb70eac5d39260John McCall 5970bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr"); 5980bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr"); 5990bab0cdab751248ca389a5592bcb70eac5d39260John McCall 600e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // This condition tests whether L.ptr == R.ptr. This must always be 601e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // true for equality to hold. 602e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr"); 603e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 604e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // This condition, together with the assumption that L.ptr == R.ptr, 605e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // tests whether the pointers are both null. ARM imposes an extra 606e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // condition. 607e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType()); 608e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null"); 609e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 610e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // This condition tests whether L.adj == R.adj. If this isn't 611e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // true, the pointers are unequal unless they're both null. 612d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj"); 613d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj"); 614e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj"); 615e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 616e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // Null member function pointers on ARM clear the low bit of Adj, 617e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // so the zero condition has to check that neither low bit is set. 618e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall if (IsARM) { 619e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1); 620e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 621e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // Compute (l.adj | r.adj) & 1 and test it against zero. 622e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj"); 623e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One); 624e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero, 625e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall "cmp.or.adj"); 626e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero); 627e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } 628e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 629e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // Tie together all our conditions. 630e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq); 631e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Result = Builder.CreateBinOp(And, PtrEq, Result, 632e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Inequality ? "memptr.ne" : "memptr.eq"); 633e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall return Result; 634e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall} 635e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 636e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCallllvm::Value * 6370bab0cdab751248ca389a5592bcb70eac5d39260John McCallItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, 6380bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *MemPtr, 6390bab0cdab751248ca389a5592bcb70eac5d39260John McCall const MemberPointerType *MPT) { 640e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall CGBuilderTy &Builder = CGF.Builder; 6410bab0cdab751248ca389a5592bcb70eac5d39260John McCall 6420bab0cdab751248ca389a5592bcb70eac5d39260John McCall /// For member data pointers, this is just a check against -1. 6430bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (MPT->isMemberDataPointer()) { 6440bab0cdab751248ca389a5592bcb70eac5d39260John McCall assert(MemPtr->getType() == getPtrDiffTy()); 6450bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *NegativeOne = 6460bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Constant::getAllOnesValue(MemPtr->getType()); 6470bab0cdab751248ca389a5592bcb70eac5d39260John McCall return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool"); 6480bab0cdab751248ca389a5592bcb70eac5d39260John McCall } 649e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 650db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar // In Itanium, a member function pointer is not null if 'ptr' is not null. 651d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr"); 652e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 653e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0); 654e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool"); 655e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 656db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar // On ARM, a member function pointer is also non-null if the low bit of 'adj' 657db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar // (the virtual bit) is set. 658e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall if (IsARM) { 659e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1); 660d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj"); 661e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit"); 662db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero, 663db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar "memptr.isvirtual"); 664db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar Result = Builder.CreateOr(Result, IsVirtual); 665e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } 666e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 667e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall return Result; 668e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall} 669875ab10245d3bf37252dd822aa1616bb0a391095John McCall 670f16aa103d3afd42fbca2ab346f191bf745cec092John McCall/// The Itanium ABI requires non-zero initialization only for data 671f16aa103d3afd42fbca2ab346f191bf745cec092John McCall/// member pointers, for which '0' is a valid offset. 672f16aa103d3afd42fbca2ab346f191bf745cec092John McCallbool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) { 673f16aa103d3afd42fbca2ab346f191bf745cec092John McCall return MPT->getPointeeType()->isFunctionType(); 674cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall} 6754c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6764c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// The generic ABI passes 'this', plus a VTT if it's initializing a 6774c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// base subobject. 6784c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, 6794c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXCtorType Type, 6804c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 6814c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys) { 6829cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Context = getContext(); 6834c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6844c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // 'this' is already there. 6854c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6864c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // Check if we need to add a VTT parameter (which has type void **). 6874c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0) 6884c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); 6894c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 6904c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6914c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// The ARM ABI does the same as the Itanium ABI, but returns 'this'. 6924c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ARMCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, 6934c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXCtorType Type, 6944c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 6954c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys) { 6964c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ItaniumCXXABI::BuildConstructorSignature(Ctor, Type, ResTy, ArgTys); 6974c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ResTy = ArgTys[0]; 6984c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 6994c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7004c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// The generic ABI passes 'this', plus a VTT if it's destroying a 7014c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// base subobject. 7024c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, 7034c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXDtorType Type, 7044c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 7054c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys) { 7069cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Context = getContext(); 7074c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7084c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // 'this' is already there. 7094c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7104c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // Check if we need to add a VTT parameter (which has type void **). 7114c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0) 7124c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); 7134c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7144c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7154c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// The ARM ABI does the same as the Itanium ABI, but returns 'this' 7164c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// for non-deleting destructors. 7174c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ARMCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, 7184c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXDtorType Type, 7194c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 7204c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys) { 7214c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ItaniumCXXABI::BuildDestructorSignature(Dtor, Type, ResTy, ArgTys); 7224c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7234c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (Type != Dtor_Deleting) 7244c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ResTy = ArgTys[0]; 7254c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7264c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7274c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, 7284c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall QualType &ResTy, 7294c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall FunctionArgList &Params) { 7304c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// Create the 'this' variable. 7314c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall BuildThisParam(CGF, Params); 7324c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7334c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); 7344c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall assert(MD->isInstance()); 7354c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7364c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // Check if we need a VTT parameter as well. 7374c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (CodeGenVTables::needsVTTParameter(CGF.CurGD)) { 7389cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Context = getContext(); 7394c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7404c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // FIXME: avoid the fake decl 7414c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall QualType T = Context.getPointerType(Context.VoidPtrTy); 7424c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ImplicitParamDecl *VTTDecl 7434c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall = ImplicitParamDecl::Create(Context, 0, MD->getLocation(), 7444c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall &Context.Idents.get("vtt"), T); 745d26bc76c98006609002d9930f8840490e88ac5b5John McCall Params.push_back(VTTDecl); 7464c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall getVTTDecl(CGF) = VTTDecl; 7474c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall } 7484c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7494c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7504c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ARMCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, 7514c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall QualType &ResTy, 7524c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall FunctionArgList &Params) { 7534c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ItaniumCXXABI::BuildInstanceFunctionParams(CGF, ResTy, Params); 7544c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7554c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // Return 'this' from certain constructors and destructors. 7564c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (HasThisReturn(CGF.CurGD)) 757d26bc76c98006609002d9930f8840490e88ac5b5John McCall ResTy = Params[0]->getType(); 7584c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7594c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7604c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { 7614c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// Initialize the 'this' slot. 7624c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall EmitThisParam(CGF); 7634c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7644c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// Initialize the 'vtt' slot if needed. 7654c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (getVTTDecl(CGF)) { 7664c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall getVTTValue(CGF) 7674c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)), 7684c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall "vtt"); 7694c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall } 7704c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7714c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7724c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { 7734c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ItaniumCXXABI::EmitInstanceFunctionProlog(CGF); 7744c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7754c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// Initialize the return slot to 'this' at the start of the 7764c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// function. 7774c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (HasThisReturn(CGF.CurGD)) 7784c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CGF.Builder.CreateStore(CGF.LoadCXXThis(), CGF.ReturnValue); 7794c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7804c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7814c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, 7824c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall RValue RV, QualType ResultType) { 7834c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl())) 7844c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType); 7854c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7864c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // Destructor thunks in the ARM ABI have indeterminate results. 7874c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall const llvm::Type *T = 7884c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall cast<llvm::PointerType>(CGF.ReturnValue->getType())->getElementType(); 7894c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall RValue Undef = RValue::get(llvm::UndefValue::get(T)); 7904c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType); 7914c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7921e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 7931e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall/************************** Array allocation cookies **************************/ 7941e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 7956ec278d1a354517e20f13a877481453ee7940c78John McCallbool ItaniumCXXABI::NeedsArrayCookie(const CXXNewExpr *expr) { 7966ec278d1a354517e20f13a877481453ee7940c78John McCall // If the class's usual deallocation function takes two arguments, 7976ec278d1a354517e20f13a877481453ee7940c78John McCall // it needs a cookie. 7986ec278d1a354517e20f13a877481453ee7940c78John McCall if (expr->doesUsualArrayDeleteWantSize()) 7996ec278d1a354517e20f13a877481453ee7940c78John McCall return true; 8006ec278d1a354517e20f13a877481453ee7940c78John McCall 801f85e193739c953358c865005855253af4f68a497John McCall // Automatic Reference Counting: 802f85e193739c953358c865005855253af4f68a497John McCall // We need an array cookie for pointers with strong or weak lifetime. 803f85e193739c953358c865005855253af4f68a497John McCall QualType AllocatedType = expr->getAllocatedType(); 804f85e193739c953358c865005855253af4f68a497John McCall if (getContext().getLangOptions().ObjCAutoRefCount && 805f85e193739c953358c865005855253af4f68a497John McCall AllocatedType->isObjCLifetimeType()) { 806f85e193739c953358c865005855253af4f68a497John McCall switch (AllocatedType.getObjCLifetime()) { 807f85e193739c953358c865005855253af4f68a497John McCall case Qualifiers::OCL_None: 808f85e193739c953358c865005855253af4f68a497John McCall case Qualifiers::OCL_ExplicitNone: 809f85e193739c953358c865005855253af4f68a497John McCall case Qualifiers::OCL_Autoreleasing: 810f85e193739c953358c865005855253af4f68a497John McCall return false; 811f85e193739c953358c865005855253af4f68a497John McCall 812f85e193739c953358c865005855253af4f68a497John McCall case Qualifiers::OCL_Strong: 813f85e193739c953358c865005855253af4f68a497John McCall case Qualifiers::OCL_Weak: 814f85e193739c953358c865005855253af4f68a497John McCall return true; 815f85e193739c953358c865005855253af4f68a497John McCall } 816f85e193739c953358c865005855253af4f68a497John McCall } 817f85e193739c953358c865005855253af4f68a497John McCall 8186ec278d1a354517e20f13a877481453ee7940c78John McCall // Otherwise, if the class has a non-trivial destructor, it always 8196ec278d1a354517e20f13a877481453ee7940c78John McCall // needs a cookie. 8206ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXRecordDecl *record = 821f85e193739c953358c865005855253af4f68a497John McCall AllocatedType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); 8226ec278d1a354517e20f13a877481453ee7940c78John McCall return (record && !record->hasTrivialDestructor()); 8236ec278d1a354517e20f13a877481453ee7940c78John McCall} 8241e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8256ec278d1a354517e20f13a877481453ee7940c78John McCallbool ItaniumCXXABI::NeedsArrayCookie(const CXXDeleteExpr *expr, 8266ec278d1a354517e20f13a877481453ee7940c78John McCall QualType elementType) { 8271e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // If the class's usual deallocation function takes two arguments, 8286ec278d1a354517e20f13a877481453ee7940c78John McCall // it needs a cookie. 8296ec278d1a354517e20f13a877481453ee7940c78John McCall if (expr->doesUsualArrayDeleteWantSize()) 8306ec278d1a354517e20f13a877481453ee7940c78John McCall return true; 8316ec278d1a354517e20f13a877481453ee7940c78John McCall 832f85e193739c953358c865005855253af4f68a497John McCall // Automatic Reference Counting: 833f85e193739c953358c865005855253af4f68a497John McCall // We need an array cookie for pointers with strong or weak lifetime. 834f85e193739c953358c865005855253af4f68a497John McCall if (getContext().getLangOptions().ObjCAutoRefCount && 835f85e193739c953358c865005855253af4f68a497John McCall elementType->isObjCLifetimeType()) { 836f85e193739c953358c865005855253af4f68a497John McCall switch (elementType.getObjCLifetime()) { 837f85e193739c953358c865005855253af4f68a497John McCall case Qualifiers::OCL_None: 838f85e193739c953358c865005855253af4f68a497John McCall case Qualifiers::OCL_ExplicitNone: 839f85e193739c953358c865005855253af4f68a497John McCall case Qualifiers::OCL_Autoreleasing: 840f85e193739c953358c865005855253af4f68a497John McCall return false; 841f85e193739c953358c865005855253af4f68a497John McCall 842f85e193739c953358c865005855253af4f68a497John McCall case Qualifiers::OCL_Strong: 843f85e193739c953358c865005855253af4f68a497John McCall case Qualifiers::OCL_Weak: 844f85e193739c953358c865005855253af4f68a497John McCall return true; 845f85e193739c953358c865005855253af4f68a497John McCall } 846f85e193739c953358c865005855253af4f68a497John McCall } 847f85e193739c953358c865005855253af4f68a497John McCall 8486ec278d1a354517e20f13a877481453ee7940c78John McCall // Otherwise, if the class has a non-trivial destructor, it always 8496ec278d1a354517e20f13a877481453ee7940c78John McCall // needs a cookie. 8506ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXRecordDecl *record = 8516ec278d1a354517e20f13a877481453ee7940c78John McCall elementType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); 8526ec278d1a354517e20f13a877481453ee7940c78John McCall return (record && !record->hasTrivialDestructor()); 8531e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 8541e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8556ec278d1a354517e20f13a877481453ee7940c78John McCallCharUnits ItaniumCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { 8566ec278d1a354517e20f13a877481453ee7940c78John McCall if (!NeedsArrayCookie(expr)) 8571e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return CharUnits::Zero(); 8581e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8596ec278d1a354517e20f13a877481453ee7940c78John McCall // Padding is the maximum of sizeof(size_t) and alignof(elementType) 8609cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Ctx = getContext(); 8611e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()), 8626ec278d1a354517e20f13a877481453ee7940c78John McCall Ctx.getTypeAlignInChars(expr->getAllocatedType())); 8631e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 8641e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8651e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCallllvm::Value *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 8661e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NewPtr, 8671e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElements, 8686ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXNewExpr *expr, 8691e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType) { 8706ec278d1a354517e20f13a877481453ee7940c78John McCall assert(NeedsArrayCookie(expr)); 8711e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8721e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace(); 8731e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8749cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Ctx = getContext(); 8751e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType SizeTy = Ctx.getSizeType(); 8761e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits SizeSize = Ctx.getTypeSizeInChars(SizeTy); 8771e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8781e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The size of the cookie. 8791e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits CookieSize = 8801e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall std::max(SizeSize, Ctx.getTypeAlignInChars(ElementType)); 8811e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8821e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Compute an offset to the cookie. 8831e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *CookiePtr = NewPtr; 8841e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits CookieOffset = CookieSize - SizeSize; 8851e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall if (!CookieOffset.isZero()) 8861e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_64(CookiePtr, 8871e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieOffset.getQuantity()); 8881e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8891e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Write the number of elements into the appropriate slot. 8901e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElementsPtr 8911e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall = CGF.Builder.CreateBitCast(CookiePtr, 8921e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.ConvertType(SizeTy)->getPointerTo(AS)); 8931e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateStore(NumElements, NumElementsPtr); 8941e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8951e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Finally, compute a pointer to the actual data buffer by skipping 8961e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // over the cookie completely. 8971e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr, 8981e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize.getQuantity()); 8991e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 9001e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9011e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCallvoid ItaniumCXXABI::ReadArrayCookie(CodeGenFunction &CGF, 9021e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *Ptr, 9036ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXDeleteExpr *expr, 9041e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType, 9051e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&NumElements, 9061e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&AllocPtr, 9071e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits &CookieSize) { 9081e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Derive a char* in the same address space as the pointer. 9091e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace(); 9101e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall const llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS); 9111e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9121e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // If we don't need an array cookie, bail out early. 9136ec278d1a354517e20f13a877481453ee7940c78John McCall if (!NeedsArrayCookie(expr, ElementType)) { 9141e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 9151e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElements = 0; 9161e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize = CharUnits::Zero(); 9171e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return; 9181e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall } 9191e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9209cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall QualType SizeTy = getContext().getSizeType(); 9219cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy); 9221e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall const llvm::Type *SizeLTy = CGF.ConvertType(SizeTy); 9231e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9241e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize 9259cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall = std::max(SizeSize, getContext().getTypeAlignInChars(ElementType)); 9261e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9271e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits NumElementsOffset = CookieSize - SizeSize; 9281e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9291e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Compute the allocated pointer. 9301e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 9311e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr, 9321e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall -CookieSize.getQuantity()); 9331e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9341e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElementsPtr = AllocPtr; 9351e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall if (!NumElementsOffset.isZero()) 9361e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElementsPtr = 9371e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateConstInBoundsGEP1_64(NumElementsPtr, 9381e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElementsOffset.getQuantity()); 9391e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElementsPtr = 9401e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS)); 9411e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElements = CGF.Builder.CreateLoad(NumElementsPtr); 9421e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 9431e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9446ec278d1a354517e20f13a877481453ee7940c78John McCallCharUnits ARMCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { 9456ec278d1a354517e20f13a877481453ee7940c78John McCall if (!NeedsArrayCookie(expr)) 9461e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return CharUnits::Zero(); 9471e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9481e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // On ARM, the cookie is always: 9491e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // struct array_cookie { 9501e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // std::size_t element_size; // element_size != 0 9511e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // std::size_t element_count; 9521e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // }; 9531e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // TODO: what should we do if the allocated type actually wants 9541e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // greater alignment? 9551e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return getContext().getTypeSizeInChars(getContext().getSizeType()) * 2; 9561e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 9571e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9581e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCallllvm::Value *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 9591e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NewPtr, 9601e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElements, 9616ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXNewExpr *expr, 9621e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType) { 9636ec278d1a354517e20f13a877481453ee7940c78John McCall assert(NeedsArrayCookie(expr)); 9641e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9651e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // NewPtr is a char*. 9661e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9671e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace(); 9681e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9699cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Ctx = getContext(); 9701e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits SizeSize = Ctx.getTypeSizeInChars(Ctx.getSizeType()); 9711e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall const llvm::IntegerType *SizeTy = 9721e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall cast<llvm::IntegerType>(CGF.ConvertType(Ctx.getSizeType())); 9731e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9741e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The cookie is always at the start of the buffer. 9751e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *CookiePtr = NewPtr; 9761e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9771e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The first element is the element size. 9781e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookiePtr = CGF.Builder.CreateBitCast(CookiePtr, SizeTy->getPointerTo(AS)); 9791e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *ElementSize = llvm::ConstantInt::get(SizeTy, 9801e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall Ctx.getTypeSizeInChars(ElementType).getQuantity()); 9811e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateStore(ElementSize, CookiePtr); 9821e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9831e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The second element is the element count. 9841e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_32(CookiePtr, 1); 9851e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateStore(NumElements, CookiePtr); 9861e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9871e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Finally, compute a pointer to the actual data buffer by skipping 9881e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // over the cookie completely. 9891e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits CookieSize = 2 * SizeSize; 9901e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr, 9911e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize.getQuantity()); 9921e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 9931e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9941e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCallvoid ARMCXXABI::ReadArrayCookie(CodeGenFunction &CGF, 9951e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *Ptr, 9966ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXDeleteExpr *expr, 9971e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType, 9981e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&NumElements, 9991e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&AllocPtr, 10001e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits &CookieSize) { 10011e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Derive a char* in the same address space as the pointer. 10021e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace(); 10031e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall const llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS); 10041e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 10051e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // If we don't need an array cookie, bail out early. 10066ec278d1a354517e20f13a877481453ee7940c78John McCall if (!NeedsArrayCookie(expr, ElementType)) { 10071e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 10081e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElements = 0; 10091e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize = CharUnits::Zero(); 10101e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return; 10111e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall } 10121e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 10139cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall QualType SizeTy = getContext().getSizeType(); 10149cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy); 10151e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall const llvm::Type *SizeLTy = CGF.ConvertType(SizeTy); 10161e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 10171e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The cookie size is always 2 * sizeof(size_t). 10181e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize = 2 * SizeSize; 10191e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 10201e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The allocated pointer is the input ptr, minus that amount. 10211e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 10221e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr, 10231e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall -CookieSize.getQuantity()); 10241e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 10251e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The number of elements is at offset sizeof(size_t) relative to that. 10261e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElementsPtr 10271e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr, 10281e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall SizeSize.getQuantity()); 10291e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElementsPtr = 10301e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS)); 10311e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElements = CGF.Builder.CreateLoad(NumElementsPtr); 10321e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 10331e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 10345cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall/*********************** Static local initialization **************************/ 10355cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10365cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCallstatic llvm::Constant *getGuardAcquireFn(CodeGenModule &CGM, 10379cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner llvm::PointerType *GuardPtrTy) { 10385cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // int __cxa_guard_acquire(__guard *guard_object); 10399cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner llvm::Type *ArgTys[] = { GuardPtrTy }; 10405cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall const llvm::FunctionType *FTy = 10415cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy), 10429cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner ArgTys, /*isVarArg=*/false); 10435cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10445cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire"); 10455cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall} 10465cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10475cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCallstatic llvm::Constant *getGuardReleaseFn(CodeGenModule &CGM, 10489cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner llvm::PointerType *GuardPtrTy) { 10495cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // void __cxa_guard_release(__guard *guard_object); 10509cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner llvm::Type *ArgTys[] = { GuardPtrTy }; 10515cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall const llvm::FunctionType *FTy = 10525cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), 10539cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner ArgTys, /*isVarArg=*/false); 10545cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10555cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release"); 10565cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall} 10575cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10585cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCallstatic llvm::Constant *getGuardAbortFn(CodeGenModule &CGM, 10599cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner llvm::PointerType *GuardPtrTy) { 10605cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // void __cxa_guard_abort(__guard *guard_object); 10619cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner llvm::Type *ArgTys[] = { GuardPtrTy }; 10625cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall const llvm::FunctionType *FTy = 10635cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), 10649cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner ArgTys, /*isVarArg=*/false); 10655cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10665cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort"); 10675cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall} 10685cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10695cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCallnamespace { 10705cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall struct CallGuardAbort : EHScopeStack::Cleanup { 10715cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::GlobalVariable *Guard; 10725cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {} 10735cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10745cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall void Emit(CodeGenFunction &CGF, bool IsForEH) { 10755cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.Builder.CreateCall(getGuardAbortFn(CGF.CGM, Guard->getType()), Guard) 10765cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall ->setDoesNotThrow(); 10775cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } 10785cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall }; 10795cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall} 10805cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10815cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall/// The ARM code here follows the Itanium code closely enough that we 10825cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall/// just special-case it at particular places. 10833030eb82593097502469a8b3fc26112c79c75605John McCallvoid ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, 10843030eb82593097502469a8b3fc26112c79c75605John McCall const VarDecl &D, 10853030eb82593097502469a8b3fc26112c79c75605John McCall llvm::GlobalVariable *GV) { 10865cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGBuilderTy &Builder = CGF.Builder; 10873030eb82593097502469a8b3fc26112c79c75605John McCall 10883030eb82593097502469a8b3fc26112c79c75605John McCall // We only need to use thread-safe statics for local variables; 10893030eb82593097502469a8b3fc26112c79c75605John McCall // global initialization is always single-threaded. 10900502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall bool threadsafe = 10910502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall (getContext().getLangOptions().ThreadsafeStatics && D.isLocalVarDecl()); 1092173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson 1093173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson const llvm::IntegerType *GuardTy; 1094173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson 1095173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson // If we have a global variable with internal linkage and thread-safe statics 1096173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson // are disabled, we can just let the guard variable be of type i8. 10970502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall bool useInt8GuardVariable = !threadsafe && GV->hasInternalLinkage(); 10980502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall if (useInt8GuardVariable) { 10990502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall GuardTy = CGF.Int8Ty; 11000502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall } else { 1101173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson // Guard variables are 64 bits in the generic ABI and 32 bits on ARM. 11020502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall GuardTy = (IsARM ? CGF.Int32Ty : CGF.Int64Ty); 1103173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson } 11049cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner llvm::PointerType *GuardPtrTy = GuardTy->getPointerTo(); 11055cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11065cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Create the guard variable. 11075cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::SmallString<256> GuardVName; 1108f0be979bddb8baa28e77693a3dc931e487b2a9f2Rafael Espindola llvm::raw_svector_ostream Out(GuardVName); 1109f0be979bddb8baa28e77693a3dc931e487b2a9f2Rafael Espindola getMangleContext().mangleItaniumGuardVariable(&D, Out); 1110f0be979bddb8baa28e77693a3dc931e487b2a9f2Rafael Espindola Out.flush(); 1111112c967bd5c862a0f5d7913aa06700c048807db8John McCall 11123030eb82593097502469a8b3fc26112c79c75605John McCall // Just absorb linkage and visibility from the variable. 11135cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::GlobalVariable *GuardVariable = 11145cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall new llvm::GlobalVariable(CGM.getModule(), GuardTy, 11153030eb82593097502469a8b3fc26112c79c75605John McCall false, GV->getLinkage(), 11165cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::ConstantInt::get(GuardTy, 0), 11175cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall GuardVName.str()); 1118112c967bd5c862a0f5d7913aa06700c048807db8John McCall GuardVariable->setVisibility(GV->getVisibility()); 11195cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11205cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Test whether the variable has completed initialization. 11215cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::Value *IsInitialized; 11225cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11235cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // ARM C++ ABI 3.2.3.1: 11245cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // To support the potential use of initialization guard variables 11255cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // as semaphores that are the target of ARM SWP and LDREX/STREX 11265cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // synchronizing instructions we define a static initialization 11275cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // guard variable to be a 4-byte aligned, 4- byte word with the 11285cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // following inline access protocol. 11295cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // #define INITIALIZED 1 11305cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // if ((obj_guard & INITIALIZED) != INITIALIZED) { 11315cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // if (__cxa_guard_acquire(&obj_guard)) 11325cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // ... 11335cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // } 11340502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall if (IsARM && !useInt8GuardVariable) { 11355cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::Value *V = Builder.CreateLoad(GuardVariable); 11365cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall V = Builder.CreateAnd(V, Builder.getInt32(1)); 11375cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized"); 11385cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11395cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Itanium C++ ABI 3.3.2: 11405cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // The following is pseudo-code showing how these functions can be used: 11415cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // if (obj_guard.first_byte == 0) { 11425cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // if ( __cxa_guard_acquire (&obj_guard) ) { 11435cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // try { 11445cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // ... initialize the object ...; 11455cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // } catch (...) { 11465cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // __cxa_guard_abort (&obj_guard); 11475cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // throw; 11485cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // } 11495cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // ... queue object destructor with __cxa_atexit() ...; 11505cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // __cxa_guard_release (&obj_guard); 11515cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // } 11525cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // } 11535cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } else { 11545cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Load the first byte of the guard variable. 11555cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall const llvm::Type *PtrTy = Builder.getInt8PtrTy(); 11565cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::Value *V = 11575cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp"); 11585cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11595cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized"); 11605cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } 11615cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11625cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check"); 11635cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end"); 11645cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11650502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall llvm::BasicBlock *NoCheckBlock = EndBlock; 11660502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall if (threadsafe) NoCheckBlock = CGF.createBasicBlock("init.barrier"); 11670502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall 11685cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Check if the first byte of the guard variable is zero. 11690502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall Builder.CreateCondBr(IsInitialized, InitCheckBlock, NoCheckBlock); 11705cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11715cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.EmitBlock(InitCheckBlock); 11725cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11735cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Variables used when coping with thread-safe statics and exceptions. 11740502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall if (threadsafe) { 11755cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Call __cxa_guard_acquire. 11765cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::Value *V 11775cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall = Builder.CreateCall(getGuardAcquireFn(CGM, GuardPtrTy), GuardVariable); 11785cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11795cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); 11805cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11815cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), 11825cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall InitBlock, EndBlock); 11835cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11845cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Call __cxa_guard_abort along the exceptional edge. 11855cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable); 11865cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11875cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.EmitBlock(InitBlock); 11885cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } 11895cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11905cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Emit the initializer and add a global destructor if appropriate. 11915cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.EmitCXXGlobalVarDeclInit(D, GV); 11925cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11930502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall if (threadsafe) { 11945cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Pop the guard-abort cleanup if we pushed one. 11955cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.PopCleanupBlock(); 11965cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11975cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Call __cxa_guard_release. This cannot throw. 11985cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall Builder.CreateCall(getGuardReleaseFn(CGM, GuardPtrTy), GuardVariable); 11995cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } else { 12005cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall Builder.CreateStore(llvm::ConstantInt::get(GuardTy, 1), GuardVariable); 12015cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } 12025cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 12030502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall // Emit an acquire memory barrier if using thread-safe statics: 12040502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall // Itanium ABI: 12050502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall // An implementation supporting thread-safety on multiprocessor 12060502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall // systems must also guarantee that references to the initialized 12070502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall // object do not occur before the load of the initialization flag. 12080502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall if (threadsafe) { 12090502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall Builder.CreateBr(EndBlock); 12100502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall CGF.EmitBlock(NoCheckBlock); 12110502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall 12120502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall llvm::Value *_false = Builder.getFalse(); 12130502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall llvm::Value *_true = Builder.getTrue(); 12140502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall 12150502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall Builder.CreateCall5(CGM.getIntrinsic(llvm::Intrinsic::memory_barrier), 12160502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall /* load-load, load-store */ _true, _true, 12170502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall /* store-load, store-store */ _false, _false, 12180502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall /* device or I/O */ _false); 12190502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall } 12200502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall 12215cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.EmitBlock(EndBlock); 12225cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall} 1223